summary refs log tree commit diff
path: root/libnm-glib
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2012-03-24 01:37:02 +0100
committerMichael Biebl <biebl@debian.org>2012-03-24 01:37:02 +0100
commitde06e5715e780baade318f3490ac7a4c9ce84e32 (patch)
tree23fbc3fafc12072476eff98bee60100eb54c29db /libnm-glib
parentb436a68a20ff3114ded32a7a3d70cdd4954039f9 (diff)
Imported Upstream version 0.9.4.0 upstream/0.9.4.0
Diffstat (limited to 'libnm-glib')
-rw-r--r--libnm-glib/Makefile.am132
-rw-r--r--libnm-glib/Makefile.in307
-rw-r--r--libnm-glib/libnm-glib-test.c2
-rw-r--r--libnm-glib/libnm-glib.ver48
-rw-r--r--libnm-glib/nm-access-point.c179
-rw-r--r--libnm-glib/nm-active-connection.c336
-rw-r--r--libnm-glib/nm-active-connection.h2
-rw-r--r--libnm-glib/nm-client.c782
-rw-r--r--libnm-glib/nm-client.h9
-rw-r--r--libnm-glib/nm-dbus-utils.c215
-rw-r--r--libnm-glib/nm-dbus-utils.h57
-rw-r--r--libnm-glib/nm-device-bond.c300
-rw-r--r--libnm-glib/nm-device-bond.h82
-rw-r--r--libnm-glib/nm-device-bt.c141
-rw-r--r--libnm-glib/nm-device-bt.h23
-rw-r--r--libnm-glib/nm-device-ethernet.c156
-rw-r--r--libnm-glib/nm-device-ethernet.h21
-rw-r--r--libnm-glib/nm-device-infiniband.c310
-rw-r--r--libnm-glib/nm-device-infiniband.h84
-rw-r--r--libnm-glib/nm-device-modem.c118
-rw-r--r--libnm-glib/nm-device-modem.h19
-rw-r--r--libnm-glib/nm-device-olpc-mesh.c333
-rw-r--r--libnm-glib/nm-device-olpc-mesh.h84
-rw-r--r--libnm-glib/nm-device-private.h12
-rw-r--r--libnm-glib/nm-device-vlan.c338
-rw-r--r--libnm-glib/nm-device-vlan.h86
-rw-r--r--libnm-glib/nm-device-wifi.c340
-rw-r--r--libnm-glib/nm-device-wifi.h27
-rw-r--r--libnm-glib/nm-device-wimax.c339
-rw-r--r--libnm-glib/nm-device-wimax.h21
-rw-r--r--libnm-glib/nm-device.c786
-rw-r--r--libnm-glib/nm-device.h13
-rw-r--r--libnm-glib/nm-dhcp4-config.c55
-rw-r--r--libnm-glib/nm-dhcp6-config.c55
-rw-r--r--libnm-glib/nm-glib-enum-types.c367
-rw-r--r--libnm-glib/nm-glib-enum-types.h47
-rw-r--r--libnm-glib/nm-glib-marshal.c167
-rw-r--r--libnm-glib/nm-glib-marshal.h36
-rw-r--r--libnm-glib/nm-ip4-config.c157
-rw-r--r--libnm-glib/nm-ip6-config.c123
-rw-r--r--libnm-glib/nm-object-cache.c14
-rw-r--r--libnm-glib/nm-object-cache.h2
-rw-r--r--libnm-glib/nm-object-private.h105
-rw-r--r--libnm-glib/nm-object.c1096
-rw-r--r--libnm-glib/nm-remote-connection.c223
-rw-r--r--libnm-glib/nm-remote-settings.c430
-rw-r--r--libnm-glib/nm-remote-settings.h18
-rw-r--r--libnm-glib/nm-secret-agent.c77
-rw-r--r--libnm-glib/nm-secret-agent.h82
-rw-r--r--libnm-glib/nm-types.c22
-rw-r--r--libnm-glib/nm-types.h2
-rw-r--r--libnm-glib/nm-vpn-connection.c89
-rw-r--r--libnm-glib/nm-vpn-enum-types.c61
-rw-r--r--libnm-glib/nm-vpn-enum-types.h21
-rw-r--r--libnm-glib/nm-vpn-plugin.c28
-rw-r--r--libnm-glib/nm-vpn-plugin.h19
-rw-r--r--libnm-glib/nm-wimax-nsp.c75
-rw-r--r--libnm-glib/tests/Makefile.am2
-rw-r--r--libnm-glib/tests/Makefile.in11
59 files changed, 5772 insertions, 3314 deletions
diff --git a/libnm-glib/Makefile.am b/libnm-glib/Makefile.am
index 4eec4016..b2ea3b79 100644
--- a/libnm-glib/Makefile.am
+++ b/libnm-glib/Makefile.am
@@ -1,28 +1,16 @@
+include $(GLIB_MAKEFILE)
+
 SUBDIRS=. tests
 
 INCLUDES = \
 	-I$(top_srcdir)/include \
+	-I$(top_builddir)/include \
 	-I$(top_srcdir)/libnm-util \
+	-I$(top_builddir)/libnm-util \
 	-I$(top_builddir)/marshallers
 
 BUILT_SOURCES = \
-	nm-access-point-bindings.h \
-	nm-client-bindings.h \
-	nm-device-bindings.h \
-	nm-device-ethernet-bindings.h \
-	nm-device-wifi-bindings.h \
-	nm-device-bt-bindings.h \
-	nm-settings-connection-bindings.h \
-	nm-device-wimax-bindings.h \
-	nm-device-modem-bindings.h \
-	nm-settings-bindings.h \
-	nm-vpn-connection-bindings.h \
 	nm-vpn-plugin-glue.h \
-	nm-active-connection-bindings.h \
-	nm-ip4-config-bindings.h \
-	nm-dhcp4-config-bindings.h \
-	nm-ip6-config-bindings.h \
-	nm-dhcp6-config-bindings.h \
 	nm-secret-agent-glue.h
 
 
@@ -58,7 +46,7 @@ libdeprecated_HEADERS = libnm_glib.h
 lib_LTLIBRARIES = libnm-glib.la libnm-glib-vpn.la
 
 libnm_glib_la_CFLAGS = \
-	$(GLIB_CFLAGS) \
+	$(GIO_CFLAGS) \
 	$(DBUS_CFLAGS) \
 	$(GUDEV_CFLAGS)
 
@@ -70,8 +58,12 @@ libnminclude_HEADERS = \
 	nm-client.h \
 	nm-device.h \
 	nm-device-ethernet.h \
+	nm-device-infiniband.h \
 	nm-device-wifi.h \
 	nm-device-bt.h \
+	nm-device-olpc-mesh.h \
+	nm-device-bond.h \
+	nm-device-vlan.h \
 	nm-access-point.h \
 	nm-ip4-config.h \
 	nm-device-modem.h \
@@ -85,21 +77,26 @@ libnminclude_HEADERS = \
 	nm-remote-settings.h \
 	nm-secret-agent.h \
 	nm-device-wimax.h \
-	nm-wimax-nsp.h
+	nm-wimax-nsp.h \
+	nm-glib-enum-types.h
 
 libnmvpn_HEADERS = \
 	nm-vpn-plugin.h \
 	nm-vpn-plugin-ui-interface.h \
-	nm-vpn-plugin-utils.h
+	nm-vpn-plugin-utils.h \
+	nm-vpn-enum-types.h
 
 libnm_glib_la_csources = \
 	nm-object.c \
 	nm-client.c \
-	nm-dbus-utils.c \
 	nm-device.c \
 	nm-device-ethernet.c \
+	nm-device-infiniband.c \
 	nm-device-wifi.c \
 	nm-device-bt.c \
+	nm-device-olpc-mesh.c \
+	nm-device-bond.c \
+	nm-device-vlan.c \
 	nm-access-point.c \
 	nm-ip4-config.c \
 	nm-device-modem.c \
@@ -114,55 +111,69 @@ libnm_glib_la_csources = \
 	nm-remote-settings.c \
 	nm-secret-agent.c \
 	nm-device-wimax.c \
-	nm-wimax-nsp.c
+	nm-wimax-nsp.c \
+	nm-glib-enum-types.c \
+	nm-glib-marshal.c
 
 libnm_glib_la_private_headers = \
 	nm-object-private.h \
-	nm-dbus-utils.h \
 	nm-device-private.h \
 	nm-types-private.h \
 	nm-object-cache.h \
-	nm-remote-connection-private.h
+	nm-remote-connection-private.h \
+	nm-glib-marshal.h
 
 libnm_glib_la_SOURCES = \
 	$(libnm_glib_la_csources) \
 	$(libnm_glib_la_private_headers)
 
+GLIB_GENERATED = nm-glib-enum-types.h nm-glib-enum-types.c
+nm_glib_enum_types_sources = $(libnminclude_HEADERS)
+GLIB_MKENUMS_H_FLAGS = --identifier-prefix NM
+GLIB_MKENUMS_C_FLAGS = --identifier-prefix NM
+
+GLIB_GENERATED += nm-glib-marshal.h nm-glib-marshal.c
+nm_glib_marshal_sources = $(libnm_glib_la_SOURCES)
+
 libnm_glib_la_LIBADD = \
 	$(top_builddir)/libnm-util/libnm-util.la \
-	$(top_builddir)/marshallers/libmarshallers.la \
 	$(builddir)/libdeprecated-nm-glib.la \
-	$(GLIB_LIBS) \
+	$(GIO_LIBS) \
 	$(DBUS_LIBS) \
 	$(GUDEV_LIBS)
 
 SYMBOL_VIS_FILE=$(srcdir)/libnm-glib.ver
 
 libnm_glib_la_LDFLAGS = -Wl,--version-script=$(SYMBOL_VIS_FILE) \
-	-version-info "6:0:2"
+	-version-info "7:0:3"
 
 noinst_PROGRAMS = libnm-glib-test
 
 libnm_glib_test_SOURCES = libnm-glib-test.c
-libnm_glib_test_CFLAGS = $(GLIB_CFLAGS) $(DBUS_CFLAGS)
-libnm_glib_test_LDADD = libnm-glib.la $(top_builddir)/libnm-util/libnm-util.la $(GLIB_LIBS) $(DBUS_LIBS)
+libnm_glib_test_CFLAGS = $(GIO_CFLAGS) $(DBUS_CFLAGS)
+libnm_glib_test_LDADD = libnm-glib.la $(top_builddir)/libnm-util/libnm-util.la $(GIO_LIBS) $(DBUS_LIBS)
 
 
 libnm_glib_vpn_la_SOURCES = \
 	nm-vpn-plugin.c \
 	nm-vpn-plugin-ui-interface.c \
-	nm-vpn-plugin-utils.c
-libnm_glib_vpn_la_CFLAGS = $(GLIB_CFLAGS) $(DBUS_CFLAGS)
-libnm_glib_vpn_la_LIBADD = $(top_builddir)/libnm-util/libnm-util.la $(GLIB_LIBS) $(DBUS_LIBS)
+	nm-vpn-plugin-utils.c \
+	nm-vpn-enum-types.c
+GLIB_GENERATED += nm-vpn-enum-types.h nm-vpn-enum-types.c
+nm_vpn_enum_types_sources = $(libnmvpn_HEADERS)
+libnm_glib_vpn_la_CFLAGS = $(GIO_CFLAGS) $(DBUS_CFLAGS)
+libnm_glib_vpn_la_LIBADD = $(top_builddir)/libnm-util/libnm-util.la $(GIO_LIBS) $(DBUS_LIBS)
 libnm_glib_vpn_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libnm-glib-vpn.ver \
 	-version-info "2:0:1"
 
+BUILT_SOURCES += $(GLIB_GENERATED)
+
 #####################################################
 # Test libnm-glib stuff
 #####################################################
 
 libnm_glib_test_la_CFLAGS = \
-	$(GLIB_CFLAGS) \
+	$(GIO_CFLAGS) \
 	$(DBUS_CFLAGS) \
 	$(GUDEV_CFLAGS) \
 	-DLIBNM_GLIB_TEST
@@ -173,67 +184,18 @@ libnm_glib_test_la_SOURCES = \
 
 libnm_glib_test_la_LIBADD = \
 	$(top_builddir)/libnm-util/libnm-util.la \
-	$(top_builddir)/marshallers/libmarshallers.la \
-	$(GLIB_LIBS) \
+	$(GIO_LIBS) \
 	$(DBUS_LIBS) \
 	$(GUDEV_LIBS)
 
 #####################################################
 
-nm-client-bindings.h: $(top_srcdir)/introspection/nm-manager.xml
-	$(AM_V_GEN) dbus-binding-tool --prefix=nm_client --mode=glib-client --output=$@ $<
-
-nm-device-bindings.h: $(top_srcdir)/introspection/nm-device.xml
-	$(AM_V_GEN) dbus-binding-tool --prefix=nm_device --mode=glib-client --output=$@ $<
-
-nm-device-ethernet-bindings.h: $(top_srcdir)/introspection/nm-device-ethernet.xml
-	$(AM_V_GEN) dbus-binding-tool --prefix=nm_device_ethernet --mode=glib-client --output=$@ $<
-
-nm-device-wifi-bindings.h: $(top_srcdir)/introspection/nm-device-wifi.xml
-	$(AM_V_GEN) dbus-binding-tool --prefix=nm_device_wifi --mode=glib-client --output=$@ $<
-
-nm-device-bt-bindings.h: $(top_srcdir)/introspection/nm-device-bt.xml
-	$(AM_V_GEN) dbus-binding-tool --prefix=nm_device_bt --mode=glib-client --output=$@ $<
-
-nm-access-point-bindings.h: $(top_srcdir)/introspection/nm-access-point.xml
-	$(AM_V_GEN) dbus-binding-tool --prefix=nm_access_point --mode=glib-client --output=$@ $<
-
-nm-settings-bindings.h: $(top_srcdir)/introspection/nm-settings.xml
-	$(AM_V_GEN) dbus-binding-tool --prefix=nm_settings --mode=glib-client --output=$@ $<
-
-nm-settings-connection-bindings.h: $(top_srcdir)/introspection/nm-settings-connection.xml
-	$(AM_V_GEN) dbus-binding-tool --prefix=nm_settings_connection --mode=glib-client --output=$@ $<
-
-nm-vpn-connection-bindings.h: $(top_srcdir)/introspection/nm-vpn-connection.xml
-	$(AM_V_GEN) dbus-binding-tool --prefix=nm_vpn_connection --mode=glib-client --output=$@ $<
-
 nm-vpn-plugin-glue.h: $(top_srcdir)/introspection/nm-vpn-plugin.xml
 	$(AM_V_GEN) dbus-binding-tool --prefix=nm_vpn_plugin --mode=glib-server --output=$@ $<
 
-nm-active-connection-bindings.h: $(top_srcdir)/introspection/nm-active-connection.xml
-	$(AM_V_GEN) dbus-binding-tool --prefix=nm_active_connection --mode=glib-client --output=$@ $<
-
-nm-ip4-config-bindings.h: $(top_srcdir)/introspection/nm-ip4-config.xml
-	$(AM_V_GEN) dbus-binding-tool --prefix=nm_ip4_config --mode=glib-client --output=$@ $<
-
-nm-dhcp4-config-bindings.h: $(top_srcdir)/introspection/nm-dhcp4-config.xml
-	$(AM_V_GEN) dbus-binding-tool --prefix=nm_dhcp4_config --mode=glib-client --output=$@ $<
-
-nm-ip6-config-bindings.h: $(top_srcdir)/introspection/nm-ip6-config.xml
-	$(AM_V_GEN) dbus-binding-tool --prefix=nm_ip6_config --mode=glib-client --output=$@ $<
-
-nm-dhcp6-config-bindings.h: $(top_srcdir)/introspection/nm-dhcp6-config.xml
-	$(AM_V_GEN) dbus-binding-tool --prefix=nm_dhcp6_config --mode=glib-client --output=$@ $<
-
 nm-secret-agent-glue.h: $(top_srcdir)/introspection/nm-secret-agent.xml
 	$(AM_V_GEN) dbus-binding-tool --prefix=nm_secret_agent --mode=glib-server --output=$@ $<
 
-nm-device-wimax-bindings.h: $(top_srcdir)/introspection/nm-device-wimax.xml
-	dbus-binding-tool --prefix=nm_device_wimax --mode=glib-client --output=$@ $<
-
-nm-device-modem-bindings.h: $(top_srcdir)/introspection/nm-device-modem.xml
-	dbus-binding-tool --prefix=nm_device_modem --mode=glib-client --output=$@ $<
-
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = libnm-glib.pc libnm-glib-vpn.pc
 
@@ -241,7 +203,7 @@ DISTCLEANFILES = libnm-glib.pc libnm-glib.pc
 
 EXTRA_DIST = libnm-glib.pc.in libnm-glib-vpn.pc.in libnm-glib.ver libnm-glib-vpn.ver
 
-CLEANFILES = $(BUILT_SOURCES) *-bindings.h *-glue.h
+CLEANFILES = $(BUILT_SOURCES)
 
 -include $(INTROSPECTION_MAKEFILE)
 INTROSPECTION_GIRS =
@@ -251,8 +213,8 @@ if HAVE_INTROSPECTION
 introspection_sources = $(libnminclude_HEADERS) $(libnm_glib_la_csources)
 
 NMClient-1.0.gir: libnm-glib.la
-NMClient_1_0_gir_INCLUDES = GObject-2.0 DBusGLib-1.0
-NMClient_1_0_gir_PACKAGES = gobject-2.0 dbus-glib-1 gudev-1.0
+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_CFLAGS = $(INCLUDES) -I$(top_srcdir)/libnm-glib -I$(top_srcdir)/libnm-util
 NMClient_1_0_gir_LIBS = libnm-glib.la
 NMClient_1_0_gir_FILES = $(introspection_sources)
diff --git a/libnm-glib/Makefile.in b/libnm-glib/Makefile.in
index cbfa06f4..5a013e87 100644
--- a/libnm-glib/Makefile.in
+++ b/libnm-glib/Makefile.in
@@ -100,18 +100,19 @@ AM_V_lt = $(am__v_lt_$(V))
 am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
 am__v_lt_0 = --silent
 libnm_glib_test_la_DEPENDENCIES =  \
-	$(top_builddir)/libnm-util/libnm-util.la \
-	$(top_builddir)/marshallers/libmarshallers.la \
-	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
-	$(am__DEPENDENCIES_1)
+	$(top_builddir)/libnm-util/libnm-util.la $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
 am__objects_1 =
 am__objects_2 = libnm_glib_test_la-nm-object.lo \
 	libnm_glib_test_la-nm-client.lo \
-	libnm_glib_test_la-nm-dbus-utils.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-wifi.lo \
 	libnm_glib_test_la-nm-device-bt.lo \
+	libnm_glib_test_la-nm-device-olpc-mesh.lo \
+	libnm_glib_test_la-nm-device-bond.lo \
+	libnm_glib_test_la-nm-device-vlan.lo \
 	libnm_glib_test_la-nm-access-point.lo \
 	libnm_glib_test_la-nm-ip4-config.lo \
 	libnm_glib_test_la-nm-device-modem.lo \
@@ -126,7 +127,9 @@ am__objects_2 = libnm_glib_test_la-nm-object.lo \
 	libnm_glib_test_la-nm-remote-settings.lo \
 	libnm_glib_test_la-nm-secret-agent.lo \
 	libnm_glib_test_la-nm-device-wimax.lo \
-	libnm_glib_test_la-nm-wimax-nsp.lo
+	libnm_glib_test_la-nm-wimax-nsp.lo \
+	libnm_glib_test_la-nm-glib-enum-types.lo \
+	libnm_glib_test_la-nm-glib-marshal.lo
 am__objects_3 = $(am__objects_2) $(am__objects_1)
 am_libnm_glib_test_la_OBJECTS = $(am__objects_1) $(am__objects_3)
 libnm_glib_test_la_OBJECTS = $(am_libnm_glib_test_la_OBJECTS)
@@ -139,20 +142,23 @@ libnm_glib_vpn_la_DEPENDENCIES =  \
 	$(am__DEPENDENCIES_1)
 am_libnm_glib_vpn_la_OBJECTS = libnm_glib_vpn_la-nm-vpn-plugin.lo \
 	libnm_glib_vpn_la-nm-vpn-plugin-ui-interface.lo \
-	libnm_glib_vpn_la-nm-vpn-plugin-utils.lo
+	libnm_glib_vpn_la-nm-vpn-plugin-utils.lo \
+	libnm_glib_vpn_la-nm-vpn-enum-types.lo
 libnm_glib_vpn_la_OBJECTS = $(am_libnm_glib_vpn_la_OBJECTS)
 libnm_glib_vpn_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
 	$(libnm_glib_vpn_la_CFLAGS) $(CFLAGS) \
 	$(libnm_glib_vpn_la_LDFLAGS) $(LDFLAGS) -o $@
 libnm_glib_la_DEPENDENCIES = $(top_builddir)/libnm-util/libnm-util.la \
-	$(top_builddir)/marshallers/libmarshallers.la \
 	$(builddir)/libdeprecated-nm-glib.la $(am__DEPENDENCIES_1) \
 	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
 am__objects_4 = libnm_glib_la-nm-object.lo libnm_glib_la-nm-client.lo \
-	libnm_glib_la-nm-dbus-utils.lo libnm_glib_la-nm-device.lo \
-	libnm_glib_la-nm-device-ethernet.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-wifi.lo libnm_glib_la-nm-device-bt.lo \
+	libnm_glib_la-nm-device-olpc-mesh.lo \
+	libnm_glib_la-nm-device-bond.lo \
+	libnm_glib_la-nm-device-vlan.lo \
 	libnm_glib_la-nm-access-point.lo \
 	libnm_glib_la-nm-ip4-config.lo \
 	libnm_glib_la-nm-device-modem.lo \
@@ -165,7 +171,9 @@ am__objects_4 = libnm_glib_la-nm-object.lo libnm_glib_la-nm-client.lo \
 	libnm_glib_la-nm-remote-connection.lo \
 	libnm_glib_la-nm-remote-settings.lo \
 	libnm_glib_la-nm-secret-agent.lo \
-	libnm_glib_la-nm-device-wimax.lo libnm_glib_la-nm-wimax-nsp.lo
+	libnm_glib_la-nm-device-wimax.lo libnm_glib_la-nm-wimax-nsp.lo \
+	libnm_glib_la-nm-glib-enum-types.lo \
+	libnm_glib_la-nm-glib-marshal.lo
 am_libnm_glib_la_OBJECTS = $(am__objects_4) $(am__objects_1)
 libnm_glib_la_OBJECTS = $(am_libnm_glib_la_OBJECTS)
 libnm_glib_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
@@ -303,6 +311,8 @@ GIO_LIBS = @GIO_LIBS@
 GLIB_CFLAGS = @GLIB_CFLAGS@
 GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
 GLIB_LIBS = @GLIB_LIBS@
+GLIB_MAKEFILE = @GLIB_MAKEFILE@
+GLIB_MKENUMS = @GLIB_MKENUMS@
 GMODULE_CFLAGS = @GMODULE_CFLAGS@
 GMODULE_LIBS = @GMODULE_LIBS@
 GMSGFMT = @GMSGFMT@
@@ -357,11 +367,15 @@ LIBNL2_LIBS = @LIBNL2_LIBS@
 LIBNL3_CFLAGS = @LIBNL3_CFLAGS@
 LIBNL3_LIBS = @LIBNL3_LIBS@
 LIBNL_CFLAGS = @LIBNL_CFLAGS@
+LIBNL_GENL3_CFLAGS = @LIBNL_GENL3_CFLAGS@
+LIBNL_GENL3_LIBS = @LIBNL_GENL3_LIBS@
 LIBNL_LIBS = @LIBNL_LIBS@
 LIBNL_ROUTE3_CFLAGS = @LIBNL_ROUTE3_CFLAGS@
 LIBNL_ROUTE3_LIBS = @LIBNL_ROUTE3_LIBS@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
+LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@
+LIBSOUP_LIBS = @LIBSOUP_LIBS@
 LIBTOOL = @LIBTOOL@
 LIPO = @LIPO@
 LN_S = @LN_S@
@@ -372,6 +386,7 @@ MAINT = @MAINT@
 MAKEINFO = @MAKEINFO@
 MANIFEST_TOOL = @MANIFEST_TOOL@
 MKDIR_P = @MKDIR_P@
+MOC = @MOC@
 MSGFMT = @MSGFMT@
 MSGFMT_015 = @MSGFMT_015@
 MSGMERGE = @MSGMERGE@
@@ -411,6 +426,8 @@ SED = @SED@
 SET_MAKE = @SET_MAKE@
 SHELL = @SHELL@
 STRIP = @STRIP@
+SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@
+SYSTEMD_LIBS = @SYSTEMD_LIBS@
 SYSTEM_CA_PATH = @SYSTEM_CA_PATH@
 UDEV_BASE_DIR = @UDEV_BASE_DIR@
 USE_NLS = @USE_NLS@
@@ -477,29 +494,13 @@ top_srcdir = @top_srcdir@
 SUBDIRS = . tests
 INCLUDES = \
 	-I$(top_srcdir)/include \
+	-I$(top_builddir)/include \
 	-I$(top_srcdir)/libnm-util \
+	-I$(top_builddir)/libnm-util \
 	-I$(top_builddir)/marshallers
 
-BUILT_SOURCES = \
-	nm-access-point-bindings.h \
-	nm-client-bindings.h \
-	nm-device-bindings.h \
-	nm-device-ethernet-bindings.h \
-	nm-device-wifi-bindings.h \
-	nm-device-bt-bindings.h \
-	nm-settings-connection-bindings.h \
-	nm-device-wimax-bindings.h \
-	nm-device-modem-bindings.h \
-	nm-settings-bindings.h \
-	nm-vpn-connection-bindings.h \
-	nm-vpn-plugin-glue.h \
-	nm-active-connection-bindings.h \
-	nm-ip4-config-bindings.h \
-	nm-dhcp4-config-bindings.h \
-	nm-ip6-config-bindings.h \
-	nm-dhcp6-config-bindings.h \
-	nm-secret-agent-glue.h
-
+BUILT_SOURCES = nm-vpn-plugin-glue.h nm-secret-agent-glue.h \
+	$(GLIB_GENERATED)
 noinst_LTLIBRARIES = \
 	libdeprecated-nm-glib.la \
 	libnm-glib-test.la
@@ -530,7 +531,7 @@ libdeprecated_HEADERS = libnm_glib.h
 #####################################################
 lib_LTLIBRARIES = libnm-glib.la libnm-glib-vpn.la
 libnm_glib_la_CFLAGS = \
-	$(GLIB_CFLAGS) \
+	$(GIO_CFLAGS) \
 	$(DBUS_CFLAGS) \
 	$(GUDEV_CFLAGS)
 
@@ -541,8 +542,12 @@ libnminclude_HEADERS = \
 	nm-client.h \
 	nm-device.h \
 	nm-device-ethernet.h \
+	nm-device-infiniband.h \
 	nm-device-wifi.h \
 	nm-device-bt.h \
+	nm-device-olpc-mesh.h \
+	nm-device-bond.h \
+	nm-device-vlan.h \
 	nm-access-point.h \
 	nm-ip4-config.h \
 	nm-device-modem.h \
@@ -556,21 +561,26 @@ libnminclude_HEADERS = \
 	nm-remote-settings.h \
 	nm-secret-agent.h \
 	nm-device-wimax.h \
-	nm-wimax-nsp.h
+	nm-wimax-nsp.h \
+	nm-glib-enum-types.h
 
 libnmvpn_HEADERS = \
 	nm-vpn-plugin.h \
 	nm-vpn-plugin-ui-interface.h \
-	nm-vpn-plugin-utils.h
+	nm-vpn-plugin-utils.h \
+	nm-vpn-enum-types.h
 
 libnm_glib_la_csources = \
 	nm-object.c \
 	nm-client.c \
-	nm-dbus-utils.c \
 	nm-device.c \
 	nm-device-ethernet.c \
+	nm-device-infiniband.c \
 	nm-device-wifi.c \
 	nm-device-bt.c \
+	nm-device-olpc-mesh.c \
+	nm-device-bond.c \
+	nm-device-vlan.c \
 	nm-access-point.c \
 	nm-ip4-config.c \
 	nm-device-modem.c \
@@ -585,42 +595,52 @@ libnm_glib_la_csources = \
 	nm-remote-settings.c \
 	nm-secret-agent.c \
 	nm-device-wimax.c \
-	nm-wimax-nsp.c
+	nm-wimax-nsp.c \
+	nm-glib-enum-types.c \
+	nm-glib-marshal.c
 
 libnm_glib_la_private_headers = \
 	nm-object-private.h \
-	nm-dbus-utils.h \
 	nm-device-private.h \
 	nm-types-private.h \
 	nm-object-cache.h \
-	nm-remote-connection-private.h
+	nm-remote-connection-private.h \
+	nm-glib-marshal.h
 
 libnm_glib_la_SOURCES = \
 	$(libnm_glib_la_csources) \
 	$(libnm_glib_la_private_headers)
 
+GLIB_GENERATED = nm-glib-enum-types.h nm-glib-enum-types.c \
+	nm-glib-marshal.h nm-glib-marshal.c nm-vpn-enum-types.h \
+	nm-vpn-enum-types.c
+nm_glib_enum_types_sources = $(libnminclude_HEADERS)
+GLIB_MKENUMS_H_FLAGS = --identifier-prefix NM
+GLIB_MKENUMS_C_FLAGS = --identifier-prefix NM
+nm_glib_marshal_sources = $(libnm_glib_la_SOURCES)
 libnm_glib_la_LIBADD = \
 	$(top_builddir)/libnm-util/libnm-util.la \
-	$(top_builddir)/marshallers/libmarshallers.la \
 	$(builddir)/libdeprecated-nm-glib.la \
-	$(GLIB_LIBS) \
+	$(GIO_LIBS) \
 	$(DBUS_LIBS) \
 	$(GUDEV_LIBS)
 
 SYMBOL_VIS_FILE = $(srcdir)/libnm-glib.ver
 libnm_glib_la_LDFLAGS = -Wl,--version-script=$(SYMBOL_VIS_FILE) \
-	-version-info "6:0:2"
+	-version-info "7:0:3"
 
 libnm_glib_test_SOURCES = libnm-glib-test.c
-libnm_glib_test_CFLAGS = $(GLIB_CFLAGS) $(DBUS_CFLAGS)
-libnm_glib_test_LDADD = libnm-glib.la $(top_builddir)/libnm-util/libnm-util.la $(GLIB_LIBS) $(DBUS_LIBS)
+libnm_glib_test_CFLAGS = $(GIO_CFLAGS) $(DBUS_CFLAGS)
+libnm_glib_test_LDADD = libnm-glib.la $(top_builddir)/libnm-util/libnm-util.la $(GIO_LIBS) $(DBUS_LIBS)
 libnm_glib_vpn_la_SOURCES = \
 	nm-vpn-plugin.c \
 	nm-vpn-plugin-ui-interface.c \
-	nm-vpn-plugin-utils.c
+	nm-vpn-plugin-utils.c \
+	nm-vpn-enum-types.c
 
-libnm_glib_vpn_la_CFLAGS = $(GLIB_CFLAGS) $(DBUS_CFLAGS)
-libnm_glib_vpn_la_LIBADD = $(top_builddir)/libnm-util/libnm-util.la $(GLIB_LIBS) $(DBUS_LIBS)
+nm_vpn_enum_types_sources = $(libnmvpn_HEADERS)
+libnm_glib_vpn_la_CFLAGS = $(GIO_CFLAGS) $(DBUS_CFLAGS)
+libnm_glib_vpn_la_LIBADD = $(top_builddir)/libnm-util/libnm-util.la $(GIO_LIBS) $(DBUS_LIBS)
 libnm_glib_vpn_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libnm-glib-vpn.ver \
 	-version-info "2:0:1"
 
@@ -629,7 +649,7 @@ libnm_glib_vpn_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libnm-glib-vpn.ver \
 # Test libnm-glib stuff
 #####################################################
 libnm_glib_test_la_CFLAGS = \
-	$(GLIB_CFLAGS) \
+	$(GIO_CFLAGS) \
 	$(DBUS_CFLAGS) \
 	$(GUDEV_CFLAGS) \
 	-DLIBNM_GLIB_TEST
@@ -640,8 +660,7 @@ libnm_glib_test_la_SOURCES = \
 
 libnm_glib_test_la_LIBADD = \
 	$(top_builddir)/libnm-util/libnm-util.la \
-	$(top_builddir)/marshallers/libmarshallers.la \
-	$(GLIB_LIBS) \
+	$(GIO_LIBS) \
 	$(DBUS_LIBS) \
 	$(GUDEV_LIBS)
 
@@ -649,12 +668,12 @@ pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = libnm-glib.pc libnm-glib-vpn.pc
 DISTCLEANFILES = libnm-glib.pc libnm-glib.pc
 EXTRA_DIST = libnm-glib.pc.in libnm-glib-vpn.pc.in libnm-glib.ver libnm-glib-vpn.ver
-CLEANFILES = $(BUILT_SOURCES) *-bindings.h *-glue.h $(am__append_2)
+CLEANFILES = $(BUILT_SOURCES) $(am__append_2)
 INTROSPECTION_GIRS = $(am__append_1)
 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 = GObject-2.0 DBusGLib-1.0
-@HAVE_INTROSPECTION_TRUE@NMClient_1_0_gir_PACKAGES = gobject-2.0 dbus-glib-1 gudev-1.0
+@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_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_FILES = $(introspection_sources)
@@ -773,15 +792,20 @@ 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-dbus-utils.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@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_la-nm-device-infiniband.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_la-nm-device-modem.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_la-nm-device-olpc-mesh.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_la-nm-device-vlan.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_la-nm-device-wifi.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_la-nm-device-wimax.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_la-nm-device.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_la-nm-dhcp4-config.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_la-nm-dhcp6-config.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_la-nm-glib-enum-types.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_la-nm-glib-marshal.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_la-nm-ip4-config.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_la-nm-ip6-config.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_la-nm-object-cache.Plo@am__quote@
@@ -796,15 +820,20 @@ 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-dbus-utils.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@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_test_la-nm-device-infiniband.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_test_la-nm-device-modem.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_test_la-nm-device-olpc-mesh.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_test_la-nm-device-vlan.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_test_la-nm-device-wifi.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_test_la-nm-device-wimax.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_test_la-nm-device.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_test_la-nm-dhcp4-config.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_test_la-nm-dhcp6-config.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_test_la-nm-glib-enum-types.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_test_la-nm-glib-marshal.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_test_la-nm-ip4-config.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_test_la-nm-ip6-config.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_test_la-nm-object-cache.Plo@am__quote@
@@ -815,6 +844,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_test_la-nm-types.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_test_la-nm-vpn-connection.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_test_la-nm-wimax-nsp.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_vpn_la-nm-vpn-enum-types.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_vpn_la-nm-vpn-plugin-ui-interface.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_vpn_la-nm-vpn-plugin-utils.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_vpn_la-nm-vpn-plugin.Plo@am__quote@
@@ -870,14 +900,6 @@ libnm_glib_test_la-nm-client.lo: nm-client.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-client.lo `test -f 'nm-client.c' || echo '$(srcdir)/'`nm-client.c
 
-libnm_glib_test_la-nm-dbus-utils.lo: nm-dbus-utils.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnm_glib_test_la_CFLAGS) $(CFLAGS) -MT libnm_glib_test_la-nm-dbus-utils.lo -MD -MP -MF $(DEPDIR)/libnm_glib_test_la-nm-dbus-utils.Tpo -c -o libnm_glib_test_la-nm-dbus-utils.lo `test -f 'nm-dbus-utils.c' || echo '$(srcdir)/'`nm-dbus-utils.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_glib_test_la-nm-dbus-utils.Tpo $(DEPDIR)/libnm_glib_test_la-nm-dbus-utils.Plo
-@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-dbus-utils.c' object='libnm_glib_test_la-nm-dbus-utils.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-dbus-utils.lo `test -f 'nm-dbus-utils.c' || echo '$(srcdir)/'`nm-dbus-utils.c
-
 libnm_glib_test_la-nm-device.lo: nm-device.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.lo -MD -MP -MF $(DEPDIR)/libnm_glib_test_la-nm-device.Tpo -c -o libnm_glib_test_la-nm-device.lo `test -f 'nm-device.c' || echo '$(srcdir)/'`nm-device.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_glib_test_la-nm-device.Tpo $(DEPDIR)/libnm_glib_test_la-nm-device.Plo
@@ -894,6 +916,14 @@ libnm_glib_test_la-nm-device-ethernet.lo: nm-device-ethernet.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-ethernet.lo `test -f 'nm-device-ethernet.c' || echo '$(srcdir)/'`nm-device-ethernet.c
 
+libnm_glib_test_la-nm-device-infiniband.lo: nm-device-infiniband.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-infiniband.lo -MD -MP -MF $(DEPDIR)/libnm_glib_test_la-nm-device-infiniband.Tpo -c -o libnm_glib_test_la-nm-device-infiniband.lo `test -f 'nm-device-infiniband.c' || echo '$(srcdir)/'`nm-device-infiniband.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_glib_test_la-nm-device-infiniband.Tpo $(DEPDIR)/libnm_glib_test_la-nm-device-infiniband.Plo
+@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-device-infiniband.c' object='libnm_glib_test_la-nm-device-infiniband.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-infiniband.lo `test -f 'nm-device-infiniband.c' || echo '$(srcdir)/'`nm-device-infiniband.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
@@ -910,6 +940,30 @@ libnm_glib_test_la-nm-device-bt.lo: nm-device-bt.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-bt.lo `test -f 'nm-device-bt.c' || echo '$(srcdir)/'`nm-device-bt.c
 
+libnm_glib_test_la-nm-device-olpc-mesh.lo: nm-device-olpc-mesh.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnm_glib_test_la_CFLAGS) $(CFLAGS) -MT libnm_glib_test_la-nm-device-olpc-mesh.lo -MD -MP -MF $(DEPDIR)/libnm_glib_test_la-nm-device-olpc-mesh.Tpo -c -o libnm_glib_test_la-nm-device-olpc-mesh.lo `test -f 'nm-device-olpc-mesh.c' || echo '$(srcdir)/'`nm-device-olpc-mesh.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_glib_test_la-nm-device-olpc-mesh.Tpo $(DEPDIR)/libnm_glib_test_la-nm-device-olpc-mesh.Plo
+@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-device-olpc-mesh.c' object='libnm_glib_test_la-nm-device-olpc-mesh.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-olpc-mesh.lo `test -f 'nm-device-olpc-mesh.c' || echo '$(srcdir)/'`nm-device-olpc-mesh.c
+
+libnm_glib_test_la-nm-device-bond.lo: nm-device-bond.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-bond.lo -MD -MP -MF $(DEPDIR)/libnm_glib_test_la-nm-device-bond.Tpo -c -o libnm_glib_test_la-nm-device-bond.lo `test -f 'nm-device-bond.c' || echo '$(srcdir)/'`nm-device-bond.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_glib_test_la-nm-device-bond.Tpo $(DEPDIR)/libnm_glib_test_la-nm-device-bond.Plo
+@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-device-bond.c' object='libnm_glib_test_la-nm-device-bond.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-bond.lo `test -f 'nm-device-bond.c' || echo '$(srcdir)/'`nm-device-bond.c
+
+libnm_glib_test_la-nm-device-vlan.lo: nm-device-vlan.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnm_glib_test_la_CFLAGS) $(CFLAGS) -MT libnm_glib_test_la-nm-device-vlan.lo -MD -MP -MF $(DEPDIR)/libnm_glib_test_la-nm-device-vlan.Tpo -c -o libnm_glib_test_la-nm-device-vlan.lo `test -f 'nm-device-vlan.c' || echo '$(srcdir)/'`nm-device-vlan.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_glib_test_la-nm-device-vlan.Tpo $(DEPDIR)/libnm_glib_test_la-nm-device-vlan.Plo
+@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-device-vlan.c' object='libnm_glib_test_la-nm-device-vlan.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-vlan.lo `test -f 'nm-device-vlan.c' || echo '$(srcdir)/'`nm-device-vlan.c
+
 libnm_glib_test_la-nm-access-point.lo: nm-access-point.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-access-point.lo -MD -MP -MF $(DEPDIR)/libnm_glib_test_la-nm-access-point.Tpo -c -o libnm_glib_test_la-nm-access-point.lo `test -f 'nm-access-point.c' || echo '$(srcdir)/'`nm-access-point.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_glib_test_la-nm-access-point.Tpo $(DEPDIR)/libnm_glib_test_la-nm-access-point.Plo
@@ -1030,6 +1084,22 @@ libnm_glib_test_la-nm-wimax-nsp.lo: nm-wimax-nsp.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-wimax-nsp.lo `test -f 'nm-wimax-nsp.c' || echo '$(srcdir)/'`nm-wimax-nsp.c
 
+libnm_glib_test_la-nm-glib-enum-types.lo: nm-glib-enum-types.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnm_glib_test_la_CFLAGS) $(CFLAGS) -MT libnm_glib_test_la-nm-glib-enum-types.lo -MD -MP -MF $(DEPDIR)/libnm_glib_test_la-nm-glib-enum-types.Tpo -c -o libnm_glib_test_la-nm-glib-enum-types.lo `test -f 'nm-glib-enum-types.c' || echo '$(srcdir)/'`nm-glib-enum-types.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_glib_test_la-nm-glib-enum-types.Tpo $(DEPDIR)/libnm_glib_test_la-nm-glib-enum-types.Plo
+@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-glib-enum-types.c' object='libnm_glib_test_la-nm-glib-enum-types.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-glib-enum-types.lo `test -f 'nm-glib-enum-types.c' || echo '$(srcdir)/'`nm-glib-enum-types.c
+
+libnm_glib_test_la-nm-glib-marshal.lo: nm-glib-marshal.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-glib-marshal.lo -MD -MP -MF $(DEPDIR)/libnm_glib_test_la-nm-glib-marshal.Tpo -c -o libnm_glib_test_la-nm-glib-marshal.lo `test -f 'nm-glib-marshal.c' || echo '$(srcdir)/'`nm-glib-marshal.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_glib_test_la-nm-glib-marshal.Tpo $(DEPDIR)/libnm_glib_test_la-nm-glib-marshal.Plo
+@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-glib-marshal.c' object='libnm_glib_test_la-nm-glib-marshal.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-glib-marshal.lo `test -f 'nm-glib-marshal.c' || echo '$(srcdir)/'`nm-glib-marshal.c
+
 libnm_glib_vpn_la-nm-vpn-plugin.lo: nm-vpn-plugin.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnm_glib_vpn_la_CFLAGS) $(CFLAGS) -MT libnm_glib_vpn_la-nm-vpn-plugin.lo -MD -MP -MF $(DEPDIR)/libnm_glib_vpn_la-nm-vpn-plugin.Tpo -c -o libnm_glib_vpn_la-nm-vpn-plugin.lo `test -f 'nm-vpn-plugin.c' || echo '$(srcdir)/'`nm-vpn-plugin.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_glib_vpn_la-nm-vpn-plugin.Tpo $(DEPDIR)/libnm_glib_vpn_la-nm-vpn-plugin.Plo
@@ -1054,6 +1124,14 @@ libnm_glib_vpn_la-nm-vpn-plugin-utils.lo: nm-vpn-plugin-utils.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_vpn_la_CFLAGS) $(CFLAGS) -c -o libnm_glib_vpn_la-nm-vpn-plugin-utils.lo `test -f 'nm-vpn-plugin-utils.c' || echo '$(srcdir)/'`nm-vpn-plugin-utils.c
 
+libnm_glib_vpn_la-nm-vpn-enum-types.lo: nm-vpn-enum-types.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnm_glib_vpn_la_CFLAGS) $(CFLAGS) -MT libnm_glib_vpn_la-nm-vpn-enum-types.lo -MD -MP -MF $(DEPDIR)/libnm_glib_vpn_la-nm-vpn-enum-types.Tpo -c -o libnm_glib_vpn_la-nm-vpn-enum-types.lo `test -f 'nm-vpn-enum-types.c' || echo '$(srcdir)/'`nm-vpn-enum-types.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_glib_vpn_la-nm-vpn-enum-types.Tpo $(DEPDIR)/libnm_glib_vpn_la-nm-vpn-enum-types.Plo
+@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-vpn-enum-types.c' object='libnm_glib_vpn_la-nm-vpn-enum-types.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_vpn_la_CFLAGS) $(CFLAGS) -c -o libnm_glib_vpn_la-nm-vpn-enum-types.lo `test -f 'nm-vpn-enum-types.c' || echo '$(srcdir)/'`nm-vpn-enum-types.c
+
 libnm_glib_la-nm-object.lo: nm-object.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-object.lo -MD -MP -MF $(DEPDIR)/libnm_glib_la-nm-object.Tpo -c -o libnm_glib_la-nm-object.lo `test -f 'nm-object.c' || echo '$(srcdir)/'`nm-object.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_glib_la-nm-object.Tpo $(DEPDIR)/libnm_glib_la-nm-object.Plo
@@ -1070,14 +1148,6 @@ libnm_glib_la-nm-client.lo: nm-client.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-client.lo `test -f 'nm-client.c' || echo '$(srcdir)/'`nm-client.c
 
-libnm_glib_la-nm-dbus-utils.lo: nm-dbus-utils.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnm_glib_la_CFLAGS) $(CFLAGS) -MT libnm_glib_la-nm-dbus-utils.lo -MD -MP -MF $(DEPDIR)/libnm_glib_la-nm-dbus-utils.Tpo -c -o libnm_glib_la-nm-dbus-utils.lo `test -f 'nm-dbus-utils.c' || echo '$(srcdir)/'`nm-dbus-utils.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_glib_la-nm-dbus-utils.Tpo $(DEPDIR)/libnm_glib_la-nm-dbus-utils.Plo
-@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-dbus-utils.c' object='libnm_glib_la-nm-dbus-utils.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-dbus-utils.lo `test -f 'nm-dbus-utils.c' || echo '$(srcdir)/'`nm-dbus-utils.c
-
 libnm_glib_la-nm-device.lo: nm-device.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.lo -MD -MP -MF $(DEPDIR)/libnm_glib_la-nm-device.Tpo -c -o libnm_glib_la-nm-device.lo `test -f 'nm-device.c' || echo '$(srcdir)/'`nm-device.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_glib_la-nm-device.Tpo $(DEPDIR)/libnm_glib_la-nm-device.Plo
@@ -1094,6 +1164,14 @@ libnm_glib_la-nm-device-ethernet.lo: nm-device-ethernet.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-ethernet.lo `test -f 'nm-device-ethernet.c' || echo '$(srcdir)/'`nm-device-ethernet.c
 
+libnm_glib_la-nm-device-infiniband.lo: nm-device-infiniband.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-infiniband.lo -MD -MP -MF $(DEPDIR)/libnm_glib_la-nm-device-infiniband.Tpo -c -o libnm_glib_la-nm-device-infiniband.lo `test -f 'nm-device-infiniband.c' || echo '$(srcdir)/'`nm-device-infiniband.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_glib_la-nm-device-infiniband.Tpo $(DEPDIR)/libnm_glib_la-nm-device-infiniband.Plo
+@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-device-infiniband.c' object='libnm_glib_la-nm-device-infiniband.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-infiniband.lo `test -f 'nm-device-infiniband.c' || echo '$(srcdir)/'`nm-device-infiniband.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
@@ -1110,6 +1188,30 @@ libnm_glib_la-nm-device-bt.lo: nm-device-bt.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-bt.lo `test -f 'nm-device-bt.c' || echo '$(srcdir)/'`nm-device-bt.c
 
+libnm_glib_la-nm-device-olpc-mesh.lo: nm-device-olpc-mesh.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnm_glib_la_CFLAGS) $(CFLAGS) -MT libnm_glib_la-nm-device-olpc-mesh.lo -MD -MP -MF $(DEPDIR)/libnm_glib_la-nm-device-olpc-mesh.Tpo -c -o libnm_glib_la-nm-device-olpc-mesh.lo `test -f 'nm-device-olpc-mesh.c' || echo '$(srcdir)/'`nm-device-olpc-mesh.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_glib_la-nm-device-olpc-mesh.Tpo $(DEPDIR)/libnm_glib_la-nm-device-olpc-mesh.Plo
+@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-device-olpc-mesh.c' object='libnm_glib_la-nm-device-olpc-mesh.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-olpc-mesh.lo `test -f 'nm-device-olpc-mesh.c' || echo '$(srcdir)/'`nm-device-olpc-mesh.c
+
+libnm_glib_la-nm-device-bond.lo: nm-device-bond.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-bond.lo -MD -MP -MF $(DEPDIR)/libnm_glib_la-nm-device-bond.Tpo -c -o libnm_glib_la-nm-device-bond.lo `test -f 'nm-device-bond.c' || echo '$(srcdir)/'`nm-device-bond.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_glib_la-nm-device-bond.Tpo $(DEPDIR)/libnm_glib_la-nm-device-bond.Plo
+@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-device-bond.c' object='libnm_glib_la-nm-device-bond.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-bond.lo `test -f 'nm-device-bond.c' || echo '$(srcdir)/'`nm-device-bond.c
+
+libnm_glib_la-nm-device-vlan.lo: nm-device-vlan.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnm_glib_la_CFLAGS) $(CFLAGS) -MT libnm_glib_la-nm-device-vlan.lo -MD -MP -MF $(DEPDIR)/libnm_glib_la-nm-device-vlan.Tpo -c -o libnm_glib_la-nm-device-vlan.lo `test -f 'nm-device-vlan.c' || echo '$(srcdir)/'`nm-device-vlan.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_glib_la-nm-device-vlan.Tpo $(DEPDIR)/libnm_glib_la-nm-device-vlan.Plo
+@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-device-vlan.c' object='libnm_glib_la-nm-device-vlan.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-vlan.lo `test -f 'nm-device-vlan.c' || echo '$(srcdir)/'`nm-device-vlan.c
+
 libnm_glib_la-nm-access-point.lo: nm-access-point.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-access-point.lo -MD -MP -MF $(DEPDIR)/libnm_glib_la-nm-access-point.Tpo -c -o libnm_glib_la-nm-access-point.lo `test -f 'nm-access-point.c' || echo '$(srcdir)/'`nm-access-point.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_glib_la-nm-access-point.Tpo $(DEPDIR)/libnm_glib_la-nm-access-point.Plo
@@ -1230,6 +1332,22 @@ libnm_glib_la-nm-wimax-nsp.lo: nm-wimax-nsp.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-wimax-nsp.lo `test -f 'nm-wimax-nsp.c' || echo '$(srcdir)/'`nm-wimax-nsp.c
 
+libnm_glib_la-nm-glib-enum-types.lo: nm-glib-enum-types.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnm_glib_la_CFLAGS) $(CFLAGS) -MT libnm_glib_la-nm-glib-enum-types.lo -MD -MP -MF $(DEPDIR)/libnm_glib_la-nm-glib-enum-types.Tpo -c -o libnm_glib_la-nm-glib-enum-types.lo `test -f 'nm-glib-enum-types.c' || echo '$(srcdir)/'`nm-glib-enum-types.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_glib_la-nm-glib-enum-types.Tpo $(DEPDIR)/libnm_glib_la-nm-glib-enum-types.Plo
+@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-glib-enum-types.c' object='libnm_glib_la-nm-glib-enum-types.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-glib-enum-types.lo `test -f 'nm-glib-enum-types.c' || echo '$(srcdir)/'`nm-glib-enum-types.c
+
+libnm_glib_la-nm-glib-marshal.lo: nm-glib-marshal.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-glib-marshal.lo -MD -MP -MF $(DEPDIR)/libnm_glib_la-nm-glib-marshal.Tpo -c -o libnm_glib_la-nm-glib-marshal.lo `test -f 'nm-glib-marshal.c' || echo '$(srcdir)/'`nm-glib-marshal.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_glib_la-nm-glib-marshal.Tpo $(DEPDIR)/libnm_glib_la-nm-glib-marshal.Plo
+@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-glib-marshal.c' object='libnm_glib_la-nm-glib-marshal.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-glib-marshal.lo `test -f 'nm-glib-marshal.c' || echo '$(srcdir)/'`nm-glib-marshal.c
+
 libnm_glib_test-libnm-glib-test.o: libnm-glib-test.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnm_glib_test_CFLAGS) $(CFLAGS) -MT libnm_glib_test-libnm-glib-test.o -MD -MP -MF $(DEPDIR)/libnm_glib_test-libnm-glib-test.Tpo -c -o libnm_glib_test-libnm-glib-test.o `test -f 'libnm-glib-test.c' || echo '$(srcdir)/'`libnm-glib-test.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_glib_test-libnm-glib-test.Tpo $(DEPDIR)/libnm_glib_test-libnm-glib-test.Po
@@ -1707,63 +1825,16 @@ uninstall-am: uninstall-girDATA uninstall-libLTLIBRARIES \
 	uninstall-libnmvpnHEADERS uninstall-pkgconfigDATA \
 	uninstall-typelibDATA
 
+include $(GLIB_MAKEFILE)
 
 #####################################################
 
-nm-client-bindings.h: $(top_srcdir)/introspection/nm-manager.xml
-	$(AM_V_GEN) dbus-binding-tool --prefix=nm_client --mode=glib-client --output=$@ $<
-
-nm-device-bindings.h: $(top_srcdir)/introspection/nm-device.xml
-	$(AM_V_GEN) dbus-binding-tool --prefix=nm_device --mode=glib-client --output=$@ $<
-
-nm-device-ethernet-bindings.h: $(top_srcdir)/introspection/nm-device-ethernet.xml
-	$(AM_V_GEN) dbus-binding-tool --prefix=nm_device_ethernet --mode=glib-client --output=$@ $<
-
-nm-device-wifi-bindings.h: $(top_srcdir)/introspection/nm-device-wifi.xml
-	$(AM_V_GEN) dbus-binding-tool --prefix=nm_device_wifi --mode=glib-client --output=$@ $<
-
-nm-device-bt-bindings.h: $(top_srcdir)/introspection/nm-device-bt.xml
-	$(AM_V_GEN) dbus-binding-tool --prefix=nm_device_bt --mode=glib-client --output=$@ $<
-
-nm-access-point-bindings.h: $(top_srcdir)/introspection/nm-access-point.xml
-	$(AM_V_GEN) dbus-binding-tool --prefix=nm_access_point --mode=glib-client --output=$@ $<
-
-nm-settings-bindings.h: $(top_srcdir)/introspection/nm-settings.xml
-	$(AM_V_GEN) dbus-binding-tool --prefix=nm_settings --mode=glib-client --output=$@ $<
-
-nm-settings-connection-bindings.h: $(top_srcdir)/introspection/nm-settings-connection.xml
-	$(AM_V_GEN) dbus-binding-tool --prefix=nm_settings_connection --mode=glib-client --output=$@ $<
-
-nm-vpn-connection-bindings.h: $(top_srcdir)/introspection/nm-vpn-connection.xml
-	$(AM_V_GEN) dbus-binding-tool --prefix=nm_vpn_connection --mode=glib-client --output=$@ $<
-
 nm-vpn-plugin-glue.h: $(top_srcdir)/introspection/nm-vpn-plugin.xml
 	$(AM_V_GEN) dbus-binding-tool --prefix=nm_vpn_plugin --mode=glib-server --output=$@ $<
 
-nm-active-connection-bindings.h: $(top_srcdir)/introspection/nm-active-connection.xml
-	$(AM_V_GEN) dbus-binding-tool --prefix=nm_active_connection --mode=glib-client --output=$@ $<
-
-nm-ip4-config-bindings.h: $(top_srcdir)/introspection/nm-ip4-config.xml
-	$(AM_V_GEN) dbus-binding-tool --prefix=nm_ip4_config --mode=glib-client --output=$@ $<
-
-nm-dhcp4-config-bindings.h: $(top_srcdir)/introspection/nm-dhcp4-config.xml
-	$(AM_V_GEN) dbus-binding-tool --prefix=nm_dhcp4_config --mode=glib-client --output=$@ $<
-
-nm-ip6-config-bindings.h: $(top_srcdir)/introspection/nm-ip6-config.xml
-	$(AM_V_GEN) dbus-binding-tool --prefix=nm_ip6_config --mode=glib-client --output=$@ $<
-
-nm-dhcp6-config-bindings.h: $(top_srcdir)/introspection/nm-dhcp6-config.xml
-	$(AM_V_GEN) dbus-binding-tool --prefix=nm_dhcp6_config --mode=glib-client --output=$@ $<
-
 nm-secret-agent-glue.h: $(top_srcdir)/introspection/nm-secret-agent.xml
 	$(AM_V_GEN) dbus-binding-tool --prefix=nm_secret_agent --mode=glib-server --output=$@ $<
 
-nm-device-wimax-bindings.h: $(top_srcdir)/introspection/nm-device-wimax.xml
-	dbus-binding-tool --prefix=nm_device_wimax --mode=glib-client --output=$@ $<
-
-nm-device-modem-bindings.h: $(top_srcdir)/introspection/nm-device-modem.xml
-	dbus-binding-tool --prefix=nm_device_modem --mode=glib-client --output=$@ $<
-
 -include $(INTROSPECTION_MAKEFILE)
 
 @HAVE_INTROSPECTION_TRUE@NMClient-1.0.gir: libnm-glib.la
diff --git a/libnm-glib/libnm-glib-test.c b/libnm-glib/libnm-glib-test.c
index 16e6fad6..4e80806f 100644
--- a/libnm-glib/libnm-glib-test.c
+++ b/libnm-glib/libnm-glib-test.c
@@ -28,8 +28,6 @@
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
-#include "wireless-helper.h"
-
 #include "nm-client.h"
 #include "nm-device.h"
 #include "nm-device-ethernet.h"
diff --git a/libnm-glib/libnm-glib.ver b/libnm-glib/libnm-glib.ver
index 1a4a68cf..427e2484 100644
--- a/libnm-glib/libnm-glib.ver
+++ b/libnm-glib/libnm-glib.ver
@@ -23,6 +23,7 @@ global:
 	nm_active_connection_get_default6;
 	nm_active_connection_get_default;
 	nm_active_connection_get_devices;
+	nm_active_connection_get_master;
 	nm_active_connection_get_specific_object;
 	nm_active_connection_get_state;
 	nm_active_connection_get_type;
@@ -43,6 +44,10 @@ global:
 	nm_client_networking_get_enabled;
 	nm_client_networking_set_enabled;
 	nm_client_new;
+	nm_client_new_async;
+	nm_client_new_finish;
+	nm_client_permission_get_type;
+	nm_client_permission_result_get_type;
 	nm_client_sleep;
 	nm_client_wimax_get_enabled;
 	nm_client_wimax_hardware_get_enabled;
@@ -53,13 +58,24 @@ global:
 	nm_client_wwan_get_enabled;
 	nm_client_wwan_hardware_get_enabled;
 	nm_client_wwan_set_enabled;
+	nm_device_bond_error_get_type;
+	nm_device_bond_error_quark;
+	nm_device_bond_get_carrier;
+	nm_device_bond_get_hw_address;
+	nm_device_bond_get_type;
+	nm_device_bond_new;
+	nm_device_bt_error_get_type;
+	nm_device_bt_error_quark;
 	nm_device_bt_get_capabilities;
 	nm_device_bt_get_hw_address;
 	nm_device_bt_get_name;
 	nm_device_bt_get_type;
 	nm_device_bt_new;
+	nm_device_connection_compatible;
 	nm_device_connection_valid;
 	nm_device_disconnect;
+	nm_device_ethernet_error_get_type;
+	nm_device_ethernet_error_quark;
 	nm_device_ethernet_get_carrier;
 	nm_device_ethernet_get_hw_address;
 	nm_device_ethernet_get_permanent_hw_address;
@@ -81,13 +97,38 @@ global:
 	nm_device_get_managed;
 	nm_device_get_product;
 	nm_device_get_state;
+	nm_device_get_state_reason;
 	nm_device_get_type;
 	nm_device_get_udi;
 	nm_device_get_vendor;
+	nm_device_infiniband_error_get_type;
+	nm_device_infiniband_error_quark;
+	nm_device_infiniband_get_carrier;
+	nm_device_infiniband_get_hw_address;
+	nm_device_infiniband_get_type;
+	nm_device_infiniband_new;
+	nm_device_modem_error_get_type;
+	nm_device_modem_error_quark;
 	nm_device_modem_get_current_capabilities;
 	nm_device_modem_get_modem_capabilities;
 	nm_device_modem_get_type;
 	nm_device_new;
+	nm_device_olpc_mesh_error_get_type;
+	nm_device_olpc_mesh_error_quark;
+	nm_device_olpc_mesh_get_active_channel;
+	nm_device_olpc_mesh_get_companion;
+	nm_device_olpc_mesh_get_hw_address;
+	nm_device_olpc_mesh_get_type;
+	nm_device_olpc_mesh_new;
+	nm_device_vlan_error_get_type;
+	nm_device_vlan_error_quark;
+	nm_device_vlan_get_carrier;
+	nm_device_vlan_get_hw_address;
+	nm_device_vlan_get_type;
+	nm_device_vlan_get_vlan_id;
+	nm_device_vlan_new;
+	nm_device_wifi_error_get_type;
+	nm_device_wifi_error_quark;
 	nm_device_wifi_get_access_point_by_path;
 	nm_device_wifi_get_access_points;
 	nm_device_wifi_get_active_access_point;
@@ -98,6 +139,8 @@ global:
 	nm_device_wifi_get_permanent_hw_address;
 	nm_device_wifi_get_type;
 	nm_device_wifi_new;
+	nm_device_wimax_error_get_type;
+	nm_device_wimax_error_quark;
 	nm_device_wimax_get_active_nsp;
 	nm_device_wimax_get_bsid;
 	nm_device_wimax_get_center_frequency;
@@ -150,11 +193,15 @@ global:
 	nm_remote_settings_get_type;
 	nm_remote_settings_list_connections;
 	nm_remote_settings_new;
+	nm_remote_settings_new_async;
+	nm_remote_settings_new_finish;
 	nm_remote_settings_save_hostname;
 	nm_secret_agent_delete_secrets;
 	nm_secret_agent_error_get_type;
 	nm_secret_agent_error_quark;
+	nm_secret_agent_get_registered;
 	nm_secret_agent_get_secrets;
+	nm_secret_agent_get_secrets_flags_get_type;
 	nm_secret_agent_get_type;
 	nm_secret_agent_register;
 	nm_secret_agent_save_secrets;
@@ -172,6 +219,7 @@ global:
 	nm_wimax_nsp_get_network_type;
 	nm_wimax_nsp_get_signal_quality;
 	nm_wimax_nsp_get_type;
+	nm_wimax_nsp_network_type_get_type;
 	nm_wimax_nsp_new;
 local:
 	*;
diff --git a/libnm-glib/nm-access-point.c b/libnm-glib/nm-access-point.c
index 415700d9..53993b07 100644
--- a/libnm-glib/nm-access-point.c
+++ b/libnm-glib/nm-access-point.c
@@ -36,8 +36,6 @@
 #include "nm-types-private.h"
 #include "nm-object-private.h"
 
-#include "nm-access-point-bindings.h"
-
 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))
@@ -115,19 +113,10 @@ nm_access_point_new (DBusGConnection *connection, const char *path)
 NM80211ApFlags
 nm_access_point_get_flags (NMAccessPoint *ap)
 {
-	NMAccessPointPrivate *priv;
-
 	g_return_val_if_fail (NM_IS_ACCESS_POINT (ap), NM_802_11_AP_FLAGS_NONE);
 
-	priv = NM_ACCESS_POINT_GET_PRIVATE (ap);
-	if (!priv->flags) {
-		priv->flags = _nm_object_get_uint_property (NM_OBJECT (ap),
-		                                           NM_DBUS_INTERFACE_ACCESS_POINT,
-		                                           DBUS_PROP_FLAGS,
-		                                           NULL);
-	}
-
-	return priv->flags;
+	_nm_object_ensure_inited (NM_OBJECT (ap));
+	return NM_ACCESS_POINT_GET_PRIVATE (ap)->flags;
 }
 
 /**
@@ -141,19 +130,10 @@ nm_access_point_get_flags (NMAccessPoint *ap)
 NM80211ApSecurityFlags
 nm_access_point_get_wpa_flags (NMAccessPoint *ap)
 {
-	NMAccessPointPrivate *priv;
-
 	g_return_val_if_fail (NM_IS_ACCESS_POINT (ap), NM_802_11_AP_SEC_NONE);
 
-	priv = NM_ACCESS_POINT_GET_PRIVATE (ap);
-	if (!priv->wpa_flags) {
-		priv->wpa_flags = _nm_object_get_uint_property (NM_OBJECT (ap),
-		                                               NM_DBUS_INTERFACE_ACCESS_POINT,
-		                                               DBUS_PROP_WPA_FLAGS,
-		                                               NULL);
-	}
-
-	return priv->wpa_flags;
+	_nm_object_ensure_inited (NM_OBJECT (ap));
+	return NM_ACCESS_POINT_GET_PRIVATE (ap)->wpa_flags;
 }
 
 /**
@@ -168,19 +148,10 @@ nm_access_point_get_wpa_flags (NMAccessPoint *ap)
 NM80211ApSecurityFlags
 nm_access_point_get_rsn_flags (NMAccessPoint *ap)
 {
-	NMAccessPointPrivate *priv;
-
 	g_return_val_if_fail (NM_IS_ACCESS_POINT (ap), NM_802_11_AP_SEC_NONE);
 
-	priv = NM_ACCESS_POINT_GET_PRIVATE (ap);
-	if (!priv->rsn_flags) {
-		priv->rsn_flags = _nm_object_get_uint_property (NM_OBJECT (ap),
-		                                               NM_DBUS_INTERFACE_ACCESS_POINT,
-		                                               DBUS_PROP_RSN_FLAGS,
-		                                               NULL);
-	}
-
-	return priv->rsn_flags;
+	_nm_object_ensure_inited (NM_OBJECT (ap));
+	return NM_ACCESS_POINT_GET_PRIVATE (ap)->rsn_flags;
 }
 
 /**
@@ -195,19 +166,10 @@ nm_access_point_get_rsn_flags (NMAccessPoint *ap)
 const GByteArray *
 nm_access_point_get_ssid (NMAccessPoint *ap)
 {
-	NMAccessPointPrivate *priv;
-
 	g_return_val_if_fail (NM_IS_ACCESS_POINT (ap), NULL);
 
-	priv = NM_ACCESS_POINT_GET_PRIVATE (ap);
-	if (!priv->ssid) {
-		priv->ssid = _nm_object_get_byte_array_property (NM_OBJECT (ap),
-		                                                NM_DBUS_INTERFACE_ACCESS_POINT,
-		                                                DBUS_PROP_SSID,
-		                                                NULL);
-	}
-
-	return priv->ssid;
+	_nm_object_ensure_inited (NM_OBJECT (ap));
+	return NM_ACCESS_POINT_GET_PRIVATE (ap)->ssid;
 }
 
 /**
@@ -221,19 +183,10 @@ nm_access_point_get_ssid (NMAccessPoint *ap)
 guint32
 nm_access_point_get_frequency (NMAccessPoint *ap)
 {
-	NMAccessPointPrivate *priv;
-
 	g_return_val_if_fail (NM_IS_ACCESS_POINT (ap), 0);
 
-	priv = NM_ACCESS_POINT_GET_PRIVATE (ap);
-	if (!priv->frequency) {
-		priv->frequency = _nm_object_get_uint_property (NM_OBJECT (ap),
-		                                               NM_DBUS_INTERFACE_ACCESS_POINT,
-		                                               DBUS_PROP_FREQUENCY,
-		                                               NULL);
-	}
-
-	return priv->frequency;
+	_nm_object_ensure_inited (NM_OBJECT (ap));
+	return NM_ACCESS_POINT_GET_PRIVATE (ap)->frequency;
 }
 
 /**
@@ -248,19 +201,10 @@ nm_access_point_get_frequency (NMAccessPoint *ap)
 const char *
 nm_access_point_get_bssid (NMAccessPoint *ap)
 {
-	NMAccessPointPrivate *priv;
-
 	g_return_val_if_fail (NM_IS_ACCESS_POINT (ap), NULL);
 
-	priv = NM_ACCESS_POINT_GET_PRIVATE (ap);
-	if (!priv->bssid) {
-		priv->bssid = _nm_object_get_string_property (NM_OBJECT (ap),
-		                                              NM_DBUS_INTERFACE_ACCESS_POINT,
-		                                              DBUS_PROP_HW_ADDRESS,
-		                                              NULL);
-	}
-
-	return priv->bssid;
+	_nm_object_ensure_inited (NM_OBJECT (ap));
+	return NM_ACCESS_POINT_GET_PRIVATE (ap)->bssid;
 }
 
 /**
@@ -291,19 +235,10 @@ nm_access_point_get_hw_address (NMAccessPoint *ap)
 NM80211Mode
 nm_access_point_get_mode (NMAccessPoint *ap)
 {
-	NMAccessPointPrivate *priv;
-
 	g_return_val_if_fail (NM_IS_ACCESS_POINT (ap), 0);
 
-	priv = NM_ACCESS_POINT_GET_PRIVATE (ap);
-	if (!priv->mode) {
-		priv->mode = _nm_object_get_uint_property (NM_OBJECT (ap),
-		                                          NM_DBUS_INTERFACE_ACCESS_POINT,
-		                                          DBUS_PROP_MODE,
-		                                          NULL);
-	}
-
-	return priv->mode;
+	_nm_object_ensure_inited (NM_OBJECT (ap));
+	return NM_ACCESS_POINT_GET_PRIVATE (ap)->mode;
 }
 
 /**
@@ -317,19 +252,10 @@ nm_access_point_get_mode (NMAccessPoint *ap)
 guint32
 nm_access_point_get_max_bitrate (NMAccessPoint *ap)
 {
-	NMAccessPointPrivate *priv;
-
 	g_return_val_if_fail (NM_IS_ACCESS_POINT (ap), 0);
 
-	priv = NM_ACCESS_POINT_GET_PRIVATE (ap);
-	if (!priv->max_bitrate) {
-		priv->max_bitrate = _nm_object_get_uint_property (NM_OBJECT (ap),
-		                                              NM_DBUS_INTERFACE_ACCESS_POINT,
-		                                              DBUS_PROP_MAX_BITRATE,
-		                                              NULL);
-	}
-
-	return priv->max_bitrate;
+	_nm_object_ensure_inited (NM_OBJECT (ap));
+	return NM_ACCESS_POINT_GET_PRIVATE (ap)->max_bitrate;
 }
 
 /**
@@ -343,25 +269,16 @@ nm_access_point_get_max_bitrate (NMAccessPoint *ap)
 guint8
 nm_access_point_get_strength (NMAccessPoint *ap)
 {
-	NMAccessPointPrivate *priv;
-
 	g_return_val_if_fail (NM_IS_ACCESS_POINT (ap), 0);
 
-	priv = NM_ACCESS_POINT_GET_PRIVATE (ap);
-	if (!priv->strength) {
-		priv->strength = _nm_object_get_byte_property (NM_OBJECT (ap),
-		                                              NM_DBUS_INTERFACE_ACCESS_POINT,
-		                                              DBUS_PROP_STRENGTH,
-		                                              NULL);
-	}
-
-	return priv->strength;
+	_nm_object_ensure_inited (NM_OBJECT (ap));
+	return NM_ACCESS_POINT_GET_PRIVATE (ap)->strength;
 }
 
 /**
- * nm_access_point_filter_connections:
+ * nm_access_point_connection_valid:
  * @ap: an #NMAccessPoint to validate @connection against
- * @connections: an #NMConnection to validate against @ap
+ * @connection: an #NMConnection to validate against @ap
  *
  * Validates a given connection against a given WiFi access point to ensure that
  * the connection may be activated with that AP.  The connection must match the
@@ -475,6 +392,11 @@ nm_access_point_connection_valid (NMAccessPoint *ap, NMConnection *connection)
  * returned connections will match the @ap's SSID and (if given) BSSID and
  * other attributes like security settings, channel, etc.
  *
+ * To obtain the list of connections that are compatible with this access point,
+ * use nm_remote_settings_list_connections() and then filter the returned list
+ * for a given #NMDevice using nm_device_filter_connections() and finally
+ * filter that list with this function.
+ *
  * Returns: (transfer container) (element-type NetworkManager.Connection): a
  * list of #NMConnection objects that could be activated with the given @ap.
  * The elements of the list are owned by their creator and should not be freed
@@ -590,51 +512,42 @@ demarshal_ssid (NMObject *object, GParamSpec *pspec, GValue *value, gpointer fie
 }
 
 static void
-register_for_property_changed (NMAccessPoint *ap)
+register_properties (NMAccessPoint *ap)
 {
 	NMAccessPointPrivate *priv = NM_ACCESS_POINT_GET_PRIVATE (ap);
-	const NMPropertiesChangedInfo property_changed_info[] = {
-		{ NM_ACCESS_POINT_FLAGS,       _nm_object_demarshal_generic, &priv->flags },
-		{ NM_ACCESS_POINT_WPA_FLAGS,   _nm_object_demarshal_generic, &priv->wpa_flags },
-		{ NM_ACCESS_POINT_RSN_FLAGS,   _nm_object_demarshal_generic, &priv->rsn_flags },
-		{ NM_ACCESS_POINT_SSID,        demarshal_ssid,               &priv->ssid },
-		{ NM_ACCESS_POINT_FREQUENCY,   _nm_object_demarshal_generic, &priv->frequency },
-		{ NM_ACCESS_POINT_HW_ADDRESS,  _nm_object_demarshal_generic, &priv->bssid },
-		{ NM_ACCESS_POINT_MODE,        _nm_object_demarshal_generic, &priv->mode },
-		{ NM_ACCESS_POINT_MAX_BITRATE, _nm_object_demarshal_generic, &priv->max_bitrate },
-		{ NM_ACCESS_POINT_STRENGTH,    _nm_object_demarshal_generic, &priv->strength },
+	const NMPropertiesInfo property_info[] = {
+		{ NM_ACCESS_POINT_FLAGS,       &priv->flags },
+		{ NM_ACCESS_POINT_WPA_FLAGS,   &priv->wpa_flags },
+		{ NM_ACCESS_POINT_RSN_FLAGS,   &priv->rsn_flags },
+		{ NM_ACCESS_POINT_SSID,        &priv->ssid, demarshal_ssid },
+		{ NM_ACCESS_POINT_FREQUENCY,   &priv->frequency },
+		{ NM_ACCESS_POINT_HW_ADDRESS,  &priv->bssid },
+		{ NM_ACCESS_POINT_MODE,        &priv->mode },
+		{ NM_ACCESS_POINT_MAX_BITRATE, &priv->max_bitrate },
+		{ NM_ACCESS_POINT_STRENGTH,    &priv->strength },
 		{ NULL },
 	};
 
-	_nm_object_handle_properties_changed (NM_OBJECT (ap),
-	                                     priv->proxy,
-	                                     property_changed_info);
+	_nm_object_register_properties (NM_OBJECT (ap),
+	                                priv->proxy,
+	                                property_info);
 }
 
-static GObject*
-constructor (GType type,
-			 guint n_construct_params,
-			 GObjectConstructParam *construct_params)
+static void
+constructed (GObject *object)
 {
-	NMObject *object;
 	NMAccessPointPrivate *priv;
 
-	object = (NMObject *) G_OBJECT_CLASS (nm_access_point_parent_class)->constructor (type,
-																	  n_construct_params,
-																	  construct_params);
-	if (!object)
-		return NULL;
+	G_OBJECT_CLASS (nm_access_point_parent_class)->constructed (object);
 
 	priv = NM_ACCESS_POINT_GET_PRIVATE (object);
 
-	priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (object),
+	priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (NM_OBJECT (object)),
 									    NM_DBUS_SERVICE,
-									    nm_object_get_path (object),
+									    nm_object_get_path (NM_OBJECT (object)),
 									    NM_DBUS_INTERFACE_ACCESS_POINT);
 
-	register_for_property_changed (NM_ACCESS_POINT (object));
-
-	return G_OBJECT (object);
+	register_properties (NM_ACCESS_POINT (object));
 }
 
 
@@ -646,7 +559,7 @@ nm_access_point_class_init (NMAccessPointClass *ap_class)
 	g_type_class_add_private (ap_class, sizeof (NMAccessPointPrivate));
 
 	/* virtual methods */
-	object_class->constructor = constructor;
+	object_class->constructed = constructed;
 	object_class->get_property = get_property;
 	object_class->dispose = dispose;
 	object_class->finalize = finalize;
diff --git a/libnm-glib/nm-active-connection.c b/libnm-glib/nm-active-connection.c
index 7dc1c2db..59d8a6af 100644
--- a/libnm-glib/nm-active-connection.c
+++ b/libnm-glib/nm-active-connection.c
@@ -28,17 +28,26 @@
 #include "nm-object-private.h"
 #include "nm-types-private.h"
 #include "nm-device.h"
+#include "nm-device-private.h"
 #include "nm-connection.h"
-
-#include "nm-active-connection-bindings.h"
-
-G_DEFINE_TYPE (NMActiveConnection, nm_active_connection, NM_TYPE_OBJECT)
+#include "nm-vpn-connection.h"
+#include "nm-glib-compat.h"
+
+static GType _nm_active_connection_type_for_path (DBusGConnection *connection,
+                                                  const char *path);
+static void  _nm_active_connection_type_for_path_async (DBusGConnection *connection,
+                                                        const char *path,
+                                                        NMObjectTypeCallbackFunc callback,
+                                                        gpointer user_data);
+
+G_DEFINE_TYPE_WITH_CODE (NMActiveConnection, nm_active_connection, NM_TYPE_OBJECT,
+                         _nm_object_register_type_func (g_define_type_id,
+                                                        _nm_active_connection_type_for_path,
+                                                        _nm_active_connection_type_for_path_async);
+                         )
 
 #define NM_ACTIVE_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_ACTIVE_CONNECTION, NMActiveConnectionPrivate))
 
-static gboolean demarshal_devices (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field);
-
-
 typedef struct {
 	gboolean disposed;
 	DBusGProxy *proxy;
@@ -50,6 +59,7 @@ typedef struct {
 	NMActiveConnectionState state;
 	gboolean is_default;
 	gboolean is_default6;
+	char *master;
 } NMActiveConnectionPrivate;
 
 enum {
@@ -61,6 +71,7 @@ enum {
 	PROP_STATE,
 	PROP_DEFAULT,
 	PROP_DEFAULT6,
+	PROP_MASTER,
 
 	LAST_PROP
 };
@@ -72,6 +83,7 @@ enum {
 #define DBUS_PROP_STATE "State"
 #define DBUS_PROP_DEFAULT "Default"
 #define DBUS_PROP_DEFAULT6 "Default6"
+#define DBUS_PROP_MASTER "Master"
 
 /**
  * nm_active_connection_new:
@@ -94,6 +106,104 @@ nm_active_connection_new (DBusGConnection *connection, const char *path)
 						 NULL);
 }
 
+static GType
+_nm_active_connection_type_for_path (DBusGConnection *connection,
+                                     const char *path)
+{
+	DBusGProxy *proxy;
+	GError *error = NULL;
+	GValue value = {0,};
+	GType type;
+
+	proxy = dbus_g_proxy_new_for_name (connection,
+	                                   NM_DBUS_SERVICE,
+	                                   path,
+	                                   "org.freedesktop.DBus.Properties");
+	if (!proxy) {
+		g_warning ("%s: couldn't create D-Bus object proxy.", __func__);
+		return G_TYPE_INVALID;
+	}
+
+	/* Have to create an NMVPNConnection if it's a VPN connection, otherwise
+	 * a plain NMActiveConnection.
+	 */
+	if (dbus_g_proxy_call (proxy,
+	                       "Get", &error,
+	                       G_TYPE_STRING, NM_DBUS_INTERFACE_ACTIVE_CONNECTION,
+	                       G_TYPE_STRING, "Vpn",
+	                       G_TYPE_INVALID,
+	                       G_TYPE_VALUE, &value, G_TYPE_INVALID)) {
+		if (g_value_get_boolean (&value))
+			type = NM_TYPE_VPN_CONNECTION;
+		else
+			type = NM_TYPE_ACTIVE_CONNECTION;
+	} else {
+		g_warning ("Error in getting active connection 'Vpn' property: (%d) %s",
+		           error->code, error->message);
+		g_error_free (error);
+		type = G_TYPE_INVALID;
+	}
+
+	g_object_unref (proxy);
+	return type;
+}
+
+typedef struct {
+	DBusGConnection *connection;
+	NMObjectTypeCallbackFunc callback;
+	gpointer user_data;
+} NMActiveConnectionAsyncData;
+
+static void
+async_got_type (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data)
+{
+	NMActiveConnectionAsyncData *async_data = user_data;
+	GValue value = G_VALUE_INIT;
+	const char *path = dbus_g_proxy_get_path (proxy);
+	GError *error = NULL;
+	GType type;
+
+	if (dbus_g_proxy_end_call (proxy, call, &error,
+	                           G_TYPE_VALUE, &value,
+	                           G_TYPE_INVALID)) {
+		if (g_value_get_boolean (&value))
+			type = NM_TYPE_VPN_CONNECTION;
+		else
+			type = NM_TYPE_ACTIVE_CONNECTION;
+	} else {
+		g_warning ("%s: could not read properties for %s: %s", __func__, path, error->message);
+		type = G_TYPE_INVALID;
+	}
+
+	async_data->callback (type, async_data->user_data);
+
+	g_object_unref (proxy);
+	g_slice_free (NMActiveConnectionAsyncData, async_data);
+}
+
+static void
+_nm_active_connection_type_for_path_async (DBusGConnection *connection,
+                                           const char *path,
+                                           NMObjectTypeCallbackFunc callback,
+                                           gpointer user_data)
+{
+	NMActiveConnectionAsyncData *async_data;
+	DBusGProxy *proxy;
+
+	async_data = g_slice_new (NMActiveConnectionAsyncData);
+	async_data->connection = connection;
+	async_data->callback = callback;
+	async_data->user_data = user_data;
+
+	proxy = dbus_g_proxy_new_for_name (connection, NM_DBUS_SERVICE, path,
+	                                   "org.freedesktop.DBus.Properties");
+	dbus_g_proxy_begin_call (proxy, "Get",
+	                         async_got_type, async_data, NULL,
+	                         G_TYPE_STRING, NM_DBUS_INTERFACE_ACTIVE_CONNECTION,
+	                         G_TYPE_STRING, "Vpn",
+	                         G_TYPE_INVALID);
+}
+
 /**
  * nm_active_connection_get_connection:
  * @connection: a #NMActiveConnection
@@ -106,19 +216,10 @@ nm_active_connection_new (DBusGConnection *connection, const char *path)
 const char *
 nm_active_connection_get_connection (NMActiveConnection *connection)
 {
-	NMActiveConnectionPrivate *priv;
-
 	g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), NULL);
 
-	priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (connection);
-	if (!priv->connection) {
-		priv->connection = _nm_object_get_string_property (NM_OBJECT (connection),
-		                                                  NM_DBUS_INTERFACE_ACTIVE_CONNECTION,
-		                                                  DBUS_PROP_CONNECTION,
-		                                                  NULL);
-	}
-
-	return priv->connection;
+	_nm_object_ensure_inited (NM_OBJECT (connection));
+	return NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->connection;
 }
 
 /**
@@ -133,19 +234,10 @@ nm_active_connection_get_connection (NMActiveConnection *connection)
 const char *
 nm_active_connection_get_uuid (NMActiveConnection *connection)
 {
-	NMActiveConnectionPrivate *priv;
-
 	g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), NULL);
 
-	priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (connection);
-	if (!priv->uuid) {
-		priv->uuid = _nm_object_get_string_property (NM_OBJECT (connection),
-		                                             NM_DBUS_INTERFACE_ACTIVE_CONNECTION,
-		                                             DBUS_PROP_UUID,
-		                                             NULL);
-	}
-
-	return priv->uuid;
+	_nm_object_ensure_inited (NM_OBJECT (connection));
+	return NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->uuid;
 }
 
 /**
@@ -160,19 +252,10 @@ nm_active_connection_get_uuid (NMActiveConnection *connection)
 const char *
 nm_active_connection_get_specific_object (NMActiveConnection *connection)
 {
-	NMActiveConnectionPrivate *priv;
-
 	g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), NULL);
 
-	priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (connection);
-	if (!priv->specific_object) {
-		priv->specific_object = _nm_object_get_string_property (NM_OBJECT (connection),
-		                                                       NM_DBUS_INTERFACE_ACTIVE_CONNECTION,
-		                                                       DBUS_PROP_SPECIFIC_OBJECT,
-		                                                       NULL);
-	}
-
-	return priv->specific_object;
+	_nm_object_ensure_inited (NM_OBJECT (connection));
+	return NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->specific_object;
 }
 
 /**
@@ -187,27 +270,10 @@ nm_active_connection_get_specific_object (NMActiveConnection *connection)
 const GPtrArray *
 nm_active_connection_get_devices (NMActiveConnection *connection)
 {
-	NMActiveConnectionPrivate *priv;
-	GValue value = { 0, };
-
 	g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), NULL);
 
-	priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (connection);
-	if (priv->devices)
-		return handle_ptr_array_return (priv->devices);
-
-	if (!_nm_object_get_property (NM_OBJECT (connection),
-	                             NM_DBUS_INTERFACE_ACTIVE_CONNECTION,
-	                             DBUS_PROP_DEVICES,
-	                             &value,
-	                             NULL)) {
-		return NULL;
-	}
-
-	demarshal_devices (NM_OBJECT (connection), NULL, &value, &priv->devices);
-	g_value_unset (&value);
-
-	return handle_ptr_array_return (priv->devices);
+	_nm_object_ensure_inited (NM_OBJECT (connection));
+	return handle_ptr_array_return (NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->devices);
 }
 
 /**
@@ -221,19 +287,10 @@ nm_active_connection_get_devices (NMActiveConnection *connection)
 NMActiveConnectionState
 nm_active_connection_get_state (NMActiveConnection *connection)
 {
-	NMActiveConnectionPrivate *priv;
-
 	g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), NM_ACTIVE_CONNECTION_STATE_UNKNOWN);
 
-	priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (connection);
-	if (!priv->state) {
-		priv->state = _nm_object_get_uint_property (NM_OBJECT (connection),
-		                                           NM_DBUS_INTERFACE_ACTIVE_CONNECTION,
-		                                           DBUS_PROP_STATE,
-		                                           NULL);
-	}
-
-	return priv->state;
+	_nm_object_ensure_inited (NM_OBJECT (connection));
+	return NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->state;
 }
 
 /**
@@ -248,19 +305,10 @@ nm_active_connection_get_state (NMActiveConnection *connection)
 gboolean
 nm_active_connection_get_default (NMActiveConnection *connection)
 {
-	NMActiveConnectionPrivate *priv;
-
 	g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), FALSE);
 
-	priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (connection);
-	if (!priv->is_default) {
-		priv->is_default = _nm_object_get_boolean_property (NM_OBJECT (connection),
-		                                                    NM_DBUS_INTERFACE_ACTIVE_CONNECTION,
-		                                                    DBUS_PROP_DEFAULT,
-		                                                    NULL);
-	}
-
-	return priv->is_default;
+	_nm_object_ensure_inited (NM_OBJECT (connection));
+	return NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->is_default;
 }
 
 /**
@@ -275,19 +323,28 @@ nm_active_connection_get_default (NMActiveConnection *connection)
 gboolean
 nm_active_connection_get_default6 (NMActiveConnection *connection)
 {
-	NMActiveConnectionPrivate *priv;
-
 	g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), FALSE);
 
-	priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (connection);
-	if (!priv->is_default6) {
-		priv->is_default6 = _nm_object_get_boolean_property (NM_OBJECT (connection),
-		                                                     NM_DBUS_INTERFACE_ACTIVE_CONNECTION,
-		                                                     DBUS_PROP_DEFAULT6,
-		                                                     NULL);
-	}
+	_nm_object_ensure_inited (NM_OBJECT (connection));
+	return NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->is_default6;
+}
 
-	return priv->is_default6;
+/**
+ * nm_active_connection_get_master:
+ * @connection: a #NMActiveConnection
+ *
+ * Gets the path to the master #NMDevice of the connection.
+ *
+ * Returns: the path of the master #NMDevice of the #NMActiveConnection.
+ * This is the internal string used by the connection, and must not be modified.
+ **/
+const char *
+nm_active_connection_get_master (NMActiveConnection *connection)
+{
+	g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), NULL);
+
+	_nm_object_ensure_inited (NM_OBJECT (connection));
+	return NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->master;
 }
 
 static void
@@ -324,6 +381,7 @@ finalize (GObject *object)
 	g_free (priv->connection);
 	g_free (priv->uuid);
 	g_free (priv->specific_object);
+	g_free (priv->master);
 
 	G_OBJECT_CLASS (nm_active_connection_parent_class)->finalize (object);
 }
@@ -340,6 +398,9 @@ get_property (GObject *object,
 	case PROP_CONNECTION:
 		g_value_set_string (value, nm_active_connection_get_connection (self));
 		break;
+	case PROP_UUID:
+		g_value_set_string (value, nm_active_connection_get_uuid (self));
+		break;
 	case PROP_SPECIFIC_OBJECT:
 		g_value_set_boxed (value, nm_active_connection_get_specific_object (self));
 		break;
@@ -355,68 +416,55 @@ get_property (GObject *object,
 	case PROP_DEFAULT6:
 		g_value_set_boolean (value, nm_active_connection_get_default6 (self));
 		break;
+	case PROP_MASTER:
+		g_value_set_string (value, nm_active_connection_get_master (self));
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
 	}
 }
 
-static gboolean
-demarshal_devices (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field)
-{
-	DBusGConnection *connection;
-
-	connection = nm_object_get_connection (object);
-	if (!_nm_object_array_demarshal (value, (GPtrArray **) field, connection, nm_device_new))
-		return FALSE;
-
-	_nm_object_queue_notify (object, NM_ACTIVE_CONNECTION_DEVICES);
-	return TRUE;
-}
-
 static void
-register_for_property_changed (NMActiveConnection *connection)
+register_properties (NMActiveConnection *connection)
 {
 	NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (connection);
-	const NMPropertiesChangedInfo property_changed_info[] = {
-		{ NM_ACTIVE_CONNECTION_CONNECTION,          _nm_object_demarshal_generic, &priv->connection },
-		{ NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT,     _nm_object_demarshal_generic, &priv->specific_object },
-		{ NM_ACTIVE_CONNECTION_DEVICES,             demarshal_devices,           &priv->devices },
-		{ NM_ACTIVE_CONNECTION_STATE,               _nm_object_demarshal_generic, &priv->state },
-		{ NM_ACTIVE_CONNECTION_DEFAULT,             _nm_object_demarshal_generic, &priv->is_default },
-		{ NM_ACTIVE_CONNECTION_DEFAULT6,            _nm_object_demarshal_generic, &priv->is_default6 },
+	const NMPropertiesInfo property_info[] = {
+		{ NM_ACTIVE_CONNECTION_CONNECTION,          &priv->connection },
+		{ NM_ACTIVE_CONNECTION_UUID,                &priv->uuid },
+		{ NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT,     &priv->specific_object },
+		{ NM_ACTIVE_CONNECTION_DEVICES,             &priv->devices, NULL, NM_TYPE_DEVICE },
+		{ NM_ACTIVE_CONNECTION_STATE,               &priv->state },
+		{ NM_ACTIVE_CONNECTION_DEFAULT,             &priv->is_default },
+		{ NM_ACTIVE_CONNECTION_DEFAULT6,            &priv->is_default6 },
+		{ NM_ACTIVE_CONNECTION_MASTER,              &priv->master },
+
+		/* not tracked after construction time */
+		{ "vpn", NULL },
+
 		{ NULL },
 	};
 
-	_nm_object_handle_properties_changed (NM_OBJECT (connection),
-	                                     priv->proxy,
-	                                     property_changed_info);
+	_nm_object_register_properties (NM_OBJECT (connection),
+	                                priv->proxy,
+	                                property_info);
 }
 
-static GObject*
-constructor (GType type,
-			 guint n_construct_params,
-			 GObjectConstructParam *construct_params)
+static void
+constructed (GObject *object)
 {
-	NMObject *object;
 	NMActiveConnectionPrivate *priv;
 
-	object = (NMObject *) G_OBJECT_CLASS (nm_active_connection_parent_class)->constructor (type,
-																	  n_construct_params,
-																	  construct_params);
-	if (!object)
-		return NULL;
+	G_OBJECT_CLASS (nm_active_connection_parent_class)->constructed (object);
 
 	priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (object);
 
-	priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (object),
+	priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (NM_OBJECT (object)),
 									    NM_DBUS_SERVICE,
-									    nm_object_get_path (object),
+									    nm_object_get_path (NM_OBJECT (object)),
 									    NM_DBUS_INTERFACE_ACTIVE_CONNECTION);
 
-	register_for_property_changed (NM_ACTIVE_CONNECTION (object));
-
-	return G_OBJECT (object);
+	register_properties (NM_ACTIVE_CONNECTION (object));
 }
 
 
@@ -428,7 +476,7 @@ nm_active_connection_class_init (NMActiveConnectionClass *ap_class)
 	g_type_class_add_private (ap_class, sizeof (NMActiveConnectionPrivate));
 
 	/* virtual methods */
-	object_class->constructor = constructor;
+	object_class->constructed = constructed;
 	object_class->get_property = get_property;
 	object_class->dispose = dispose;
 	object_class->finalize = finalize;
@@ -449,6 +497,19 @@ nm_active_connection_class_init (NMActiveConnectionClass *ap_class)
 						      G_PARAM_READABLE));
 
 	/**
+	 * NMActiveConnection:uuid:
+	 *
+	 * The active connection's UUID
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_UUID,
+		 g_param_spec_string (NM_ACTIVE_CONNECTION_UUID,
+						      "UUID",
+						      "UUID",
+						      NULL,
+						      G_PARAM_READABLE));
+
+	/**
 	 * NMActiveConnection:specific-object:
 	 *
 	 * The specific object's path of the active connection.
@@ -514,4 +575,17 @@ nm_active_connection_class_init (NMActiveConnectionClass *ap_class)
 							   "Is the default IPv6 active connection",
 							   FALSE,
 							   G_PARAM_READABLE));
+
+	/**
+	 * NMActiveConnection:master:
+	 *
+	 * The path of the master device if one exists.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_MASTER,
+		 g_param_spec_string (NM_ACTIVE_CONNECTION_MASTER,
+						      "Master",
+						      "Path of the master device",
+						      NULL,
+						      G_PARAM_READABLE));
 }
diff --git a/libnm-glib/nm-active-connection.h b/libnm-glib/nm-active-connection.h
index 974e551a..d6426e90 100644
--- a/libnm-glib/nm-active-connection.h
+++ b/libnm-glib/nm-active-connection.h
@@ -46,6 +46,7 @@ G_BEGIN_DECLS
 #define NM_ACTIVE_CONNECTION_STATE               "state"
 #define NM_ACTIVE_CONNECTION_DEFAULT             "default"
 #define NM_ACTIVE_CONNECTION_DEFAULT6            "default6"
+#define NM_ACTIVE_CONNECTION_MASTER              "master"
 
 typedef struct {
 	NMObject parent;
@@ -74,6 +75,7 @@ const GPtrArray *nm_active_connection_get_devices         (NMActiveConnection *c
 NMActiveConnectionState nm_active_connection_get_state    (NMActiveConnection *connection);
 gboolean nm_active_connection_get_default                 (NMActiveConnection *connection);
 gboolean nm_active_connection_get_default6                (NMActiveConnection *connection);
+const char * nm_active_connection_get_master              (NMActiveConnection *connection);
 
 G_END_DECLS
 
diff --git a/libnm-glib/nm-client.c b/libnm-glib/nm-client.c
index 0769de1a..937a1bf8 100644
--- a/libnm-glib/nm-client.c
+++ b/libnm-glib/nm-client.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 <dbus/dbus-glib.h>
@@ -29,19 +29,26 @@
 #include "nm-device-ethernet.h"
 #include "nm-device-wifi.h"
 #include "nm-device-private.h"
-#include "nm-marshal.h"
+#include "nm-glib-marshal.h"
 #include "nm-types-private.h"
 #include "nm-object-private.h"
 #include "nm-active-connection.h"
 #include "nm-vpn-connection.h"
 #include "nm-object-cache.h"
 #include "nm-dbus-glib-types.h"
-
-#include "nm-client-bindings.h"
+#include "nm-glib-compat.h"
 
 void _nm_device_wifi_set_wireless_enabled (NMDeviceWifi *device, gboolean enabled);
 
-G_DEFINE_TYPE (NMClient, nm_client, NM_TYPE_OBJECT)
+static void nm_client_initable_iface_init (GInitableIface *iface);
+static void nm_client_async_initable_iface_init (GAsyncInitableIface *iface);
+static GInitableIface *nm_client_parent_initable_iface;
+static GAsyncInitableIface *nm_client_parent_async_initable_iface;
+
+G_DEFINE_TYPE_WITH_CODE (NMClient, nm_client, NM_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, nm_client_initable_iface_init);
+                         G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, nm_client_async_initable_iface_init);
+                         )
 
 #define NM_CLIENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_CLIENT, NMClientPrivate))
 
@@ -64,7 +71,6 @@ typedef struct {
 	 */
 	GSList *pending_activations;
 
-	gboolean have_networking_enabled;
 	gboolean networking_enabled;
 	gboolean wireless_enabled;
 	gboolean wireless_hw_enabled;
@@ -109,20 +115,8 @@ static void proxy_name_owner_changed (DBusGProxy *proxy,
 									  const char *new_owner,
 									  gpointer user_data);
 
-static void client_device_added_proxy (DBusGProxy *proxy, char *path, gpointer user_data);
-static void client_device_removed_proxy (DBusGProxy *proxy, char *path, gpointer user_data);
-
-static void
-handle_net_enabled_changed (GObject *object,
-                            GParamSpec *pspec,
-                            GValue *value,
-                            gpointer user_data)
-{
-	NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (object);
-
-	/* Update the cache flag when it changes */
-	priv->have_networking_enabled = TRUE;
-}
+static void client_device_added (NMObject *client, NMObject *device);
+static void client_device_removed (NMObject *client, NMObject *device);
 
 static void
 nm_client_init (NMClient *client)
@@ -132,11 +126,6 @@ nm_client_init (NMClient *client)
 	priv->state = NM_STATE_UNKNOWN;
 
 	priv->permissions = g_hash_table_new (g_direct_hash, g_direct_equal);
-
-	g_signal_connect (client,
-	                  "notify::" NM_CLIENT_NETWORKING_ENABLED,
-	                  G_CALLBACK (handle_net_enabled_changed),
-	                  client);
 }
 
 static void
@@ -154,188 +143,40 @@ poke_wireless_devices_with_rf_status (NMClient *client)
 }
 
 static void
-update_wireless_status (NMClient *client, gboolean notify)
-{
-	NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client);
-	gboolean val;
-	gboolean poke = FALSE;
-
-	val = _nm_object_get_boolean_property (NM_OBJECT (client),
-	                                       NM_DBUS_INTERFACE,
-	                                       "WirelessHardwareEnabled",
-	                                       NULL);
-	if (val != priv->wireless_hw_enabled) {
-		priv->wireless_hw_enabled = val;
-		poke = TRUE;
-		if (notify)
-			_nm_object_queue_notify (NM_OBJECT (client), NM_CLIENT_WIRELESS_HARDWARE_ENABLED);
-	}
-
-	if (priv->wireless_hw_enabled == FALSE)
-		val = FALSE;
-	else
-		val = _nm_object_get_boolean_property (NM_OBJECT (client),
-		                                       NM_DBUS_INTERFACE,
-		                                       "WirelessEnabled",
-		                                       NULL);
-	if (val != priv->wireless_enabled) {
-		priv->wireless_enabled = val;
-		poke = TRUE;
-		if (notify)
-			_nm_object_queue_notify (NM_OBJECT (client), NM_CLIENT_WIRELESS_ENABLED);
-	}
-
-	if (poke)
-		poke_wireless_devices_with_rf_status (client);
-}
-
-static void
 wireless_enabled_cb (GObject *object, GParamSpec *pspec, gpointer user_data)
 {
 	poke_wireless_devices_with_rf_status (NM_CLIENT (object));
 }
 
 static void
-update_wwan_status (NMClient *client, gboolean notify)
-{
-	NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client);
-	gboolean val;
-
-	val = _nm_object_get_boolean_property (NM_OBJECT (client),
-	                                       NM_DBUS_INTERFACE,
-	                                       "WwanHardwareEnabled",
-	                                       NULL);
-	if (val != priv->wwan_hw_enabled) {
-		priv->wwan_hw_enabled = val;
-		if (notify)
-			_nm_object_queue_notify (NM_OBJECT (client), NM_CLIENT_WWAN_HARDWARE_ENABLED);
-	}
-
-	if (priv->wwan_hw_enabled == FALSE)
-		val = FALSE;
-	else {
-		val = _nm_object_get_boolean_property (NM_OBJECT (client),
-		                                       NM_DBUS_INTERFACE,
-		                                       "WwanEnabled",
-		                                       NULL);
-	}
-
-	if (val != priv->wwan_enabled) {
-		priv->wwan_enabled = val;
-		if (notify)
-			_nm_object_queue_notify (NM_OBJECT (client), NM_CLIENT_WWAN_ENABLED);
-	}
-}
-
-static void
-update_wimax_status (NMClient *client, gboolean notify)
+register_properties (NMClient *client)
 {
 	NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client);
-	gboolean val;
-
-	val = _nm_object_get_boolean_property (NM_OBJECT (client),
-	                                       NM_DBUS_INTERFACE,
-	                                       "WimaxHardwareEnabled",
-	                                       NULL);
-	if (val != priv->wimax_hw_enabled) {
-		priv->wimax_hw_enabled = val;
-		if (notify)
-			_nm_object_queue_notify (NM_OBJECT (client), NM_CLIENT_WIMAX_HARDWARE_ENABLED);
-	}
-
-	if (priv->wimax_hw_enabled == FALSE)
-		val = FALSE;
-	else {
-		val = _nm_object_get_boolean_property (NM_OBJECT (client),
-		                                       NM_DBUS_INTERFACE,
-		                                       "WimaxEnabled",
-		                                       NULL);
-	}
-
-	if (val != priv->wimax_enabled) {
-		priv->wimax_enabled = val;
-		if (notify)
-			_nm_object_queue_notify (NM_OBJECT (client), NM_CLIENT_WIMAX_ENABLED);
-	}
-}
-
-static GObject *
-new_active_connection (DBusGConnection *connection, const char *path)
-{
-	DBusGProxy *proxy;
-	GError *error = NULL;
-	GValue value = {0,};
-	GObject *object = NULL;
-
-	proxy = dbus_g_proxy_new_for_name (connection,
-									   NM_DBUS_SERVICE,
-									   path,
-									   "org.freedesktop.DBus.Properties");
-	if (!proxy) {
-		g_warning ("%s: couldn't create D-Bus object proxy.", __func__);
-		return NULL;
-	}
-
-	/* Have to create an NMVPNConnection if it's a VPN connection, otherwise
-	 * a plain NMActiveConnection.
-	 */
-	if (dbus_g_proxy_call (proxy,
-	                       "Get", &error,
-	                       G_TYPE_STRING, NM_DBUS_INTERFACE_ACTIVE_CONNECTION,
-	                       G_TYPE_STRING, "Vpn",
-	                       G_TYPE_INVALID,
-	                       G_TYPE_VALUE, &value, G_TYPE_INVALID)) {
-		if (g_value_get_boolean (&value))
-			object = nm_vpn_connection_new (connection, path);
-		else
-			object = nm_active_connection_new (connection, path);
-	} else {
-		g_warning ("Error in getting active connection 'Vpn' property: (%d) %s",
-		           error->code, error->message);
-		g_error_free (error);
-	}
-
-	g_object_unref (proxy);
-	return object;
-}
-
-static gboolean
-demarshal_active_connections (NMObject *object,
-                              GParamSpec *pspec,
-                              GValue *value,
-                              gpointer field)
-{
-	DBusGConnection *connection;
-
-	connection = nm_object_get_connection (object);
-	if (!_nm_object_array_demarshal (value, (GPtrArray **) field, connection, new_active_connection))
-		return FALSE;
-
-	_nm_object_queue_notify (object, NM_CLIENT_ACTIVE_CONNECTIONS);
-	return TRUE;
-}
-
-static void
-register_for_property_changed (NMClient *client)
-{
-	NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client);
-	const NMPropertiesChangedInfo property_changed_info[] = {
-		{ NM_CLIENT_VERSION,                   _nm_object_demarshal_generic,  &priv->version },
-		{ NM_CLIENT_STATE,                     _nm_object_demarshal_generic,  &priv->state },
-		{ NM_CLIENT_NETWORKING_ENABLED,        _nm_object_demarshal_generic,  &priv->networking_enabled },
-		{ NM_CLIENT_WIRELESS_ENABLED,          _nm_object_demarshal_generic,  &priv->wireless_enabled },
-		{ NM_CLIENT_WIRELESS_HARDWARE_ENABLED, _nm_object_demarshal_generic,  &priv->wireless_hw_enabled },
-		{ NM_CLIENT_WWAN_ENABLED,              _nm_object_demarshal_generic,  &priv->wwan_enabled },
-		{ NM_CLIENT_WWAN_HARDWARE_ENABLED,     _nm_object_demarshal_generic,  &priv->wwan_hw_enabled },
-		{ NM_CLIENT_WIMAX_ENABLED,             _nm_object_demarshal_generic,  &priv->wimax_enabled },
-		{ NM_CLIENT_WIMAX_HARDWARE_ENABLED,    _nm_object_demarshal_generic,  &priv->wimax_hw_enabled },
-		{ NM_CLIENT_ACTIVE_CONNECTIONS,        demarshal_active_connections, &priv->active_connections },
+	const NMPropertiesInfo property_info[] = {
+		{ NM_CLIENT_VERSION,                   &priv->version },
+		{ NM_CLIENT_STATE,                     &priv->state },
+		{ NM_CLIENT_NETWORKING_ENABLED,        &priv->networking_enabled },
+		{ NM_CLIENT_WIRELESS_ENABLED,          &priv->wireless_enabled },
+		{ NM_CLIENT_WIRELESS_HARDWARE_ENABLED, &priv->wireless_hw_enabled },
+		{ NM_CLIENT_WWAN_ENABLED,              &priv->wwan_enabled },
+		{ NM_CLIENT_WWAN_HARDWARE_ENABLED,     &priv->wwan_hw_enabled },
+		{ NM_CLIENT_WIMAX_ENABLED,             &priv->wimax_enabled },
+		{ NM_CLIENT_WIMAX_HARDWARE_ENABLED,    &priv->wimax_hw_enabled },
+		{ NM_CLIENT_ACTIVE_CONNECTIONS,        &priv->active_connections, NULL, NM_TYPE_ACTIVE_CONNECTION },
 		{ NULL },
 	};
 
-	_nm_object_handle_properties_changed (NM_OBJECT (client),
+	_nm_object_register_properties (NM_OBJECT (client),
+	                                priv->client_proxy,
+	                                property_info);
+
+	_nm_object_register_pseudo_property (NM_OBJECT (client),
 	                                     priv->client_proxy,
-	                                     property_changed_info);
+	                                     "Devices",
+	                                     &priv->devices,
+	                                     NM_TYPE_DEVICE,
+	                                     client_device_added,
+	                                     client_device_removed);
 }
 
 #define NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK     "org.freedesktop.NetworkManager.enable-disable-network"
@@ -444,31 +285,38 @@ update_permissions (NMClient *self, GHashTable *permissions)
 	g_list_free (keys);
 }
 
-static void
-get_permissions_sync (NMClient *self)
+static gboolean
+get_permissions_sync (NMClient *self, GError **error)
 {
 	gboolean success;
 	GHashTable *permissions = NULL;
 
 	success = dbus_g_proxy_call_with_timeout (NM_CLIENT_GET_PRIVATE (self)->client_proxy,
-	                                          "GetPermissions", 3000, NULL,
+	                                          "GetPermissions", 3000, error,
 	                                          G_TYPE_INVALID,
 	                                          DBUS_TYPE_G_MAP_OF_STRING, &permissions, G_TYPE_INVALID);
 	update_permissions (self, success ? permissions : NULL);
 	if (permissions)
 		g_hash_table_destroy (permissions);
+
+	return success;
 }
 
 static void
 get_permissions_reply (DBusGProxy *proxy,
-                       GHashTable *permissions,
-                       GError *error,
+                       DBusGProxyCall *call,
                        gpointer user_data)
 {
 	NMClient *self = NM_CLIENT (user_data);
+	GHashTable *permissions;
+	GError *error = NULL;
 
+	dbus_g_proxy_end_call (proxy, call, &error,
+	                       DBUS_TYPE_G_MAP_OF_STRING, &permissions,
+	                       G_TYPE_INVALID);
 	NM_CLIENT_GET_PRIVATE (self)->perm_call = NULL;
 	update_permissions (NM_CLIENT (user_data), error ? NULL : permissions);
+	g_clear_error (&error);
 }
 
 static void
@@ -478,9 +326,9 @@ client_recheck_permissions (DBusGProxy *proxy, gpointer user_data)
 	NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self);
 
 	if (!priv->perm_call) {
-		priv->perm_call = org_freedesktop_NetworkManager_get_permissions_async (NM_CLIENT_GET_PRIVATE (self)->client_proxy,
-	                                                                            get_permissions_reply,
-	                                                                            self);
+		priv->perm_call = dbus_g_proxy_begin_call (NM_CLIENT_GET_PRIVATE (self)->client_proxy, "GetPermissions",
+		                                           get_permissions_reply, self, NULL,
+		                                           G_TYPE_INVALID);
 	}
 }
 
@@ -496,31 +344,11 @@ client_recheck_permissions (DBusGProxy *proxy, gpointer user_data)
 const GPtrArray *
 nm_client_get_devices (NMClient *client)
 {
-	NMClientPrivate *priv;
-	DBusGConnection *connection;
-	GValue value = { 0, };
-	GError *error = NULL;
-	GPtrArray *temp;
-
 	g_return_val_if_fail (NM_IS_CLIENT (client), NULL);
 
-	priv = NM_CLIENT_GET_PRIVATE (client);
-	if (priv->devices)
-		return handle_ptr_array_return (priv->devices);
-
-	if (!org_freedesktop_NetworkManager_get_devices (priv->client_proxy, &temp, &error)) {
-		g_warning ("%s: error getting devices: %s\n", __func__, error->message);
-		g_error_free (error);
-		return NULL;
-	}
-
-	g_value_init (&value, DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH);
-	g_value_take_boxed (&value, temp);
-	connection = nm_object_get_connection (NM_OBJECT (client));
-	_nm_object_array_demarshal (&value, &priv->devices, connection, nm_device_new);
-	g_value_unset (&value);
+	_nm_object_ensure_inited (NM_OBJECT (client));
 
-	return handle_ptr_array_return (priv->devices);
+	return handle_ptr_array_return (NM_CLIENT_GET_PRIVATE (client)->devices);
 }
 
 /**
@@ -664,17 +492,22 @@ recheck_pending_activations (NMClient *self)
 
 static void
 activate_cb (DBusGProxy *proxy,
-             char *path,
-             GError *error,
+             DBusGProxyCall *call,
              gpointer user_data)
 {
 	ActivateInfo *info = user_data;
+	char *path;
+	GError *error = NULL;
 
+	dbus_g_proxy_end_call (proxy, call, &error,
+	                       DBUS_TYPE_G_OBJECT_PATH, &path,
+	                       G_TYPE_INVALID);
 	if (error) {
 		activate_info_complete (info, NULL, error);
 		activate_info_free (info);
+		g_clear_error (&error);
 	} else {
-		info->active_path = g_strdup (path);
+		info->active_path = path;
 		recheck_pending_activations (info->client);
 	}
 }
@@ -726,29 +559,34 @@ nm_client_activate_connection (NMClient *client,
 	priv = NM_CLIENT_GET_PRIVATE (client);
 	priv->pending_activations = g_slist_prepend (priv->pending_activations, info);
 
-	org_freedesktop_NetworkManager_activate_connection_async (priv->client_proxy,
-	                                                          nm_connection_get_path (connection),
-	                                                          device ? nm_object_get_path (NM_OBJECT (device)) : "/",
-	                                                          specific_object ? specific_object : "/",
-	                                                          activate_cb,
-	                                                          info);
+	dbus_g_proxy_begin_call (priv->client_proxy, "ActivateConnection",
+	                         activate_cb, info, NULL,
+	                         DBUS_TYPE_G_OBJECT_PATH, nm_connection_get_path (connection),
+	                         DBUS_TYPE_G_OBJECT_PATH, device ? nm_object_get_path (NM_OBJECT (device)) : "/",
+	                         DBUS_TYPE_G_OBJECT_PATH, specific_object ? specific_object : "/",
+	                         G_TYPE_INVALID);
 }
 
 static void
 add_activate_cb (DBusGProxy *proxy,
-                 char *connection_path,
-                 char *active_path,
-                 GError *error,
+                 DBusGProxyCall *call,
                  gpointer user_data)
 {
 	ActivateInfo *info = user_data;
+	char *connection_path;
+	char *active_path;
+	GError *error = NULL;
 
+	dbus_g_proxy_end_call (proxy, call, &error,
+	                       DBUS_TYPE_G_OBJECT_PATH, &connection_path,
+	                       DBUS_TYPE_G_OBJECT_PATH, &active_path,
+	                       G_TYPE_INVALID);
 	if (error) {
 		activate_info_complete (info, NULL, error);
 		activate_info_free (info);
 	} else {
-		info->new_connection_path = g_strdup (connection_path);
-		info->active_path = g_strdup (active_path);
+		info->new_connection_path = connection_path;
+		info->active_path = active_path;
 		recheck_pending_activations (info->client);
 	}
 }
@@ -803,12 +641,12 @@ nm_client_add_and_activate_connection (NMClient *client,
 	priv = NM_CLIENT_GET_PRIVATE (client);
 	priv->pending_activations = g_slist_prepend (priv->pending_activations, info);
 
-	org_freedesktop_NetworkManager_add_and_activate_connection_async (priv->client_proxy,
-	                                                                  hash,
-	                                                                  nm_object_get_path (NM_OBJECT (device)),
-	                                                                  specific_object ? specific_object : "/",
-	                                                                  add_activate_cb,
-	                                                                  info);
+	dbus_g_proxy_begin_call (priv->client_proxy, "AddAndActivateConnection",
+	                         add_activate_cb, info, NULL,
+	                         DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, hash,
+	                         DBUS_TYPE_G_OBJECT_PATH, nm_object_get_path (NM_OBJECT (device)),
+	                         DBUS_TYPE_G_OBJECT_PATH, specific_object ? specific_object : "/",
+	                         G_TYPE_INVALID);
 	g_hash_table_unref (hash);
 }
 
@@ -838,7 +676,10 @@ nm_client_deactivate_connection (NMClient *client, NMActiveConnection *active)
 	// FIXME: return errors
 	priv = NM_CLIENT_GET_PRIVATE (client);
 	path = nm_object_get_path (NM_OBJECT (active));
-	if (!org_freedesktop_NetworkManager_deactivate_connection (priv->client_proxy, path, &error)) {
+	if (!dbus_g_proxy_call (priv->client_proxy, "DeactivateConnection", &error,
+	                        DBUS_TYPE_G_OBJECT_PATH, path,
+	                        G_TYPE_INVALID,
+	                        G_TYPE_INVALID)) {
 		g_warning ("Could not deactivate connection '%s': %s", path, error->message);
 		g_error_free (error);
 	}
@@ -858,28 +699,15 @@ const GPtrArray *
 nm_client_get_active_connections (NMClient *client)
 {
 	NMClientPrivate *priv;
-	GValue value = { 0, };
 
 	g_return_val_if_fail (NM_IS_CLIENT (client), NULL);
 
-	priv = NM_CLIENT_GET_PRIVATE (client);
-	if (priv->active_connections)
-		return handle_ptr_array_return (priv->active_connections);
+	_nm_object_ensure_inited (NM_OBJECT (client));
 
+	priv = NM_CLIENT_GET_PRIVATE (client);
 	if (!priv->manager_running)
 		return NULL;
 
-	if (!_nm_object_get_property (NM_OBJECT (client),
-	                             "org.freedesktop.NetworkManager",
-	                             "ActiveConnections",
-	                             &value,
-	                             NULL)) {
-		return NULL;
-	}
-
-	demarshal_active_connections (NM_OBJECT (client), NULL, &value, &priv->active_connections);
-	g_value_unset (&value);
-
 	return handle_ptr_array_return (priv->active_connections);
 }
 
@@ -896,6 +724,7 @@ nm_client_wireless_get_enabled (NMClient *client)
 {
 	g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
 
+	_nm_object_ensure_inited (NM_OBJECT (client));
 	return NM_CLIENT_GET_PRIVATE (client)->wireless_enabled;
 }
 
@@ -935,6 +764,7 @@ nm_client_wireless_hardware_get_enabled (NMClient *client)
 {
 	g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
 
+	_nm_object_ensure_inited (NM_OBJECT (client));
 	return NM_CLIENT_GET_PRIVATE (client)->wireless_hw_enabled;
 }
 
@@ -951,6 +781,7 @@ nm_client_wwan_get_enabled (NMClient *client)
 {
 	g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
 
+	_nm_object_ensure_inited (NM_OBJECT (client));
 	return NM_CLIENT_GET_PRIVATE (client)->wwan_enabled;
 }
 
@@ -990,6 +821,7 @@ nm_client_wwan_hardware_get_enabled (NMClient *client)
 {
 	g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
 
+	_nm_object_ensure_inited (NM_OBJECT (client));
 	return NM_CLIENT_GET_PRIVATE (client)->wwan_hw_enabled;
 }
 
@@ -1006,6 +838,7 @@ nm_client_wimax_get_enabled (NMClient *client)
 {
 	g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
 
+	_nm_object_ensure_inited (NM_OBJECT (client));
 	return NM_CLIENT_GET_PRIVATE (client)->wimax_enabled;
 }
 
@@ -1045,6 +878,7 @@ nm_client_wimax_hardware_get_enabled (NMClient *client)
 {
 	g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
 
+	_nm_object_ensure_inited (NM_OBJECT (client));
 	return NM_CLIENT_GET_PRIVATE (client)->wimax_hw_enabled;
 }
 
@@ -1060,23 +894,14 @@ const char *
 nm_client_get_version (NMClient *client)
 {
 	NMClientPrivate *priv;
-	GError *err = NULL;
 
 	g_return_val_if_fail (NM_IS_CLIENT (client), NULL);
 
 	priv = NM_CLIENT_GET_PRIVATE (client);
 
-	if (!priv->manager_running)
-		return NULL;
-
-	if (!priv->version)
-		priv->version = _nm_object_get_string_property (NM_OBJECT (client), NM_DBUS_INTERFACE, "Version", &err);
+	_nm_object_ensure_inited (NM_OBJECT (client));
 
-	/* TODO: we don't pass the error to the caller yet, maybe later */
-	if (err)
-		g_error_free (err);
-
-	return priv->version;
+	return priv->manager_running ? priv->version : NULL;
 }
 
 /**
@@ -1090,19 +915,11 @@ nm_client_get_version (NMClient *client)
 NMState
 nm_client_get_state (NMClient *client)
 {
-	NMClientPrivate *priv;
-
 	g_return_val_if_fail (NM_IS_CLIENT (client), NM_STATE_UNKNOWN);
 
-	priv = NM_CLIENT_GET_PRIVATE (client);
-
-	if (!priv->manager_running)
-		return NM_STATE_UNKNOWN;
-
-	if (priv->state == NM_STATE_UNKNOWN)
-		priv->state = _nm_object_get_uint_property (NM_OBJECT (client), NM_DBUS_INTERFACE, "State", NULL);
+	_nm_object_ensure_inited (NM_OBJECT (client));
 
-	return priv->state;
+	return NM_CLIENT_GET_PRIVATE (client)->state;
 }
 
 /**
@@ -1116,23 +933,10 @@ nm_client_get_state (NMClient *client)
 gboolean
 nm_client_networking_get_enabled (NMClient *client)
 {
-	NMClientPrivate *priv;
-
 	g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
 
-	priv = NM_CLIENT_GET_PRIVATE (client);
-	if (!priv->have_networking_enabled) {
-		priv = NM_CLIENT_GET_PRIVATE (client);
-		if (!priv->networking_enabled) {
-			priv->networking_enabled = _nm_object_get_boolean_property (NM_OBJECT (client),
-			                                                            NM_DBUS_INTERFACE,
-			                                                            "NetworkingEnabled",
-			                                                            NULL);
-			priv->have_networking_enabled = TRUE;
-		}
-	}
-
-	return priv->networking_enabled;
+	_nm_object_ensure_inited (NM_OBJECT (client));
+	return NM_CLIENT_GET_PRIVATE (client)->networking_enabled;
 }
 
 /**
@@ -1151,7 +955,10 @@ nm_client_networking_set_enabled (NMClient *client, gboolean enable)
 
 	g_return_if_fail (NM_IS_CLIENT (client));
 
-	if (!org_freedesktop_NetworkManager_enable (NM_CLIENT_GET_PRIVATE (client)->client_proxy, enable, &err)) {
+	if (!dbus_g_proxy_call (NM_CLIENT_GET_PRIVATE (client)->client_proxy, "Enable", &err,
+	                        G_TYPE_BOOLEAN, enable,
+	                        G_TYPE_INVALID,
+	                        G_TYPE_INVALID)) {
 		g_warning ("Error enabling/disabling networking: %s", err->message);
 		g_error_free (err);
 	}
@@ -1160,14 +967,14 @@ nm_client_networking_set_enabled (NMClient *client, gboolean enable)
 /**
  * nm_client_sleep:
  * @client: a #NMClient
- * @sleep: %TRUE to put the daemon to sleep
+ * @sleep_: %TRUE to put the daemon to sleep
  *
  * Deprecated; use nm_client_networking_set_enabled() instead.
  **/
 void
-nm_client_sleep (NMClient *client, gboolean sleep)
+nm_client_sleep (NMClient *client, gboolean sleep_)
 {
-	nm_client_networking_set_enabled (client, !sleep);
+	nm_client_networking_set_enabled (client, !sleep_);
 }
 
 /**
@@ -1223,6 +1030,35 @@ free_object_array (GPtrArray **array)
 }
 
 static void
+dispose_and_free_object_array (GPtrArray **array)
+{
+	g_return_if_fail (array != NULL);
+
+	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);
+	}
+}
+
+static void
+updated_properties (GObject *object, GAsyncResult *result, gpointer user_data)
+{
+	NMClient *client = NM_CLIENT (user_data);
+	GError *error = NULL;
+
+	if (!_nm_object_reload_properties_finish (NM_OBJECT (object), result, &error)) {
+		g_warning ("%s: error reading NMClient properties: %s", __func__, error->message);
+		g_error_free (error);
+	}
+
+	_nm_object_queue_notify (NM_OBJECT (client), NM_CLIENT_MANAGER_RUNNING);
+}
+
+static void
 proxy_name_owner_changed (DBusGProxy *proxy,
 						  const char *name,
 						  const char *old_owner,
@@ -1250,61 +1086,34 @@ proxy_name_owner_changed (DBusGProxy *proxy,
 	if (!priv->manager_running) {
 		priv->state = NM_STATE_UNKNOWN;
 		_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);
-		free_object_array (&priv->active_connections);
+		dispose_and_free_object_array (&priv->active_connections);
 		priv->wireless_enabled = FALSE;
 		priv->wireless_hw_enabled = FALSE;
 		priv->wwan_enabled = FALSE;
 		priv->wwan_hw_enabled = FALSE;
 		priv->wimax_enabled = FALSE;
 		priv->wimax_hw_enabled = FALSE;
+		g_free (priv->version);
+		priv->version = NULL;
 	} else {
-		_nm_object_queue_notify (NM_OBJECT (client), NM_CLIENT_MANAGER_RUNNING);
-		update_wireless_status (client, TRUE);
-		update_wwan_status (client, TRUE);
-		update_wimax_status (client, TRUE);
+		_nm_object_suppress_property_updates (NM_OBJECT (client), FALSE);
+		_nm_object_reload_properties_async (NM_OBJECT (client), updated_properties, client);
 	}
 }
 
 static void
-client_device_added_proxy (DBusGProxy *proxy, char *path, gpointer user_data)
+client_device_added (NMObject *client, NMObject *device)
 {
-	NMClient *client = NM_CLIENT (user_data);
-	NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client);
-	GObject *device;
-
-	device = G_OBJECT (nm_client_get_device_by_path (client, path));
-	if (!device) {
-		DBusGConnection *connection = nm_object_get_connection (NM_OBJECT (client));
-
-		device = G_OBJECT (_nm_object_cache_get (path));
-		if (device) {
-			g_ptr_array_add (priv->devices, device);
-		} else {
-			device = G_OBJECT (nm_device_new (connection, path));
-			if (device)
-				g_ptr_array_add (priv->devices, device);
-		}
-	}
-
-	if (device)
-		g_signal_emit (client, signals[DEVICE_ADDED], 0, device);
+	g_signal_emit (client, signals[DEVICE_ADDED], 0, device);
 }
 
 static void
-client_device_removed_proxy (DBusGProxy *proxy, char *path, gpointer user_data)
+client_device_removed (NMObject *client, NMObject *device)
 {
-	NMClient *client = NM_CLIENT (user_data);
-	NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client);
-	NMDevice *device;
-
-	device = nm_client_get_device_by_path (client, path);
-	if (device) {
-		g_signal_emit (client, signals[DEVICE_REMOVED], 0, device);
-		g_ptr_array_remove (priv->devices, device);
-		g_object_unref (device);
-	}
+	g_signal_emit (client, signals[DEVICE_REMOVED], 0, device);
 }
 
 /****************************************************************/
@@ -1314,6 +1123,14 @@ client_device_removed_proxy (DBusGProxy *proxy, char *path, gpointer user_data)
  *
  * Creates a new #NMClient.
  *
+ * Note that this will do blocking D-Bus calls to initialize the
+ * client. You can use nm_client_new_async() if you want to avoid
+ * that.
+ *
+ * NOTE: #NMClient provides information about devices and a mechanism to
+ * control them.  To access and modify network configuration data, use the
+ * #NMRemoteSettings object.
+ *
  * Returns: a new #NMClient
  **/
 NMClient *
@@ -1321,6 +1138,7 @@ nm_client_new (void)
 {
 	DBusGConnection *connection;
 	GError *err = NULL;
+	NMClient *client;
 
 #ifdef LIBNM_GLIB_TEST
 	connection = dbus_g_bus_get (DBUS_BUS_SESSION, &err);
@@ -1333,51 +1151,115 @@ nm_client_new (void)
 		return NULL;
 	}
 
-	return (NMClient *) g_object_new (NM_TYPE_CLIENT,
-									  NM_OBJECT_DBUS_CONNECTION, connection,
-									  NM_OBJECT_DBUS_PATH, NM_DBUS_PATH,
-									  NULL);
+	client = g_object_new (NM_TYPE_CLIENT,
+	                       NM_OBJECT_DBUS_CONNECTION, connection,
+	                       NM_OBJECT_DBUS_PATH, NM_DBUS_PATH,
+	                       NULL);
+	_nm_object_ensure_inited (NM_OBJECT (client));
+	return client;
+}
+
+static void
+client_inited (GObject *source, GAsyncResult *result, gpointer user_data)
+{
+	GSimpleAsyncResult *simple = user_data;
+	GError *error = NULL;
+
+	if (!g_async_initable_init_finish (G_ASYNC_INITABLE (source), result, &error))
+		g_simple_async_result_take_error (simple, error);
+	else
+		g_simple_async_result_set_op_res_gpointer (simple, source, g_object_unref);
+	g_simple_async_result_complete (simple);
+	g_object_unref (simple);
 }
 
-static GObject*
-constructor (GType type,
-		   guint n_construct_params,
-		   GObjectConstructParam *construct_params)
+/**
+ * nm_client_new_async:
+ * @cancellable: a #GCancellable, or %NULL
+ * @callback: callback to call when the client is created
+ * @user_data: data for @callback
+ *
+ * Creates a new #NMClient and begins asynchronously initializing it.
+ * @callback will be called when it is done; use
+ * nm_client_new_finish() to get the result.
+ *
+ * NOTE: #NMClient provides information about devices and a mechanism to
+ * control them.  To access and modify network configuration data, use the
+ * #NMRemoteSettings object.
+ **/
+void
+nm_client_new_async (GCancellable *cancellable, GAsyncReadyCallback callback,
+                     gpointer user_data)
 {
-	NMObject *object;
 	DBusGConnection *connection;
-	NMClientPrivate *priv;
 	GError *err = NULL;
+	NMClient *client;
+	GSimpleAsyncResult *simple;
 
-	object = (NMObject *) G_OBJECT_CLASS (nm_client_parent_class)->constructor (type,
-																 n_construct_params,
-																 construct_params);
-	if (!object)
+	simple = g_simple_async_result_new (NULL, callback, user_data, nm_client_new_async);
+
+#ifdef LIBNM_GLIB_TEST
+	connection = dbus_g_bus_get (DBUS_BUS_SESSION, &err);
+#else
+	connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &err);
+#endif
+	if (!connection) {
+		g_simple_async_result_take_error (simple, err);
+		g_simple_async_result_complete_in_idle (simple);
+		g_object_unref (simple);
+		return;
+	}
+
+	client = g_object_new (NM_TYPE_CLIENT,
+	                       NM_OBJECT_DBUS_CONNECTION, connection,
+	                       NM_OBJECT_DBUS_PATH, NM_DBUS_PATH,
+	                       NULL);
+	g_async_initable_init_async (G_ASYNC_INITABLE (client), G_PRIORITY_DEFAULT,
+	                             cancellable, client_inited, simple);
+}
+
+/**
+ * nm_client_new_finish:
+ * @result: a #GAsyncResult
+ * @error: location for a #GError, or %NULL
+ *
+ * Gets the result of an nm_client_new_async() call.
+ *
+ * Returns: a new #NMClient, or %NULL on error
+ **/
+NMClient *
+nm_client_new_finish (GAsyncResult *result, GError **error)
+{
+	GSimpleAsyncResult *simple;
+
+	g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL, nm_client_new_async), NULL);
+
+	simple = G_SIMPLE_ASYNC_RESULT (result);
+	if (g_simple_async_result_propagate_error (simple, error))
 		return NULL;
+	else
+		return g_object_ref (g_simple_async_result_get_op_res_gpointer (simple));
+}
+
+static void
+constructed (GObject *object)
+{
+	DBusGConnection *connection;
+	NMClientPrivate *priv;
+
+	nm_utils_init (NULL);
+
+	G_OBJECT_CLASS (nm_client_parent_class)->constructed (object);
 
 	priv = NM_CLIENT_GET_PRIVATE (object);
-	connection = nm_object_get_connection (object);
+	connection = nm_object_get_connection (NM_OBJECT (object));
 
 	priv->client_proxy = dbus_g_proxy_new_for_name (connection,
 										   NM_DBUS_SERVICE,
-										   nm_object_get_path (object),
+										   nm_object_get_path (NM_OBJECT (object)),
 										   NM_DBUS_INTERFACE);
 
-	register_for_property_changed (NM_CLIENT (object));
-
-	dbus_g_proxy_add_signal (priv->client_proxy, "DeviceAdded", DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID);
-	dbus_g_proxy_connect_signal (priv->client_proxy,
-						    "DeviceAdded",
-						    G_CALLBACK (client_device_added_proxy),
-						    object,
-						    NULL);
-
-	dbus_g_proxy_add_signal (priv->client_proxy, "DeviceRemoved", DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID);
-	dbus_g_proxy_connect_signal (priv->client_proxy,
-						    "DeviceRemoved",
-						    G_CALLBACK (client_device_removed_proxy),
-						    object,
-						    NULL);
+	register_properties (NM_CLIENT (object));
 
 	/* Permissions */
 	dbus_g_proxy_add_signal (priv->client_proxy, "CheckPermissions", G_TYPE_INVALID);
@@ -1386,7 +1268,6 @@ constructor (GType type,
 	                             G_CALLBACK (client_recheck_permissions),
 	                             object,
 	                             NULL);
-	get_permissions_sync (NM_CLIENT (object));
 
 	priv->bus_proxy = dbus_g_proxy_new_for_name (connection,
 	                                             DBUS_SERVICE_DBUS,
@@ -1401,30 +1282,136 @@ constructor (GType type,
 						    G_CALLBACK (proxy_name_owner_changed),
 						    object, NULL);
 
+	g_signal_connect (object, "notify::" NM_CLIENT_WIRELESS_ENABLED,
+	                  G_CALLBACK (wireless_enabled_cb), NULL);
+
+	g_signal_connect (object, "notify::" NM_CLIENT_ACTIVE_CONNECTIONS,
+	                  G_CALLBACK (active_connections_changed_cb), NULL);
+}
+
+static gboolean
+init_sync (GInitable *initable, GCancellable *cancellable, GError **error)
+{
+	NMClient *client = NM_CLIENT (initable);
+	NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client);
+
+	if (!nm_client_parent_initable_iface->init (initable, cancellable, error))
+		return FALSE;
+
 	if (!dbus_g_proxy_call (priv->bus_proxy,
-					    "NameHasOwner", &err,
-					    G_TYPE_STRING, NM_DBUS_SERVICE,
-					    G_TYPE_INVALID,
-					    G_TYPE_BOOLEAN, &priv->manager_running,
-					    G_TYPE_INVALID)) {
-		g_warning ("Error on NameHasOwner DBUS call: %s", err->message);
-		g_error_free (err);
+	                        "NameHasOwner", error,
+	                        G_TYPE_STRING, NM_DBUS_SERVICE,
+	                        G_TYPE_INVALID,
+	                        G_TYPE_BOOLEAN, &priv->manager_running,
+	                        G_TYPE_INVALID))
+		return FALSE;
+
+	if (priv->manager_running && !get_permissions_sync (client, error))
+		return FALSE;
+
+	return TRUE;
+}
+
+typedef struct {
+	NMClient *client;
+	GSimpleAsyncResult *result;
+	gboolean properties_pending;
+	gboolean permissions_pending;
+} NMClientInitData;
+
+static void
+init_async_complete (NMClientInitData *init_data)
+{
+	if (init_data->properties_pending || init_data->permissions_pending)
+		return;
+
+	g_simple_async_result_complete (init_data->result);
+	g_object_unref (init_data->result);
+	g_slice_free (NMClientInitData, init_data);
+}
+
+static void
+init_async_got_permissions (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data)
+{
+	NMClientInitData *init_data = user_data;
+	GHashTable *permissions;
+	GError *error = NULL;
+
+	dbus_g_proxy_end_call (proxy, call, &error,
+	                       DBUS_TYPE_G_MAP_OF_STRING, &permissions,
+	                       G_TYPE_INVALID);
+	update_permissions (init_data->client, error ? NULL : permissions);
+	g_clear_error (&error);
+
+	init_data->permissions_pending = FALSE;
+	init_async_complete (init_data);
+}
+
+static void
+init_async_got_properties (GObject *source, GAsyncResult *result, gpointer user_data)
+{
+	NMClientInitData *init_data = user_data;
+	GError *error = NULL;
+
+	if (!nm_client_parent_async_initable_iface->init_finish (G_ASYNC_INITABLE (source), result, &error))
+		g_simple_async_result_take_error (init_data->result, error);
+
+	init_data->properties_pending = FALSE;
+	init_async_complete (init_data);
+}
+
+static void
+init_async_got_manager_running (DBusGProxy *proxy, DBusGProxyCall *call,
+                                gpointer user_data)
+{
+	NMClientInitData *init_data = user_data;
+	NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (init_data->client);
+	GError *error = NULL;
+
+	if (!dbus_g_proxy_end_call (proxy, call, &error,
+	                            G_TYPE_BOOLEAN, &priv->manager_running,
+	                            G_TYPE_INVALID)) {
+		g_simple_async_result_take_error (init_data->result, error);
+		init_async_complete (init_data);
+		return;
 	}
 
-	if (priv->manager_running) {
-		update_wireless_status (NM_CLIENT (object), FALSE);
-		update_wwan_status (NM_CLIENT (object), FALSE);
-		update_wimax_status (NM_CLIENT (object), FALSE);
-		nm_client_get_state (NM_CLIENT (object));
+	if (!priv->manager_running) {
+		init_async_complete (init_data);
+		return;
 	}
 
-	g_signal_connect (G_OBJECT (object), "notify::" NM_CLIENT_WIRELESS_ENABLED,
-	                  G_CALLBACK (wireless_enabled_cb), NULL);
+	nm_client_parent_async_initable_iface->init_async (G_ASYNC_INITABLE (init_data->client),
+	                                                   G_PRIORITY_DEFAULT, NULL, /* FIXME cancellable */
+	                                                   init_async_got_properties, init_data);
+	init_data->properties_pending = TRUE;
 
-	g_signal_connect (object, "notify::" NM_CLIENT_ACTIVE_CONNECTIONS,
-	                  G_CALLBACK (active_connections_changed_cb), NULL);
+	dbus_g_proxy_begin_call (priv->client_proxy, "GetPermissions",
+	                         init_async_got_permissions, init_data, NULL,
+	                         G_TYPE_INVALID);
+	init_data->permissions_pending = TRUE;
+}
 
-	return G_OBJECT (object);
+static void
+init_async (GAsyncInitable *initable, int io_priority,
+			GCancellable *cancellable, GAsyncReadyCallback callback,
+			gpointer user_data)
+{
+	NMClientInitData *init_data;
+	NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (initable);
+
+	init_data = g_slice_new0 (NMClientInitData);
+	init_data->client = NM_CLIENT (initable);
+	init_data->result = g_simple_async_result_new (G_OBJECT (initable), callback,
+	                                               user_data, init_async);
+	g_simple_async_result_set_op_res_gboolean (init_data->result, TRUE);
+
+	/* Check if NM is running */
+	dbus_g_proxy_begin_call (priv->bus_proxy, "NameHasOwner",
+	                         init_async_got_manager_running,
+	                         init_data, NULL,
+	                         G_TYPE_STRING, NM_DBUS_SERVICE,
+	                         G_TYPE_INVALID);
 }
 
 static void
@@ -1444,7 +1431,7 @@ dispose (GObject *object)
 	g_object_unref (priv->bus_proxy);
 
 	free_object_array (&priv->devices);
-	free_object_array (&priv->active_connections);
+	dispose_and_free_object_array (&priv->active_connections);
 
 	g_slist_foreach (priv->pending_activations, (GFunc) activate_info_free, NULL);
 	g_slist_free (priv->pending_activations);
@@ -1563,7 +1550,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;
 	object_class->dispose = dispose;
@@ -1763,7 +1750,22 @@ nm_client_class_init (NMClientClass *client_class)
 					  G_OBJECT_CLASS_TYPE (object_class),
 					  G_SIGNAL_RUN_FIRST,
 					  0, NULL, NULL,
-					  _nm_marshal_VOID__UINT_UINT,
+					  _nm_glib_marshal_VOID__UINT_UINT,
 					  G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
 }
 
+static void
+nm_client_initable_iface_init (GInitableIface *iface)
+{
+	nm_client_parent_initable_iface = g_type_interface_peek_parent (iface);
+
+	iface->init = init_sync;
+}
+
+static void
+nm_client_async_initable_iface_init (GAsyncInitableIface *iface)
+{
+	nm_client_parent_async_initable_iface = g_type_interface_peek_parent (iface);
+
+	iface->init_async = init_async;
+}
diff --git a/libnm-glib/nm-client.h b/libnm-glib/nm-client.h
index c9fd7c10..684326ff 100644
--- a/libnm-glib/nm-client.h
+++ b/libnm-glib/nm-client.h
@@ -26,6 +26,7 @@
 
 #include <glib.h>
 #include <glib-object.h>
+#include <gio/gio.h>
 #include <dbus/dbus-glib.h>
 #include <NetworkManager.h>
 #include "nm-object.h"
@@ -106,6 +107,12 @@ GType nm_client_get_type (void);
 
 NMClient *nm_client_new (void);
 
+void      nm_client_new_async  (GCancellable         *cancellable,
+                                GAsyncReadyCallback   callback,
+                                gpointer              user_data);
+NMClient *nm_client_new_finish (GAsyncResult         *result,
+                                GError              **error);
+
 const GPtrArray *nm_client_get_devices    (NMClient *client);
 NMDevice *nm_client_get_device_by_path    (NMClient *client, const char *object_path);
 NMDevice *nm_client_get_device_by_iface   (NMClient *client, const char *iface);
@@ -156,7 +163,7 @@ const char *nm_client_get_version        (NMClient *client);
 NMState   nm_client_get_state            (NMClient *client);
 gboolean  nm_client_get_manager_running  (NMClient *client);
 const GPtrArray *nm_client_get_active_connections (NMClient *client);
-void      nm_client_sleep                (NMClient *client, gboolean sleep);
+void      nm_client_sleep                (NMClient *client, gboolean sleep_);
 
 NMClientPermissionResult nm_client_get_permission_result (NMClient *client,
                                                           NMClientPermission permission);
diff --git a/libnm-glib/nm-dbus-utils.c b/libnm-glib/nm-dbus-utils.c
deleted file mode 100644
index f641f185..00000000
--- a/libnm-glib/nm-dbus-utils.c
+++ /dev/null
@@ -1,215 +0,0 @@
-/* -*- 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) 2007 - 2008 Novell, Inc.
- */
-
-#include "nm-dbus-utils.h"
-
-char *
-_nm_dbus_get_string_property (DBusGProxy *proxy,
-							 const char *interface,
-							 const char *prop_name)
-{
-	GError *err = NULL;
-	char *str = NULL;
-	GValue value = {0,};
-
-	g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), NULL);
-
-	if (dbus_g_proxy_call (proxy, "Get", &err,
-						   G_TYPE_STRING, interface,
-						   G_TYPE_STRING, prop_name,
-						   G_TYPE_INVALID,
-						   G_TYPE_VALUE, &value,
-						   G_TYPE_INVALID)) {
-		str = g_strdup (g_value_get_string (&value));
-	} else {
-		g_warning ("Error in device_get_property: %s\n", err->message);
-		g_error_free (err);
-	}
-
-	return str;
-}
-
-char *
-_nm_dbus_get_object_path_property (DBusGProxy *proxy,
-								  const char *interface,
-								  const char *prop_name)
-{
-	GError *err = NULL;
-	char *path = NULL;
-	GValue value = {0,};
-
-	g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), NULL);
-
-	if (dbus_g_proxy_call (proxy, "Get", &err,
-						   G_TYPE_STRING, interface,
-						   G_TYPE_STRING, prop_name,
-						   G_TYPE_INVALID,
-						   G_TYPE_VALUE, &value,
-						   G_TYPE_INVALID)) {
-		path = g_strdup (g_value_get_boxed (&value));
-	} else {
-		g_warning ("Error in device_get_property: %s\n", err->message);
-		g_error_free (err);
-	}
-
-	return path;
-}
-
-gint32
-_nm_dbus_get_int_property (DBusGProxy *proxy,
-						  const char *interface,
-						  const char *prop_name)
-{
-	GError *err = NULL;
-	gint32 i = 0;
-	GValue value = {0,};
-
-	g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), 0);
-
-	if (dbus_g_proxy_call (proxy, "Get", &err,
-						   G_TYPE_STRING, interface,
-						   G_TYPE_STRING, prop_name,
-						   G_TYPE_INVALID,
-						   G_TYPE_VALUE, &value,
-						   G_TYPE_INVALID)) {
-		i = g_value_get_int (&value);
-	} else {
-		g_warning ("Error in device_get_property: %s\n", err->message);
-		g_error_free (err);
-	}
-
-	return i;
-}
-
-guint32
-_nm_dbus_get_uint_property (DBusGProxy *proxy,
-						   const char *interface,
-						   const char *prop_name)
-{
-	GError *err = NULL;
-	guint32 i = 0;
-	GValue value = {0,};
-
-	g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), 0);
-
-	if (dbus_g_proxy_call (proxy, "Get", &err,
-						   G_TYPE_STRING, interface,
-						   G_TYPE_STRING, prop_name,
-						   G_TYPE_INVALID,
-						   G_TYPE_VALUE, &value,
-						   G_TYPE_INVALID)) {
-		i = g_value_get_uint (&value);
-	} else {
-		g_warning ("Error in device_get_property: %s\n", err->message);
-		g_error_free (err);
-	}
-
-	return i;
-}
-
-gboolean
-_nm_dbus_get_property (DBusGProxy *proxy,
-					  const char *interface,
-					  const char *prop_name,
-					  GValue *value)
-{
-	DBusGProxy *properties_proxy;
-	GError *err = NULL;
-	gboolean ret = TRUE;
-
-	g_return_val_if_fail (proxy != NULL, FALSE);
-	g_return_val_if_fail (interface != NULL, FALSE);
-	g_return_val_if_fail (prop_name != NULL, FALSE);
-
-	properties_proxy = dbus_g_proxy_new_from_proxy (proxy,
-													"org.freedesktop.DBus.Properties",
-													dbus_g_proxy_get_path (proxy));
-
-	if (!dbus_g_proxy_call (properties_proxy, "Get", &err,
-							G_TYPE_STRING, interface,
-							G_TYPE_STRING, prop_name,
-							G_TYPE_INVALID,
-							G_TYPE_VALUE, value,
-							G_TYPE_INVALID)) {
-		g_warning ("Error in device_get_property: %s\n", err->message);
-		g_error_free (err);
-		ret = FALSE;
-	}
-
-	g_object_unref (properties_proxy);
-
-	return ret;
-}
-
-void
-_nm_dbus_set_property (DBusGProxy *proxy,
-					  const char *interface,
-					  const char *prop_name,
-					  GValue *value)
-{
-	DBusGProxy *properties_proxy;
-
-	g_return_if_fail (proxy != NULL);
-	g_return_if_fail (interface != NULL);
-	g_return_if_fail (prop_name != NULL);
-
-	properties_proxy = dbus_g_proxy_new_from_proxy (proxy,
-													"org.freedesktop.DBus.Properties",
-													dbus_g_proxy_get_path (proxy));
-
-	dbus_g_proxy_call_no_reply (properties_proxy, "Set",
-								G_TYPE_STRING, interface,
-								G_TYPE_STRING, prop_name,
-								G_TYPE_VALUE, value,
-								G_TYPE_INVALID);
-
-	g_object_unref (properties_proxy);
-}
-
-char *
-_nm_dbus_introspect (DBusGConnection *connection,
-					const char *interface,
-					const char *path)
-{
-	DBusGProxy *remote_object_introspectable;
-	char *introspect_data = NULL;
-	GError *err = NULL;
-
-	g_return_val_if_fail (connection != NULL, NULL);
-	g_return_val_if_fail (interface != NULL, NULL);
-	g_return_val_if_fail (path != NULL, NULL);
-
-	remote_object_introspectable = dbus_g_proxy_new_for_name (connection,
-															  interface,
-															  path,
-															  "org.freedesktop.DBus.Introspectable");
-	if (!dbus_g_proxy_call (remote_object_introspectable, "Introspect", &err,
-							G_TYPE_INVALID,
-							G_TYPE_STRING, &introspect_data, G_TYPE_INVALID)) {
-		g_error ("Failed to complete Introspect %s", err->message);
-		g_error_free (err);
-	}
-
-	g_object_unref (G_OBJECT (remote_object_introspectable));
-
-	return introspect_data;
-}
diff --git a/libnm-glib/nm-dbus-utils.h b/libnm-glib/nm-dbus-utils.h
deleted file mode 100644
index 4002c3a0..00000000
--- a/libnm-glib/nm-dbus-utils.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/* -*- 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) 2007 - 2008 Novell, Inc.
- */
-
-#ifndef NM_UTILS_H
-#define NM_UTILS_H
-
-#include <dbus/dbus-glib.h>
-
-char *_nm_dbus_get_string_property (DBusGProxy *proxy,
-								   const char *interface,
-								   const char *prop_name);
-
-char *_nm_dbus_get_object_path_property (DBusGProxy *proxy,
-										const char *interface,
-										const char *prop_name);
-
-gint32 _nm_dbus_get_int_property (DBusGProxy *proxy,
-								 const char *interface,
-								 const char *prop_name);
-
-guint32 _nm_dbus_get_uint_property (DBusGProxy *proxy,
-								   const char *interface,
-								   const char *prop_name);
-
-gboolean  _nm_dbus_get_property (DBusGProxy *proxy,
-								const char *interface,
-								const char *prop_name,
-								GValue *value);
-void      _nm_dbus_set_property (DBusGProxy *proxy,
-								const char *interface,
-								const char *prop_name,
-								GValue *value);
-
-char     *_nm_dbus_introspect   (DBusGConnection *connection,
-								const char *interface,
-								const char *path);
-
-#endif /* NM_UTILS_H */
diff --git a/libnm-glib/nm-device-bond.c b/libnm-glib/nm-device-bond.c
new file mode 100644
index 00000000..034b7b3c
--- /dev/null
+++ b/libnm-glib/nm-device-bond.c
@@ -0,0 +1,300 @@
+/* -*- 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) 2012 Red Hat, Inc.
+ */
+
+#include <config.h>
+#include <string.h>
+#include <netinet/ether.h>
+
+#include <nm-setting-connection.h>
+#include <nm-setting-bond.h>
+#include <nm-utils.h>
+
+#include "nm-device-bond.h"
+#include "nm-device-private.h"
+#include "nm-object-private.h"
+
+G_DEFINE_TYPE (NMDeviceBond, nm_device_bond, NM_TYPE_DEVICE)
+
+#define NM_DEVICE_BOND_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_BOND, NMDeviceBondPrivate))
+
+typedef struct {
+	DBusGProxy *proxy;
+
+	char *hw_address;
+	gboolean carrier;
+} NMDeviceBondPrivate;
+
+enum {
+	PROP_0,
+	PROP_HW_ADDRESS,
+	PROP_CARRIER,
+
+	LAST_PROP
+};
+
+#define DBUS_PROP_HW_ADDRESS "HwAddress"
+#define DBUS_PROP_CARRIER "Carrier"
+
+/**
+ * nm_device_bond_error_quark:
+ *
+ * Registers an error quark for #NMDeviceBond if necessary.
+ *
+ * Returns: the error quark used for #NMDeviceBond errors.
+ **/
+GQuark
+nm_device_bond_error_quark (void)
+{
+	static GQuark quark = 0;
+
+	if (G_UNLIKELY (quark == 0))
+		quark = g_quark_from_static_string ("nm-device-bond-error-quark");
+	return quark;
+}
+
+/**
+ * nm_device_bond_new:
+ * @connection: the #DBusGConnection
+ * @path: the DBus object path of the device
+ *
+ * Creates a new #NMDeviceBond.
+ *
+ * Returns: (transfer full): a new device
+ **/
+GObject *
+nm_device_bond_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_BOND,
+			       NM_OBJECT_DBUS_CONNECTION, connection,
+			       NM_OBJECT_DBUS_PATH, path,
+			       NULL);
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return device;
+}
+
+/**
+ * nm_device_bond_get_hw_address:
+ * @device: a #NMDeviceBond
+ *
+ * Gets the hardware (MAC) address of the #NMDeviceBond
+ *
+ * Returns: the hardware address. This is the internal string used by the
+ * device, and must not be modified.
+ **/
+const char *
+nm_device_bond_get_hw_address (NMDeviceBond *device)
+{
+	g_return_val_if_fail (NM_IS_DEVICE_BOND (device), NULL);
+
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return NM_DEVICE_BOND_GET_PRIVATE (device)->hw_address;
+}
+
+/**
+ * nm_device_bond_get_carrier:
+ * @device: a #NMDeviceBond
+ *
+ * Whether the device has carrier.
+ *
+ * Returns: %TRUE if the device has carrier
+ **/
+gboolean
+nm_device_bond_get_carrier (NMDeviceBond *device)
+{
+	g_return_val_if_fail (NM_IS_DEVICE_BOND (device), FALSE);
+
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return NM_DEVICE_BOND_GET_PRIVATE (device)->carrier;
+}
+
+static gboolean
+connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
+{
+	NMSettingConnection *s_con;
+	NMSettingBond *s_bond;
+	const char *ctype, *dev_iface_name, *bond_iface_name;
+
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+	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_BOND_SETTING_NAME) != 0) {
+		g_set_error (error, NM_DEVICE_BOND_ERROR, NM_DEVICE_BOND_ERROR_NOT_BOND_CONNECTION,
+		             "The connection was not a bond connection.");
+		return FALSE;
+	}
+
+	s_bond = nm_connection_get_setting_bond (connection);
+	if (!s_bond) {
+		g_set_error (error, NM_DEVICE_BOND_ERROR, NM_DEVICE_BOND_ERROR_INVALID_BOND_CONNECTION,
+		             "The connection was not a valid bond connection.");
+		return FALSE;
+	}
+
+	dev_iface_name = nm_device_get_iface (device);
+	bond_iface_name = nm_setting_bond_get_interface_name (s_bond);
+	if (g_strcmp0 (dev_iface_name, bond_iface_name) != 0) {
+		g_set_error (error, NM_DEVICE_BOND_ERROR, NM_DEVICE_BOND_ERROR_INTERFACE_MISMATCH,
+		             "The interfaces of the device and the connection didn't match.");
+		return FALSE;
+	}
+
+	/* FIXME: check slaves? But we can't... */
+
+	return TRUE;
+}
+
+/***********************************************************/
+
+static void
+nm_device_bond_init (NMDeviceBond *device)
+{
+	_nm_device_set_device_type (NM_DEVICE (device), NM_DEVICE_TYPE_BOND);
+}
+
+static void
+register_properties (NMDeviceBond *device)
+{
+	NMDeviceBondPrivate *priv = NM_DEVICE_BOND_GET_PRIVATE (device);
+	const NMPropertiesInfo property_info[] = {
+		{ NM_DEVICE_BOND_HW_ADDRESS, &priv->hw_address },
+		{ NM_DEVICE_BOND_CARRIER,    &priv->carrier },
+		{ NULL },
+	};
+
+	_nm_object_register_properties (NM_OBJECT (device),
+	                                priv->proxy,
+	                                property_info);
+}
+
+static void
+constructed (GObject *object)
+{
+	NMDeviceBondPrivate *priv;
+
+	G_OBJECT_CLASS (nm_device_bond_parent_class)->constructed (object);
+
+	priv = NM_DEVICE_BOND_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_BOND);
+
+	register_properties (NM_DEVICE_BOND (object));
+}
+
+static void
+dispose (GObject *object)
+{
+	NMDeviceBondPrivate *priv = NM_DEVICE_BOND_GET_PRIVATE (object);
+
+	if (priv->proxy) {
+		g_object_unref (priv->proxy);
+		priv->proxy = NULL;
+	}
+
+	G_OBJECT_CLASS (nm_device_bond_parent_class)->dispose (object);
+}
+
+static void
+finalize (GObject *object)
+{
+	NMDeviceBondPrivate *priv = NM_DEVICE_BOND_GET_PRIVATE (object);
+
+	g_free (priv->hw_address);
+
+	G_OBJECT_CLASS (nm_device_bond_parent_class)->finalize (object);
+}
+
+static void
+get_property (GObject *object,
+              guint prop_id,
+              GValue *value,
+              GParamSpec *pspec)
+{
+	NMDeviceBond *device = NM_DEVICE_BOND (object);
+
+	switch (prop_id) {
+	case PROP_HW_ADDRESS:
+		g_value_set_string (value, nm_device_bond_get_hw_address (device));
+		break;
+	case PROP_CARRIER:
+		g_value_set_boolean (value, nm_device_bond_get_carrier (device));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+nm_device_bond_class_init (NMDeviceBondClass *eth_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (eth_class);
+	NMDeviceClass *device_class = NM_DEVICE_CLASS (eth_class);
+
+	g_type_class_add_private (eth_class, sizeof (NMDeviceBondPrivate));
+
+	/* 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 */
+
+	/**
+	 * NMDeviceBond:hw-address:
+	 *
+	 * The hardware (MAC) address of the device.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_HW_ADDRESS,
+		 g_param_spec_string (NM_DEVICE_BOND_HW_ADDRESS,
+		                      "Active MAC Address",
+		                      "Currently set hardware MAC address",
+		                      NULL,
+		                      G_PARAM_READABLE));
+
+	/**
+	 * NMDeviceBond:carrier:
+	 *
+	 * Whether the device has carrier.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_CARRIER,
+		 g_param_spec_boolean (NM_DEVICE_BOND_CARRIER,
+		                       "Carrier",
+		                       "Carrier",
+		                       FALSE,
+		                       G_PARAM_READABLE));
+
+}
diff --git a/libnm-glib/nm-device-bond.h b/libnm-glib/nm-device-bond.h
new file mode 100644
index 00000000..db4a90fc
--- /dev/null
+++ b/libnm-glib/nm-device-bond.h
@@ -0,0 +1,82 @@
+/* -*- 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) 2012 Red Hat, Inc.
+ */
+
+#ifndef NM_DEVICE_BOND_H
+#define NM_DEVICE_BOND_H
+
+#include "nm-device.h"
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_DEVICE_BOND            (nm_device_bond_get_type ())
+#define NM_DEVICE_BOND(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_BOND, NMDeviceBond))
+#define NM_DEVICE_BOND_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_BOND, NMDeviceBondClass))
+#define NM_IS_DEVICE_BOND(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_BOND))
+#define NM_IS_DEVICE_BOND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_DEVICE_BOND))
+#define NM_DEVICE_BOND_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_BOND, NMDeviceBondClass))
+
+/**
+ * NMDeviceBondError:
+ * @NM_DEVICE_BOND_ERROR_UNKNOWN: unknown or unclassified error
+ * @NM_DEVICE_BOND_ERROR_NOT_BOND_CONNECTION: the connection was not of bond type
+ * @NM_DEVICE_BOND_ERROR_INVALID_BOND_CONNECTION: the bond connection was invalid
+ * @NM_DEVICE_BOND_ERROR_INTERFACE_MISMATCH: the interfaces of the connection and the device mismatched
+ */
+typedef enum {
+	NM_DEVICE_BOND_ERROR_UNKNOWN = 0,             /*< nick=UnknownError >*/
+	NM_DEVICE_BOND_ERROR_NOT_BOND_CONNECTION,     /*< nick=NotBondConnection >*/
+	NM_DEVICE_BOND_ERROR_INVALID_BOND_CONNECTION, /*< nick=InvalidBondConnection >*/
+	NM_DEVICE_BOND_ERROR_INTERFACE_MISMATCH,      /*< nick=InterfaceMismatch >*/
+} NMDeviceBondError;
+
+#define NM_DEVICE_BOND_ERROR nm_device_bond_error_quark ()
+GQuark nm_device_bond_error_quark (void);
+
+#define NM_DEVICE_BOND_HW_ADDRESS  "hw-address"
+#define NM_DEVICE_BOND_CARRIER     "carrier"
+
+typedef struct {
+	NMDevice parent;
+} NMDeviceBond;
+
+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);
+} NMDeviceBondClass;
+
+GType nm_device_bond_get_type (void);
+
+GObject *nm_device_bond_new (DBusGConnection *connection, const char *path);
+
+const char * nm_device_bond_get_hw_address (NMDeviceBond *device);
+gboolean     nm_device_bond_get_carrier (NMDeviceBond *device);
+
+G_END_DECLS
+
+#endif /* NM_DEVICE_BOND_H */
diff --git a/libnm-glib/nm-device-bt.c b/libnm-glib/nm-device-bt.c
index dc60d258..8e0ff200 100644
--- a/libnm-glib/nm-device-bt.c
+++ b/libnm-glib/nm-device-bt.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 <config.h>
@@ -32,8 +32,6 @@
 #include "nm-device-private.h"
 #include "nm-object-private.h"
 
-#include "nm-device-bt-bindings.h"
-
 G_DEFINE_TYPE (NMDeviceBt, nm_device_bt, NM_TYPE_DEVICE)
 
 #define NM_DEVICE_BT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_BT, NMDeviceBtPrivate))
@@ -44,7 +42,6 @@ typedef struct {
 	char *hw_address;
 	char *name;
 	guint32 bt_capabilities;
-	gboolean bt_capabilities_valid;
 
 	gboolean disposed;
 } NMDeviceBtPrivate;
@@ -63,6 +60,23 @@ enum {
 #define DBUS_PROP_BT_CAPABILITIES "BtCapabilities"
 
 /**
+ * nm_device_bt_error_quark:
+ *
+ * Registers an error quark for #NMDeviceBt if necessary.
+ *
+ * Returns: the error quark used for #NMDeviceBt errors.
+ **/
+GQuark
+nm_device_bt_error_quark (void)
+{
+	static GQuark quark = 0;
+
+	if (G_UNLIKELY (quark == 0))
+		quark = g_quark_from_static_string ("nm-device-bt-error-quark");
+	return quark;
+}
+
+/**
  * nm_device_bt_new:
  * @connection: the #DBusGConnection
  * @path: the DBus object path of the device
@@ -95,19 +109,10 @@ nm_device_bt_new (DBusGConnection *connection, const char *path)
 const char *
 nm_device_bt_get_hw_address (NMDeviceBt *device)
 {
-	NMDeviceBtPrivate *priv;
-
 	g_return_val_if_fail (NM_IS_DEVICE_BT (device), NULL);
 
-	priv = NM_DEVICE_BT_GET_PRIVATE (device);
-	if (!priv->hw_address) {
-		priv->hw_address = _nm_object_get_string_property (NM_OBJECT (device),
-		                                                   NM_DBUS_INTERFACE_DEVICE_BLUETOOTH,
-		                                                   DBUS_PROP_HW_ADDRESS,
-		                                                   NULL);
-	}
-
-	return priv->hw_address;
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return NM_DEVICE_BT_GET_PRIVATE (device)->hw_address;
 }
 
 /**
@@ -121,19 +126,10 @@ nm_device_bt_get_hw_address (NMDeviceBt *device)
 const char *
 nm_device_bt_get_name (NMDeviceBt *device)
 {
-	NMDeviceBtPrivate *priv;
-
 	g_return_val_if_fail (NM_IS_DEVICE_BT (device), NULL);
 
-	priv = NM_DEVICE_BT_GET_PRIVATE (device);
-	if (!priv->name) {
-		priv->name = _nm_object_get_string_property (NM_OBJECT (device),
-		                                             NM_DBUS_INTERFACE_DEVICE_BLUETOOTH,
-		                                             DBUS_PROP_NAME,
-		                                             NULL);
-	}
-
-	return priv->name;
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return NM_DEVICE_BT_GET_PRIVATE (device)->name;
 }
 
 /**
@@ -147,20 +143,10 @@ nm_device_bt_get_name (NMDeviceBt *device)
 NMBluetoothCapabilities
 nm_device_bt_get_capabilities (NMDeviceBt *device)
 {
-	NMDeviceBtPrivate *priv;
-
 	g_return_val_if_fail (NM_IS_DEVICE_BT (device), NM_BT_CAPABILITY_NONE);
 
-	priv = NM_DEVICE_BT_GET_PRIVATE (device);
-	if (!priv->bt_capabilities_valid) {
-		priv->bt_capabilities = _nm_object_get_uint_property (NM_OBJECT (device),
-		                                                      NM_DBUS_INTERFACE_DEVICE_BLUETOOTH,
-		                                                      DBUS_PROP_BT_CAPABILITIES,
-		                                                      NULL);
-		priv->bt_capabilities_valid = TRUE;
-	}
-
-	return priv->bt_capabilities;
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return NM_DEVICE_BT_GET_PRIVATE (device)->bt_capabilities;
 }
 
 static NMBluetoothCapabilities
@@ -169,7 +155,7 @@ get_connection_bt_type (NMConnection *connection)
 	NMSettingBluetooth *s_bt;
 	const char *bt_type;
 
-	s_bt = (NMSettingBluetooth *) nm_connection_get_setting (connection, NM_TYPE_SETTING_BLUETOOTH);
+	s_bt = nm_connection_get_setting_bluetooth (connection);
 	if (!s_bt)
 		return NM_BT_CAPABILITY_NONE;
 
@@ -185,7 +171,7 @@ get_connection_bt_type (NMConnection *connection)
 }
 
 static gboolean
-connection_valid (NMDevice *device, NMConnection *connection)
+connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
 {
 	NMSettingConnection *s_con;
 	NMSettingBluetooth *s_bt;
@@ -196,30 +182,49 @@ connection_valid (NMDevice *device, NMConnection *connection)
 	NMBluetoothCapabilities dev_caps;
 	NMBluetoothCapabilities bt_type;
 
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
 	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_BLUETOOTH_SETTING_NAME) != 0)
+	if (strcmp (ctype, NM_SETTING_BLUETOOTH_SETTING_NAME) != 0) {
+		g_set_error (error, NM_DEVICE_BT_ERROR, NM_DEVICE_BT_ERROR_NOT_BT_CONNECTION,
+		             "The connection was not a Bluetooth connection.");
 		return FALSE;
+	}
 
 	s_bt = nm_connection_get_setting_bluetooth (connection);
-	if (!s_bt)
+	if (!s_bt) {
+		g_set_error (error, NM_DEVICE_BT_ERROR, NM_DEVICE_BT_ERROR_INVALID_BT_CONNECTION,
+		             "The connection was not a valid Bluetooth connection.");
 		return FALSE;
+	}
 
 	/* Check BT address */
 	hw_str = nm_device_bt_get_hw_address (NM_DEVICE_BT (device));
 	if (hw_str) {
 		hw_mac = ether_aton (hw_str);
+		if (!hw_mac) {
+			g_set_error (error, NM_DEVICE_BT_ERROR, NM_DEVICE_BT_ERROR_INVALID_DEVICE_MAC,
+			             "Invalid device MAC address.");
+			return FALSE;
+		}
 		mac = nm_setting_bluetooth_get_bdaddr (s_bt);
-		if (mac && hw_mac && memcmp (mac->data, hw_mac->ether_addr_octet, ETH_ALEN))
+		if (mac && hw_mac && memcmp (mac->data, hw_mac->ether_addr_octet, ETH_ALEN)) {
+			g_set_error (error, NM_DEVICE_BT_ERROR, NM_DEVICE_BT_ERROR_MAC_MISMATCH,
+			             "The MACs of the device and the connection didn't match.");
 			return FALSE;
+		}
 	}
 
 	dev_caps = nm_device_bt_get_capabilities (NM_DEVICE_BT (device));
 	bt_type = get_connection_bt_type (connection);
-	if (!(bt_type & dev_caps))
+	if (!(bt_type & dev_caps)) {
+		g_set_error (error, NM_DEVICE_BT_ERROR, NM_DEVICE_BT_ERROR_MISSING_DEVICE_CAPS,
+		             "The device missed BT capabilities required by the connection.");
 		return FALSE;
+	}
 
 	return TRUE;
 }
@@ -229,46 +234,38 @@ connection_valid (NMDevice *device, NMConnection *connection)
 static void
 nm_device_bt_init (NMDeviceBt *device)
 {
+	_nm_device_set_device_type (NM_DEVICE (device), NM_DEVICE_TYPE_BT);
 }
 
 static void
-register_for_property_changed (NMDeviceBt *device)
+register_properties (NMDeviceBt *device)
 {
 	NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device);
-	const NMPropertiesChangedInfo property_changed_info[] = {
-		{ NM_DEVICE_BT_HW_ADDRESS,   _nm_object_demarshal_generic, &priv->hw_address },
-		{ NM_DEVICE_BT_NAME,         _nm_object_demarshal_generic, &priv->name },
-		{ NM_DEVICE_BT_CAPABILITIES, _nm_object_demarshal_generic, &priv->bt_capabilities },
+	const NMPropertiesInfo property_info[] = {
+		{ NM_DEVICE_BT_HW_ADDRESS,   &priv->hw_address },
+		{ NM_DEVICE_BT_NAME,         &priv->name },
+		{ NM_DEVICE_BT_CAPABILITIES, &priv->bt_capabilities },
 		{ NULL },
 	};
 
-	_nm_object_handle_properties_changed (NM_OBJECT (device),
-	                                     priv->proxy,
-	                                     property_changed_info);
+	_nm_object_register_properties (NM_OBJECT (device),
+	                                priv->proxy,
+	                                property_info);
 }
 
-static GObject*
-constructor (GType type,
-			 guint n_construct_params,
-			 GObjectConstructParam *construct_params)
+static void
+constructed (GObject *object)
 {
-	GObject *object;
-
-	object = G_OBJECT_CLASS (nm_device_bt_parent_class)->constructor (type,
-	                                                                  n_construct_params,
-	                                                                  construct_params);
-	if (object) {
-			NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (object);
+	NMDeviceBtPrivate *priv = NM_DEVICE_BT_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_BLUETOOTH);
+	G_OBJECT_CLASS (nm_device_bt_parent_class)->constructed (object);
 
-		register_for_property_changed (NM_DEVICE_BT (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_BLUETOOTH);
 
-	return object;
+	register_properties (NM_DEVICE_BT (object));
 }
 
 static void
@@ -331,11 +328,11 @@ nm_device_bt_class_init (NMDeviceBtClass *bt_class)
 	g_type_class_add_private (bt_class, sizeof (NMDeviceBtPrivate));
 
 	/* virtual methods */
-	object_class->constructor = constructor;
+	object_class->constructed = constructed;
 	object_class->dispose = dispose;
 	object_class->finalize = finalize;
 	object_class->get_property = get_property;
-	device_class->connection_valid = connection_valid;
+	device_class->connection_compatible = connection_compatible;
 
 	/* properties */
 
diff --git a/libnm-glib/nm-device-bt.h b/libnm-glib/nm-device-bt.h
index 71817f84..8f9a78a7 100644
--- a/libnm-glib/nm-device-bt.h
+++ b/libnm-glib/nm-device-bt.h
@@ -17,7 +17,7 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * Copyright (C) 2008 - 2009 Red Hat, Inc.
+ * Copyright (C) 2008 - 2012 Red Hat, Inc.
  * Copyright (C) 2008 Novell, Inc.
  */
 
@@ -36,6 +36,27 @@ G_BEGIN_DECLS
 #define NM_IS_DEVICE_BT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_DEVICE_BT))
 #define NM_DEVICE_BT_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_BT, NMDeviceBtClass))
 
+/**
+ * NMDeviceBtError:
+ * @NM_DEVICE_BT_ERROR_UNKNOWN: unknown or unclassified error
+ * @NM_DEVICE_BT_ERROR_NOT_BT_CONNECTION: the connection was not of bluetooth type
+ * @NM_DEVICE_BT_ERROR_INVALID_BT_CONNECTION: the bluetooth connection was invalid
+ * @NM_DEVICE_BT_ERROR_INVALID_DEVICE_MAC: the device's MAC was invalid
+ * @NM_DEVICE_BT_ERROR_MAC_MISMATCH: the MACs of the connection and the device mismatched
+ * @NM_DEVICE_BT_ERROR_MISSING_DEVICE_CAPS: the device missed required capabilities
+ */
+typedef enum {
+	NM_DEVICE_BT_ERROR_UNKNOWN = 0,           /*< nick=UnknownError >*/
+	NM_DEVICE_BT_ERROR_NOT_BT_CONNECTION,     /*< nick=NotBtConnection >*/
+	NM_DEVICE_BT_ERROR_INVALID_BT_CONNECTION, /*< nick=InvalidBtConnection >*/
+	NM_DEVICE_BT_ERROR_INVALID_DEVICE_MAC,    /*< nick=InvalidDeviceMac >*/
+	NM_DEVICE_BT_ERROR_MAC_MISMATCH,          /*< nick=MacMismatch >*/
+	NM_DEVICE_BT_ERROR_MISSING_DEVICE_CAPS,   /*< nick=MissingDeviceCaps >*/
+} NMDeviceBtError;
+
+#define NM_DEVICE_BT_ERROR nm_device_bt_error_quark ()
+GQuark nm_device_bt_error_quark (void);
+
 #define NM_DEVICE_BT_HW_ADDRESS   "hw-address"
 #define NM_DEVICE_BT_NAME         "name"
 #define NM_DEVICE_BT_CAPABILITIES "bt-capabilities"
diff --git a/libnm-glib/nm-device-ethernet.c b/libnm-glib/nm-device-ethernet.c
index 58013213..62aedbbf 100644
--- a/libnm-glib/nm-device-ethernet.c
+++ b/libnm-glib/nm-device-ethernet.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 <config.h>
@@ -33,8 +33,6 @@
 #include "nm-device-private.h"
 #include "nm-object-private.h"
 
-#include "nm-device-ethernet-bindings.h"
-
 G_DEFINE_TYPE (NMDeviceEthernet, nm_device_ethernet, NM_TYPE_DEVICE)
 
 #define NM_DEVICE_ETHERNET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_ETHERNET, NMDeviceEthernetPrivate))
@@ -46,7 +44,6 @@ typedef struct {
 	char *perm_hw_address;
 	guint32 speed;
 	gboolean carrier;
-	gboolean carrier_valid;
 
 	gboolean disposed;
 } NMDeviceEthernetPrivate;
@@ -67,6 +64,23 @@ enum {
 #define DBUS_PROP_CARRIER "Carrier"
 
 /**
+ * nm_device_ethernet_error_quark:
+ *
+ * Registers an error quark for #NMDeviceEthernet if necessary.
+ *
+ * Returns: the error quark used for #NMDeviceEthernet errors.
+ **/
+GQuark
+nm_device_ethernet_error_quark (void)
+{
+	static GQuark quark = 0;
+
+	if (G_UNLIKELY (quark == 0))
+		quark = g_quark_from_static_string ("nm-device-ethernet-error-quark");
+	return quark;
+}
+
+/**
  * nm_device_ethernet_new:
  * @connection: the #DBusGConnection
  * @path: the DBus object path of the device
@@ -78,13 +92,17 @@ enum {
 GObject *
 nm_device_ethernet_new (DBusGConnection *connection, const char *path)
 {
+	GObject *device;
+
 	g_return_val_if_fail (connection != NULL, NULL);
 	g_return_val_if_fail (path != NULL, NULL);
 
-	return g_object_new (NM_TYPE_DEVICE_ETHERNET,
-	                     NM_OBJECT_DBUS_CONNECTION, connection,
-	                     NM_OBJECT_DBUS_PATH, path,
-	                     NULL);
+	device = g_object_new (NM_TYPE_DEVICE_ETHERNET,
+						   NM_OBJECT_DBUS_CONNECTION, connection,
+						   NM_OBJECT_DBUS_PATH, path,
+						   NULL);
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return device;
 }
 
 /**
@@ -99,19 +117,10 @@ nm_device_ethernet_new (DBusGConnection *connection, const char *path)
 const char *
 nm_device_ethernet_get_hw_address (NMDeviceEthernet *device)
 {
-	NMDeviceEthernetPrivate *priv;
-
 	g_return_val_if_fail (NM_IS_DEVICE_ETHERNET (device), NULL);
 
-	priv = NM_DEVICE_ETHERNET_GET_PRIVATE (device);
-	if (!priv->hw_address) {
-		priv->hw_address = _nm_object_get_string_property (NM_OBJECT (device),
-		                                                  NM_DBUS_INTERFACE_DEVICE_WIRED,
-		                                                  DBUS_PROP_HW_ADDRESS,
-		                                                  NULL);
-	}
-
-	return priv->hw_address;
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return NM_DEVICE_ETHERNET_GET_PRIVATE (device)->hw_address;
 }
 
 /**
@@ -126,19 +135,10 @@ nm_device_ethernet_get_hw_address (NMDeviceEthernet *device)
 const char *
 nm_device_ethernet_get_permanent_hw_address (NMDeviceEthernet *device)
 {
-	NMDeviceEthernetPrivate *priv;
-
 	g_return_val_if_fail (NM_IS_DEVICE_ETHERNET (device), NULL);
 
-	priv = NM_DEVICE_ETHERNET_GET_PRIVATE (device);
-	if (!priv->perm_hw_address) {
-		priv->perm_hw_address = _nm_object_get_string_property (NM_OBJECT (device),
-		                                                        NM_DBUS_INTERFACE_DEVICE_WIRED,
-		                                                        DBUS_PROP_PERM_HW_ADDRESS,
-		                                                        NULL);
-	}
-
-	return priv->perm_hw_address;
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return NM_DEVICE_ETHERNET_GET_PRIVATE (device)->perm_hw_address;
 }
 
 /**
@@ -152,19 +152,10 @@ nm_device_ethernet_get_permanent_hw_address (NMDeviceEthernet *device)
 guint32
 nm_device_ethernet_get_speed (NMDeviceEthernet *device)
 {
-	NMDeviceEthernetPrivate *priv;
-
 	g_return_val_if_fail (NM_IS_DEVICE_ETHERNET (device), 0);
 
-	priv = NM_DEVICE_ETHERNET_GET_PRIVATE (device);
-	if (!priv->speed) {
-		priv->speed = _nm_object_get_uint_property (NM_OBJECT (device),
-		                                           NM_DBUS_INTERFACE_DEVICE_WIRED,
-		                                           DBUS_PROP_SPEED,
-		                                           NULL);
-	}
-
-	return priv->speed;
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return NM_DEVICE_ETHERNET_GET_PRIVATE (device)->speed;
 }
 
 /**
@@ -178,43 +169,41 @@ nm_device_ethernet_get_speed (NMDeviceEthernet *device)
 gboolean
 nm_device_ethernet_get_carrier (NMDeviceEthernet *device)
 {
-	NMDeviceEthernetPrivate *priv;
-
 	g_return_val_if_fail (NM_IS_DEVICE_ETHERNET (device), FALSE);
 
-	priv = NM_DEVICE_ETHERNET_GET_PRIVATE (device);
-	if (!priv->carrier_valid) {
-		priv->carrier = _nm_object_get_boolean_property (NM_OBJECT (device),
-		                                                NM_DBUS_INTERFACE_DEVICE_WIRED,
-		                                                DBUS_PROP_CARRIER,
-		                                                NULL);
-		priv->carrier_valid = TRUE;
-	}
-
-	return priv->carrier;
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return NM_DEVICE_ETHERNET_GET_PRIVATE (device)->carrier;
 }
 
 static gboolean
-connection_valid (NMDevice *device, NMConnection *connection)
+connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
 {
 	NMSettingConnection *s_con;
 	NMSettingWired *s_wired;
 	const char *ctype;
 	gboolean is_pppoe = FALSE;
 
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
 	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_PPPOE_SETTING_NAME))
 		is_pppoe = TRUE;
-	else if (strcmp (ctype, NM_SETTING_WIRED_SETTING_NAME) != 0)
+	else if (strcmp (ctype, NM_SETTING_WIRED_SETTING_NAME) != 0) {
+		g_set_error (error, NM_DEVICE_ETHERNET_ERROR, NM_DEVICE_ETHERNET_ERROR_NOT_ETHERNET_CONNECTION,
+		             "The connection was not a wired or PPPoE connection.");
 		return FALSE;
+	}
 
 	s_wired = nm_connection_get_setting_wired (connection);
 	/* Wired setting optional for PPPoE */
-	if (!is_pppoe && !s_wired)
+	if (!is_pppoe && !s_wired) {
+		g_set_error (error, NM_DEVICE_ETHERNET_ERROR, NM_DEVICE_ETHERNET_ERROR_INVALID_ETHERNET_CONNECTION,
+		             "The connection was not a valid ethernet connection.");
 		return FALSE;
+	}
 
 	if (s_wired) {
 		const GByteArray *mac;
@@ -227,9 +216,17 @@ connection_valid (NMDevice *device, NMConnection *connection)
 		perm_str = nm_device_ethernet_get_permanent_hw_address (NM_DEVICE_ETHERNET (device));
 		if (perm_str) {
 			perm_mac = ether_aton (perm_str);
+			if (!perm_mac) {
+				g_set_error (error, NM_DEVICE_ETHERNET_ERROR, NM_DEVICE_ETHERNET_ERROR_INVALID_DEVICE_MAC,
+				             "Invalid device MAC address.");
+				return FALSE;
+			}
 			mac = nm_setting_wired_get_mac_address (s_wired);
-			if (mac && perm_mac && memcmp (mac->data, perm_mac->ether_addr_octet, ETH_ALEN))
+			if (mac && perm_mac && memcmp (mac->data, perm_mac->ether_addr_octet, ETH_ALEN)) {
+				g_set_error (error, NM_DEVICE_ETHERNET_ERROR, NM_DEVICE_ETHERNET_ERROR_MAC_MISMATCH,
+				             "The MACs of the device and the connection didn't match.");
 				return FALSE;
+			}
 		}
 	}
 
@@ -241,43 +238,32 @@ connection_valid (NMDevice *device, NMConnection *connection)
 static void
 nm_device_ethernet_init (NMDeviceEthernet *device)
 {
-	NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (device);
-
-	priv->disposed = FALSE;
-	priv->carrier = FALSE;
-	priv->carrier_valid = FALSE;
+	_nm_device_set_device_type (NM_DEVICE (device), NM_DEVICE_TYPE_ETHERNET);
 }
 
 static void
-register_for_property_changed (NMDeviceEthernet *device)
+register_properties (NMDeviceEthernet *device)
 {
 	NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (device);
-	const NMPropertiesChangedInfo property_changed_info[] = {
-		{ NM_DEVICE_ETHERNET_HW_ADDRESS,           _nm_object_demarshal_generic, &priv->hw_address },
-		{ NM_DEVICE_ETHERNET_PERMANENT_HW_ADDRESS, _nm_object_demarshal_generic, &priv->perm_hw_address },
-		{ NM_DEVICE_ETHERNET_SPEED,                _nm_object_demarshal_generic, &priv->speed },
-		{ NM_DEVICE_ETHERNET_CARRIER,              _nm_object_demarshal_generic, &priv->carrier },
+	const NMPropertiesInfo property_info[] = {
+		{ NM_DEVICE_ETHERNET_HW_ADDRESS,           &priv->hw_address },
+		{ NM_DEVICE_ETHERNET_PERMANENT_HW_ADDRESS, &priv->perm_hw_address },
+		{ NM_DEVICE_ETHERNET_SPEED,                &priv->speed },
+		{ NM_DEVICE_ETHERNET_CARRIER,              &priv->carrier },
 		{ NULL },
 	};
 
-	_nm_object_handle_properties_changed (NM_OBJECT (device),
-	                                     priv->proxy,
-	                                     property_changed_info);
+	_nm_object_register_properties (NM_OBJECT (device),
+	                                priv->proxy,
+	                                property_info);
 }
 
-static GObject*
-constructor (GType type,
-			 guint n_construct_params,
-			 GObjectConstructParam *construct_params)
+static void
+constructed (GObject *object)
 {
-	GObject *object;
 	NMDeviceEthernetPrivate *priv;
 
-	object = G_OBJECT_CLASS (nm_device_ethernet_parent_class)->constructor (type,
-																				  n_construct_params,
-																				  construct_params);
-	if (!object)
-		return NULL;
+	G_OBJECT_CLASS (nm_device_ethernet_parent_class)->constructed (object);
 
 	priv = NM_DEVICE_ETHERNET_GET_PRIVATE (object);
 
@@ -286,9 +272,7 @@ constructor (GType type,
 	                                         nm_object_get_path (NM_OBJECT (object)),
 	                                         NM_DBUS_INTERFACE_DEVICE_WIRED);
 
-	register_for_property_changed (NM_DEVICE_ETHERNET (object));
-
-	return object;
+	register_properties (NM_DEVICE_ETHERNET (object));
 }
 
 static void
@@ -355,11 +339,11 @@ nm_device_ethernet_class_init (NMDeviceEthernetClass *eth_class)
 	g_type_class_add_private (eth_class, sizeof (NMDeviceEthernetPrivate));
 
 	/* virtual methods */
-	object_class->constructor = constructor;
+	object_class->constructed = constructed;
 	object_class->dispose = dispose;
 	object_class->finalize = finalize;
 	object_class->get_property = get_property;
-	device_class->connection_valid = connection_valid;
+	device_class->connection_compatible = connection_compatible;
 
 	/* properties */
 
diff --git a/libnm-glib/nm-device-ethernet.h b/libnm-glib/nm-device-ethernet.h
index 305ca022..f14cd045 100644
--- a/libnm-glib/nm-device-ethernet.h
+++ b/libnm-glib/nm-device-ethernet.h
@@ -18,7 +18,7 @@
  * Boston, MA 02110-1301 USA.
  *
  * Copyright (C) 2007 - 2008 Novell, Inc.
- * Copyright (C) 2007 - 2010 Red Hat, Inc.
+ * Copyright (C) 2007 - 2012 Red Hat, Inc.
  */
 
 #ifndef NM_DEVICE_ETHERNET_H
@@ -35,6 +35,25 @@ G_BEGIN_DECLS
 #define NM_IS_DEVICE_ETHERNET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_DEVICE_ETHERNET))
 #define NM_DEVICE_ETHERNET_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_ETHERNET, NMDeviceEthernetClass))
 
+/**
+ * NMDeviceEthernetError:
+ * @NM_DEVICE_ETHERNET_ERROR_UNKNOWN: unknown or unclassified error
+ * @NM_DEVICE_ETHERNET_ERROR_NOT_ETHERNET_CONNECTION: the connection was not of ethernet or PPPoE type
+ * @NM_DEVICE_ETHERNET_ERROR_INVALID_ETHERNET_CONNECTION: the ethernet connection was invalid
+ * @NM_DEVICE_ETHERNET_ERROR_INVALID_DEVICE_MAC: the device's MAC was invalid
+ * @NM_DEVICE_ETHERNET_ERROR_MAC_MISMATCH: the MACs of the connection and the device mismatched
+ */
+typedef enum {
+	NM_DEVICE_ETHERNET_ERROR_UNKNOWN = 0,                 /*< nick=UnknownError >*/
+	NM_DEVICE_ETHERNET_ERROR_NOT_ETHERNET_CONNECTION,     /*< nick=NotEthernetConnection >*/
+	NM_DEVICE_ETHERNET_ERROR_INVALID_ETHERNET_CONNECTION, /*< nick=InvalidEthernetConnection >*/
+	NM_DEVICE_ETHERNET_ERROR_INVALID_DEVICE_MAC,          /*< nick=InvalidDeviceMac >*/
+	NM_DEVICE_ETHERNET_ERROR_MAC_MISMATCH,                /*< nick=MacMismatch >*/
+} NMDeviceEthernetError;
+
+#define NM_DEVICE_ETHERNET_ERROR nm_device_ethernet_error_quark ()
+GQuark nm_device_ethernet_error_quark (void);
+
 #define NM_DEVICE_ETHERNET_HW_ADDRESS  "hw-address"
 #define NM_DEVICE_ETHERNET_PERMANENT_HW_ADDRESS "perm-hw-address"
 #define NM_DEVICE_ETHERNET_SPEED       "speed"
diff --git a/libnm-glib/nm-device-infiniband.c b/libnm-glib/nm-device-infiniband.c
new file mode 100644
index 00000000..ec5f4a8b
--- /dev/null
+++ b/libnm-glib/nm-device-infiniband.c
@@ -0,0 +1,310 @@
+/* -*- 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 - 2012 Red Hat, Inc.
+ */
+
+#include <config.h>
+#include <string.h>
+#include <linux/if_infiniband.h>
+#include <netinet/ether.h>
+
+#include <nm-setting-connection.h>
+#include <nm-setting-infiniband.h>
+#include <nm-utils.h>
+
+#include "nm-device-infiniband.h"
+#include "nm-device-private.h"
+#include "nm-object-private.h"
+
+G_DEFINE_TYPE (NMDeviceInfiniband, nm_device_infiniband, NM_TYPE_DEVICE)
+
+#define NM_DEVICE_INFINIBAND_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_INFINIBAND, NMDeviceInfinibandPrivate))
+
+typedef struct {
+	DBusGProxy *proxy;
+
+	char *hw_address;
+	gboolean carrier;
+} NMDeviceInfinibandPrivate;
+
+enum {
+	PROP_0,
+	PROP_HW_ADDRESS,
+	PROP_CARRIER,
+
+	LAST_PROP
+};
+
+#define DBUS_PROP_HW_ADDRESS "HwAddress"
+#define DBUS_PROP_CARRIER "Carrier"
+
+/**
+ * nm_device_infiniband_error_quark:
+ *
+ * Registers an error quark for #NMDeviceInfiniband if necessary.
+ *
+ * Returns: the error quark used for #NMDeviceInfiniband errors.
+ **/
+GQuark
+nm_device_infiniband_error_quark (void)
+{
+	static GQuark quark = 0;
+
+	if (G_UNLIKELY (quark == 0))
+		quark = g_quark_from_static_string ("nm-device-infiniband-error-quark");
+	return quark;
+}
+
+/**
+ * nm_device_infiniband_new:
+ * @connection: the #DBusGConnection
+ * @path: the DBus object path of the device
+ *
+ * Creates a new #NMDeviceInfiniband.
+ *
+ * Returns: (transfer full): a new device
+ **/
+GObject *
+nm_device_infiniband_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_INFINIBAND,
+						   NM_OBJECT_DBUS_CONNECTION, connection,
+						   NM_OBJECT_DBUS_PATH, path,
+						   NULL);
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return device;
+}
+
+/**
+ * nm_device_infiniband_get_hw_address:
+ * @device: a #NMDeviceInfiniband
+ *
+ * Gets the hardware (MAC) address of the #NMDeviceInfiniband
+ *
+ * Returns: the hardware address. This is the internal string used by the
+ * device, and must not be modified.
+ **/
+const char *
+nm_device_infiniband_get_hw_address (NMDeviceInfiniband *device)
+{
+	g_return_val_if_fail (NM_IS_DEVICE_INFINIBAND (device), NULL);
+
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return NM_DEVICE_INFINIBAND_GET_PRIVATE (device)->hw_address;
+}
+
+/**
+ * nm_device_infiniband_get_carrier:
+ * @device: a #NMDeviceInfiniband
+ *
+ * Whether the device has carrier.
+ *
+ * Returns: %TRUE if the device has carrier
+ **/
+gboolean
+nm_device_infiniband_get_carrier (NMDeviceInfiniband *device)
+{
+	g_return_val_if_fail (NM_IS_DEVICE_INFINIBAND (device), FALSE);
+
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return NM_DEVICE_INFINIBAND_GET_PRIVATE (device)->carrier;
+}
+
+static gboolean
+connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
+{
+	NMSettingConnection *s_con;
+	NMSettingInfiniband *s_infiniband;
+	const char *ctype, *hwaddr_str;
+	const GByteArray *mac;
+	guint8 *hwaddr, hwaddr_buf[INFINIBAND_ALEN];
+
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+	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_INFINIBAND_SETTING_NAME) != 0) {
+		g_set_error (error, NM_DEVICE_INFINIBAND_ERROR, NM_DEVICE_INFINIBAND_ERROR_NOT_INFINIBAND_CONNECTION,
+		             "The connection was not a InfiniBand connection.");
+		return FALSE;
+	}
+
+	s_infiniband = nm_connection_get_setting_infiniband (connection);
+	if (!s_infiniband) {
+		g_set_error (error, NM_DEVICE_INFINIBAND_ERROR, NM_DEVICE_INFINIBAND_ERROR_INVALID_INFINIBAND_CONNECTION,
+		             "The connection was not a valid InfiniBand connection.");
+		return FALSE;
+	}
+
+	hwaddr_str = nm_device_infiniband_get_hw_address (NM_DEVICE_INFINIBAND (device));
+	if (hwaddr_str) {
+		hwaddr = nm_utils_hwaddr_aton (hwaddr_str, ARPHRD_INFINIBAND, hwaddr_buf);
+		if (!hwaddr) {
+			g_set_error (error, NM_DEVICE_INFINIBAND_ERROR, NM_DEVICE_INFINIBAND_ERROR_INVALID_DEVICE_MAC,
+			             "Invalid device MAC address.");
+			return FALSE;
+		}
+		mac = nm_setting_infiniband_get_mac_address (s_infiniband);
+		if (mac && hwaddr && memcmp (mac->data, hwaddr, INFINIBAND_ALEN)) {
+			g_set_error (error, NM_DEVICE_INFINIBAND_ERROR, NM_DEVICE_INFINIBAND_ERROR_MAC_MISMATCH,
+			             "The MACs of the device and the connection didn't match.");
+			return FALSE;
+		}
+	}
+
+	return TRUE;
+}
+
+/***********************************************************/
+
+static void
+nm_device_infiniband_init (NMDeviceInfiniband *device)
+{
+	_nm_device_set_device_type (NM_DEVICE (device), NM_DEVICE_TYPE_INFINIBAND);
+}
+
+static void
+register_properties (NMDeviceInfiniband *device)
+{
+	NMDeviceInfinibandPrivate *priv = NM_DEVICE_INFINIBAND_GET_PRIVATE (device);
+	const NMPropertiesInfo property_info[] = {
+		{ NM_DEVICE_INFINIBAND_HW_ADDRESS, &priv->hw_address },
+		{ NM_DEVICE_INFINIBAND_CARRIER,    &priv->carrier },
+		{ NULL },
+	};
+
+	_nm_object_register_properties (NM_OBJECT (device),
+	                                priv->proxy,
+	                                property_info);
+}
+
+static void
+constructed (GObject *object)
+{
+	NMDeviceInfinibandPrivate *priv;
+
+	G_OBJECT_CLASS (nm_device_infiniband_parent_class)->constructed (object);
+
+	priv = NM_DEVICE_INFINIBAND_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_INFINIBAND);
+
+	register_properties (NM_DEVICE_INFINIBAND (object));
+}
+
+static void
+dispose (GObject *object)
+{
+	NMDeviceInfinibandPrivate *priv = NM_DEVICE_INFINIBAND_GET_PRIVATE (object);
+
+	if (priv->proxy) {
+		g_object_unref (priv->proxy);
+		priv->proxy = NULL;
+	}
+
+	G_OBJECT_CLASS (nm_device_infiniband_parent_class)->dispose (object);
+}
+
+static void
+finalize (GObject *object)
+{
+	NMDeviceInfinibandPrivate *priv = NM_DEVICE_INFINIBAND_GET_PRIVATE (object);
+
+	g_free (priv->hw_address);
+
+	G_OBJECT_CLASS (nm_device_infiniband_parent_class)->finalize (object);
+}
+
+static void
+get_property (GObject *object,
+              guint prop_id,
+              GValue *value,
+              GParamSpec *pspec)
+{
+	NMDeviceInfiniband *device = NM_DEVICE_INFINIBAND (object);
+
+	switch (prop_id) {
+	case PROP_HW_ADDRESS:
+		g_value_set_string (value, nm_device_infiniband_get_hw_address (device));
+		break;
+	case PROP_CARRIER:
+		g_value_set_boolean (value, nm_device_infiniband_get_carrier (device));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+nm_device_infiniband_class_init (NMDeviceInfinibandClass *eth_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (eth_class);
+	NMDeviceClass *device_class = NM_DEVICE_CLASS (eth_class);
+
+	g_type_class_add_private (eth_class, sizeof (NMDeviceInfinibandPrivate));
+
+	/* 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 */
+
+	/**
+	 * NMDeviceInfiniband:hw-address:
+	 *
+	 * The hardware (MAC) address of the device.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_HW_ADDRESS,
+		 g_param_spec_string (NM_DEVICE_INFINIBAND_HW_ADDRESS,
+		                      "Active MAC Address",
+		                      "Currently set hardware MAC address",
+		                      NULL,
+		                      G_PARAM_READABLE));
+
+	/**
+	 * NMDeviceInfiniband:carrier:
+	 *
+	 * Whether the device has carrier.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_CARRIER,
+		 g_param_spec_boolean (NM_DEVICE_INFINIBAND_CARRIER,
+		                       "Carrier",
+		                       "Carrier",
+		                       FALSE,
+		                       G_PARAM_READABLE));
+
+}
+
diff --git a/libnm-glib/nm-device-infiniband.h b/libnm-glib/nm-device-infiniband.h
new file mode 100644
index 00000000..d0e754b3
--- /dev/null
+++ b/libnm-glib/nm-device-infiniband.h
@@ -0,0 +1,84 @@
+/* -*- 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 - 2012 Red Hat, Inc.
+ */
+
+#ifndef NM_DEVICE_INFINIBAND_H
+#define NM_DEVICE_INFINIBAND_H
+
+#include "nm-device.h"
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_DEVICE_INFINIBAND            (nm_device_infiniband_get_type ())
+#define NM_DEVICE_INFINIBAND(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_INFINIBAND, NMDeviceInfiniband))
+#define NM_DEVICE_INFINIBAND_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_INFINIBAND, NMDeviceInfinibandClass))
+#define NM_IS_DEVICE_INFINIBAND(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_INFINIBAND))
+#define NM_IS_DEVICE_INFINIBAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_DEVICE_INFINIBAND))
+#define NM_DEVICE_INFINIBAND_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_INFINIBAND, NMDeviceInfinibandClass))
+
+/**
+ * NMDeviceInfinibandError:
+ * @NM_DEVICE_INFINIBAND_ERROR_UNKNOWN: unknown or unclassified error
+ * @NM_DEVICE_INFINIBAND_ERROR_NOT_INFINIBAND_CONNECTION: the connection was not of InfiniBand type
+ * @NM_DEVICE_INFINIBAND_ERROR_INVALID_INFINIBAND_CONNECTION: the InfiniBand connection was invalid
+ * @NM_DEVICE_INFINIBAND_ERROR_INVALID_DEVICE_MAC: the device's MAC was invalid
+ * @NM_DEVICE_INFINIBAND_ERROR_MAC_MISMATCH: the MACs of the connection and the device mismatched
+ */
+typedef enum {
+	NM_DEVICE_INFINIBAND_ERROR_UNKNOWN = 0,                   /*< nick=UnknownError >*/
+	NM_DEVICE_INFINIBAND_ERROR_NOT_INFINIBAND_CONNECTION,     /*< nick=NotInfinibandConnection >*/
+	NM_DEVICE_INFINIBAND_ERROR_INVALID_INFINIBAND_CONNECTION, /*< nick=InvalidInfinibandConnection >*/
+	NM_DEVICE_INFINIBAND_ERROR_INVALID_DEVICE_MAC,            /*< nick=InvalidDeviceMac >*/
+	NM_DEVICE_INFINIBAND_ERROR_MAC_MISMATCH,                  /*< nick=MacMismatch >*/
+} NMDeviceInfinibandError;
+
+#define NM_DEVICE_INFINIBAND_ERROR nm_device_infiniband_error_quark ()
+GQuark nm_device_infiniband_error_quark (void);
+
+#define NM_DEVICE_INFINIBAND_HW_ADDRESS  "hw-address"
+#define NM_DEVICE_INFINIBAND_CARRIER     "carrier"
+
+typedef struct {
+	NMDevice parent;
+} NMDeviceInfiniband;
+
+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);
+} NMDeviceInfinibandClass;
+
+GType nm_device_infiniband_get_type (void);
+
+GObject *nm_device_infiniband_new (DBusGConnection *connection, const char *path);
+
+const char * nm_device_infiniband_get_hw_address (NMDeviceInfiniband *device);
+gboolean     nm_device_infiniband_get_carrier (NMDeviceInfiniband *device);
+
+G_END_DECLS
+
+#endif /* NM_DEVICE_INFINIBAND_H */
diff --git a/libnm-glib/nm-device-modem.c b/libnm-glib/nm-device-modem.c
index e71e9305..f1d1389b 100644
--- a/libnm-glib/nm-device-modem.c
+++ b/libnm-glib/nm-device-modem.c
@@ -17,7 +17,7 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * Copyright (C) 2011 Red Hat, Inc.
+ * Copyright (C) 2011 - 2012 Red Hat, Inc.
  * Copyright (C) 2008 Novell, Inc.
  */
 
@@ -31,7 +31,7 @@
 #include "nm-device-modem.h"
 #include "nm-device-private.h"
 #include "nm-object-private.h"
-#include "nm-marshal.h"
+#include "nm-glib-marshal.h"
 
 G_DEFINE_TYPE (NMDeviceModem, nm_device_modem, NM_TYPE_DEVICE)
 
@@ -59,6 +59,23 @@ enum {
 #define DBUS_PROP_CURRENT_CAPS "CurrentCapabilities"
 
 /**
+ * nm_device_modem_error_quark:
+ *
+ * Registers an error quark for #NMDeviceModem if necessary.
+ *
+ * Returns: the error quark used for #NMDeviceModem errors.
+ **/
+GQuark
+nm_device_modem_error_quark (void)
+{
+	static GQuark quark = 0;
+
+	if (G_UNLIKELY (quark == 0))
+		quark = g_quark_from_static_string ("nm-device-modem-error-quark");
+	return quark;
+}
+
+/**
  * nm_device_modem_get_modem_capabilities:
  * @self: a #NMDeviceModem
  *
@@ -71,20 +88,11 @@ enum {
 NMDeviceModemCapabilities
 nm_device_modem_get_modem_capabilities (NMDeviceModem *self)
 {
-	NMDeviceModemPrivate *priv;
-
 	g_return_val_if_fail (self != NULL, NM_DEVICE_MODEM_CAPABILITY_NONE);
 	g_return_val_if_fail (NM_IS_DEVICE_MODEM (self), NM_DEVICE_MODEM_CAPABILITY_NONE);
 
-	priv = NM_DEVICE_MODEM_GET_PRIVATE (self);
-	if (!priv->caps) {
-		priv->caps = _nm_object_get_uint_property (NM_OBJECT (self),
-		                                           NM_DBUS_INTERFACE_DEVICE_MODEM,
-		                                           DBUS_PROP_MODEM_CAPS,
-		                                           NULL);
-	}
-
-	return priv->caps;
+	_nm_object_ensure_inited (NM_OBJECT (self));
+	return NM_DEVICE_MODEM_GET_PRIVATE (self)->caps;
 }
 
 /**
@@ -101,24 +109,15 @@ nm_device_modem_get_modem_capabilities (NMDeviceModem *self)
 NMDeviceModemCapabilities
 nm_device_modem_get_current_capabilities (NMDeviceModem *self)
 {
-	NMDeviceModemPrivate *priv;
-
 	g_return_val_if_fail (self != NULL, NM_DEVICE_MODEM_CAPABILITY_NONE);
 	g_return_val_if_fail (NM_IS_DEVICE_MODEM (self), NM_DEVICE_MODEM_CAPABILITY_NONE);
 
-	priv = NM_DEVICE_MODEM_GET_PRIVATE (self);
-	if (!priv->current_caps) {
-		priv->current_caps = _nm_object_get_uint_property (NM_OBJECT (self),
-		                                                   NM_DBUS_INTERFACE_DEVICE_MODEM,
-		                                                   DBUS_PROP_CURRENT_CAPS,
-		                                                   NULL);
-	}
-
-	return priv->current_caps;
+	_nm_object_ensure_inited (NM_OBJECT (self));
+	return NM_DEVICE_MODEM_GET_PRIVATE (self)->current_caps;
 }
 
 static gboolean
-connection_valid (NMDevice *device, NMConnection *connection)
+connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
 {
 	NMSettingConnection *s_con;
 	NMSettingGsm *s_gsm;
@@ -126,22 +125,32 @@ connection_valid (NMDevice *device, NMConnection *connection)
 	const char *ctype;
 	NMDeviceModemCapabilities current_caps;
 
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
 	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_GSM_SETTING_NAME) != 0
-	    && strcmp (ctype, NM_SETTING_CDMA_SETTING_NAME) != 0)
+	    && strcmp (ctype, NM_SETTING_CDMA_SETTING_NAME) != 0) {
+		g_set_error (error, NM_DEVICE_MODEM_ERROR, NM_DEVICE_MODEM_ERROR_NOT_MODEM_CONNECTION,
+		             "The connection was not a modem connection.");
 		return FALSE;
+	}
 
 	s_gsm = nm_connection_get_setting_gsm (connection);
 	s_cdma = nm_connection_get_setting_cdma (connection);
-	if (!s_cdma && !s_gsm)
+	if (!s_cdma && !s_gsm) {
+		g_set_error (error, NM_DEVICE_MODEM_ERROR, NM_DEVICE_MODEM_ERROR_INVALID_MODEM_CONNECTION,
+		             "The connection was not a valid modem connection.");
 		return FALSE;
+	}
 
 	current_caps = nm_device_modem_get_current_capabilities (NM_DEVICE_MODEM (device));
 	if (   !(s_gsm && (current_caps & NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS))
 	    && !(s_cdma && (current_caps & NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO))) {
+		g_set_error (error, NM_DEVICE_MODEM_ERROR, NM_DEVICE_MODEM_ERROR_MISSING_DEVICE_CAPS,
+		             "The device missed capabilities required by the GSM/CDMA connection.");
 		return FALSE;
 	}
 
@@ -151,48 +160,41 @@ connection_valid (NMDevice *device, NMConnection *connection)
 /*******************************************************************/
 
 static void
-register_for_property_changed (NMDeviceModem *device)
+nm_device_modem_init (NMDeviceModem *device)
+{
+	_nm_device_set_device_type (NM_DEVICE (device), NM_DEVICE_TYPE_MODEM);
+}
+
+static void
+register_properties (NMDeviceModem *device)
 {
 	NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (device);
-	const NMPropertiesChangedInfo property_changed_info[] = {
-		{ NM_DEVICE_MODEM_MODEM_CAPABILITIES,   _nm_object_demarshal_generic, &priv->caps },
-		{ NM_DEVICE_MODEM_CURRENT_CAPABILITIES, _nm_object_demarshal_generic, &priv->current_caps },
+	const NMPropertiesInfo property_info[] = {
+		{ NM_DEVICE_MODEM_MODEM_CAPABILITIES,   &priv->caps },
+		{ NM_DEVICE_MODEM_CURRENT_CAPABILITIES, &priv->current_caps },
 		{ NULL },
 	};
 
-	_nm_object_handle_properties_changed (NM_OBJECT (device),
-	                                      priv->proxy,
-	                                      property_changed_info);
+	_nm_object_register_properties (NM_OBJECT (device),
+	                                priv->proxy,
+	                                property_info);
 }
 
-static GObject*
-constructor (GType type,
-             guint n_construct_params,
-             GObjectConstructParam *construct_params)
+static void
+constructed (GObject *object)
 {
-	GObject *object;
 	NMDeviceModemPrivate *priv;
 
-	object = G_OBJECT_CLASS (nm_device_modem_parent_class)->constructor (type,
-	                                                                     n_construct_params,
-	                                                                     construct_params);
-	if (object) {
-		priv = NM_DEVICE_MODEM_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_MODEM);
+	G_OBJECT_CLASS (nm_device_modem_parent_class)->constructed (object);
 
-		register_for_property_changed (NM_DEVICE_MODEM (object));
-	}
+	priv = NM_DEVICE_MODEM_GET_PRIVATE (object);
 
-	return 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_MODEM);
 
-static void
-nm_device_modem_init (NMDeviceModem *device)
-{
+	register_properties (NM_DEVICE_MODEM (object));
 }
 
 static void
@@ -242,10 +244,10 @@ nm_device_modem_class_init (NMDeviceModemClass *modem_class)
 	g_type_class_add_private (modem_class, sizeof (NMDeviceModemPrivate));
 
 	/* virtual methods */
-	object_class->constructor = constructor;
+	object_class->constructed = constructed;
 	object_class->get_property = get_property;
 	object_class->dispose = dispose;
-	device_class->connection_valid = connection_valid;
+	device_class->connection_compatible = connection_compatible;
 
 	/**
 	 * NMDeviceModem:modem-capabilities:
diff --git a/libnm-glib/nm-device-modem.h b/libnm-glib/nm-device-modem.h
index bf84b90d..6f9666dd 100644
--- a/libnm-glib/nm-device-modem.h
+++ b/libnm-glib/nm-device-modem.h
@@ -17,7 +17,7 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * Copyright (C) 2011 Red Hat, Inc.
+ * Copyright (C) 2011 - 2012 Red Hat, Inc.
  * Copyright (C) 2008 Novell, Inc.
  */
 
@@ -35,6 +35,23 @@ G_BEGIN_DECLS
 #define NM_IS_DEVICE_MODEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_DEVICE_MODEM))
 #define NM_DEVICE_MODEM_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_MODEM, NMDeviceModemClass))
 
+/**
+ * NMDeviceModemError:
+ * @NM_DEVICE_MODEM_ERROR_UNKNOWN: unknown or unclassified error
+ * @NM_DEVICE_MODEM_ERROR_NOT_MODEM_CONNECTION: the connection was not of modem type
+ * @NM_DEVICE_MODEM_ERROR_INVALID_MODEM_CONNECTION: the modem connection was invalid
+ * @NM_DEVICE_MODEM_ERROR_MISSING_DEVICE_CAPS: the device missed required capabilities
+ */
+typedef enum {
+	NM_DEVICE_MODEM_ERROR_UNKNOWN = 0,              /*< nick=UnknownError >*/
+	NM_DEVICE_MODEM_ERROR_NOT_MODEM_CONNECTION,     /*< nick=NotModemConnection >*/
+	NM_DEVICE_MODEM_ERROR_INVALID_MODEM_CONNECTION, /*< nick=InvalidModemConnection >*/
+	NM_DEVICE_MODEM_ERROR_MISSING_DEVICE_CAPS,      /*< nick=MissingDeviceCaps >*/
+} NMDeviceModemError;
+
+#define NM_DEVICE_MODEM_ERROR nm_device_modem_error_quark ()
+GQuark nm_device_modem_error_quark (void);
+
 #define NM_DEVICE_MODEM_MODEM_CAPABILITIES   "modem-capabilities"
 #define NM_DEVICE_MODEM_CURRENT_CAPABILITIES "current-capabilities"
 
diff --git a/libnm-glib/nm-device-olpc-mesh.c b/libnm-glib/nm-device-olpc-mesh.c
new file mode 100644
index 00000000..ed48ecb6
--- /dev/null
+++ b/libnm-glib/nm-device-olpc-mesh.c
@@ -0,0 +1,333 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* vim: set ft=c ts=4 sts=4 sw=4 noexpandtab smartindent: */
+/*
+ * 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) 2012 Red Hat, Inc.
+ */
+
+#include <config.h>
+#include <string.h>
+
+#include <nm-setting-connection.h>
+#include <nm-setting-olpc-mesh.h>
+
+#include "nm-device-olpc-mesh.h"
+#include "nm-device-private.h"
+#include "nm-object-private.h"
+#include "nm-device-wifi.h"
+
+G_DEFINE_TYPE (NMDeviceOlpcMesh, nm_device_olpc_mesh, NM_TYPE_DEVICE)
+
+#define NM_DEVICE_OLPC_MESH_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_OLPC_MESH, NMDeviceOlpcMeshPrivate))
+
+typedef struct {
+	DBusGProxy *proxy;
+
+	char *hw_address;
+	NMDeviceWifi *companion;
+	guint32 active_channel;
+} NMDeviceOlpcMeshPrivate;
+
+enum {
+	PROP_0,
+	PROP_HW_ADDRESS,
+	PROP_COMPANION,
+	PROP_ACTIVE_CHANNEL,
+
+	LAST_PROP
+};
+
+#define DBUS_PROP_HW_ADDRESS      "HwAddress"
+#define DBUS_PROP_COMPANION       "Companion"
+#define DBUS_PROP_ACTIVE_CHANNEL  "ActiveChannel"
+
+/**
+ * nm_device_olpc_mesh_error_quark:
+ *
+ * Registers an error quark for #NMDeviceOlpcMesh if necessary.
+ *
+ * Returns: the error quark used for #NMDeviceOlpcMesh errors.
+ **/
+GQuark
+nm_device_olpc_mesh_error_quark (void)
+{
+	static GQuark quark = 0;
+
+	if (G_UNLIKELY (quark == 0))
+		quark = g_quark_from_static_string ("nm-device-olpc-mesh-error-quark");
+	return quark;
+}
+
+/**
+ * nm_device_olpc_mesh_new:
+ * @connection: the #DBusGConnection
+ * @path: the DBus object path of the device
+ *
+ * Creates a new #NMDeviceOlpcMesh.
+ *
+ * Returns: (transfer full): a new OlpcMesh device
+ **/
+GObject *
+nm_device_olpc_mesh_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_OLPC_MESH,
+	                     NM_OBJECT_DBUS_CONNECTION, connection,
+	                     NM_OBJECT_DBUS_PATH, path,
+	                     NULL);
+
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return device;
+}
+
+/**
+ * nm_device_olpc_mesh_get_hw_address:
+ * @device: a #NMDeviceOlpcMesh
+ *
+ * Gets the hardware (MAC) address of the #NMDeviceOlpcMesh
+ *
+ * Returns: the hardware address. This is the internal string used by the
+ * device, and must not be modified.
+ **/
+const char *
+nm_device_olpc_mesh_get_hw_address (NMDeviceOlpcMesh *device)
+{
+	g_return_val_if_fail (NM_IS_DEVICE_OLPC_MESH (device), NULL);
+
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return NM_DEVICE_OLPC_MESH_GET_PRIVATE (device)->hw_address;
+}
+
+/**
+ * nm_device_olpc_mesh_get_companion:
+ * @device: a #NMDeviceOlpcMesh
+ *
+ * Gets the companion device of the #NMDeviceOlpcMesh.
+ *
+ * Returns: (transfer none): the companion of the device of %NULL
+ **/
+NMDeviceWifi *
+nm_device_olpc_mesh_get_companion (NMDeviceOlpcMesh *device)
+{
+	g_return_val_if_fail (NM_IS_DEVICE_OLPC_MESH (device), NULL);
+
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return NM_DEVICE_OLPC_MESH_GET_PRIVATE (device)->companion;
+}
+
+/**
+ * nm_device_olpc_mesh_get_active_channel:
+ * @device: a #NMDeviceOlpcMesh
+ *
+ * Returns the active channel of the #NMDeviceOlpcMesh device.
+ *
+ * Returns: active channel of the device
+ **/
+guint32
+nm_device_olpc_mesh_get_active_channel (NMDeviceOlpcMesh *device)
+{
+	g_return_val_if_fail (NM_IS_DEVICE_OLPC_MESH (device), 0);
+
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return NM_DEVICE_OLPC_MESH_GET_PRIVATE (device)->active_channel;
+}
+
+static gboolean
+connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
+{
+	NMSettingConnection *s_con;
+	NMSettingOlpcMesh *s_olpc_mesh;
+	const char *ctype;
+
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+	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_OLPC_MESH_SETTING_NAME) != 0) {
+		g_set_error (error, NM_DEVICE_OLPC_MESH_ERROR, NM_DEVICE_OLPC_MESH_ERROR_NOT_OLPC_MESH_CONNECTION,
+		             "The connection was not a Olpc Mesh connection.");
+		return FALSE;
+	}
+
+	s_olpc_mesh = nm_connection_get_setting_olpc_mesh (connection);
+	if (!s_olpc_mesh) {
+		g_set_error (error, NM_DEVICE_OLPC_MESH_ERROR, NM_DEVICE_OLPC_MESH_ERROR_INVALID_OLPC_MESH_CONNECTION,
+		             "The connection was not a valid Olpc Mesh connection.");
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+/**************************************************************/
+
+static void
+nm_device_olpc_mesh_init (NMDeviceOlpcMesh *device)
+{
+	_nm_device_set_device_type (NM_DEVICE (device), NM_DEVICE_TYPE_OLPC_MESH);
+}
+
+static void
+register_properties (NMDeviceOlpcMesh *device)
+{
+	NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (device);
+	const NMPropertiesInfo property_info[] = {
+		{ NM_DEVICE_OLPC_MESH_HW_ADDRESS,     &priv->hw_address },
+		{ NM_DEVICE_OLPC_MESH_COMPANION,      &priv->companion, NULL, NM_TYPE_DEVICE_WIFI },
+		{ NM_DEVICE_OLPC_MESH_ACTIVE_CHANNEL, &priv->active_channel },
+		{ NULL },
+	};
+
+	_nm_object_register_properties (NM_OBJECT (device),
+	                                priv->proxy,
+	                                property_info);
+}
+
+static void
+constructed (GObject *object)
+{
+	NMDeviceOlpcMeshPrivate *priv;
+
+	G_OBJECT_CLASS (nm_device_olpc_mesh_parent_class)->constructed (object);
+
+	priv = NM_DEVICE_OLPC_MESH_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_OLPC_MESH);
+
+	register_properties (NM_DEVICE_OLPC_MESH (object));
+}
+
+static void
+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_OBJECT_CLASS (nm_device_olpc_mesh_parent_class)->dispose (object);
+}
+
+static void
+finalize (GObject *object)
+{
+	NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (object);
+
+	g_free (priv->hw_address);
+
+	G_OBJECT_CLASS (nm_device_olpc_mesh_parent_class)->finalize (object);
+}
+
+static void
+get_property (GObject *object,
+              guint prop_id,
+              GValue *value,
+              GParamSpec *pspec)
+{
+	NMDeviceOlpcMesh *device = NM_DEVICE_OLPC_MESH (object);
+
+	switch (prop_id) {
+	case PROP_HW_ADDRESS:
+		g_value_set_string (value, nm_device_olpc_mesh_get_hw_address (device));
+		break;
+	case PROP_COMPANION:
+		g_value_set_object (value, nm_device_olpc_mesh_get_companion (device));
+		break;
+	case PROP_ACTIVE_CHANNEL:
+		g_value_set_uint (value, nm_device_olpc_mesh_get_active_channel (device));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+nm_device_olpc_mesh_class_init (NMDeviceOlpcMeshClass *olpc_mesh_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (olpc_mesh_class);
+	NMDeviceClass *device_class = NM_DEVICE_CLASS (olpc_mesh_class);
+
+	g_type_class_add_private (olpc_mesh_class, sizeof (NMDeviceOlpcMeshPrivate));
+
+	/* 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 */
+
+	/**
+	 * NMDeviceOlpcMesh:hw-address:
+	 *
+	 * The hardware (MAC) address of the device.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_HW_ADDRESS,
+		 g_param_spec_string (NM_DEVICE_OLPC_MESH_HW_ADDRESS,
+		                      "MAC Address",
+		                      "Hardware MAC address",
+		                      NULL,
+		                      G_PARAM_READABLE));
+
+	/**
+	 * NMDeviceOlpcMesh:companion:
+	 *
+	 * The companion device.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_COMPANION,
+		 g_param_spec_object (NM_DEVICE_OLPC_MESH_COMPANION,
+		                     "Companion device",
+		                     "Companion device",
+		                     NM_TYPE_DEVICE_WIFI,
+		                     G_PARAM_READABLE));
+
+	/**
+	 * NMDeviceOlpcMesh:active-channel:
+	 *
+	 * The device's active channel.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_ACTIVE_CHANNEL,
+		 g_param_spec_uint (NM_DEVICE_OLPC_MESH_ACTIVE_CHANNEL,
+		                    "Active channel",
+		                    "Active channel",
+		                    0, G_MAXUINT32, 0,
+		                    G_PARAM_READABLE));
+
+}
+
diff --git a/libnm-glib/nm-device-olpc-mesh.h b/libnm-glib/nm-device-olpc-mesh.h
new file mode 100644
index 00000000..7945d0c7
--- /dev/null
+++ b/libnm-glib/nm-device-olpc-mesh.h
@@ -0,0 +1,84 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* vim: set ft=c ts=4 sts=4 sw=4 noexpandtab smartindent: */
+/*
+ * 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) 2012 Red Hat, Inc.
+ */
+
+#ifndef NM_DEVICE_OLPC_MESH_H
+#define NM_DEVICE_OLPC_MESH_H
+
+#include "nm-device.h"
+#include "nm-device-wifi.h"
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_DEVICE_OLPC_MESH            (nm_device_olpc_mesh_get_type ())
+#define NM_DEVICE_OLPC_MESH(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_OLPC_MESH, NMDeviceOlpcMesh))
+#define NM_DEVICE_OLPC_MESH_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_OLPC_MESH, NMDeviceOlpcMeshClass))
+#define NM_IS_DEVICE_OLPC_MESH(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_OLPC_MESH))
+#define NM_IS_DEVICE_OLPC_MESH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_DEVICE_OLPC_MESH))
+#define NM_DEVICE_OLPC_MESH_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_OLPC_MESH, NMDeviceOlpcMeshClass))
+
+/**
+ * NMDeviceOlpcMeshError:
+ * @NM_DEVICE_OLPC_MESH_ERROR_UNKNOWN: unknown or unclassified error
+ * @NM_DEVICE_OLPC_MESH_ERROR_NOT_OLPC_MESH_CONNECTION: the connection was not of Olpc Mesh type
+ * @NM_DEVICE_OLPC_MESH_ERROR_INVALID_OLPC_MESH_CONNECTION: the Olpc Mesh connection was invalid
+ */
+typedef enum {
+	NM_DEVICE_OLPC_MESH_ERROR_UNKNOWN = 0,                  /*< nick=UnknownError >*/
+	NM_DEVICE_OLPC_MESH_ERROR_NOT_OLPC_MESH_CONNECTION,     /*< nick=NotOlpcMeshConnection >*/
+	NM_DEVICE_OLPC_MESH_ERROR_INVALID_OLPC_MESH_CONNECTION, /*< nick=InvalidOlpcMeshConnection >*/
+} NMDeviceOlpcMeshError;
+
+#define NM_DEVICE_OLPC_MESH_ERROR nm_device_olpc_mesh_error_quark ()
+GQuark nm_device_olpc_mesh_error_quark (void);
+
+#define NM_DEVICE_OLPC_MESH_HW_ADDRESS     "hw-address"
+#define NM_DEVICE_OLPC_MESH_COMPANION      "companion"
+#define NM_DEVICE_OLPC_MESH_ACTIVE_CHANNEL "active-channel"
+
+typedef struct {
+	NMDevice parent;
+} NMDeviceOlpcMesh;
+
+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);
+} NMDeviceOlpcMeshClass;
+
+GType nm_device_olpc_mesh_get_type (void);
+
+GObject *nm_device_olpc_mesh_new (DBusGConnection *connection, const char *path);
+
+const char   *nm_device_olpc_mesh_get_hw_address     (NMDeviceOlpcMesh *device);
+NMDeviceWifi *nm_device_olpc_mesh_get_companion      (NMDeviceOlpcMesh *device);
+guint32       nm_device_olpc_mesh_get_active_channel (NMDeviceOlpcMesh *device);
+
+G_END_DECLS
+
+#endif /* NM_DEVICE_OLPC_MESH_H */
diff --git a/libnm-glib/nm-device-private.h b/libnm-glib/nm-device-private.h
index 2c56a0e6..5c674f2f 100644
--- a/libnm-glib/nm-device-private.h
+++ b/libnm-glib/nm-device-private.h
@@ -17,20 +17,12 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * Copyright (C) 2007 - 2008 Red Hat, Inc.
+ * Copyright (C) 2007 - 2012 Red Hat, Inc.
  */
 
 #ifndef NM_DEVICE_PRIVATE_H
 #define NM_DEVICE_PRIVATE_H
 
-#include <dbus/dbus-glib.h>
-
-DBusGConnection *nm_device_get_connection       (NMDevice *device);
-const char      *nm_device_get_path             (NMDevice *device);
-DBusGProxy      *nm_device_get_properties_proxy (NMDevice *device);
-
-/* static methods */
-NMDeviceType     nm_device_type_for_path (DBusGConnection *connection,
-										  const char *path);
+void _nm_device_set_device_type (NMDevice *device, NMDeviceType dtype);
 
 #endif /* NM_DEVICE_PRIVATE_H */
diff --git a/libnm-glib/nm-device-vlan.c b/libnm-glib/nm-device-vlan.c
new file mode 100644
index 00000000..08b1142d
--- /dev/null
+++ b/libnm-glib/nm-device-vlan.c
@@ -0,0 +1,338 @@
+/* -*- 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) 2012 Red Hat, Inc.
+ */
+
+#include <config.h>
+#include <string.h>
+#include <netinet/ether.h>
+
+#include <nm-setting-connection.h>
+#include <nm-setting-vlan.h>
+#include <nm-utils.h>
+
+#include "nm-device-vlan.h"
+#include "nm-device-private.h"
+#include "nm-object-private.h"
+
+G_DEFINE_TYPE (NMDeviceVlan, nm_device_vlan, NM_TYPE_DEVICE)
+
+#define NM_DEVICE_VLAN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_VLAN, NMDeviceVlanPrivate))
+
+typedef struct {
+	DBusGProxy *proxy;
+
+	char *hw_address;
+	gboolean carrier;
+	guint vlan_id;
+} NMDeviceVlanPrivate;
+
+enum {
+	PROP_0,
+	PROP_HW_ADDRESS,
+	PROP_CARRIER,
+	PROP_VLAN_ID,
+
+	LAST_PROP
+};
+
+#define DBUS_PROP_HW_ADDRESS "HwAddress"
+#define DBUS_PROP_CARRIER "Carrier"
+#define DBUS_PROP_VLAN_ID "VlanId"
+
+/**
+ * nm_device_vlan_error_quark:
+ *
+ * Registers an error quark for #NMDeviceVlan if necessary.
+ *
+ * Returns: the error quark used for #NMDeviceVlan errors.
+ **/
+GQuark
+nm_device_vlan_error_quark (void)
+{
+	static GQuark quark = 0;
+
+	if (G_UNLIKELY (quark == 0))
+		quark = g_quark_from_static_string ("nm-device-vlan-error-quark");
+	return quark;
+}
+
+/**
+ * nm_device_vlan_new:
+ * @connection: the #DBusGConnection
+ * @path: the DBus object path of the device
+ *
+ * Creates a new #NMDeviceVlan.
+ *
+ * Returns: (transfer full): a new device
+ **/
+GObject *
+nm_device_vlan_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_VLAN,
+	                       NM_OBJECT_DBUS_CONNECTION, connection,
+	                       NM_OBJECT_DBUS_PATH, path,
+	                       NULL);
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return device;
+}
+
+/**
+ * nm_device_vlan_get_hw_address:
+ * @device: a #NMDeviceVlan
+ *
+ * Gets the hardware (MAC) address of the #NMDeviceVlan
+ *
+ * Returns: the hardware address. This is the internal string used by the
+ * device, and must not be modified.
+ **/
+const char *
+nm_device_vlan_get_hw_address (NMDeviceVlan *device)
+{
+	g_return_val_if_fail (NM_IS_DEVICE_VLAN (device), NULL);
+
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return NM_DEVICE_VLAN_GET_PRIVATE (device)->hw_address;
+}
+
+/**
+ * nm_device_vlan_get_carrier:
+ * @device: a #NMDeviceVlan
+ *
+ * Whether the device has carrier.
+ *
+ * Returns: %TRUE if the device has carrier
+ **/
+gboolean
+nm_device_vlan_get_carrier (NMDeviceVlan *device)
+{
+	g_return_val_if_fail (NM_IS_DEVICE_VLAN (device), FALSE);
+
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return NM_DEVICE_VLAN_GET_PRIVATE (device)->carrier;
+}
+
+/**
+ * nm_device_vlan_get_vlan_id:
+ * @device: a #NMDeviceVlan
+ *
+ * Returns: the device's VLAN ID
+ **/
+guint
+nm_device_vlan_get_vlan_id (NMDeviceVlan *device)
+{
+	g_return_val_if_fail (NM_IS_DEVICE_VLAN (device), FALSE);
+
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return NM_DEVICE_VLAN_GET_PRIVATE (device)->vlan_id;
+}
+
+static gboolean
+connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
+{
+	NMSettingConnection *s_con;
+	NMSettingVlan *s_vlan;
+	const char *ctype, *dev_iface_name, *vlan_iface_name;
+
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+	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_VLAN_SETTING_NAME) != 0) {
+		g_set_error (error, NM_DEVICE_VLAN_ERROR, NM_DEVICE_VLAN_ERROR_NOT_VLAN_CONNECTION,
+		             "The connection was not a VLAN connection.");
+		return FALSE;
+	}
+
+	s_vlan = nm_connection_get_setting_vlan (connection);
+	if (!s_vlan) {
+		g_set_error (error, NM_DEVICE_VLAN_ERROR, NM_DEVICE_VLAN_ERROR_INVALID_VLAN_CONNECTION,
+		             "The connection was not a valid VLAN connection.");
+		return FALSE;
+	}
+
+	if (nm_setting_vlan_get_id (s_vlan) != nm_device_vlan_get_vlan_id (NM_DEVICE_VLAN (device))) {
+		g_set_error (error, NM_DEVICE_VLAN_ERROR, NM_DEVICE_VLAN_ERROR_ID_MISMATCH,
+		             "The VLAN identifiers of the device and the connection didn't match.");
+		return FALSE;
+	}
+
+	dev_iface_name = nm_device_get_iface (device);
+	vlan_iface_name = nm_setting_vlan_get_interface_name (s_vlan);
+	if (vlan_iface_name && g_strcmp0 (dev_iface_name, vlan_iface_name) != 0) {
+		g_set_error (error, NM_DEVICE_VLAN_ERROR, NM_DEVICE_VLAN_ERROR_INTERFACE_MISMATCH,
+		             "The interfaces of the device and the connection didn't match.");
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+/***********************************************************/
+
+static void
+nm_device_vlan_init (NMDeviceVlan *device)
+{
+	_nm_device_set_device_type (NM_DEVICE (device), NM_DEVICE_TYPE_VLAN);
+}
+
+static void
+register_properties (NMDeviceVlan *device)
+{
+	NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (device);
+	const NMPropertiesInfo property_info[] = {
+		{ NM_DEVICE_VLAN_HW_ADDRESS, &priv->hw_address },
+		{ NM_DEVICE_VLAN_CARRIER,    &priv->carrier },
+		{ NM_DEVICE_VLAN_VLAN_ID,    &priv->vlan_id },
+		{ NULL },
+	};
+
+	_nm_object_register_properties (NM_OBJECT (device),
+	                                priv->proxy,
+	                                property_info);
+}
+
+static void
+constructed (GObject *object)
+{
+	NMDeviceVlanPrivate *priv;
+
+	G_OBJECT_CLASS (nm_device_vlan_parent_class)->constructed (object);
+
+	priv = NM_DEVICE_VLAN_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_VLAN);
+
+	register_properties (NM_DEVICE_VLAN (object));
+}
+
+static void
+dispose (GObject *object)
+{
+	NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (object);
+
+	if (priv->proxy) {
+		g_object_unref (priv->proxy);
+		priv->proxy = NULL;
+	}
+
+	G_OBJECT_CLASS (nm_device_vlan_parent_class)->dispose (object);
+}
+
+static void
+finalize (GObject *object)
+{
+	NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (object);
+
+	g_free (priv->hw_address);
+
+	G_OBJECT_CLASS (nm_device_vlan_parent_class)->finalize (object);
+}
+
+static void
+get_property (GObject *object,
+              guint prop_id,
+              GValue *value,
+              GParamSpec *pspec)
+{
+	NMDeviceVlan *device = NM_DEVICE_VLAN (object);
+
+	switch (prop_id) {
+	case PROP_HW_ADDRESS:
+		g_value_set_string (value, nm_device_vlan_get_hw_address (device));
+		break;
+	case PROP_CARRIER:
+		g_value_set_boolean (value, nm_device_vlan_get_carrier (device));
+		break;
+	case PROP_VLAN_ID:
+		g_value_set_uint (value, nm_device_vlan_get_vlan_id (device));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+nm_device_vlan_class_init (NMDeviceVlanClass *eth_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (eth_class);
+	NMDeviceClass *device_class = NM_DEVICE_CLASS (eth_class);
+
+	g_type_class_add_private (eth_class, sizeof (NMDeviceVlanPrivate));
+
+	/* 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 */
+
+	/**
+	 * NMDeviceVlan:hw-address:
+	 *
+	 * The hardware (MAC) address of the device.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_HW_ADDRESS,
+		 g_param_spec_string (NM_DEVICE_VLAN_HW_ADDRESS,
+		                      "Active MAC Address",
+		                      "Currently set hardware MAC address",
+		                      NULL,
+		                      G_PARAM_READABLE));
+
+	/**
+	 * NMDeviceVlan:carrier:
+	 *
+	 * Whether the device has carrier.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_CARRIER,
+		 g_param_spec_boolean (NM_DEVICE_VLAN_CARRIER,
+		                       "Carrier",
+		                       "Carrier",
+		                       FALSE,
+		                       G_PARAM_READABLE));
+
+	/**
+	 * NMDeviceVlan:vlan-id:
+	 *
+	 * The device's VLAN ID.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_VLAN_ID,
+		 g_param_spec_uint (NM_DEVICE_VLAN_VLAN_ID,
+		                    "VLAN ID",
+		                    "VLAN ID",
+		                    0, 4095, 0,
+		                    G_PARAM_READABLE));
+}
diff --git a/libnm-glib/nm-device-vlan.h b/libnm-glib/nm-device-vlan.h
new file mode 100644
index 00000000..df020259
--- /dev/null
+++ b/libnm-glib/nm-device-vlan.h
@@ -0,0 +1,86 @@
+/* -*- 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) 2012 Red Hat, Inc.
+ */
+
+#ifndef NM_DEVICE_VLAN_H
+#define NM_DEVICE_VLAN_H
+
+#include "nm-device.h"
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_DEVICE_VLAN            (nm_device_vlan_get_type ())
+#define NM_DEVICE_VLAN(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_VLAN, NMDeviceVlan))
+#define NM_DEVICE_VLAN_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_VLAN, NMDeviceVlanClass))
+#define NM_IS_DEVICE_VLAN(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_VLAN))
+#define NM_IS_DEVICE_VLAN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_DEVICE_VLAN))
+#define NM_DEVICE_VLAN_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_VLAN, NMDeviceVlanClass))
+
+/**
+ * NMDeviceVlanError:
+ * @NM_DEVICE_VLAN_ERROR_UNKNOWN: unknown or unclassified error
+ * @NM_DEVICE_VLAN_ERROR_NOT_VLAN_CONNECTION: the connection was not of VLAN type
+ * @NM_DEVICE_VLAN_ERROR_INVALID_VLAN_CONNECTION: the VLAN connection was invalid
+ * @NM_DEVICE_VLAN_ERROR_ID_MISMATCH: the VLAN identifiers of the connection and the device mismatched
+ * @NM_DEVICE_VLAN_ERROR_INTERFACE_MISMATCH: the interfaces of the connection and the device mismatched
+ */
+typedef enum {
+	NM_DEVICE_VLAN_ERROR_UNKNOWN = 0,             /*< nick=UnknownError >*/
+	NM_DEVICE_VLAN_ERROR_NOT_VLAN_CONNECTION,     /*< nick=NotVlanConnection >*/
+	NM_DEVICE_VLAN_ERROR_INVALID_VLAN_CONNECTION, /*< nick=InvalidVlanConnection >*/
+	NM_DEVICE_VLAN_ERROR_ID_MISMATCH,             /*< nick=IdMismatch >*/
+	NM_DEVICE_VLAN_ERROR_INTERFACE_MISMATCH,      /*< nick=InterfaceMismatch >*/
+} NMDeviceVlanError;
+
+#define NM_DEVICE_VLAN_ERROR nm_device_vlan_error_quark ()
+GQuark nm_device_vlan_error_quark (void);
+
+#define NM_DEVICE_VLAN_HW_ADDRESS  "hw-address"
+#define NM_DEVICE_VLAN_CARRIER     "carrier"
+#define NM_DEVICE_VLAN_VLAN_ID     "vlan-id"
+
+typedef struct {
+	NMDevice parent;
+} NMDeviceVlan;
+
+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);
+} NMDeviceVlanClass;
+
+GType nm_device_vlan_get_type (void);
+
+GObject *nm_device_vlan_new (DBusGConnection *connection, const char *path);
+
+const char * nm_device_vlan_get_hw_address (NMDeviceVlan *device);
+gboolean     nm_device_vlan_get_carrier (NMDeviceVlan *device);
+guint        nm_device_vlan_get_vlan_id (NMDeviceVlan *device);
+
+G_END_DECLS
+
+#endif /* NM_DEVICE_VLAN_H */
diff --git a/libnm-glib/nm-device-wifi.c b/libnm-glib/nm-device-wifi.c
index 7d0e1b9f..6975898f 100644
--- a/libnm-glib/nm-device-wifi.c
+++ b/libnm-glib/nm-device-wifi.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 <config.h>
@@ -36,14 +36,10 @@
 #include "nm-dbus-glib-types.h"
 #include "nm-types-private.h"
 
-#include "nm-device-wifi-bindings.h"
-
 G_DEFINE_TYPE (NMDeviceWifi, nm_device_wifi, NM_TYPE_DEVICE)
 
 #define NM_DEVICE_WIFI_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_WIFI, NMDeviceWifiPrivate))
 
-static gboolean demarshal_active_ap (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field);
-
 void _nm_device_wifi_set_wireless_enabled (NMDeviceWifi *device, gboolean enabled);
 
 typedef struct {
@@ -55,7 +51,6 @@ typedef struct {
 	NM80211Mode mode;
 	guint32 rate;
 	NMAccessPoint *active_ap;
-	gboolean got_active_ap;
 	NMDeviceWifiCapabilities wireless_caps;
 	GPtrArray *aps;
 
@@ -91,6 +86,23 @@ enum {
 static guint signals[LAST_SIGNAL] = { 0 };
 
 /**
+ * nm_device_wifi_error_quark:
+ *
+ * Registers an error quark for #NMDeviceWifi if necessary.
+ *
+ * Returns: the error quark used for #NMDeviceWifi errors.
+ **/
+GQuark
+nm_device_wifi_error_quark (void)
+{
+	static GQuark quark = 0;
+
+	if (G_UNLIKELY (quark == 0))
+		quark = g_quark_from_static_string ("nm-device-wifi-error-quark");
+	return quark;
+}
+
+/**
  * nm_device_wifi_new:
  * @connection: the #DBusGConnection
  * @path: the DBus object path of the device
@@ -102,13 +114,17 @@ static guint signals[LAST_SIGNAL] = { 0 };
 GObject *
 nm_device_wifi_new (DBusGConnection *connection, const char *path)
 {
+	GObject *device;
+
 	g_return_val_if_fail (connection != NULL, NULL);
 	g_return_val_if_fail (path != NULL, NULL);
 
-	return g_object_new (NM_TYPE_DEVICE_WIFI,
-	                     NM_OBJECT_DBUS_CONNECTION, connection,
-	                     NM_OBJECT_DBUS_PATH, path,
-	                     NULL);
+	device = g_object_new (NM_TYPE_DEVICE_WIFI,
+	                       NM_OBJECT_DBUS_CONNECTION, connection,
+	                       NM_OBJECT_DBUS_PATH, path,
+	                       NULL);
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return device;
 }
 
 /**
@@ -123,19 +139,10 @@ nm_device_wifi_new (DBusGConnection *connection, const char *path)
 const char *
 nm_device_wifi_get_hw_address (NMDeviceWifi *device)
 {
-	NMDeviceWifiPrivate *priv;
-
 	g_return_val_if_fail (NM_IS_DEVICE_WIFI (device), NULL);
 
-	priv = NM_DEVICE_WIFI_GET_PRIVATE (device);
-	if (!priv->hw_address) {
-		priv->hw_address = _nm_object_get_string_property (NM_OBJECT (device),
-		                                                  NM_DBUS_INTERFACE_DEVICE_WIRELESS,
-		                                                  DBUS_PROP_HW_ADDRESS,
-		                                                  NULL);
-	}
-
-	return priv->hw_address;
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return NM_DEVICE_WIFI_GET_PRIVATE (device)->hw_address;
 }
 
 /**
@@ -150,19 +157,10 @@ nm_device_wifi_get_hw_address (NMDeviceWifi *device)
 const char *
 nm_device_wifi_get_permanent_hw_address (NMDeviceWifi *device)
 {
-	NMDeviceWifiPrivate *priv;
-
 	g_return_val_if_fail (NM_IS_DEVICE_WIFI (device), NULL);
 
-	priv = NM_DEVICE_WIFI_GET_PRIVATE (device);
-	if (!priv->perm_hw_address) {
-		priv->perm_hw_address = _nm_object_get_string_property (NM_OBJECT (device),
-		                                                        NM_DBUS_INTERFACE_DEVICE_WIRELESS,
-		                                                        DBUS_PROP_PERM_HW_ADDRESS,
-		                                                        NULL);
-	}
-
-	return priv->perm_hw_address;
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return NM_DEVICE_WIFI_GET_PRIVATE (device)->perm_hw_address;
 }
 
 /**
@@ -176,19 +174,10 @@ nm_device_wifi_get_permanent_hw_address (NMDeviceWifi *device)
 NM80211Mode
 nm_device_wifi_get_mode (NMDeviceWifi *device)
 {
-	NMDeviceWifiPrivate *priv;
-
 	g_return_val_if_fail (NM_IS_DEVICE_WIFI (device), 0);
 
-	priv = NM_DEVICE_WIFI_GET_PRIVATE (device);
-	if (!priv->mode) {
-		priv->mode = _nm_object_get_uint_property (NM_OBJECT (device),
-		                                          NM_DBUS_INTERFACE_DEVICE_WIRELESS,
-		                                          DBUS_PROP_MODE,
-		                                          NULL);
-	}
-
-	return priv->mode;
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return NM_DEVICE_WIFI_GET_PRIVATE (device)->mode;
 }
 
 /**
@@ -202,7 +191,6 @@ nm_device_wifi_get_mode (NMDeviceWifi *device)
 guint32
 nm_device_wifi_get_bitrate (NMDeviceWifi *device)
 {
-	NMDeviceWifiPrivate *priv;
 	NMDeviceState state;
 
 	g_return_val_if_fail (NM_IS_DEVICE_WIFI (device), 0);
@@ -219,15 +207,8 @@ nm_device_wifi_get_bitrate (NMDeviceWifi *device)
 		return 0;
 	}
 
-	priv = NM_DEVICE_WIFI_GET_PRIVATE (device);
-	if (!priv->rate) {
-		priv->rate = _nm_object_get_uint_property (NM_OBJECT (device),
-		                                         NM_DBUS_INTERFACE_DEVICE_WIRELESS,
-		                                         DBUS_PROP_BITRATE,
-		                                         NULL);
-	}
-
-	return priv->rate;
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return NM_DEVICE_WIFI_GET_PRIVATE (device)->rate;
 }
 
 /**
@@ -241,19 +222,10 @@ nm_device_wifi_get_bitrate (NMDeviceWifi *device)
 NMDeviceWifiCapabilities
 nm_device_wifi_get_capabilities (NMDeviceWifi *device)
 {
-	NMDeviceWifiPrivate *priv;
-
 	g_return_val_if_fail (NM_IS_DEVICE_WIFI (device), 0);
 
-	priv = NM_DEVICE_WIFI_GET_PRIVATE (device);
-	if (!priv->wireless_caps) {
-		priv->wireless_caps = _nm_object_get_uint_property (NM_OBJECT (device),
-		                                                   NM_DBUS_INTERFACE_DEVICE_WIRELESS,
-		                                                   DBUS_PROP_WIRELESS_CAPABILITIES,
-		                                                   NULL);
-	}
-
-	return priv->wireless_caps;
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return NM_DEVICE_WIFI_GET_PRIVATE (device)->wireless_caps;
 }
 
 /**
@@ -267,11 +239,7 @@ nm_device_wifi_get_capabilities (NMDeviceWifi *device)
 NMAccessPoint *
 nm_device_wifi_get_active_access_point (NMDeviceWifi *device)
 {
-	NMDeviceWifiPrivate *priv;
 	NMDeviceState state;
-	char *path;
-	GValue value = { 0, };
-	GError *error = NULL;
 
 	g_return_val_if_fail (NM_IS_DEVICE_WIFI (device), NULL);
 
@@ -291,23 +259,8 @@ nm_device_wifi_get_active_access_point (NMDeviceWifi *device)
 		break;
 	}
 
-	priv = NM_DEVICE_WIFI_GET_PRIVATE (device);
-	if (priv->got_active_ap == TRUE)
-		return priv->active_ap;
-
-	path = _nm_object_get_object_path_property (NM_OBJECT (device),
-	                                            NM_DBUS_INTERFACE_DEVICE_WIRELESS,
-	                                            DBUS_PROP_ACTIVE_ACCESS_POINT,
-	                                            &error);
-	if (error == NULL) {
-		g_value_init (&value, DBUS_TYPE_G_OBJECT_PATH);
-		g_value_take_boxed (&value, path);
-		demarshal_active_ap (NM_OBJECT (device), NULL, &value, &priv->active_ap);
-		g_value_unset (&value);
-	}
-	g_clear_error (&error);
-
-	return priv->active_ap;
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return NM_DEVICE_WIFI_GET_PRIVATE (device)->active_ap;
 }
 
 /**
@@ -323,31 +276,10 @@ nm_device_wifi_get_active_access_point (NMDeviceWifi *device)
 const GPtrArray *
 nm_device_wifi_get_access_points (NMDeviceWifi *device)
 {
-	NMDeviceWifiPrivate *priv;
-	DBusGConnection *connection;
-	GValue value = { 0, };
-	GError *error = NULL;
-	GPtrArray *temp;
-
 	g_return_val_if_fail (NM_IS_DEVICE_WIFI (device), NULL);
 
-	priv = NM_DEVICE_WIFI_GET_PRIVATE (device);
-	if (priv->aps)
-		return handle_ptr_array_return (priv->aps);
-
-	if (!org_freedesktop_NetworkManager_Device_Wireless_get_access_points (priv->proxy, &temp, &error)) {
-		g_warning ("%s: error getting access points: %s", __func__, error->message);
-		g_error_free (error);
-		return NULL;
-	}
-
-	g_value_init (&value, DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH);
-	g_value_take_boxed (&value, temp);
-	connection = nm_object_get_connection (NM_OBJECT (device));
-	_nm_object_array_demarshal (&value, &priv->aps, connection, nm_access_point_new);
-	g_value_unset (&value);
-
-	return handle_ptr_array_return (priv->aps);
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return handle_ptr_array_return (NM_DEVICE_WIFI_GET_PRIVATE (device)->aps);
 }
 
 /**
@@ -386,57 +318,28 @@ nm_device_wifi_get_access_point_by_path (NMDeviceWifi *device,
 }
 
 static void
-access_point_added_proxy (DBusGProxy *proxy, char *path, gpointer user_data)
+access_point_added (NMObject *self, NMObject *ap)
 {
-	NMDeviceWifi *self = NM_DEVICE_WIFI (user_data);
-	NMDeviceWifiPrivate *priv;
-	GObject *ap;
-
-	g_return_if_fail (self != NULL);
-
-	ap = G_OBJECT (nm_device_wifi_get_access_point_by_path (self, path));
-	if (!ap) {
-		DBusGConnection *connection = nm_object_get_connection (NM_OBJECT (self));
-
-		priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
-		ap = G_OBJECT (_nm_object_cache_get (path));
-		if (ap) {
-			g_ptr_array_add (priv->aps, ap);
-		} else {
-			ap = G_OBJECT (nm_access_point_new (connection, path));
-			if (ap)
-				g_ptr_array_add (priv->aps, ap);
-		}
-	}
-
-	if (ap)
-		g_signal_emit (self, signals[ACCESS_POINT_ADDED], 0, NM_ACCESS_POINT (ap));
+	g_signal_emit (self, signals[ACCESS_POINT_ADDED], 0, ap);
 }
 
 static void
-access_point_removed_proxy (DBusGProxy *proxy, char *path, gpointer user_data)
+access_point_removed (NMObject *self_obj, NMObject *ap_obj)
 {
-	NMDeviceWifi *self = NM_DEVICE_WIFI (user_data);
+	NMDeviceWifi *self = NM_DEVICE_WIFI (self_obj);
 	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
-	NMAccessPoint *ap;
-
-	g_return_if_fail (self != NULL);
+	NMAccessPoint *ap = NM_ACCESS_POINT (ap_obj);
 
-	ap = nm_device_wifi_get_access_point_by_path (self, path);
-	if (ap) {
-		if (ap == priv->active_ap) {
-			g_object_unref (priv->active_ap);
-			priv->active_ap = NULL;
-			_nm_object_queue_notify (NM_OBJECT (self), NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT);
-
-			priv->rate = 0;
-			_nm_object_queue_notify (NM_OBJECT (self), NM_DEVICE_WIFI_BITRATE);
-		}
+	if (ap == priv->active_ap) {
+		g_object_unref (priv->active_ap);
+		priv->active_ap = NULL;
+		_nm_object_queue_notify (NM_OBJECT (self), NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT);
 
-		g_signal_emit (self, signals[ACCESS_POINT_REMOVED], 0, ap);
-		g_ptr_array_remove (priv->aps, ap);
-		g_object_unref (G_OBJECT (ap));
+		priv->rate = 0;
+		_nm_object_queue_notify (NM_OBJECT (self), NM_DEVICE_WIFI_BITRATE);
 	}
+
+	g_signal_emit (self, signals[ACCESS_POINT_REMOVED], 0, ap);
 }
 
 static void
@@ -504,7 +407,7 @@ has_proto (NMSettingWirelessSecurity *s_wsec, const char *proto)
 }
 
 static gboolean
-connection_valid (NMDevice *device, NMConnection *connection)
+connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
 {
 	NMSettingConnection *s_con;
 	NMSettingWireless *s_wifi;
@@ -516,24 +419,40 @@ connection_valid (NMDevice *device, NMConnection *connection)
 	NMDeviceWifiCapabilities wifi_caps;
 	const char *key_mgmt;
 
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
 	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_WIRELESS_SETTING_NAME) != 0)
+	if (strcmp (ctype, NM_SETTING_WIRELESS_SETTING_NAME) != 0) {
+		g_set_error (error, NM_DEVICE_WIFI_ERROR, NM_DEVICE_WIFI_ERROR_NOT_WIFI_CONNECTION,
+		             "The connection was not a Wi-Fi connection.");
 		return FALSE;
+	}
 
 	s_wifi = nm_connection_get_setting_wireless (connection);
-	if (!s_wifi)
+	if (!s_wifi) {
+		g_set_error (error, NM_DEVICE_WIFI_ERROR, NM_DEVICE_WIFI_ERROR_INVALID_WIFI_CONNECTION,
+		             "The connection was not a valid Wi-Fi connection.");
 		return FALSE;
+	}
 
 	/* Check MAC address */
 	hw_str = nm_device_wifi_get_permanent_hw_address (NM_DEVICE_WIFI (device));
 	if (hw_str) {
 		hw_mac = ether_aton (hw_str);
+		if (!hw_mac) {
+			g_set_error (error, NM_DEVICE_WIFI_ERROR, NM_DEVICE_WIFI_ERROR_INVALID_DEVICE_MAC,
+			             "Invalid device MAC address.");
+			return FALSE;
+		}
 		mac = nm_setting_wireless_get_mac_address (s_wifi);
-		if (mac && hw_mac && memcmp (mac->data, hw_mac->ether_addr_octet, ETH_ALEN))
+		if (mac && hw_mac && memcmp (mac->data, hw_mac->ether_addr_octet, ETH_ALEN)) {
+			g_set_error (error, NM_DEVICE_WIFI_ERROR, NM_DEVICE_WIFI_ERROR_MAC_MISMATCH,
+			             "The MACs of the device and the connection didn't match.");
 			return FALSE;
+		}
 	}
 
 	/* Check device capabilities; we assume all devices can do WEP at least */
@@ -548,12 +467,18 @@ connection_valid (NMDevice *device, NMConnection *connection)
 		    || !g_strcmp0 (key_mgmt, "wpa-eap")) {
 
 			/* Is device only WEP capable? */
-			if (!(wifi_caps & WPA_CAPS))
+			if (!(wifi_caps & WPA_CAPS)) {
+				g_set_error (error, NM_DEVICE_WIFI_ERROR, NM_DEVICE_WIFI_ERROR_MISSING_DEVICE_WPA_CAPS,
+				             "The device missed WPA capabilities required by the connection.");
 				return FALSE;
+			}
 
 			/* Make sure WPA2/RSN-only connections don't get chosen for WPA-only cards */
-			if (has_proto (s_wsec, "rsn") && !has_proto (s_wsec, "wpa") && !(wifi_caps & RSN_CAPS))
+			if (has_proto (s_wsec, "rsn") && !has_proto (s_wsec, "wpa") && !(wifi_caps & RSN_CAPS)) {
+				g_set_error (error, NM_DEVICE_WIFI_ERROR, NM_DEVICE_WIFI_ERROR_MISSING_DEVICE_RSN_CAPS,
+				             "The device missed WPA2/RSN capabilities required by the connection.");
 				return FALSE;
+			}
 		}
 	}
 
@@ -565,9 +490,7 @@ connection_valid (NMDevice *device, NMConnection *connection)
 static void
 nm_device_wifi_init (NMDeviceWifi *device)
 {
-	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (device);
-
-	priv->disposed = FALSE;
+	_nm_device_set_device_type (NM_DEVICE (device), NM_DEVICE_TYPE_WIFI);
 }
 
 static void
@@ -629,74 +552,39 @@ state_changed_cb (NMDevice *device, GParamSpec *pspec, gpointer user_data)
 	}
 }
 
-static gboolean
-demarshal_active_ap (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field)
-{
-	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (object);
-	const char *path;
-	NMAccessPoint *ap = NULL;
-	DBusGConnection *connection;
-
-	if (value) {
-		if (!G_VALUE_HOLDS (value, DBUS_TYPE_G_OBJECT_PATH))
-			return FALSE;
-
-		path = g_value_get_boxed (value);
-		if (path) {
-			ap = NM_ACCESS_POINT (_nm_object_cache_get (path));
-			if (!ap) {
-				connection = nm_object_get_connection (object);
-				ap = NM_ACCESS_POINT (nm_access_point_new (connection, path));
-			}
-		}
-	}
-
-	priv->got_active_ap = TRUE;
-
-	if (priv->active_ap) {
-		g_object_unref (priv->active_ap);
-		priv->active_ap = NULL;
-	}
-
-	if (ap)
-		priv->active_ap = ap;
-
-	_nm_object_queue_notify (object, NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT);
-	return TRUE;
-}
-
 static void
-register_for_property_changed (NMDeviceWifi *device)
+register_properties (NMDeviceWifi *device)
 {
 	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (device);
-	const NMPropertiesChangedInfo property_changed_info[] = {
-		{ NM_DEVICE_WIFI_HW_ADDRESS,           _nm_object_demarshal_generic, &priv->hw_address },
-		{ NM_DEVICE_WIFI_PERMANENT_HW_ADDRESS, _nm_object_demarshal_generic, &priv->perm_hw_address },
-		{ NM_DEVICE_WIFI_MODE,                 _nm_object_demarshal_generic, &priv->mode },
-		{ NM_DEVICE_WIFI_BITRATE,              _nm_object_demarshal_generic, &priv->rate },
-		{ NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT,  demarshal_active_ap,         &priv->active_ap },
-		{ NM_DEVICE_WIFI_CAPABILITIES,         _nm_object_demarshal_generic, &priv->wireless_caps },
+	const NMPropertiesInfo property_info[] = {
+		{ NM_DEVICE_WIFI_HW_ADDRESS,           &priv->hw_address },
+		{ NM_DEVICE_WIFI_PERMANENT_HW_ADDRESS, &priv->perm_hw_address },
+		{ NM_DEVICE_WIFI_MODE,                 &priv->mode },
+		{ NM_DEVICE_WIFI_BITRATE,              &priv->rate },
+		{ NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT,  &priv->active_ap, NULL, NM_TYPE_ACCESS_POINT },
+		{ NM_DEVICE_WIFI_CAPABILITIES,         &priv->wireless_caps },
 		{ NULL },
 	};
 
-	_nm_object_handle_properties_changed (NM_OBJECT (device),
+	_nm_object_register_properties (NM_OBJECT (device),
+	                                priv->proxy,
+	                                property_info);
+
+	_nm_object_register_pseudo_property (NM_OBJECT (device),
 	                                     priv->proxy,
-	                                     property_changed_info);
+	                                     "AccessPoints",
+	                                     &priv->aps,
+	                                     NM_TYPE_ACCESS_POINT,
+	                                     access_point_added,
+	                                     access_point_removed);
 }
 
-static GObject*
-constructor (GType type,
-		   guint n_construct_params,
-		   GObjectConstructParam *construct_params)
+static void
+constructed (GObject *object)
 {
-	GObject *object;
 	NMDeviceWifiPrivate *priv;
 
-	object = G_OBJECT_CLASS (nm_device_wifi_parent_class)->constructor (type,
-																    n_construct_params,
-																    construct_params);
-	if (!object)
-		return NULL;
+	G_OBJECT_CLASS (nm_device_wifi_parent_class)->constructed (object);
 
 	priv = NM_DEVICE_WIFI_GET_PRIVATE (object);
 
@@ -705,28 +593,12 @@ constructor (GType type,
 											nm_object_get_path (NM_OBJECT (object)),
 											NM_DBUS_INTERFACE_DEVICE_WIRELESS);
 
-	dbus_g_proxy_add_signal (priv->proxy, "AccessPointAdded",
-	                         DBUS_TYPE_G_OBJECT_PATH,
-	                         G_TYPE_INVALID);
-	dbus_g_proxy_connect_signal (priv->proxy, "AccessPointAdded",
-						    G_CALLBACK (access_point_added_proxy),
-						    object, NULL);
-
-	dbus_g_proxy_add_signal (priv->proxy, "AccessPointRemoved",
-	                         DBUS_TYPE_G_OBJECT_PATH,
-	                         G_TYPE_INVALID);
-	dbus_g_proxy_connect_signal (priv->proxy, "AccessPointRemoved",
-						    G_CALLBACK (access_point_removed_proxy),
-						    object, NULL);
-
-	register_for_property_changed (NM_DEVICE_WIFI (object));
+	register_properties (NM_DEVICE_WIFI (object));
 
 	g_signal_connect (NM_DEVICE (object),
 	                  "notify::" NM_DEVICE_STATE,
 	                  G_CALLBACK (state_changed_cb),
 	                  NULL);
-
-	return object;
 }
 
 static void
@@ -767,11 +639,11 @@ nm_device_wifi_class_init (NMDeviceWifiClass *wifi_class)
 	g_type_class_add_private (wifi_class, sizeof (NMDeviceWifiPrivate));
 
 	/* virtual methods */
-	object_class->constructor = constructor;
+	object_class->constructed = constructed;
 	object_class->get_property = get_property;
 	object_class->dispose = dispose;
 	object_class->finalize = finalize;
-	device_class->connection_valid = connection_valid;
+	device_class->connection_compatible = connection_compatible;
 
 	/* properties */
 
diff --git a/libnm-glib/nm-device-wifi.h b/libnm-glib/nm-device-wifi.h
index fb2ab27d..13f1cb8a 100644
--- a/libnm-glib/nm-device-wifi.h
+++ b/libnm-glib/nm-device-wifi.h
@@ -18,7 +18,7 @@
  * Boston, MA 02110-1301 USA.
  *
  * Copyright (C) 2007 - 2008 Novell, Inc.
- * Copyright (C) 2007 - 2010 Red Hat, Inc.
+ * Copyright (C) 2007 - 2012 Red Hat, Inc.
  */
 
 #ifndef NM_DEVICE_WIFI_H
@@ -36,6 +36,31 @@ G_BEGIN_DECLS
 #define NM_IS_DEVICE_WIFI_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_DEVICE_WIFI))
 #define NM_DEVICE_WIFI_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_WIFI, NMDeviceWifiClass))
 
+/**
+ * NMDeviceWifiError:
+ * @NM_DEVICE_WIFI_ERROR_UNKNOWN: unknown or unclassified error
+ * @NM_DEVICE_WIFI_ERROR_NOT_WIFI_CONNECTION: the connection was not of Wi-Fi type
+ * @NM_DEVICE_WIFI_ERROR_INVALID_WIFI_CONNECTION: the Wi-Fi connection was invalid
+ * @NM_DEVICE_WIFI_ERROR_INVALID_DEVICE_MAC: the device's MAC was invalid
+ * @NM_DEVICE_WIFI_ERROR_MAC_MISMATCH: the MACs of the connection and the device mismatched
+ * @NM_DEVICE_WIFI_ERROR_MISSING_DEVICE_WPA_CAPS: the device missed WPA capabilities
+ * required by the connection
+ * @NM_DEVICE_WIFI_ERROR_MISSING_DEVICE_RSN_CAPS: the device missed RSN capabilities
+ * required by the connection
+ */
+typedef enum {
+	NM_DEVICE_WIFI_ERROR_UNKNOWN = 0,             /*< nick=UnknownError >*/
+	NM_DEVICE_WIFI_ERROR_NOT_WIFI_CONNECTION,     /*< nick=NotWifiConnection >*/
+	NM_DEVICE_WIFI_ERROR_INVALID_WIFI_CONNECTION, /*< nick=InvalidWifiConnection >*/
+	NM_DEVICE_WIFI_ERROR_INVALID_DEVICE_MAC,      /*< nick=InvalidDeviceMac >*/
+	NM_DEVICE_WIFI_ERROR_MAC_MISMATCH,            /*< nick=MacMismatch >*/
+	NM_DEVICE_WIFI_ERROR_MISSING_DEVICE_WPA_CAPS, /*< nick=MissingDeviceWpaCaps >*/
+	NM_DEVICE_WIFI_ERROR_MISSING_DEVICE_RSN_CAPS, /*< nick=MissingDeviceRsnCaps >*/
+} NMDeviceWifiError;
+
+#define NM_DEVICE_WIFI_ERROR nm_device_wifi_error_quark ()
+GQuark nm_device_wifi_error_quark (void);
+
 #define NM_DEVICE_WIFI_HW_ADDRESS          "hw-address"
 #define NM_DEVICE_WIFI_PERMANENT_HW_ADDRESS "perm-hw-address"
 #define NM_DEVICE_WIFI_MODE                "mode"
diff --git a/libnm-glib/nm-device-wimax.c b/libnm-glib/nm-device-wimax.c
index 4844a0e2..48a518d7 100644
--- a/libnm-glib/nm-device-wimax.c
+++ b/libnm-glib/nm-device-wimax.c
@@ -17,7 +17,7 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * Copyright (C) 2011 Red Hat, Inc.
+ * Copyright (C) 2011 - 2012 Red Hat, Inc.
  * Copyright (C) 2009 Novell, Inc.
  */
 
@@ -33,15 +33,12 @@
 #include "nm-object-cache.h"
 #include "nm-dbus-glib-types.h"
 #include "nm-types-private.h"
-
-#include "nm-device-wimax-bindings.h"
+#include "nm-device-private.h"
 
 G_DEFINE_TYPE (NMDeviceWimax, nm_device_wimax, NM_TYPE_DEVICE)
 
 #define NM_DEVICE_WIMAX_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_WIMAX, NMDeviceWimaxPrivate))
 
-static gboolean demarshal_active_nsp (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field);
-
 void _nm_device_wimax_set_wireless_enabled (NMDeviceWimax *wimax, gboolean enabled);
 
 typedef struct {
@@ -50,7 +47,6 @@ typedef struct {
 
 	char *hw_address;
 	NMWimaxNsp *active_nsp;
-	gboolean got_active_nsp;
 	GPtrArray *nsps;
 
 	guint center_freq;
@@ -91,6 +87,23 @@ enum {
 static guint signals[LAST_SIGNAL] = { 0 };
 
 /**
+ * nm_device_wimax_error_quark:
+ *
+ * Registers an error quark for #NMDeviceWimax if necessary.
+ *
+ * Returns: the error quark used for #NMDeviceWimax errors.
+ **/
+GQuark
+nm_device_wimax_error_quark (void)
+{
+	static GQuark quark = 0;
+
+	if (G_UNLIKELY (quark == 0))
+		quark = g_quark_from_static_string ("nm-device-wimax-error-quark");
+	return quark;
+}
+
+/**
  * nm_device_wimax_new:
  * @connection: the #DBusGConnection
  * @path: the D-Bus object path of the WiMAX device
@@ -102,13 +115,17 @@ static guint signals[LAST_SIGNAL] = { 0 };
 GObject *
 nm_device_wimax_new (DBusGConnection *connection, const char *path)
 {
+	GObject *device;
+
 	g_return_val_if_fail (connection != NULL, NULL);
 	g_return_val_if_fail (path != NULL, NULL);
 
-	return g_object_new (NM_TYPE_DEVICE_WIMAX,
-	                     NM_OBJECT_DBUS_CONNECTION, connection,
-	                     NM_OBJECT_DBUS_PATH, path,
-	                     NULL);
+	device = g_object_new (NM_TYPE_DEVICE_WIMAX,
+						   NM_OBJECT_DBUS_CONNECTION, connection,
+						   NM_OBJECT_DBUS_PATH, path,
+						   NULL);
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return device;
 }
 
 /**
@@ -123,19 +140,10 @@ nm_device_wimax_new (DBusGConnection *connection, const char *path)
 const char *
 nm_device_wimax_get_hw_address (NMDeviceWimax *wimax)
 {
-	NMDeviceWimaxPrivate *priv;
-
 	g_return_val_if_fail (NM_IS_DEVICE_WIMAX (wimax), NULL);
 
-	priv = NM_DEVICE_WIMAX_GET_PRIVATE (wimax);
-	if (!priv->hw_address) {
-		priv->hw_address = _nm_object_get_string_property (NM_OBJECT (wimax),
-		                                                   NM_DBUS_INTERFACE_DEVICE_WIMAX,
-		                                                   DBUS_PROP_HW_ADDRESS,
-		                                                   NULL);
-	}
-
-	return priv->hw_address;
+	_nm_object_ensure_inited (NM_OBJECT (wimax));
+	return NM_DEVICE_WIMAX_GET_PRIVATE (wimax)->hw_address;
 }
 
 /**
@@ -149,11 +157,7 @@ nm_device_wimax_get_hw_address (NMDeviceWimax *wimax)
 NMWimaxNsp *
 nm_device_wimax_get_active_nsp (NMDeviceWimax *wimax)
 {
-	NMDeviceWimaxPrivate *priv;
 	NMDeviceState state;
-	char *path;
-	GValue value = { 0, };
-	GError *error = NULL;
 
 	g_return_val_if_fail (NM_IS_DEVICE_WIMAX (wimax), NULL);
 
@@ -173,23 +177,8 @@ nm_device_wimax_get_active_nsp (NMDeviceWimax *wimax)
 		break;
 	}
 
-	priv = NM_DEVICE_WIMAX_GET_PRIVATE (wimax);
-	if (priv->got_active_nsp == TRUE)
-		return priv->active_nsp;
-
-	path = _nm_object_get_object_path_property (NM_OBJECT (wimax),
-	                                            NM_DBUS_INTERFACE_DEVICE_WIMAX,
-	                                            DBUS_PROP_ACTIVE_NSP,
-	                                            &error);
-	if (error == NULL) {
-		g_value_init (&value, DBUS_TYPE_G_OBJECT_PATH);
-		g_value_take_boxed (&value, path);
-		demarshal_active_nsp (NM_OBJECT (wimax), NULL, &value, &priv->active_nsp);
-		g_value_unset (&value);
-	}
-	g_clear_error (&error);
-
-	return priv->active_nsp;
+	_nm_object_ensure_inited (NM_OBJECT (wimax));
+	return NM_DEVICE_WIMAX_GET_PRIVATE (wimax)->active_nsp;
 }
 
 /**
@@ -205,31 +194,10 @@ nm_device_wimax_get_active_nsp (NMDeviceWimax *wimax)
 const GPtrArray *
 nm_device_wimax_get_nsps (NMDeviceWimax *wimax)
 {
-	NMDeviceWimaxPrivate *priv;
-	DBusGConnection *connection;
-	GValue value = { 0, };
-	GError *error = NULL;
-	GPtrArray *temp;
-
 	g_return_val_if_fail (NM_IS_DEVICE_WIMAX (wimax), NULL);
 
-	priv = NM_DEVICE_WIMAX_GET_PRIVATE (wimax);
-	if (priv->nsps)
-		return handle_ptr_array_return (priv->nsps);
-
-	if (!org_freedesktop_NetworkManager_Device_WiMax_get_nsp_list (priv->proxy, &temp, &error)) {
-		g_warning ("%s: error getting NSPs: %s", __func__, error->message);
-		g_error_free (error);
-		return NULL;
-	}
-
-	g_value_init (&value, DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH);
-	g_value_take_boxed (&value, temp);
-	connection = nm_object_get_connection (NM_OBJECT (wimax));
-	_nm_object_array_demarshal (&value, &priv->nsps, connection, nm_wimax_nsp_new);
-	g_value_unset (&value);
-
-	return handle_ptr_array_return (priv->nsps);
+	_nm_object_ensure_inited (NM_OBJECT (wimax));
+	return handle_ptr_array_return (NM_DEVICE_WIMAX_GET_PRIVATE (wimax)->nsps);
 }
 
 /**
@@ -268,54 +236,25 @@ nm_device_wimax_get_nsp_by_path (NMDeviceWimax *wimax,
 }
 
 static void
-nsp_added_proxy (DBusGProxy *proxy, char *path, gpointer user_data)
+nsp_added (NMObject *self, NMObject *nsp)
 {
-	NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data);
-	NMDeviceWimaxPrivate *priv;
-	GObject *nsp;
-
-	g_return_if_fail (self != NULL);
-
-	nsp = G_OBJECT (nm_device_wimax_get_nsp_by_path (self, path));
-	if (!nsp) {
-		DBusGConnection *connection = nm_object_get_connection (NM_OBJECT (self));
-
-		priv = NM_DEVICE_WIMAX_GET_PRIVATE (self);
-		nsp = G_OBJECT (_nm_object_cache_get (path));
-		if (nsp) {
-			g_ptr_array_add (priv->nsps, nsp);
-		} else {
-			nsp = G_OBJECT (nm_wimax_nsp_new (connection, path));
-			if (nsp)
-				g_ptr_array_add (priv->nsps, nsp);
-		}
-	}
-
-	if (nsp)
-		g_signal_emit (self, signals[NSP_ADDED], 0, nsp);
+	g_signal_emit (self, signals[NSP_ADDED], 0, nsp);
 }
 
 static void
-nsp_removed_proxy (DBusGProxy *proxy, char *path, gpointer user_data)
+nsp_removed (NMObject *self_obj, NMObject *nsp_obj)
 {
-	NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data);
+	NMDeviceWimax *self = NM_DEVICE_WIMAX (self_obj);
 	NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self);
-	NMWimaxNsp *nsp;
-
-	g_return_if_fail (self != NULL);
-
-	nsp = nm_device_wimax_get_nsp_by_path (self, path);
-	if (nsp) {
-		if (nsp == priv->active_nsp) {
-			g_object_unref (priv->active_nsp);
-			priv->active_nsp = NULL;
-			_nm_object_queue_notify (NM_OBJECT (self), NM_DEVICE_WIMAX_ACTIVE_NSP);
-		}
+	NMWimaxNsp *nsp = NM_WIMAX_NSP (nsp_obj);
 
-		g_signal_emit (self, signals[NSP_REMOVED], 0, nsp);
-		g_ptr_array_remove (priv->nsps, nsp);
-		g_object_unref (G_OBJECT (nsp));
+	if (nsp == priv->active_nsp) {
+		g_object_unref (priv->active_nsp);
+		priv->active_nsp = NULL;
+		_nm_object_queue_notify (NM_OBJECT (self), NM_DEVICE_WIMAX_ACTIVE_NSP);
 	}
+
+	g_signal_emit (self, signals[NSP_REMOVED], 0, nsp);
 }
 
 static void
@@ -359,18 +298,10 @@ clean_up_nsps (NMDeviceWimax *self, gboolean notify)
 guint
 nm_device_wimax_get_center_frequency (NMDeviceWimax *self)
 {
-	NMDeviceWimaxPrivate *priv;
-
 	g_return_val_if_fail (NM_IS_DEVICE_WIMAX (self), 0);
 
-	priv = NM_DEVICE_WIMAX_GET_PRIVATE (self);
-	if (!priv->center_freq) {
-		priv->center_freq = _nm_object_get_uint_property (NM_OBJECT (self),
-		                                                  NM_DBUS_INTERFACE_DEVICE_WIMAX,
-		                                                  DBUS_PROP_CENTER_FREQUENCY,
-		                                                  NULL);
-	}
-	return priv->center_freq;
+	_nm_object_ensure_inited (NM_OBJECT (self));
+	return NM_DEVICE_WIMAX_GET_PRIVATE (self)->center_freq;
 }
 
 /**
@@ -387,18 +318,10 @@ nm_device_wimax_get_center_frequency (NMDeviceWimax *self)
 gint
 nm_device_wimax_get_rssi (NMDeviceWimax *self)
 {
-	NMDeviceWimaxPrivate *priv;
-
 	g_return_val_if_fail (NM_IS_DEVICE_WIMAX (self), 0);
 
-	priv = NM_DEVICE_WIMAX_GET_PRIVATE (self);
-	if (!priv->rssi) {
-		priv->rssi = _nm_object_get_int_property (NM_OBJECT (self),
-		                                          NM_DBUS_INTERFACE_DEVICE_WIMAX,
-		                                          DBUS_PROP_RSSI,
-		                                          NULL);
-	}
-	return priv->rssi;
+	_nm_object_ensure_inited (NM_OBJECT (self));
+	return NM_DEVICE_WIMAX_GET_PRIVATE (self)->rssi;
 }
 
 /**
@@ -414,18 +337,10 @@ nm_device_wimax_get_rssi (NMDeviceWimax *self)
 gint
 nm_device_wimax_get_cinr (NMDeviceWimax *self)
 {
-	NMDeviceWimaxPrivate *priv;
-
 	g_return_val_if_fail (NM_IS_DEVICE_WIMAX (self), 0);
 
-	priv = NM_DEVICE_WIMAX_GET_PRIVATE (self);
-	if (!priv->cinr) {
-		priv->cinr = _nm_object_get_int_property (NM_OBJECT (self),
-		                                          NM_DBUS_INTERFACE_DEVICE_WIMAX,
-		                                          DBUS_PROP_CINR,
-		                                          NULL);
-	}
-	return priv->cinr;
+	_nm_object_ensure_inited (NM_OBJECT (self));
+	return NM_DEVICE_WIMAX_GET_PRIVATE (self)->cinr;
 }
 
 /**
@@ -441,18 +356,10 @@ nm_device_wimax_get_cinr (NMDeviceWimax *self)
 gint
 nm_device_wimax_get_tx_power (NMDeviceWimax *self)
 {
-	NMDeviceWimaxPrivate *priv;
-
 	g_return_val_if_fail (NM_IS_DEVICE_WIMAX (self), 0);
 
-	priv = NM_DEVICE_WIMAX_GET_PRIVATE (self);
-	if (!priv->tx_power) {
-		priv->tx_power = _nm_object_get_int_property (NM_OBJECT (self),
-		                                              NM_DBUS_INTERFACE_DEVICE_WIMAX,
-		                                              DBUS_PROP_TX_POWER,
-		                                              NULL);
-	}
-	return priv->tx_power;
+	_nm_object_ensure_inited (NM_OBJECT (self));
+	return NM_DEVICE_WIMAX_GET_PRIVATE (self)->tx_power;
 }
 
 /**
@@ -466,22 +373,14 @@ nm_device_wimax_get_tx_power (NMDeviceWimax *self)
 const char *
 nm_device_wimax_get_bsid (NMDeviceWimax *self)
 {
-	NMDeviceWimaxPrivate *priv;
-
 	g_return_val_if_fail (NM_IS_DEVICE_WIMAX (self), NULL);
 
-	priv = NM_DEVICE_WIMAX_GET_PRIVATE (self);
-	if (!priv->bsid) {
-		priv->bsid = _nm_object_get_string_property (NM_OBJECT (self),
-		                                             NM_DBUS_INTERFACE_DEVICE_WIMAX,
-		                                             DBUS_PROP_BSID,
-		                                             NULL);
-	}
-	return priv->bsid;
+	_nm_object_ensure_inited (NM_OBJECT (self));
+	return NM_DEVICE_WIMAX_GET_PRIVATE (self)->bsid;
 }
 
 static gboolean
-connection_valid (NMDevice *device, NMConnection *connection)
+connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
 {
 	NMSettingConnection *s_con;
 	NMSettingWimax *s_wimax;
@@ -490,24 +389,40 @@ connection_valid (NMDevice *device, NMConnection *connection)
 	const char *hw_str;
 	struct ether_addr *hw_mac;
 
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
 	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_WIMAX_SETTING_NAME) != 0)
+	if (strcmp (ctype, NM_SETTING_WIMAX_SETTING_NAME) != 0) {
+		g_set_error (error, NM_DEVICE_WIMAX_ERROR, NM_DEVICE_WIMAX_ERROR_NOT_WIMAX_CONNECTION,
+		             "The connection was not a Wimax connection.");
 		return FALSE;
+	}
 
 	s_wimax = nm_connection_get_setting_wimax (connection);
-	if (!s_wimax)
+	if (!s_wimax) {
+		g_set_error (error, NM_DEVICE_WIMAX_ERROR, NM_DEVICE_WIMAX_ERROR_INVALID_WIMAX_CONNECTION,
+		             "The connection was not a valid Wimax connection.");
 		return FALSE;
+	}
 
 	/* Check MAC address */
 	hw_str = nm_device_wimax_get_hw_address (NM_DEVICE_WIMAX (device));
 	if (hw_str) {
 		hw_mac = ether_aton (hw_str);
+		if (!hw_mac) {
+			g_set_error (error, NM_DEVICE_WIMAX_ERROR, NM_DEVICE_WIMAX_ERROR_INVALID_DEVICE_MAC,
+			             "Invalid device MAC address.");
+			return FALSE;
+		}
 		mac = nm_setting_wimax_get_mac_address (s_wimax);
-		if (mac && hw_mac && memcmp (mac->data, hw_mac->ether_addr_octet, ETH_ALEN))
+		if (mac && hw_mac && memcmp (mac->data, hw_mac->ether_addr_octet, ETH_ALEN)) {
+			g_set_error (error, NM_DEVICE_WIMAX_ERROR, NM_DEVICE_WIMAX_ERROR_MAC_MISMATCH,
+			             "The MACs of the device and the connection didn't match.");
 			return FALSE;
+		}
 	}
 
 	return TRUE;
@@ -516,8 +431,9 @@ connection_valid (NMDevice *device, NMConnection *connection)
 /**************************************************************/
 
 static void
-nm_device_wimax_init (NMDeviceWimax *wimax)
+nm_device_wimax_init (NMDeviceWimax *device)
 {
+	_nm_device_set_device_type (NM_DEVICE (device), NM_DEVICE_TYPE_WIMAX);
 }
 
 static void
@@ -620,75 +536,40 @@ state_changed_cb (NMDevice *device, GParamSpec *pspec, gpointer user_data)
 	}
 }
 
-static gboolean
-demarshal_active_nsp (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field)
-{
-	NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (object);
-	const char *path;
-	NMWimaxNsp *nsp = NULL;
-	DBusGConnection *connection;
-
-	if (value) {
-		if (!G_VALUE_HOLDS (value, DBUS_TYPE_G_OBJECT_PATH))
-			return FALSE;
-
-		path = g_value_get_boxed (value);
-		if (path) {
-			nsp = NM_WIMAX_NSP (_nm_object_cache_get (path));
-			if (!nsp) {
-				connection = nm_object_get_connection (object);
-				nsp = NM_WIMAX_NSP (nm_wimax_nsp_new (connection, path));
-			}
-		}
-	}
-
-	priv->got_active_nsp = TRUE;
-
-	if (priv->active_nsp) {
-		g_object_unref (priv->active_nsp);
-		priv->active_nsp = NULL;
-	}
-
-	if (nsp)
-		priv->active_nsp = nsp;
-
-	_nm_object_queue_notify (object, NM_DEVICE_WIMAX_ACTIVE_NSP);
-	return TRUE;
-}
-
 static void
-register_for_property_changed (NMDeviceWimax *wimax)
+register_properties (NMDeviceWimax *wimax)
 {
 	NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (wimax);
-	const NMPropertiesChangedInfo property_changed_info[] = {
-		{ NM_DEVICE_WIMAX_HW_ADDRESS, _nm_object_demarshal_generic, &priv->hw_address },
-		{ NM_DEVICE_WIMAX_ACTIVE_NSP, demarshal_active_nsp, &priv->active_nsp },
-		{ NM_DEVICE_WIMAX_CENTER_FREQUENCY, _nm_object_demarshal_generic, &priv->center_freq },
-		{ NM_DEVICE_WIMAX_RSSI, _nm_object_demarshal_generic, &priv->rssi },
-		{ NM_DEVICE_WIMAX_CINR, _nm_object_demarshal_generic, &priv->cinr },
-		{ NM_DEVICE_WIMAX_TX_POWER, _nm_object_demarshal_generic, &priv->tx_power },
-		{ NM_DEVICE_WIMAX_BSID, _nm_object_demarshal_generic, &priv->bsid },
+	const NMPropertiesInfo property_info[] = {
+		{ NM_DEVICE_WIMAX_HW_ADDRESS, &priv->hw_address },
+		{ NM_DEVICE_WIMAX_ACTIVE_NSP, &priv->active_nsp, NULL, NM_TYPE_WIMAX_NSP },
+		{ NM_DEVICE_WIMAX_CENTER_FREQUENCY, &priv->center_freq },
+		{ NM_DEVICE_WIMAX_RSSI, &priv->rssi },
+		{ NM_DEVICE_WIMAX_CINR, &priv->cinr },
+		{ NM_DEVICE_WIMAX_TX_POWER, &priv->tx_power },
+		{ NM_DEVICE_WIMAX_BSID, &priv->bsid },
 		{ NULL },
 	};
 
-	_nm_object_handle_properties_changed (NM_OBJECT (wimax),
-										  priv->proxy,
-										  property_changed_info);
+	_nm_object_register_properties (NM_OBJECT (wimax),
+	                                priv->proxy,
+	                                property_info);
+
+	_nm_object_register_pseudo_property (NM_OBJECT (wimax),
+	                                     priv->proxy,
+	                                     "NspList",
+	                                     &priv->nsps,
+	                                     NM_TYPE_WIMAX_NSP,
+	                                     nsp_added,
+	                                     nsp_removed);
 }
 
-static GObject*
-constructor (GType type,
-		   guint n_construct_params,
-		   GObjectConstructParam *construct_params)
+static void
+constructed (GObject *object)
 {
-	GObject *object;
 	NMDeviceWimaxPrivate *priv;
 
-	object = G_OBJECT_CLASS (nm_device_wimax_parent_class)->constructor (type,
-																		 n_construct_params,
-																		 construct_params);
-	if (!object)
-		return NULL;
+	G_OBJECT_CLASS (nm_device_wimax_parent_class)->constructed (object);
 
 	priv = NM_DEVICE_WIMAX_GET_PRIVATE (object);
 
@@ -697,28 +578,12 @@ constructor (GType type,
 											 nm_object_get_path (NM_OBJECT (object)),
 											 NM_DBUS_INTERFACE_DEVICE_WIMAX);
 
-	dbus_g_proxy_add_signal (priv->proxy, "NspAdded",
-	                         DBUS_TYPE_G_OBJECT_PATH,
-	                         G_TYPE_INVALID);
-	dbus_g_proxy_connect_signal (priv->proxy, "NspAdded",
-								 G_CALLBACK (nsp_added_proxy),
-								 object, NULL);
-
-	dbus_g_proxy_add_signal (priv->proxy, "NspRemoved",
-	                         DBUS_TYPE_G_OBJECT_PATH,
-	                         G_TYPE_INVALID);
-	dbus_g_proxy_connect_signal (priv->proxy, "NspRemoved",
-								 G_CALLBACK (nsp_removed_proxy),
-								 object, NULL);
-
-	register_for_property_changed (NM_DEVICE_WIMAX (object));
+	register_properties (NM_DEVICE_WIMAX (object));
 
 	g_signal_connect (object,
 	                  "notify::" NM_DEVICE_STATE,
 	                  G_CALLBACK (state_changed_cb),
 	                  NULL);
-
-	return object;
 }
 
 static void
@@ -751,10 +616,10 @@ nm_device_wimax_class_init (NMDeviceWimaxClass *wimax_class)
 	g_type_class_add_private (wimax_class, sizeof (NMDeviceWimaxPrivate));
 
 	/* virtual methods */
-	object_class->constructor = constructor;
+	object_class->constructed = constructed;
 	object_class->get_property = get_property;
 	object_class->dispose = dispose;
-	device_class->connection_valid = connection_valid;
+	device_class->connection_compatible = connection_compatible;
 
 	/* properties */
 
diff --git a/libnm-glib/nm-device-wimax.h b/libnm-glib/nm-device-wimax.h
index 5e19bbaf..e391d4de 100644
--- a/libnm-glib/nm-device-wimax.h
+++ b/libnm-glib/nm-device-wimax.h
@@ -17,7 +17,7 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * Copyright (C) 2011 Red Hat, Inc.
+ * Copyright (C) 2011 - 2012 Red Hat, Inc.
  * Copyright (C) 2009 Novell, Inc.
  */
 
@@ -36,6 +36,25 @@ G_BEGIN_DECLS
 #define NM_IS_DEVICE_WIMAX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_DEVICE_WIMAX))
 #define NM_DEVICE_WIMAX_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_WIMAX, NMDeviceWimaxClass))
 
+/**
+ * NMDeviceWimaxError:
+ * @NM_DEVICE_WIMAX_ERROR_UNKNOWN: unknown or unclassified error
+ * @NM_DEVICE_WIMAX_ERROR_NOT_WIMAX_CONNECTION: the connection was not of WiMax type
+ * @NM_DEVICE_WIMAX_ERROR_INVALID_WIMAX_CONNECTION: the WiMax connection was invalid
+ * @NM_DEVICE_WIMAX_ERROR_INVALID_DEVICE_MAC: the device's MAC was invalid
+ * @NM_DEVICE_WIMAX_ERROR_MAC_MISMATCH: the MACs of the connection and the device mismatched
+ */
+typedef enum {
+	NM_DEVICE_WIMAX_ERROR_UNKNOWN = 0,              /*< nick=UnknownError >*/
+	NM_DEVICE_WIMAX_ERROR_NOT_WIMAX_CONNECTION,     /*< nick=NotWimaxConnection >*/
+	NM_DEVICE_WIMAX_ERROR_INVALID_WIMAX_CONNECTION, /*< nick=InvalidWimaxConnection >*/
+	NM_DEVICE_WIMAX_ERROR_INVALID_DEVICE_MAC,       /*< nick=InvalidDeviceMac >*/
+	NM_DEVICE_WIMAX_ERROR_MAC_MISMATCH,             /*< nick=MacMismatch >*/
+} NMDeviceWimaxError;
+
+#define NM_DEVICE_WIMAX_ERROR nm_device_wimax_error_quark ()
+GQuark nm_device_wimax_error_quark (void);
+
 #define NM_DEVICE_WIMAX_HW_ADDRESS       "hw-address"
 #define NM_DEVICE_WIMAX_ACTIVE_NSP       "active-nsp"
 #define NM_DEVICE_WIMAX_CENTER_FREQUENCY "center-frequency"
diff --git a/libnm-glib/nm-device.c b/libnm-glib/nm-device.c
index 1f9f3671..96a037d5 100644
--- a/libnm-glib/nm-device.c
+++ b/libnm-glib/nm-device.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>
@@ -30,16 +30,32 @@
 #include "nm-device-wifi.h"
 #include "nm-device-modem.h"
 #include "nm-device-bt.h"
+#include "nm-device-olpc-mesh.h"
 #include "nm-device-wimax.h"
+#include "nm-device-infiniband.h"
+#include "nm-device-bond.h"
+#include "nm-device-vlan.h"
 #include "nm-device.h"
 #include "nm-device-private.h"
 #include "nm-object-private.h"
 #include "nm-object-cache.h"
-#include "nm-marshal.h"
+#include "nm-glib-marshal.h"
+#include "nm-dbus-glib-types.h"
+#include "nm-glib-compat.h"
 
-#include "nm-device-bindings.h"
+static GType _nm_device_type_for_path (DBusGConnection *connection,
+                                       const char *path);
+static void _nm_device_type_for_path_async (DBusGConnection *connection,
+                                            const char *path,
+                                            NMObjectTypeCallbackFunc callback,
+                                            gpointer user_data);
 
-G_DEFINE_TYPE (NMDevice, nm_device, NM_TYPE_OBJECT)
+G_DEFINE_TYPE_WITH_CODE (NMDevice, nm_device, NM_TYPE_OBJECT,
+                         _nm_object_register_type_func (g_define_type_id, _nm_device_type_for_path,
+                                                        _nm_device_type_for_path_async);
+                         )
+
+#define DBUS_G_TYPE_UINT_STRUCT (dbus_g_type_get_struct ("GValueArray", G_TYPE_UINT, G_TYPE_UINT, G_TYPE_INVALID))
 
 #define NM_DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE, NMDevicePrivate))
 
@@ -56,17 +72,13 @@ typedef struct {
 	gboolean managed;
 	gboolean firmware_missing;
 	NMIP4Config *ip4_config;
-	gboolean got_ip4_config;
 	NMDHCP4Config *dhcp4_config;
-	gboolean got_dhcp4_config;
 	NMIP6Config *ip6_config;
-	gboolean got_ip6_config;
 	NMDHCP6Config *dhcp6_config;
-	gboolean got_dhcp6_config;
 	NMDeviceState state;
+	NMDeviceStateReason reason;
 
 	NMActiveConnection *active_connection;
-	gboolean got_active_connection;
 
 	GUdevClient *client;
 	char *product;
@@ -85,6 +97,7 @@ enum {
 	PROP_DHCP4_CONFIG,
 	PROP_IP6_CONFIG,
 	PROP_STATE,
+	PROP_STATE_REASON,
 	PROP_PRODUCT,
 	PROP_VENDOR,
 	PROP_DHCP6_CONFIG,
@@ -110,211 +123,56 @@ nm_device_init (NMDevice *device)
 	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
 
 	priv->state = NM_DEVICE_STATE_UNKNOWN;
+	priv->reason = NM_DEVICE_STATE_REASON_NONE;
 }
 
 static gboolean
-demarshal_ip4_config (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (object);
-	const char *path;
-	NMIP4Config *config = NULL;
-	DBusGConnection *connection;
-
-	if (value) {
-		if (!G_VALUE_HOLDS (value, DBUS_TYPE_G_OBJECT_PATH))
-			return FALSE;
-
-		path = g_value_get_boxed (value);
-		if (path) {
-			config = NM_IP4_CONFIG (_nm_object_cache_get (path));
-			if (!config) {
-				connection = nm_object_get_connection (object);
-				config = NM_IP4_CONFIG (nm_ip4_config_new (connection, path));
-			}
-		}
-	}
-
-	priv->got_ip4_config = TRUE;
-
-	if (priv->ip4_config) {
-		g_object_unref (priv->ip4_config);
-		priv->ip4_config = NULL;
-	}
-
-	if (config)
-		priv->ip4_config = config;
-
-	_nm_object_queue_notify (object, NM_DEVICE_IP4_CONFIG);
-	return TRUE;
-}
-
-static gboolean
-demarshal_dhcp4_config (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (object);
-	const char *path;
-	NMDHCP4Config *config = NULL;
-	DBusGConnection *connection;
-
-	if (value) {
-		if (!G_VALUE_HOLDS (value, DBUS_TYPE_G_OBJECT_PATH))
-			return FALSE;
-
-		path = g_value_get_boxed (value);
-		if (path) {
-			config = NM_DHCP4_CONFIG (_nm_object_cache_get (path));
-			if (!config) {
-				connection = nm_object_get_connection (object);
-				config = NM_DHCP4_CONFIG (nm_dhcp4_config_new (connection, path));
-			}
-		}
-	}
-
-	priv->got_dhcp4_config = TRUE;
-
-	if (priv->dhcp4_config) {
-		g_object_unref (priv->dhcp4_config);
-		priv->dhcp4_config = NULL;
-	}
-
-	if (config)
-		priv->dhcp4_config = config;
-
-	_nm_object_queue_notify (object, NM_DEVICE_DHCP4_CONFIG);
-	return TRUE;
-}
-
-static gboolean
-demarshal_ip6_config (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (object);
-	const char *path;
-	NMIP6Config *config = NULL;
-	DBusGConnection *connection;
-
-	if (value) {
-		if (!G_VALUE_HOLDS (value, DBUS_TYPE_G_OBJECT_PATH))
-			return FALSE;
-
-		path = g_value_get_boxed (value);
-		if (path) {
-			config = NM_IP6_CONFIG (_nm_object_cache_get (path));
-			if (!config) {
-				connection = nm_object_get_connection (object);
-				config = NM_IP6_CONFIG (nm_ip6_config_new (connection, path));
-			}
-		}
-	}
-
-	priv->got_ip6_config = TRUE;
-
-	if (priv->ip6_config) {
-		g_object_unref (priv->ip6_config);
-		priv->ip6_config = NULL;
-	}
-
-	if (config)
-		priv->ip6_config = config;
-
-	_nm_object_queue_notify (object, NM_DEVICE_IP6_CONFIG);
-	return TRUE;
-}
-
-static gboolean
-demarshal_dhcp6_config (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field)
+demarshal_state_reason (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field)
 {
 	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (object);
-	const char *path;
-	NMDHCP6Config *config = NULL;
-	DBusGConnection *connection;
-
-	if (value) {
-		if (!G_VALUE_HOLDS (value, DBUS_TYPE_G_OBJECT_PATH))
-			return FALSE;
-
-		path = g_value_get_boxed (value);
-		if (path) {
-			config = NM_DHCP6_CONFIG (_nm_object_cache_get (path));
-			if (!config) {
-				connection = nm_object_get_connection (object);
-				config = NM_DHCP6_CONFIG (nm_dhcp6_config_new (connection, path));
-			}
-		}
-	}
 
-	priv->got_dhcp6_config = TRUE;
-
-	if (priv->dhcp6_config) {
-		g_object_unref (priv->dhcp6_config);
-		priv->dhcp6_config = NULL;
-	}
-
-	if (config)
-		priv->dhcp6_config = config;
-
-	_nm_object_queue_notify (object, NM_DEVICE_DHCP6_CONFIG);
-	return TRUE;
-}
-
-static gboolean
-demarshal_active_connection (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (object);
-	const char *path;
-	NMActiveConnection *active = NULL;
-	DBusGConnection *connection;
-
-	if (!G_VALUE_HOLDS (value, DBUS_TYPE_G_OBJECT_PATH))
+	if (!G_VALUE_HOLDS (value, DBUS_G_TYPE_UINT_STRUCT))
 		return FALSE;
 
-	priv->got_active_connection = TRUE;
+	dbus_g_type_struct_get (value,
+	                        0, &priv->state,
+	                        1, &priv->reason,
+	                        G_MAXUINT);
 
-	if (value) {
-		path = g_value_get_boxed (value);
-		if (path) {
-			active = NM_ACTIVE_CONNECTION (_nm_object_cache_get (path));
-			if (!active) {
-				connection = nm_object_get_connection (object);
-				active = NM_ACTIVE_CONNECTION (nm_active_connection_new (connection, path));
-			}
-		}
-	}
-
-	if (priv->active_connection) {
-		g_object_unref (priv->active_connection);
-		priv->active_connection = NULL;
-	}
-
-	if (active)
-		priv->active_connection = active;
-
-	_nm_object_queue_notify (object, NM_DEVICE_ACTIVE_CONNECTION);
+	_nm_object_queue_notify (object, NM_DEVICE_STATE_REASON);
 	return TRUE;
 }
 
 static void
-register_for_property_changed (NMDevice *device)
+register_properties (NMDevice *device)
 {
 	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
-	const NMPropertiesChangedInfo property_changed_info[] = {
-		{ NM_DEVICE_UDI,              _nm_object_demarshal_generic, &priv->udi },
-		{ NM_DEVICE_INTERFACE,        _nm_object_demarshal_generic, &priv->iface },
-		{ NM_DEVICE_IP_INTERFACE,     _nm_object_demarshal_generic, &priv->ip_iface },
-		{ NM_DEVICE_DRIVER,           _nm_object_demarshal_generic, &priv->driver },
-		{ NM_DEVICE_CAPABILITIES,     _nm_object_demarshal_generic, &priv->capabilities },
-		{ NM_DEVICE_MANAGED,          _nm_object_demarshal_generic, &priv->managed },
-		{ NM_DEVICE_FIRMWARE_MISSING, _nm_object_demarshal_generic, &priv->firmware_missing },
-		{ NM_DEVICE_IP4_CONFIG,       demarshal_ip4_config,         &priv->ip4_config },
-		{ NM_DEVICE_DHCP4_CONFIG,     demarshal_dhcp4_config,       &priv->dhcp4_config },
-		{ NM_DEVICE_IP6_CONFIG,       demarshal_ip6_config,         &priv->ip6_config },
-		{ NM_DEVICE_DHCP6_CONFIG,     demarshal_dhcp6_config,       &priv->dhcp6_config },
-		{ NM_DEVICE_ACTIVE_CONNECTION,demarshal_active_connection,  &priv->active_connection },
+	const NMPropertiesInfo property_info[] = {
+		{ NM_DEVICE_UDI,               &priv->udi },
+		{ NM_DEVICE_INTERFACE,         &priv->iface },
+		{ NM_DEVICE_IP_INTERFACE,      &priv->ip_iface },
+		{ NM_DEVICE_DRIVER,            &priv->driver },
+		{ NM_DEVICE_CAPABILITIES,      &priv->capabilities },
+		{ NM_DEVICE_MANAGED,           &priv->managed },
+		{ 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 },
+		{ NM_DEVICE_IP6_CONFIG,        &priv->ip6_config, NULL, NM_TYPE_IP6_CONFIG },
+		{ NM_DEVICE_DHCP6_CONFIG,      &priv->dhcp6_config, NULL, NM_TYPE_DHCP6_CONFIG },
+		{ NM_DEVICE_STATE,             &priv->state },
+		{ NM_DEVICE_STATE_REASON,      &priv->state, demarshal_state_reason },
+		{ NM_DEVICE_ACTIVE_CONNECTION, &priv->active_connection, NULL, NM_TYPE_ACTIVE_CONNECTION },
+
+		/* Properties that exist in D-Bus but that we don't track */
+		{ "ip4-address", NULL },
+		{ "device-type", NULL },
+
 		{ NULL },
 	};
 
-	_nm_object_handle_properties_changed (NM_OBJECT (device),
-	                                     priv->proxy,
-	                                     property_changed_info);
+	_nm_object_register_properties (NM_OBJECT (device),
+	                                priv->proxy,
+	                                property_info);
 }
 
 static void
@@ -325,39 +183,68 @@ device_state_changed (DBusGProxy *proxy,
                       gpointer user_data)
 {
 	NMDevice *self = NM_DEVICE (user_data);
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
 
-	if (priv->state != new_state) {
-		priv->state = new_state;
+	if (old_state != new_state) {
+		/* Update state here since the PropertyChanged signal for state
+		 * might come in a bit later, but a client might ask for the
+		 * state via nm_device_get_state() as a result of this signal.
+		 * When the PC signal does come in that will trigger the glib
+		 * property notify signal so we don't need to do that here.
+		 */
+		NM_DEVICE_GET_PRIVATE (self)->state = new_state;
 		g_signal_emit (self, signals[STATE_CHANGED], 0, new_state, old_state, reason);
-		_nm_object_queue_notify (NM_OBJECT (self), "state");
 	}
 }
 
-static GObject*
-constructor (GType type,
-			 guint n_construct_params,
-			 GObjectConstructParam *construct_params)
+static GType
+_nm_device_gtype_from_dtype (NMDeviceType dtype)
+{
+	switch (dtype) {
+	case NM_DEVICE_TYPE_ETHERNET:
+		return NM_TYPE_DEVICE_ETHERNET;
+	case NM_DEVICE_TYPE_WIFI:
+		return NM_TYPE_DEVICE_WIFI;
+	case NM_DEVICE_TYPE_MODEM:
+		return NM_TYPE_DEVICE_MODEM;
+	case NM_DEVICE_TYPE_BT:
+		return NM_TYPE_DEVICE_BT;
+	case NM_DEVICE_TYPE_OLPC_MESH:
+		return NM_TYPE_DEVICE_OLPC_MESH;
+	case NM_DEVICE_TYPE_WIMAX:
+		return NM_TYPE_DEVICE_WIMAX;
+	case NM_DEVICE_TYPE_INFINIBAND:
+		return NM_TYPE_DEVICE_INFINIBAND;
+	case NM_DEVICE_TYPE_BOND:
+		return NM_TYPE_DEVICE_BOND;
+	case NM_DEVICE_TYPE_VLAN:
+		return NM_TYPE_DEVICE_VLAN;
+	default:
+		g_warning ("Unknown device type %d", dtype);
+		return G_TYPE_INVALID;
+	}
+}
+
+static void
+constructed (GObject *object)
 {
-	NMObject *object;
 	NMDevicePrivate *priv;
 
-	object = (NMObject *) G_OBJECT_CLASS (nm_device_parent_class)->constructor (type,
-																				n_construct_params,
-																				construct_params);
-	if (!object)
-		return NULL;
+	G_OBJECT_CLASS (nm_device_parent_class)->constructed (object);
 
 	priv = NM_DEVICE_GET_PRIVATE (object);
+	/* Catch failure of subclasses to call _nm_device_set_device_type() */
+	g_warn_if_fail (priv->device_type != NM_DEVICE_TYPE_UNKNOWN);
+	/* Catch a subclass setting the wrong type */
+	g_warn_if_fail (G_OBJECT_TYPE (object) == _nm_device_gtype_from_dtype (priv->device_type));
 
-	priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (object),
+	priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (NM_OBJECT (object)),
 											 NM_DBUS_SERVICE,
-											 nm_object_get_path (object),
+											 nm_object_get_path (NM_OBJECT (object)),
 											 NM_DBUS_INTERFACE_DEVICE);
 
-	register_for_property_changed (NM_DEVICE (object));
+	register_properties (NM_DEVICE (object));
 
-	dbus_g_object_register_marshaller (_nm_marshal_VOID__UINT_UINT_UINT,
+	dbus_g_object_register_marshaller (_nm_glib_marshal_VOID__UINT_UINT_UINT,
 									   G_TYPE_NONE,
 									   G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT,
 									   G_TYPE_INVALID);
@@ -371,8 +258,6 @@ constructor (GType type,
 								 G_CALLBACK (device_state_changed),
 								 NM_DEVICE (object),
 								 NULL);
-
-	return G_OBJECT (object);
 }
 
 static void
@@ -426,6 +311,7 @@ get_property (GObject *object,
               GParamSpec *pspec)
 {
 	NMDevice *device = NM_DEVICE (object);
+	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
 
 	switch (prop_id) {
 	case PROP_DEVICE_TYPE:
@@ -467,6 +353,14 @@ get_property (GObject *object,
 	case PROP_STATE:
 		g_value_set_uint (value, nm_device_get_state (device));
 		break;
+	case PROP_STATE_REASON:
+		g_value_set_boxed (value,
+		                   dbus_g_type_specialized_construct (DBUS_G_TYPE_UINT_STRUCT));
+		dbus_g_type_struct_set (value,
+		                        0, priv->state,
+		                        1, priv->reason,
+		                        G_MAXUINT);
+		break;
 	case PROP_ACTIVE_CONNECTION:
 		g_value_set_object (value, nm_device_get_active_connection (device));
 		break;
@@ -510,7 +404,7 @@ nm_device_class_init (NMDeviceClass *device_class)
 	g_type_class_add_private (device_class, sizeof (NMDevicePrivate));
 
 	/* virtual methods */
-	object_class->constructor = constructor;
+	object_class->constructed = constructed;
 	object_class->get_property = get_property;
 	object_class->set_property = set_property;
 	object_class->dispose = dispose;
@@ -556,7 +450,7 @@ nm_device_class_init (NMDeviceClass *device_class)
 						  "Device Type",
 						  "Numeric device type (ie ethernet, wifi, etc)",
 						  NM_DEVICE_TYPE_UNKNOWN, G_MAXUINT32, NM_DEVICE_TYPE_UNKNOWN,
-						  G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+						  G_PARAM_READABLE));
 	/**
 	 * NMDevice:udi:
 	 *
@@ -694,6 +588,19 @@ nm_device_class_init (NMDeviceClass *device_class)
 						  G_PARAM_READABLE));
 
 	/**
+	 * NMDevice:state-reason:
+	 *
+	 * The state and reason of the device.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_STATE_REASON,
+		 g_param_spec_boxed (NM_DEVICE_STATE_REASON,
+		                     "StateReason",
+		                     "StateReason",
+		                     DBUS_G_TYPE_UINT_STRUCT,
+		                     G_PARAM_READABLE));
+
+	/**
 	 * NMDevice:active-connection:
 	 *
 	 * The #NMActiveConnection object that "owns" this device during activation.
@@ -747,40 +654,50 @@ nm_device_class_init (NMDeviceClass *device_class)
 				    G_SIGNAL_RUN_FIRST,
 				    G_STRUCT_OFFSET (NMDeviceClass, state_changed),
 				    NULL, NULL,
-				    _nm_marshal_VOID__UINT_UINT_UINT,
+				    _nm_glib_marshal_VOID__UINT_UINT_UINT,
 				    G_TYPE_NONE, 3,
 				    G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT);
 }
 
 /**
- * nm_device_new:
- * @connection: the #DBusGConnection
- * @path: the DBus object path of the device
- *
- * Creates a new #NMDevice.
+ * _nm_device_set_device_type:
+ * @device: the device
+ * @dtype: the NM device type
  *
- * Returns: (transfer full): a new device
+ * Sets the NM device type if it wasn't set during construction.  INTERNAL
+ * ONLY METHOD.
  **/
-GObject *
-nm_device_new (DBusGConnection *connection, const char *path)
+void
+_nm_device_set_device_type (NMDevice *device, NMDeviceType dtype)
+{
+	NMDevicePrivate *priv;
+
+	g_return_if_fail (device != NULL);
+	g_return_if_fail (dtype != NM_DEVICE_TYPE_UNKNOWN);
+
+	priv = NM_DEVICE_GET_PRIVATE (device);
+	if (priv->device_type == NM_DEVICE_TYPE_UNKNOWN)
+		priv->device_type = dtype;
+	else
+		g_warn_if_fail (dtype == priv->device_type);
+}
+
+static GType
+_nm_device_type_for_path (DBusGConnection *connection,
+                          const char *path)
 {
 	DBusGProxy *proxy;
 	GError *err = NULL;
 	GValue value = {0,};
-	GType dtype = 0;
-	NMDevice *device = NULL;
 	NMDeviceType nm_dtype;
 
-	g_return_val_if_fail (connection != NULL, NULL);
-	g_return_val_if_fail (path != NULL, NULL);
-
 	proxy = dbus_g_proxy_new_for_name (connection,
 									   NM_DBUS_SERVICE,
 									   path,
 									   "org.freedesktop.DBus.Properties");
 	if (!proxy) {
 		g_warning ("%s: couldn't create D-Bus object proxy.", __func__);
-		return NULL;
+		return G_TYPE_INVALID;
 	}
 
 	if (!dbus_g_proxy_call (proxy,
@@ -789,44 +706,100 @@ nm_device_new (DBusGConnection *connection, const char *path)
 						    G_TYPE_STRING, "DeviceType",
 						    G_TYPE_INVALID,
 						    G_TYPE_VALUE, &value, G_TYPE_INVALID)) {
+		g_object_unref (proxy);
 		g_warning ("Error in get_property: %s\n", err->message);
 		g_error_free (err);
-		goto out;
 	}
+	g_object_unref (proxy);
 
 	nm_dtype = g_value_get_uint (&value);
-	switch (nm_dtype) {
-	case NM_DEVICE_TYPE_ETHERNET:
-		dtype = NM_TYPE_DEVICE_ETHERNET;
-		break;
-	case NM_DEVICE_TYPE_WIFI:
-		dtype = NM_TYPE_DEVICE_WIFI;
-		break;
-	case NM_DEVICE_TYPE_MODEM:
-		dtype = NM_TYPE_DEVICE_MODEM;
-		break;
-	case NM_DEVICE_TYPE_BT:
-		dtype = NM_TYPE_DEVICE_BT;
-		break;
-	case NM_DEVICE_TYPE_WIMAX:
-		dtype = NM_TYPE_DEVICE_WIMAX;
-		break;
-	default:
-		g_warning ("Unknown device type %d", g_value_get_uint (&value));
-		break;
-	}
+	return _nm_device_gtype_from_dtype (nm_dtype);
+}
 
-	if (dtype) {
-		device = (NMDevice *) g_object_new (dtype,
-											NM_OBJECT_DBUS_CONNECTION, connection,
-											NM_OBJECT_DBUS_PATH, path,
-											NM_DEVICE_DEVICE_TYPE, nm_dtype,
-											NULL);
+/**
+ * nm_device_new:
+ * @connection: the #DBusGConnection
+ * @path: the DBus object path of the device
+ *
+ * Creates a new #NMDevice.
+ *
+ * Returns: (transfer full): a new device
+ **/
+GObject *
+nm_device_new (DBusGConnection *connection, const char *path)
+{
+	GType dtype;
+	NMDevice *device = NULL;
+
+	g_return_val_if_fail (connection != NULL, NULL);
+	g_return_val_if_fail (path != NULL, NULL);
+
+	dtype = _nm_device_type_for_path (connection, path);
+	if (dtype == G_TYPE_INVALID)
+		return NULL;
+
+	device = (NMDevice *) g_object_new (dtype,
+	                                    NM_OBJECT_DBUS_CONNECTION, connection,
+	                                    NM_OBJECT_DBUS_PATH, path,
+	                                    NULL);
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return G_OBJECT (device);
+}
+
+typedef struct {
+	DBusGConnection *connection;
+	NMObjectTypeCallbackFunc callback;
+	gpointer user_data;
+} NMDeviceAsyncData;
+
+static void
+async_got_type (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data)
+{
+	NMDeviceAsyncData *async_data = user_data;
+	GValue value = G_VALUE_INIT;
+	const char *path = dbus_g_proxy_get_path (proxy);
+	GError *error = NULL;
+	GType type;
+
+	if (dbus_g_proxy_end_call (proxy, call, &error,
+	                           G_TYPE_VALUE, &value,
+	                           G_TYPE_INVALID)) {
+		NMDeviceType dtype;
+
+		dtype = g_value_get_uint (&value);
+		type = _nm_device_gtype_from_dtype (dtype);
+	} else {
+		g_warning ("%s: could not read properties for %s: %s", __func__, path, error->message);
+		g_error_free (error);
+		type = G_TYPE_INVALID;
 	}
 
-out:
+	async_data->callback (type, async_data->user_data);
 	g_object_unref (proxy);
-	return G_OBJECT (device);
+	g_slice_free (NMDeviceAsyncData, async_data);
+}
+
+static void
+_nm_device_type_for_path_async (DBusGConnection *connection,
+                                const char *path,
+                                NMObjectTypeCallbackFunc callback,
+                                gpointer user_data)
+{
+	NMDeviceAsyncData *async_data;
+	DBusGProxy *proxy;
+
+	async_data = g_slice_new (NMDeviceAsyncData);
+	async_data->connection = connection;
+	async_data->callback = callback;
+	async_data->user_data = user_data;
+
+	proxy = dbus_g_proxy_new_for_name (connection, NM_DBUS_SERVICE, path,
+	                                   "org.freedesktop.DBus.Properties");
+	dbus_g_proxy_begin_call (proxy, "Get",
+	                         async_got_type, async_data, NULL,
+	                         G_TYPE_STRING, NM_DBUS_INTERFACE_DEVICE,
+	                         G_TYPE_STRING, "DeviceType",
+	                         G_TYPE_INVALID);
 }
 
 /**
@@ -841,19 +814,10 @@ out:
 const char *
 nm_device_get_iface (NMDevice *device)
 {
-	NMDevicePrivate *priv;
-
 	g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
 
-	priv = NM_DEVICE_GET_PRIVATE (device);
-	if (!priv->iface) {
-		priv->iface = _nm_object_get_string_property (NM_OBJECT (device),
-		                                             NM_DBUS_INTERFACE_DEVICE,
-		                                             "Interface",
-		                                             NULL);
-	}
-
-	return priv->iface;
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return NM_DEVICE_GET_PRIVATE (device)->iface;
 }
 
 /**
@@ -869,19 +833,10 @@ nm_device_get_iface (NMDevice *device)
 const char *
 nm_device_get_ip_iface (NMDevice *device)
 {
-	NMDevicePrivate *priv;
-
 	g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
 
-	priv = NM_DEVICE_GET_PRIVATE (device);
-	if (!priv->ip_iface) {
-		priv->ip_iface = _nm_object_get_string_property (NM_OBJECT (device),
-		                                                 NM_DBUS_INTERFACE_DEVICE,
-		                                                 "IpInterface",
-		                                                 NULL);
-	}
-
-	return priv->ip_iface;
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return NM_DEVICE_GET_PRIVATE (device)->ip_iface;
 }
 
 /**
@@ -913,19 +868,10 @@ nm_device_get_device_type (NMDevice *self)
 const char *
 nm_device_get_udi (NMDevice *device)
 {
-	NMDevicePrivate *priv;
-
 	g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
 
-	priv = NM_DEVICE_GET_PRIVATE (device);
-	if (!priv->udi) {
-		priv->udi = _nm_object_get_string_property (NM_OBJECT (device),
-		                                           NM_DBUS_INTERFACE_DEVICE,
-		                                           "Udi",
-		                                           NULL);
-	}
-
-	return priv->udi;
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return NM_DEVICE_GET_PRIVATE (device)->udi;
 }
 
 /**
@@ -940,19 +886,10 @@ nm_device_get_udi (NMDevice *device)
 const char *
 nm_device_get_driver (NMDevice *device)
 {
-	NMDevicePrivate *priv;
-
 	g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
 
-	priv = NM_DEVICE_GET_PRIVATE (device);
-	if (!priv->driver) {
-		priv->driver = _nm_object_get_string_property (NM_OBJECT (device),
-		                                              NM_DBUS_INTERFACE_DEVICE,
-		                                              "Driver",
-		                                              NULL);
-	}
-
-	return priv->driver;
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return NM_DEVICE_GET_PRIVATE (device)->driver;
 }
 
 /**
@@ -966,19 +903,10 @@ nm_device_get_driver (NMDevice *device)
 NMDeviceCapabilities
 nm_device_get_capabilities (NMDevice *device)
 {
-	NMDevicePrivate *priv;
-
 	g_return_val_if_fail (NM_IS_DEVICE (device), 0);
 
-	priv = NM_DEVICE_GET_PRIVATE (device);
-	if (!priv->capabilities) {
-		priv->capabilities = _nm_object_get_uint_property (NM_OBJECT (device),
-		                                                  NM_DBUS_INTERFACE_DEVICE,
-		                                                  "Capabilities",
-		                                                  NULL);
-	}
-
-	return priv->capabilities;
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return NM_DEVICE_GET_PRIVATE (device)->capabilities;
 }
 
 /**
@@ -992,19 +920,10 @@ nm_device_get_capabilities (NMDevice *device)
 gboolean
 nm_device_get_managed (NMDevice *device)
 {
-	NMDevicePrivate *priv;
-
 	g_return_val_if_fail (NM_IS_DEVICE (device), 0);
 
-	priv = NM_DEVICE_GET_PRIVATE (device);
-	if (!priv->managed) {
-		priv->managed = _nm_object_get_boolean_property (NM_OBJECT (device),
-		                                                NM_DBUS_INTERFACE_DEVICE,
-		                                                "Managed",
-		                                                NULL);
-	}
-
-	return priv->managed;
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return NM_DEVICE_GET_PRIVATE (device)->managed;
 }
 
 /**
@@ -1020,19 +939,10 @@ nm_device_get_managed (NMDevice *device)
 gboolean
 nm_device_get_firmware_missing (NMDevice *device)
 {
-	NMDevicePrivate *priv;
-
 	g_return_val_if_fail (NM_IS_DEVICE (device), 0);
 
-	priv = NM_DEVICE_GET_PRIVATE (device);
-	if (!priv->firmware_missing) {
-		priv->firmware_missing = _nm_object_get_boolean_property (NM_OBJECT (device),
-		                                                          NM_DBUS_INTERFACE_DEVICE,
-		                                                          "FirmwareMissing",
-		                                                          NULL);
-	}
-
-	return priv->firmware_missing;
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return NM_DEVICE_GET_PRIVATE (device)->firmware_missing;
 }
 
 /**
@@ -1046,30 +956,10 @@ nm_device_get_firmware_missing (NMDevice *device)
 NMIP4Config *
 nm_device_get_ip4_config (NMDevice *device)
 {
-	NMDevicePrivate *priv;
-	char *path;
-	GValue value = { 0, };
-	GError *error = NULL;
-
 	g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
 
-	priv = NM_DEVICE_GET_PRIVATE (device);
-	if (priv->got_ip4_config == TRUE)
-		return priv->ip4_config;
-
-	path = _nm_object_get_object_path_property (NM_OBJECT (device),
-	                                            NM_DBUS_INTERFACE_DEVICE,
-	                                            "Ip4Config",
-	                                            &error);
-	if (error == NULL) {
-		g_value_init (&value, DBUS_TYPE_G_OBJECT_PATH);
-		g_value_take_boxed (&value, path);
-		demarshal_ip4_config (NM_OBJECT (device), NULL, &value, &priv->ip4_config);
-		g_value_unset (&value);
-	}
-	g_clear_error (&error);
-
-	return priv->ip4_config;
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return NM_DEVICE_GET_PRIVATE (device)->ip4_config;
 }
 
 /**
@@ -1084,30 +974,10 @@ nm_device_get_ip4_config (NMDevice *device)
 NMDHCP4Config *
 nm_device_get_dhcp4_config (NMDevice *device)
 {
-	NMDevicePrivate *priv;
-	char *path;
-	GValue value = { 0, };
-	GError *error = NULL;
-
 	g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
 
-	priv = NM_DEVICE_GET_PRIVATE (device);
-	if (priv->got_dhcp4_config == TRUE)
-		return priv->dhcp4_config;
-
-	path = _nm_object_get_object_path_property (NM_OBJECT (device),
-	                                            NM_DBUS_INTERFACE_DEVICE,
-	                                            "Dhcp4Config",
-	                                            &error);
-	if (error == NULL) {
-		g_value_init (&value, DBUS_TYPE_G_OBJECT_PATH);
-		g_value_take_boxed (&value, path);
-		demarshal_dhcp4_config (NM_OBJECT (device), NULL, &value, &priv->dhcp4_config);
-		g_value_unset (&value);
-	}
-	g_clear_error (&error);
-
-	return priv->dhcp4_config;
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return NM_DEVICE_GET_PRIVATE (device)->dhcp4_config;
 }
 
 /**
@@ -1121,30 +991,10 @@ nm_device_get_dhcp4_config (NMDevice *device)
 NMIP6Config *
 nm_device_get_ip6_config (NMDevice *device)
 {
-	NMDevicePrivate *priv;
-	char *path;
-	GValue value = { 0, };
-	GError *error = NULL;
-
 	g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
 
-	priv = NM_DEVICE_GET_PRIVATE (device);
-	if (priv->got_ip6_config == TRUE)
-		return priv->ip6_config;
-
-	path = _nm_object_get_object_path_property (NM_OBJECT (device),
-	                                            NM_DBUS_INTERFACE_DEVICE,
-	                                            "Ip6Config",
-	                                            &error);
-	if (error == NULL) {
-		g_value_init (&value, DBUS_TYPE_G_OBJECT_PATH);
-		g_value_take_boxed (&value, path);
-		demarshal_ip6_config (NM_OBJECT (device), NULL, &value, &priv->ip6_config);
-		g_value_unset (&value);
-	}
-	g_clear_error (&error);
-
-	return priv->ip6_config;
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return NM_DEVICE_GET_PRIVATE (device)->ip6_config;
 }
 
 /**
@@ -1159,30 +1009,10 @@ nm_device_get_ip6_config (NMDevice *device)
 NMDHCP6Config *
 nm_device_get_dhcp6_config (NMDevice *device)
 {
-	NMDevicePrivate *priv;
-	char *path;
-	GValue value = { 0, };
-	GError *error = NULL;
-
 	g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
 
-	priv = NM_DEVICE_GET_PRIVATE (device);
-	if (priv->got_dhcp6_config == TRUE)
-		return priv->dhcp6_config;
-
-	path = _nm_object_get_object_path_property (NM_OBJECT (device),
-	                                            NM_DBUS_INTERFACE_DEVICE,
-	                                            "Dhcp6Config",
-	                                            &error);
-	if (error == NULL) {
-		g_value_init (&value, DBUS_TYPE_G_OBJECT_PATH);
-		g_value_take_boxed (&value, path);
-		demarshal_dhcp6_config (NM_OBJECT (device), NULL, &value, &priv->dhcp6_config);
-		g_value_unset (&value);
-	}
-	g_clear_error (&error);
-
-	return priv->dhcp6_config;
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return NM_DEVICE_GET_PRIVATE (device)->dhcp6_config;
 }
 
 /**
@@ -1196,19 +1026,31 @@ nm_device_get_dhcp6_config (NMDevice *device)
 NMDeviceState
 nm_device_get_state (NMDevice *device)
 {
-	NMDevicePrivate *priv;
-
 	g_return_val_if_fail (NM_IS_DEVICE (device), NM_DEVICE_STATE_UNKNOWN);
 
-	priv = NM_DEVICE_GET_PRIVATE (device);
-	if (priv->state == NM_DEVICE_STATE_UNKNOWN) {
-		priv->state = _nm_object_get_uint_property (NM_OBJECT (device), 
-		                                           NM_DBUS_INTERFACE_DEVICE,
-		                                           "State",
-		                                           NULL);
-	}
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return NM_DEVICE_GET_PRIVATE (device)->state;
+}
 
-	return priv->state;
+/**
+ * nm_device_get_state_reason:
+ * @device: a #NMDevice
+ * @reason: (out) (allow-none): location to store reason (#NMDeviceStateReason), or NULL
+ *
+ * Gets the current #NMDevice state (return value) and the reason for entering
+ * the state (@reason argument).
+ *
+ * Returns: the current device state
+ **/
+NMDeviceState
+nm_device_get_state_reason (NMDevice *device, NMDeviceStateReason *reason)
+{
+	g_return_val_if_fail (NM_IS_DEVICE (device), NM_DEVICE_STATE_UNKNOWN);
+
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	if (reason)
+		*reason = NM_DEVICE_GET_PRIVATE (device)->reason;
+	return NM_DEVICE_GET_PRIVATE (device)->state;
 }
 
 /**
@@ -1223,30 +1065,10 @@ nm_device_get_state (NMDevice *device)
 NMActiveConnection *
 nm_device_get_active_connection (NMDevice *device)
 {
-	NMDevicePrivate *priv;
-	char *path;
-	GValue value = { 0, };
-	GError *error = NULL;
-
 	g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
 
-	priv = NM_DEVICE_GET_PRIVATE (device);
-	if (priv->got_active_connection == TRUE)
-		return priv->active_connection;
-
-	path = _nm_object_get_object_path_property (NM_OBJECT (device),
-	                                            NM_DBUS_INTERFACE_DEVICE,
-	                                            "ActiveConnection",
-	                                            &error);
-	if (error == NULL) {
-		g_value_init (&value, DBUS_TYPE_G_OBJECT_PATH);
-		g_value_take_boxed (&value, path);
-		demarshal_active_connection (NM_OBJECT (device), NULL, &value, &priv->active_connection);
-		g_value_unset (&value);
-	}
-	g_clear_error (&error);
-
-	return priv->active_connection;
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return NM_DEVICE_GET_PRIVATE (device)->active_connection;
 }
 
 /* From hostap, Copyright (c) 2002-2005, Jouni Malinen <jkmaline@cc.hut.fi> */
@@ -1453,11 +1275,14 @@ typedef struct {
 
 static void
 deactivate_cb (DBusGProxy *proxy,
-               GError *error,
+               DBusGProxyCall *call,
                gpointer user_data)
 {
 	DeactivateInfo *info = user_data;
+	GError *error = NULL;
 
+	dbus_g_proxy_end_call (proxy, call, &error,
+	                       G_TYPE_INVALID);
 	if (info->fn)
 		info->fn (info->device, error, info->user_data);
 	else if (error) {
@@ -1467,6 +1292,7 @@ deactivate_cb (DBusGProxy *proxy,
 		           error ? error->code : -1,
 		           error && error->message ? error->message : "(unknown)");
 	}
+	g_clear_error (&error);
 
 	g_object_unref (info->device);
 	g_slice_free (DeactivateInfo, info);
@@ -1497,9 +1323,9 @@ nm_device_disconnect (NMDevice *device,
 	info->user_data = user_data;
 	info->device = g_object_ref (device);
 
-	org_freedesktop_NetworkManager_Device_disconnect_async (NM_DEVICE_GET_PRIVATE (device)->proxy,
-	                                                        deactivate_cb,
-	                                                        info);
+	dbus_g_proxy_begin_call (NM_DEVICE_GET_PRIVATE (device)->proxy, "Disconnect",
+	                         deactivate_cb, info, NULL,
+	                         G_TYPE_INVALID);
 }
 
 /**
@@ -1521,8 +1347,35 @@ nm_device_disconnect (NMDevice *device,
 gboolean
 nm_device_connection_valid (NMDevice *device, NMConnection *connection)
 {
-	if (NM_DEVICE_GET_CLASS (device)->connection_valid)
-		return NM_DEVICE_GET_CLASS (device)->connection_valid (device, connection);
+	return nm_device_connection_compatible (device, connection, NULL);
+}
+
+/**
+ * nm_device_connection_compatible:
+ * @device: an #NMDevice to validate @connection against
+ * @connection: an #NMConnection to validate against @device
+ * @error: return location for a #GError, or %NULL
+ *
+ * Validates a given connection for a given #NMDevice object and returns
+ * whether the connection may be activated with the device. For example if
+ * @device is a WiFi device that supports only WEP encryption, the connection
+ * will only be valid if it is a WiFi connection which describes a WEP or open
+ * network, and will not be valid if it describes a WPA network, or if it is
+ * an Ethernet, Bluetooth, WWAN, etc connection that is incompatible with the
+ * device.
+ *
+ * This function does the same as nm_device_connection_valid(), i.e. checking
+ * compatibility of the given device and connection. But, in addition, it sets
+ * GError when FALSE is returned.
+ *
+ * Returns: %TRUE if the connection may be activated with this device, %FALSE
+ * if is incompatible with the device's capabilities and characteristics.
+ **/
+gboolean
+nm_device_connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
+{
+	if (NM_DEVICE_GET_CLASS (device)->connection_compatible)
+		return NM_DEVICE_GET_CLASS (device)->connection_compatible (device, connection, error);
 	return FALSE;
 }
 
@@ -1537,7 +1390,8 @@ nm_device_connection_valid (NMDevice *device, NMConnection *connection)
  * contain any WiFi connections in @connections that allow connection to
  * unencrypted or WEP-enabled SSIDs.  The returned list will not contain
  * Ethernet, Bluetooth, WiFi WPA connections, or any other connection that is
- * incompatible with the device.
+ * incompatible with the device. To get the full list of connections see
+ * nm_remote_settings_list_connections().
  *
  * Returns: (transfer container) (element-type NetworkManager.Connection): a
  * list of #NMConnection objects that could be activated with the given @device.
diff --git a/libnm-glib/nm-device.h b/libnm-glib/nm-device.h
index e21e71b1..50301dc9 100644
--- a/libnm-glib/nm-device.h
+++ b/libnm-glib/nm-device.h
@@ -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.
  */
 
 #ifndef NM_DEVICE_H
@@ -58,6 +58,7 @@ G_BEGIN_DECLS
 #define NM_DEVICE_IP6_CONFIG "ip6-config"
 #define NM_DEVICE_DHCP6_CONFIG "dhcp6-config"
 #define NM_DEVICE_STATE "state"
+#define NM_DEVICE_STATE_REASON "state-reason"
 #define NM_DEVICE_ACTIVE_CONNECTION "active-connection"
 #define NM_DEVICE_VENDOR "vendor"
 #define NM_DEVICE_PRODUCT "product"
@@ -75,8 +76,9 @@ typedef struct {
 	                       NMDeviceState old_state,
 	                       NMDeviceStateReason reason);
 
-	gboolean (*connection_valid)   (NMDevice *device,
-	                                NMConnection *connection);
+	gboolean (*connection_compatible) (NMDevice *device,
+	                                   NMConnection *connection,
+	                                   GError **error);
 
 	/* Padding for future expansion */
 	void (*_reserved1) (void);
@@ -104,6 +106,7 @@ NMDHCP4Config *      nm_device_get_dhcp4_config     (NMDevice *device);
 NMIP6Config *        nm_device_get_ip6_config       (NMDevice *device);
 NMDHCP6Config *      nm_device_get_dhcp6_config     (NMDevice *device);
 NMDeviceState        nm_device_get_state            (NMDevice *device);
+NMDeviceState        nm_device_get_state_reason     (NMDevice *device, NMDeviceStateReason *reason);
 NMActiveConnection * nm_device_get_active_connection(NMDevice *device);
 const char *         nm_device_get_product          (NMDevice *device);
 const char *         nm_device_get_vendor           (NMDevice *device);
@@ -120,6 +123,10 @@ GSList *             nm_device_filter_connections   (NMDevice *device,
 gboolean             nm_device_connection_valid     (NMDevice *device,
                                                      NMConnection *connection);
 
+gboolean             nm_device_connection_compatible (NMDevice *device,
+                                                      NMConnection *connection,
+                                                      GError **error);
+
 G_END_DECLS
 
 #endif /* NM_DEVICE_H */
diff --git a/libnm-glib/nm-dhcp4-config.c b/libnm-glib/nm-dhcp4-config.c
index 8299de02..2074e6d1 100644
--- a/libnm-glib/nm-dhcp4-config.c
+++ b/libnm-glib/nm-dhcp4-config.c
@@ -77,47 +77,38 @@ demarshal_dhcp4_options (NMObject *object, GParamSpec *pspec, GValue *value, gpo
 }
 
 static void
-register_for_property_changed (NMDHCP4Config *config)
+register_properties (NMDHCP4Config *config)
 {
 	NMDHCP4ConfigPrivate *priv = NM_DHCP4_CONFIG_GET_PRIVATE (config);
-	const NMPropertiesChangedInfo property_changed_info[] = {
-		{ NM_DHCP4_CONFIG_OPTIONS,   demarshal_dhcp4_options,  &priv->options },
+	const NMPropertiesInfo property_info[] = {
+		{ NM_DHCP4_CONFIG_OPTIONS,   &priv->options, demarshal_dhcp4_options },
 		{ NULL },
 	};
 
-	_nm_object_handle_properties_changed (NM_OBJECT (config),
-	                                     priv->proxy,
-	                                     property_changed_info);
+	_nm_object_register_properties (NM_OBJECT (config),
+	                                priv->proxy,
+	                                property_info);
 }
 
-static GObject*
-constructor (GType type,
-		   guint n_construct_params,
-		   GObjectConstructParam *construct_params)
+static void
+constructed (GObject *object)
 {
-	NMObject *object;
 	DBusGConnection *connection;
 	NMDHCP4ConfigPrivate *priv;
 
-	object = (NMObject *) G_OBJECT_CLASS (nm_dhcp4_config_parent_class)->constructor (type,
-																 n_construct_params,
-																 construct_params);
-	if (!object)
-		return NULL;
+	G_OBJECT_CLASS (nm_dhcp4_config_parent_class)->constructed (object);
 
 	priv = NM_DHCP4_CONFIG_GET_PRIVATE (object);
 	priv->options = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
 
-	connection = nm_object_get_connection (object);
+	connection = nm_object_get_connection (NM_OBJECT (object));
 
 	priv->proxy = dbus_g_proxy_new_for_name (connection,
 										   NM_DBUS_SERVICE,
-										   nm_object_get_path (object),
+										   nm_object_get_path (NM_OBJECT (object)),
 										   NM_DBUS_INTERFACE_DHCP4_CONFIG);
 
-	register_for_property_changed (NM_DHCP4_CONFIG (object));
-
-	return G_OBJECT (object);
+	register_properties (NM_DHCP4_CONFIG (object));
 }
 
 static void
@@ -159,7 +150,7 @@ nm_dhcp4_config_class_init (NMDHCP4ConfigClass *config_class)
 	g_type_class_add_private (config_class, sizeof (NMDHCP4ConfigPrivate));
 
 	/* virtual methods */
-	object_class->constructor = constructor;
+	object_class->constructed = constructed;
 	object_class->get_property = get_property;
 	object_class->finalize = finalize;
 
@@ -212,24 +203,10 @@ nm_dhcp4_config_new (DBusGConnection *connection, const char *object_path)
 GHashTable *
 nm_dhcp4_config_get_options (NMDHCP4Config *config)
 {
-	NMDHCP4ConfigPrivate *priv = NM_DHCP4_CONFIG_GET_PRIVATE (config);
-	GValue value = { 0, };
-
-	if (g_hash_table_size (priv->options))
-		return priv->options;
-
-	if (!_nm_object_get_property (NM_OBJECT (config),
-	                              NM_DBUS_INTERFACE_DHCP4_CONFIG,
-	                              "Options",
-	                              &value,
-	                              NULL))
-		goto out;
-
-	demarshal_dhcp4_options (NM_OBJECT (config), NULL, &value, &priv->options);	
-	g_value_unset (&value);
+	g_return_val_if_fail (NM_IS_DHCP4_CONFIG (config), NULL);
 
-out:
-	return priv->options;
+	_nm_object_ensure_inited (NM_OBJECT (config));
+	return NM_DHCP4_CONFIG_GET_PRIVATE (config)->options;
 }
 
 /**
diff --git a/libnm-glib/nm-dhcp6-config.c b/libnm-glib/nm-dhcp6-config.c
index 00698ed5..3764cbf0 100644
--- a/libnm-glib/nm-dhcp6-config.c
+++ b/libnm-glib/nm-dhcp6-config.c
@@ -77,47 +77,38 @@ demarshal_dhcp6_options (NMObject *object, GParamSpec *pspec, GValue *value, gpo
 }
 
 static void
-register_for_property_changed (NMDHCP6Config *config)
+register_properties (NMDHCP6Config *config)
 {
 	NMDHCP6ConfigPrivate *priv = NM_DHCP6_CONFIG_GET_PRIVATE (config);
-	const NMPropertiesChangedInfo property_changed_info[] = {
-		{ NM_DHCP6_CONFIG_OPTIONS,   demarshal_dhcp6_options,  &priv->options },
+	const NMPropertiesInfo property_info[] = {
+		{ NM_DHCP6_CONFIG_OPTIONS,   &priv->options, demarshal_dhcp6_options },
 		{ NULL },
 	};
 
-	_nm_object_handle_properties_changed (NM_OBJECT (config),
-	                                     priv->proxy,
-	                                     property_changed_info);
+	_nm_object_register_properties (NM_OBJECT (config),
+	                                priv->proxy,
+	                                property_info);
 }
 
-static GObject*
-constructor (GType type,
-		   guint n_construct_params,
-		   GObjectConstructParam *construct_params)
+static void
+constructed (GObject *object)
 {
-	NMObject *object;
 	DBusGConnection *connection;
 	NMDHCP6ConfigPrivate *priv;
 
-	object = (NMObject *) G_OBJECT_CLASS (nm_dhcp6_config_parent_class)->constructor (type,
-																 n_construct_params,
-																 construct_params);
-	if (!object)
-		return NULL;
+	G_OBJECT_CLASS (nm_dhcp6_config_parent_class)->constructed (object);
 
 	priv = NM_DHCP6_CONFIG_GET_PRIVATE (object);
 	priv->options = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
 
-	connection = nm_object_get_connection (object);
+	connection = nm_object_get_connection (NM_OBJECT (object));
 
 	priv->proxy = dbus_g_proxy_new_for_name (connection,
 										   NM_DBUS_SERVICE,
-										   nm_object_get_path (object),
+										   nm_object_get_path (NM_OBJECT (object)),
 										   NM_DBUS_INTERFACE_DHCP6_CONFIG);
 
-	register_for_property_changed (NM_DHCP6_CONFIG (object));
-
-	return G_OBJECT (object);
+	register_properties (NM_DHCP6_CONFIG (object));
 }
 
 static void
@@ -159,7 +150,7 @@ nm_dhcp6_config_class_init (NMDHCP6ConfigClass *config_class)
 	g_type_class_add_private (config_class, sizeof (NMDHCP6ConfigPrivate));
 
 	/* virtual methods */
-	object_class->constructor = constructor;
+	object_class->constructed = constructed;
 	object_class->get_property = get_property;
 	object_class->finalize = finalize;
 
@@ -212,24 +203,10 @@ nm_dhcp6_config_new (DBusGConnection *connection, const char *object_path)
 GHashTable *
 nm_dhcp6_config_get_options (NMDHCP6Config *config)
 {
-	NMDHCP6ConfigPrivate *priv = NM_DHCP6_CONFIG_GET_PRIVATE (config);
-	GValue value = { 0, };
-
-	if (g_hash_table_size (priv->options))
-		return priv->options;
-
-	if (!_nm_object_get_property (NM_OBJECT (config),
-	                              NM_DBUS_INTERFACE_DHCP6_CONFIG,
-	                              "Options",
-	                              &value,
-	                              NULL))
-		goto out;
-
-	demarshal_dhcp6_options (NM_OBJECT (config), NULL, &value, &priv->options);	
-	g_value_unset (&value);
+	g_return_val_if_fail (NM_IS_DHCP6_CONFIG (config), NULL);
 
-out:
-	return priv->options;
+	_nm_object_ensure_inited (NM_OBJECT (config));
+	return NM_DHCP6_CONFIG_GET_PRIVATE (config)->options;
 }
 
 /**
diff --git a/libnm-glib/nm-glib-enum-types.c b/libnm-glib/nm-glib-enum-types.c
new file mode 100644
index 00000000..9fc4de96
--- /dev/null
+++ b/libnm-glib/nm-glib-enum-types.c
@@ -0,0 +1,367 @@
+
+
+
+/* Generated by glib-mkenums. Do not edit */
+
+#include "nm-glib-enum-types.h"
+
+#include "nm-object.h" 
+#include "nm-client.h" 
+#include "nm-device.h" 
+#include "nm-device-ethernet.h" 
+#include "nm-device-infiniband.h" 
+#include "nm-device-wifi.h" 
+#include "nm-device-bt.h" 
+#include "nm-device-olpc-mesh.h" 
+#include "nm-device-bond.h" 
+#include "nm-device-vlan.h" 
+#include "nm-access-point.h" 
+#include "nm-ip4-config.h" 
+#include "nm-device-modem.h" 
+#include "nm-vpn-connection.h" 
+#include "nm-types.h" 
+#include "nm-active-connection.h" 
+#include "nm-dhcp4-config.h" 
+#include "nm-ip6-config.h" 
+#include "nm-dhcp6-config.h" 
+#include "nm-remote-connection.h" 
+#include "nm-remote-settings.h" 
+#include "nm-secret-agent.h" 
+#include "nm-device-wimax.h" 
+#include "nm-wimax-nsp.h"
+
+GType
+nm_client_permission_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_CLIENT_PERMISSION_NONE, "NM_CLIENT_PERMISSION_NONE", "none" },
+        { NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK, "NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK", "enable-disable-network" },
+        { NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIFI, "NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIFI", "enable-disable-wifi" },
+        { NM_CLIENT_PERMISSION_ENABLE_DISABLE_WWAN, "NM_CLIENT_PERMISSION_ENABLE_DISABLE_WWAN", "enable-disable-wwan" },
+        { NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIMAX, "NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIMAX", "enable-disable-wimax" },
+        { NM_CLIENT_PERMISSION_SLEEP_WAKE, "NM_CLIENT_PERMISSION_SLEEP_WAKE", "sleep-wake" },
+        { NM_CLIENT_PERMISSION_NETWORK_CONTROL, "NM_CLIENT_PERMISSION_NETWORK_CONTROL", "network-control" },
+        { NM_CLIENT_PERMISSION_WIFI_SHARE_PROTECTED, "NM_CLIENT_PERMISSION_WIFI_SHARE_PROTECTED", "wifi-share-protected" },
+        { NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN, "NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN", "wifi-share-open" },
+        { NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM, "NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM", "settings-modify-system" },
+        { NM_CLIENT_PERMISSION_SETTINGS_MODIFY_OWN, "NM_CLIENT_PERMISSION_SETTINGS_MODIFY_OWN", "settings-modify-own" },
+        { NM_CLIENT_PERMISSION_SETTINGS_MODIFY_HOSTNAME, "NM_CLIENT_PERMISSION_SETTINGS_MODIFY_HOSTNAME", "settings-modify-hostname" },
+        { NM_CLIENT_PERMISSION_LAST, "NM_CLIENT_PERMISSION_LAST", "last" },
+        { 0, NULL, NULL }
+      };
+      GType g_define_type_id =
+        g_enum_register_static (g_intern_static_string ("NMClientPermission"), values);
+      g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+    }
+
+  return g_define_type_id__volatile;
+}
+GType
+nm_client_permission_result_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_CLIENT_PERMISSION_RESULT_UNKNOWN, "NM_CLIENT_PERMISSION_RESULT_UNKNOWN", "unknown" },
+        { NM_CLIENT_PERMISSION_RESULT_YES, "NM_CLIENT_PERMISSION_RESULT_YES", "yes" },
+        { NM_CLIENT_PERMISSION_RESULT_AUTH, "NM_CLIENT_PERMISSION_RESULT_AUTH", "auth" },
+        { NM_CLIENT_PERMISSION_RESULT_NO, "NM_CLIENT_PERMISSION_RESULT_NO", "no" },
+        { 0, NULL, NULL }
+      };
+      GType g_define_type_id =
+        g_enum_register_static (g_intern_static_string ("NMClientPermissionResult"), values);
+      g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+    }
+
+  return g_define_type_id__volatile;
+}
+GType
+nm_device_ethernet_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_ETHERNET_ERROR_UNKNOWN, "NM_DEVICE_ETHERNET_ERROR_UNKNOWN", "UnknownError" },
+        { NM_DEVICE_ETHERNET_ERROR_NOT_ETHERNET_CONNECTION, "NM_DEVICE_ETHERNET_ERROR_NOT_ETHERNET_CONNECTION", "NotEthernetConnection" },
+        { NM_DEVICE_ETHERNET_ERROR_INVALID_ETHERNET_CONNECTION, "NM_DEVICE_ETHERNET_ERROR_INVALID_ETHERNET_CONNECTION", "InvalidEthernetConnection" },
+        { NM_DEVICE_ETHERNET_ERROR_INVALID_DEVICE_MAC, "NM_DEVICE_ETHERNET_ERROR_INVALID_DEVICE_MAC", "InvalidDeviceMac" },
+        { NM_DEVICE_ETHERNET_ERROR_MAC_MISMATCH, "NM_DEVICE_ETHERNET_ERROR_MAC_MISMATCH", "MacMismatch" },
+        { 0, NULL, NULL }
+      };
+      GType g_define_type_id =
+        g_enum_register_static (g_intern_static_string ("NMDeviceEthernetError"), values);
+      g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+    }
+
+  return g_define_type_id__volatile;
+}
+GType
+nm_device_infiniband_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_INFINIBAND_ERROR_UNKNOWN, "NM_DEVICE_INFINIBAND_ERROR_UNKNOWN", "UnknownError" },
+        { NM_DEVICE_INFINIBAND_ERROR_NOT_INFINIBAND_CONNECTION, "NM_DEVICE_INFINIBAND_ERROR_NOT_INFINIBAND_CONNECTION", "NotInfinibandConnection" },
+        { NM_DEVICE_INFINIBAND_ERROR_INVALID_INFINIBAND_CONNECTION, "NM_DEVICE_INFINIBAND_ERROR_INVALID_INFINIBAND_CONNECTION", "InvalidInfinibandConnection" },
+        { NM_DEVICE_INFINIBAND_ERROR_INVALID_DEVICE_MAC, "NM_DEVICE_INFINIBAND_ERROR_INVALID_DEVICE_MAC", "InvalidDeviceMac" },
+        { NM_DEVICE_INFINIBAND_ERROR_MAC_MISMATCH, "NM_DEVICE_INFINIBAND_ERROR_MAC_MISMATCH", "MacMismatch" },
+        { 0, NULL, NULL }
+      };
+      GType g_define_type_id =
+        g_enum_register_static (g_intern_static_string ("NMDeviceInfinibandError"), 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;
+
+  if (g_once_init_enter (&g_define_type_id__volatile))
+    {
+      static const GEnumValue values[] = {
+        { NM_DEVICE_WIFI_ERROR_UNKNOWN, "NM_DEVICE_WIFI_ERROR_UNKNOWN", "UnknownError" },
+        { NM_DEVICE_WIFI_ERROR_NOT_WIFI_CONNECTION, "NM_DEVICE_WIFI_ERROR_NOT_WIFI_CONNECTION", "NotWifiConnection" },
+        { NM_DEVICE_WIFI_ERROR_INVALID_WIFI_CONNECTION, "NM_DEVICE_WIFI_ERROR_INVALID_WIFI_CONNECTION", "InvalidWifiConnection" },
+        { NM_DEVICE_WIFI_ERROR_INVALID_DEVICE_MAC, "NM_DEVICE_WIFI_ERROR_INVALID_DEVICE_MAC", "InvalidDeviceMac" },
+        { NM_DEVICE_WIFI_ERROR_MAC_MISMATCH, "NM_DEVICE_WIFI_ERROR_MAC_MISMATCH", "MacMismatch" },
+        { NM_DEVICE_WIFI_ERROR_MISSING_DEVICE_WPA_CAPS, "NM_DEVICE_WIFI_ERROR_MISSING_DEVICE_WPA_CAPS", "MissingDeviceWpaCaps" },
+        { NM_DEVICE_WIFI_ERROR_MISSING_DEVICE_RSN_CAPS, "NM_DEVICE_WIFI_ERROR_MISSING_DEVICE_RSN_CAPS", "MissingDeviceRsnCaps" },
+        { 0, NULL, NULL }
+      };
+      GType g_define_type_id =
+        g_enum_register_static (g_intern_static_string ("NMDeviceWifiError"), values);
+      g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+    }
+
+  return g_define_type_id__volatile;
+}
+GType
+nm_device_bt_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_BT_ERROR_UNKNOWN, "NM_DEVICE_BT_ERROR_UNKNOWN", "UnknownError" },
+        { NM_DEVICE_BT_ERROR_NOT_BT_CONNECTION, "NM_DEVICE_BT_ERROR_NOT_BT_CONNECTION", "NotBtConnection" },
+        { NM_DEVICE_BT_ERROR_INVALID_BT_CONNECTION, "NM_DEVICE_BT_ERROR_INVALID_BT_CONNECTION", "InvalidBtConnection" },
+        { NM_DEVICE_BT_ERROR_INVALID_DEVICE_MAC, "NM_DEVICE_BT_ERROR_INVALID_DEVICE_MAC", "InvalidDeviceMac" },
+        { NM_DEVICE_BT_ERROR_MAC_MISMATCH, "NM_DEVICE_BT_ERROR_MAC_MISMATCH", "MacMismatch" },
+        { NM_DEVICE_BT_ERROR_MISSING_DEVICE_CAPS, "NM_DEVICE_BT_ERROR_MISSING_DEVICE_CAPS", "MissingDeviceCaps" },
+        { 0, NULL, NULL }
+      };
+      GType g_define_type_id =
+        g_enum_register_static (g_intern_static_string ("NMDeviceBtError"), values);
+      g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+    }
+
+  return g_define_type_id__volatile;
+}
+GType
+nm_device_olpc_mesh_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_OLPC_MESH_ERROR_UNKNOWN, "NM_DEVICE_OLPC_MESH_ERROR_UNKNOWN", "UnknownError" },
+        { NM_DEVICE_OLPC_MESH_ERROR_NOT_OLPC_MESH_CONNECTION, "NM_DEVICE_OLPC_MESH_ERROR_NOT_OLPC_MESH_CONNECTION", "NotOlpcMeshConnection" },
+        { NM_DEVICE_OLPC_MESH_ERROR_INVALID_OLPC_MESH_CONNECTION, "NM_DEVICE_OLPC_MESH_ERROR_INVALID_OLPC_MESH_CONNECTION", "InvalidOlpcMeshConnection" },
+        { 0, NULL, NULL }
+      };
+      GType g_define_type_id =
+        g_enum_register_static (g_intern_static_string ("NMDeviceOlpcMeshError"), values);
+      g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+    }
+
+  return g_define_type_id__volatile;
+}
+GType
+nm_device_bond_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_BOND_ERROR_UNKNOWN, "NM_DEVICE_BOND_ERROR_UNKNOWN", "UnknownError" },
+        { NM_DEVICE_BOND_ERROR_NOT_BOND_CONNECTION, "NM_DEVICE_BOND_ERROR_NOT_BOND_CONNECTION", "NotBondConnection" },
+        { NM_DEVICE_BOND_ERROR_INVALID_BOND_CONNECTION, "NM_DEVICE_BOND_ERROR_INVALID_BOND_CONNECTION", "InvalidBondConnection" },
+        { NM_DEVICE_BOND_ERROR_INTERFACE_MISMATCH, "NM_DEVICE_BOND_ERROR_INTERFACE_MISMATCH", "InterfaceMismatch" },
+        { 0, NULL, NULL }
+      };
+      GType g_define_type_id =
+        g_enum_register_static (g_intern_static_string ("NMDeviceBondError"), values);
+      g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+    }
+
+  return g_define_type_id__volatile;
+}
+GType
+nm_device_vlan_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_VLAN_ERROR_UNKNOWN, "NM_DEVICE_VLAN_ERROR_UNKNOWN", "UnknownError" },
+        { NM_DEVICE_VLAN_ERROR_NOT_VLAN_CONNECTION, "NM_DEVICE_VLAN_ERROR_NOT_VLAN_CONNECTION", "NotVlanConnection" },
+        { NM_DEVICE_VLAN_ERROR_INVALID_VLAN_CONNECTION, "NM_DEVICE_VLAN_ERROR_INVALID_VLAN_CONNECTION", "InvalidVlanConnection" },
+        { NM_DEVICE_VLAN_ERROR_ID_MISMATCH, "NM_DEVICE_VLAN_ERROR_ID_MISMATCH", "IdMismatch" },
+        { NM_DEVICE_VLAN_ERROR_INTERFACE_MISMATCH, "NM_DEVICE_VLAN_ERROR_INTERFACE_MISMATCH", "InterfaceMismatch" },
+        { 0, NULL, NULL }
+      };
+      GType g_define_type_id =
+        g_enum_register_static (g_intern_static_string ("NMDeviceVlanError"), values);
+      g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+    }
+
+  return g_define_type_id__volatile;
+}
+GType
+nm_device_modem_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_MODEM_ERROR_UNKNOWN, "NM_DEVICE_MODEM_ERROR_UNKNOWN", "UnknownError" },
+        { NM_DEVICE_MODEM_ERROR_NOT_MODEM_CONNECTION, "NM_DEVICE_MODEM_ERROR_NOT_MODEM_CONNECTION", "NotModemConnection" },
+        { NM_DEVICE_MODEM_ERROR_INVALID_MODEM_CONNECTION, "NM_DEVICE_MODEM_ERROR_INVALID_MODEM_CONNECTION", "InvalidModemConnection" },
+        { NM_DEVICE_MODEM_ERROR_MISSING_DEVICE_CAPS, "NM_DEVICE_MODEM_ERROR_MISSING_DEVICE_CAPS", "MissingDeviceCaps" },
+        { 0, NULL, NULL }
+      };
+      GType g_define_type_id =
+        g_enum_register_static (g_intern_static_string ("NMDeviceModemError"), values);
+      g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+    }
+
+  return g_define_type_id__volatile;
+}
+GType
+nm_remote_settings_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_REMOTE_SETTINGS_ERROR_UNKNOWN, "NM_REMOTE_SETTINGS_ERROR_UNKNOWN", "UnknownError" },
+        { NM_REMOTE_SETTINGS_ERROR_CONNECTION_REMOVED, "NM_REMOTE_SETTINGS_ERROR_CONNECTION_REMOVED", "ConnectionRemoved" },
+        { NM_REMOTE_SETTINGS_ERROR_CONNECTION_UNAVAILABLE, "NM_REMOTE_SETTINGS_ERROR_CONNECTION_UNAVAILABLE", "ConnectionUnavailable" },
+        { 0, NULL, NULL }
+      };
+      GType g_define_type_id =
+        g_enum_register_static (g_intern_static_string ("NMRemoteSettingsError"), values);
+      g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+    }
+
+  return g_define_type_id__volatile;
+}
+GType
+nm_secret_agent_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_SECRET_AGENT_ERROR_NOT_AUTHORIZED, "NM_SECRET_AGENT_ERROR_NOT_AUTHORIZED", "NotAuthorized" },
+        { NM_SECRET_AGENT_ERROR_INVALID_CONNECTION, "NM_SECRET_AGENT_ERROR_INVALID_CONNECTION", "InvalidConnection" },
+        { NM_SECRET_AGENT_ERROR_USER_CANCELED, "NM_SECRET_AGENT_ERROR_USER_CANCELED", "UserCanceled" },
+        { NM_SECRET_AGENT_ERROR_AGENT_CANCELED, "NM_SECRET_AGENT_ERROR_AGENT_CANCELED", "AgentCanceled" },
+        { NM_SECRET_AGENT_ERROR_INTERNAL_ERROR, "NM_SECRET_AGENT_ERROR_INTERNAL_ERROR", "InternalError" },
+        { NM_SECRET_AGENT_ERROR_NO_SECRETS, "NM_SECRET_AGENT_ERROR_NO_SECRETS", "NoSecrets" },
+        { 0, NULL, NULL }
+      };
+      GType g_define_type_id =
+        g_enum_register_static (g_intern_static_string ("NMSecretAgentError"), values);
+      g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+    }
+
+  return g_define_type_id__volatile;
+}
+GType
+nm_secret_agent_get_secrets_flags_get_type (void)
+{
+  static volatile gsize g_define_type_id__volatile = 0;
+
+  if (g_once_init_enter (&g_define_type_id__volatile))
+    {
+      static const GEnumValue values[] = {
+        { NM_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" },
+        { 0, NULL, NULL }
+      };
+      GType g_define_type_id =
+        g_enum_register_static (g_intern_static_string ("NMSecretAgentGetSecretsFlags"), values);
+      g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+    }
+
+  return g_define_type_id__volatile;
+}
+GType
+nm_device_wimax_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_WIMAX_ERROR_UNKNOWN, "NM_DEVICE_WIMAX_ERROR_UNKNOWN", "UnknownError" },
+        { NM_DEVICE_WIMAX_ERROR_NOT_WIMAX_CONNECTION, "NM_DEVICE_WIMAX_ERROR_NOT_WIMAX_CONNECTION", "NotWimaxConnection" },
+        { NM_DEVICE_WIMAX_ERROR_INVALID_WIMAX_CONNECTION, "NM_DEVICE_WIMAX_ERROR_INVALID_WIMAX_CONNECTION", "InvalidWimaxConnection" },
+        { NM_DEVICE_WIMAX_ERROR_INVALID_DEVICE_MAC, "NM_DEVICE_WIMAX_ERROR_INVALID_DEVICE_MAC", "InvalidDeviceMac" },
+        { NM_DEVICE_WIMAX_ERROR_MAC_MISMATCH, "NM_DEVICE_WIMAX_ERROR_MAC_MISMATCH", "MacMismatch" },
+        { 0, NULL, NULL }
+      };
+      GType g_define_type_id =
+        g_enum_register_static (g_intern_static_string ("NMDeviceWimaxError"), values);
+      g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+    }
+
+  return g_define_type_id__volatile;
+}
+GType
+nm_wimax_nsp_network_type_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_WIMAX_NSP_NETWORK_TYPE_UNKNOWN, "NM_WIMAX_NSP_NETWORK_TYPE_UNKNOWN", "unknown" },
+        { NM_WIMAX_NSP_NETWORK_TYPE_HOME, "NM_WIMAX_NSP_NETWORK_TYPE_HOME", "home" },
+        { NM_WIMAX_NSP_NETWORK_TYPE_PARTNER, "NM_WIMAX_NSP_NETWORK_TYPE_PARTNER", "partner" },
+        { NM_WIMAX_NSP_NETWORK_TYPE_ROAMING_PARTNER, "NM_WIMAX_NSP_NETWORK_TYPE_ROAMING_PARTNER", "roaming-partner" },
+        { 0, NULL, NULL }
+      };
+      GType g_define_type_id =
+        g_enum_register_static (g_intern_static_string ("NMWimaxNspNetworkType"), values);
+      g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+    }
+
+  return g_define_type_id__volatile;
+}
+
+
+
diff --git a/libnm-glib/nm-glib-enum-types.h b/libnm-glib/nm-glib-enum-types.h
new file mode 100644
index 00000000..9aa5fa90
--- /dev/null
+++ b/libnm-glib/nm-glib-enum-types.h
@@ -0,0 +1,47 @@
+
+
+
+/* Generated by glib-mkenums. Do not edit */
+
+#ifndef __NM_GLIB_ENUM_TYPES_H__
+#define __NM_GLIB_ENUM_TYPES_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+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;
+#define NM_TYPE_CLIENT_PERMISSION_RESULT (nm_client_permission_result_get_type ())
+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_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;
+#define NM_TYPE_DEVICE_BT_ERROR (nm_device_bt_error_get_type ())
+GType nm_device_olpc_mesh_error_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_DEVICE_OLPC_MESH_ERROR (nm_device_olpc_mesh_error_get_type ())
+GType nm_device_bond_error_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_DEVICE_BOND_ERROR (nm_device_bond_error_get_type ())
+GType nm_device_vlan_error_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_DEVICE_VLAN_ERROR (nm_device_vlan_error_get_type ())
+GType nm_device_modem_error_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_DEVICE_MODEM_ERROR (nm_device_modem_error_get_type ())
+GType nm_remote_settings_error_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_REMOTE_SETTINGS_ERROR (nm_remote_settings_error_get_type ())
+GType nm_secret_agent_error_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_SECRET_AGENT_ERROR (nm_secret_agent_error_get_type ())
+GType nm_secret_agent_get_secrets_flags_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_SECRET_AGENT_GET_SECRETS_FLAGS (nm_secret_agent_get_secrets_flags_get_type ())
+GType nm_device_wimax_error_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_DEVICE_WIMAX_ERROR (nm_device_wimax_error_get_type ())
+GType nm_wimax_nsp_network_type_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_WIMAX_NSP_NETWORK_TYPE (nm_wimax_nsp_network_type_get_type ())
+G_END_DECLS
+
+#endif /* __NM_GLIB_ENUM_TYPES_H__ */
+
+
+
diff --git a/libnm-glib/nm-glib-marshal.c b/libnm-glib/nm-glib-marshal.c
new file mode 100644
index 00000000..a6ca0113
--- /dev/null
+++ b/libnm-glib/nm-glib-marshal.c
@@ -0,0 +1,167 @@
+#include "nm-glib-marshal.h"
+
+#include	<glib-object.h>
+
+
+#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_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)
+#define g_marshal_value_peek_long(v)     g_value_get_long (v)
+#define g_marshal_value_peek_ulong(v)    g_value_get_ulong (v)
+#define g_marshal_value_peek_int64(v)    g_value_get_int64 (v)
+#define g_marshal_value_peek_uint64(v)   g_value_get_uint64 (v)
+#define g_marshal_value_peek_enum(v)     g_value_get_enum (v)
+#define g_marshal_value_peek_flags(v)    g_value_get_flags (v)
+#define g_marshal_value_peek_float(v)    g_value_get_float (v)
+#define g_marshal_value_peek_double(v)   g_value_get_double (v)
+#define g_marshal_value_peek_string(v)   (char*) g_value_get_string (v)
+#define g_marshal_value_peek_param(v)    g_value_get_param (v)
+#define g_marshal_value_peek_boxed(v)    g_value_get_boxed (v)
+#define g_marshal_value_peek_pointer(v)  g_value_get_pointer (v)
+#define g_marshal_value_peek_object(v)   g_value_get_object (v)
+#define g_marshal_value_peek_variant(v)  g_value_get_variant (v)
+#else /* !G_ENABLE_DEBUG */
+/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
+ *          Do not access GValues directly in your code. Instead, use the
+ *          g_value_get_*() functions
+ */
+#define g_marshal_value_peek_boolean(v)  (v)->data[0].v_int
+#define g_marshal_value_peek_char(v)     (v)->data[0].v_int
+#define g_marshal_value_peek_uchar(v)    (v)->data[0].v_uint
+#define g_marshal_value_peek_int(v)      (v)->data[0].v_int
+#define g_marshal_value_peek_uint(v)     (v)->data[0].v_uint
+#define g_marshal_value_peek_long(v)     (v)->data[0].v_long
+#define g_marshal_value_peek_ulong(v)    (v)->data[0].v_ulong
+#define g_marshal_value_peek_int64(v)    (v)->data[0].v_int64
+#define g_marshal_value_peek_uint64(v)   (v)->data[0].v_uint64
+#define g_marshal_value_peek_enum(v)     (v)->data[0].v_long
+#define g_marshal_value_peek_flags(v)    (v)->data[0].v_ulong
+#define g_marshal_value_peek_float(v)    (v)->data[0].v_float
+#define g_marshal_value_peek_double(v)   (v)->data[0].v_double
+#define g_marshal_value_peek_string(v)   (v)->data[0].v_pointer
+#define g_marshal_value_peek_param(v)    (v)->data[0].v_pointer
+#define g_marshal_value_peek_boxed(v)    (v)->data[0].v_pointer
+#define g_marshal_value_peek_pointer(v)  (v)->data[0].v_pointer
+#define g_marshal_value_peek_object(v)   (v)->data[0].v_pointer
+#define g_marshal_value_peek_variant(v)  (v)->data[0].v_pointer
+#endif /* !G_ENABLE_DEBUG */
+
+
+/* VOID:STRING,STRING,STRING (nm-glib-marshal.list:1) */
+void
+_nm_glib_marshal_VOID__STRING_STRING_STRING (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__STRING_STRING_STRING) (gpointer     data1,
+                                                           gpointer     arg_1,
+                                                           gpointer     arg_2,
+                                                           gpointer     arg_3,
+                                                           gpointer     data2);
+  register GMarshalFunc_VOID__STRING_STRING_STRING callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+
+  g_return_if_fail (n_param_values == 4);
+
+  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__STRING_STRING_STRING) (marshal_data ? marshal_data : cc->callback);
+
+  callback (data1,
+            g_marshal_value_peek_string (param_values + 1),
+            g_marshal_value_peek_string (param_values + 2),
+            g_marshal_value_peek_string (param_values + 3),
+            data2);
+}
+
+/* VOID:UINT,UINT (nm-glib-marshal.list:2) */
+void
+_nm_glib_marshal_VOID__UINT_UINT (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__UINT_UINT) (gpointer     data1,
+                                                guint        arg_1,
+                                                guint        arg_2,
+                                                gpointer     data2);
+  register GMarshalFunc_VOID__UINT_UINT 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__UINT_UINT) (marshal_data ? marshal_data : cc->callback);
+
+  callback (data1,
+            g_marshal_value_peek_uint (param_values + 1),
+            g_marshal_value_peek_uint (param_values + 2),
+            data2);
+}
+
+/* VOID:UINT,UINT,UINT (nm-glib-marshal.list:3) */
+void
+_nm_glib_marshal_VOID__UINT_UINT_UINT (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__UINT_UINT_UINT) (gpointer     data1,
+                                                     guint        arg_1,
+                                                     guint        arg_2,
+                                                     guint        arg_3,
+                                                     gpointer     data2);
+  register GMarshalFunc_VOID__UINT_UINT_UINT callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+
+  g_return_if_fail (n_param_values == 4);
+
+  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__UINT_UINT_UINT) (marshal_data ? marshal_data : cc->callback);
+
+  callback (data1,
+            g_marshal_value_peek_uint (param_values + 1),
+            g_marshal_value_peek_uint (param_values + 2),
+            g_marshal_value_peek_uint (param_values + 3),
+            data2);
+}
+
diff --git a/libnm-glib/nm-glib-marshal.h b/libnm-glib/nm-glib-marshal.h
new file mode 100644
index 00000000..53d8c06b
--- /dev/null
+++ b/libnm-glib/nm-glib-marshal.h
@@ -0,0 +1,36 @@
+
+#ifndef ___nm_glib_marshal_MARSHAL_H__
+#define ___nm_glib_marshal_MARSHAL_H__
+
+#include	<glib-object.h>
+
+G_BEGIN_DECLS
+
+/* VOID:STRING,STRING,STRING (nm-glib-marshal.list:1) */
+extern void _nm_glib_marshal_VOID__STRING_STRING_STRING (GClosure     *closure,
+                                                         GValue       *return_value,
+                                                         guint         n_param_values,
+                                                         const GValue *param_values,
+                                                         gpointer      invocation_hint,
+                                                         gpointer      marshal_data);
+
+/* VOID:UINT,UINT (nm-glib-marshal.list:2) */
+extern void _nm_glib_marshal_VOID__UINT_UINT (GClosure     *closure,
+                                              GValue       *return_value,
+                                              guint         n_param_values,
+                                              const GValue *param_values,
+                                              gpointer      invocation_hint,
+                                              gpointer      marshal_data);
+
+/* VOID:UINT,UINT,UINT (nm-glib-marshal.list:3) */
+extern void _nm_glib_marshal_VOID__UINT_UINT_UINT (GClosure     *closure,
+                                                   GValue       *return_value,
+                                                   guint         n_param_values,
+                                                   const GValue *param_values,
+                                                   gpointer      invocation_hint,
+                                                   gpointer      marshal_data);
+
+G_END_DECLS
+
+#endif /* ___nm_glib_marshal_MARSHAL_H__ */
+
diff --git a/libnm-glib/nm-ip4-config.c b/libnm-glib/nm-ip4-config.c
index a72fa893..56678545 100644
--- a/libnm-glib/nm-ip4-config.c
+++ b/libnm-glib/nm-ip4-config.c
@@ -115,49 +115,40 @@ demarshal_ip4_routes_array (NMObject *object, GParamSpec *pspec, GValue *value,
 }
 
 static void
-register_for_property_changed (NMIP4Config *config)
+register_properties (NMIP4Config *config)
 {
 	NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
-	const NMPropertiesChangedInfo property_changed_info[] = {
-		{ NM_IP4_CONFIG_ADDRESSES,    demarshal_ip4_address_array,  &priv->addresses },
-		{ NM_IP4_CONFIG_NAMESERVERS,  demarshal_ip4_array,          &priv->nameservers },
-		{ NM_IP4_CONFIG_DOMAINS,      demarshal_domains,            &priv->domains },
-		{ NM_IP4_CONFIG_ROUTES,       demarshal_ip4_routes_array,   &priv->routes },
-		{ NM_IP4_CONFIG_WINS_SERVERS, demarshal_ip4_array,          &priv->wins },
+	const NMPropertiesInfo property_info[] = {
+		{ NM_IP4_CONFIG_ADDRESSES,    &priv->addresses, demarshal_ip4_address_array },
+		{ NM_IP4_CONFIG_NAMESERVERS,  &priv->nameservers, demarshal_ip4_array },
+		{ NM_IP4_CONFIG_DOMAINS,      &priv->domains, demarshal_domains },
+		{ NM_IP4_CONFIG_ROUTES,       &priv->routes, demarshal_ip4_routes_array },
+		{ NM_IP4_CONFIG_WINS_SERVERS, &priv->wins, demarshal_ip4_array },
 		{ NULL },
 	};
 
-	_nm_object_handle_properties_changed (NM_OBJECT (config),
-	                                     priv->proxy,
-	                                     property_changed_info);
+	_nm_object_register_properties (NM_OBJECT (config),
+	                                priv->proxy,
+	                                property_info);
 }
 
-static GObject*
-constructor (GType type,
-		   guint n_construct_params,
-		   GObjectConstructParam *construct_params)
+static void
+constructed (GObject *object)
 {
-	NMObject *object;
 	DBusGConnection *connection;
 	NMIP4ConfigPrivate *priv;
 
-	object = (NMObject *) G_OBJECT_CLASS (nm_ip4_config_parent_class)->constructor (type,
-																 n_construct_params,
-																 construct_params);
-	if (!object)
-		return NULL;
+	G_OBJECT_CLASS (nm_ip4_config_parent_class)->constructed (object);
 
 	priv = NM_IP4_CONFIG_GET_PRIVATE (object);
-	connection = nm_object_get_connection (object);
+	connection = nm_object_get_connection (NM_OBJECT (object));
 
 	priv->proxy = dbus_g_proxy_new_for_name (connection,
 										   NM_DBUS_SERVICE,
-										   nm_object_get_path (object),
+										   nm_object_get_path (NM_OBJECT (object)),
 										   NM_DBUS_INTERFACE_IP4_CONFIG);
 
-	register_for_property_changed (NM_IP4_CONFIG (object));
-
-	return G_OBJECT (object);
+	register_properties (NM_IP4_CONFIG (object));
 }
 
 static void
@@ -226,7 +217,7 @@ nm_ip4_config_class_init (NMIP4ConfigClass *config_class)
 	g_type_class_add_private (config_class, sizeof (NMIP4ConfigPrivate));
 
 	/* virtual methods */
-	object_class->constructor = constructor;
+	object_class->constructed = constructed;
 	object_class->get_property = get_property;
 	object_class->finalize = finalize;
 
@@ -326,27 +317,10 @@ nm_ip4_config_new (DBusGConnection *connection, const char *object_path)
 const GSList *
 nm_ip4_config_get_addresses (NMIP4Config *config)
 {
-	NMIP4ConfigPrivate *priv;
-	GValue value = { 0, };
-
 	g_return_val_if_fail (NM_IS_IP4_CONFIG (config), NULL);
 
-	priv = NM_IP4_CONFIG_GET_PRIVATE (config);
-	if (priv->addresses)
-		return priv->addresses;
-
-	if (!_nm_object_get_property (NM_OBJECT (config),
-	                              NM_DBUS_INTERFACE_IP4_CONFIG,
-	                              "Addresses",
-	                              &value,
-	                              NULL)) {
-		return NULL;
-	}
-
-	demarshal_ip4_address_array (NM_OBJECT (config), NULL, &value, &priv->addresses);	
-	g_value_unset (&value);
-
-	return priv->addresses;
+	_nm_object_ensure_inited (NM_OBJECT (config));
+	return NM_IP4_CONFIG_GET_PRIVATE (config)->addresses;
 }
 
 /**
@@ -361,29 +335,10 @@ nm_ip4_config_get_addresses (NMIP4Config *config)
 const GArray *
 nm_ip4_config_get_nameservers (NMIP4Config *config)
 {
-	NMIP4ConfigPrivate *priv;
-	GArray *array = NULL;
-	GValue value = {0,};
-
 	g_return_val_if_fail (NM_IS_IP4_CONFIG (config), NULL);
 
-	priv = NM_IP4_CONFIG_GET_PRIVATE (config);
-	if (!priv->nameservers) {
-		if (_nm_object_get_property (NM_OBJECT (config),
-		                             NM_DBUS_INTERFACE_IP4_CONFIG,
-		                             "Nameservers",
-		                             &value,
-		                             NULL)) {
-			array = (GArray *) g_value_get_boxed (&value);
-			if (array && array->len) {
-				priv->nameservers = g_array_sized_new (FALSE, TRUE, sizeof (guint32), array->len);
-				g_array_append_vals (priv->nameservers, array->data, array->len);
-			}
-			g_value_unset (&value);
-		}
-	}
-
-	return priv->nameservers;
+	_nm_object_ensure_inited (NM_OBJECT (config));
+	return NM_IP4_CONFIG_GET_PRIVATE (config)->nameservers;
 }
 
 /**
@@ -398,32 +353,10 @@ nm_ip4_config_get_nameservers (NMIP4Config *config)
 const GPtrArray *
 nm_ip4_config_get_domains (NMIP4Config *config)
 {
-	NMIP4ConfigPrivate *priv;
-	GValue value = {0,};
-
 	g_return_val_if_fail (NM_IS_IP4_CONFIG (config), NULL);
 
-	priv = NM_IP4_CONFIG_GET_PRIVATE (config);
-	if (priv->domains)
-		return handle_ptr_array_return (priv->domains);
-
-	if (_nm_object_get_property (NM_OBJECT (config),
-	                             NM_DBUS_INTERFACE_IP4_CONFIG,
-	                             "Domains",
-	                             &value,
-	                             NULL)) {
-		char **array = NULL, **p;
-
-		array = (char **) g_value_get_boxed (&value);
-		if (array && g_strv_length (array)) {
-			priv->domains = g_ptr_array_sized_new (g_strv_length (array));
-			for (p = array; *p; p++)
-				g_ptr_array_add (priv->domains, g_strdup (*p));
-		}
-		g_value_unset (&value);
-	}
-
-	return handle_ptr_array_return (priv->domains);
+	_nm_object_ensure_inited (NM_OBJECT (config));
+	return handle_ptr_array_return (NM_IP4_CONFIG_GET_PRIVATE (config)->domains);
 }
 
 /**
@@ -438,29 +371,10 @@ nm_ip4_config_get_domains (NMIP4Config *config)
 const GArray *
 nm_ip4_config_get_wins_servers (NMIP4Config *config)
 {
-	NMIP4ConfigPrivate *priv;
-	GArray *array = NULL;
-	GValue value = {0,};
-
 	g_return_val_if_fail (NM_IS_IP4_CONFIG (config), NULL);
 
-	priv = NM_IP4_CONFIG_GET_PRIVATE (config);
-	if (!priv->wins) {
-		if (_nm_object_get_property (NM_OBJECT (config),
-		                             NM_DBUS_INTERFACE_IP4_CONFIG,
-		                             "WinsServers",
-		                             &value,
-		                             NULL)) {
-			array = (GArray *) g_value_get_boxed (&value);
-			if (array && array->len) {
-				priv->wins = g_array_sized_new (FALSE, TRUE, sizeof (guint32), array->len);
-				g_array_append_vals (priv->wins, array->data, array->len);
-			}
-			g_value_unset (&value);
-		}
-	}
-
-	return priv->wins;
+	_nm_object_ensure_inited (NM_OBJECT (config));
+	return NM_IP4_CONFIG_GET_PRIVATE (config)->wins;
 }
 
 /**
@@ -476,26 +390,9 @@ nm_ip4_config_get_wins_servers (NMIP4Config *config)
 const GSList *
 nm_ip4_config_get_routes (NMIP4Config *config)
 {
-	NMIP4ConfigPrivate *priv;
-	GValue value = { 0, };
-
 	g_return_val_if_fail (NM_IS_IP4_CONFIG (config), NULL);
 
-	priv = NM_IP4_CONFIG_GET_PRIVATE (config);
-	if (priv->routes)
-		return priv->routes;
-
-	if (!_nm_object_get_property (NM_OBJECT (config),
-	                              NM_DBUS_INTERFACE_IP4_CONFIG,
-	                              "Routes",
-	                              &value,
-	                              NULL)) {
-		return NULL;
-	}
-
-	demarshal_ip4_routes_array (NM_OBJECT (config), NULL, &value, &priv->routes);
-	g_value_unset (&value);
-
-	return priv->routes;
+	_nm_object_ensure_inited (NM_OBJECT (config));
+	return NM_IP4_CONFIG_GET_PRIVATE (config)->routes;
 }
 
diff --git a/libnm-glib/nm-ip6-config.c b/libnm-glib/nm-ip6-config.c
index 7e9bf3cd..c9a26279 100644
--- a/libnm-glib/nm-ip6-config.c
+++ b/libnm-glib/nm-ip6-config.c
@@ -124,20 +124,20 @@ demarshal_ip6_routes_array (NMObject *object, GParamSpec *pspec, GValue *value,
 }
 
 static void
-register_for_property_changed (NMIP6Config *config)
+register_properties (NMIP6Config *config)
 {
 	NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config);
-	const NMPropertiesChangedInfo property_changed_info[] = {
-		{ NM_IP6_CONFIG_ADDRESSES,    demarshal_ip6_address_array,    &priv->addresses },
-		{ NM_IP6_CONFIG_NAMESERVERS,  demarshal_ip6_nameserver_array, &priv->nameservers },
-		{ NM_IP6_CONFIG_DOMAINS,      demarshal_domains,              &priv->domains },
-		{ NM_IP6_CONFIG_ROUTES,       demarshal_ip6_routes_array,     &priv->routes },
+	const NMPropertiesInfo property_info[] = {
+		{ NM_IP6_CONFIG_ADDRESSES,    &priv->addresses, demarshal_ip6_address_array },
+		{ NM_IP6_CONFIG_NAMESERVERS,  &priv->nameservers, demarshal_ip6_nameserver_array },
+		{ NM_IP6_CONFIG_DOMAINS,      &priv->domains, demarshal_domains },
+		{ NM_IP6_CONFIG_ROUTES,       &priv->routes, demarshal_ip6_routes_array },
 		{ NULL },
 	};
 
-	_nm_object_handle_properties_changed (NM_OBJECT (config),
-	                                      priv->proxy,
-	                                      property_changed_info);
+	_nm_object_register_properties (NM_OBJECT (config),
+	                                priv->proxy,
+	                                property_info);
 }
 
 /**
@@ -153,27 +153,10 @@ register_for_property_changed (NMIP6Config *config)
 const GSList *
 nm_ip6_config_get_addresses (NMIP6Config *config)
 {
-	NMIP6ConfigPrivate *priv;
-	GValue value = { 0, };
-
 	g_return_val_if_fail (NM_IS_IP6_CONFIG (config), NULL);
 
-	priv = NM_IP6_CONFIG_GET_PRIVATE (config);
-	if (priv->addresses)
-		return priv->addresses;
-
-	if (!_nm_object_get_property (NM_OBJECT (config),
-	                              NM_DBUS_INTERFACE_IP6_CONFIG,
-	                              "Addresses",
-	                              &value,
-	                              NULL)) {
-		return NULL;
-	}
-
-	demarshal_ip6_address_array (NM_OBJECT (config), NULL, &value, &priv->addresses);	
-	g_value_unset (&value);
-
-	return priv->addresses;
+	_nm_object_ensure_inited (NM_OBJECT (config));
+	return NM_IP6_CONFIG_GET_PRIVATE (config)->addresses;
 }
 
 /* FIXME: like in libnm_util, in6_addr is not introspectable, so skipping here */
@@ -190,29 +173,10 @@ nm_ip6_config_get_addresses (NMIP6Config *config)
 const GSList *
 nm_ip6_config_get_nameservers (NMIP6Config *config)
 {
-	NMIP6ConfigPrivate *priv;
-	GParamSpec *pspec;
-	GValue value = {0,};
-
 	g_return_val_if_fail (NM_IS_IP6_CONFIG (config), NULL);
 
-	priv = NM_IP6_CONFIG_GET_PRIVATE (config);
-	if (priv->nameservers)
-		return priv->nameservers;
-
-	if (!_nm_object_get_property (NM_OBJECT (config),
-	                              NM_DBUS_INTERFACE_IP6_CONFIG,
-	                              "Nameservers",
-	                              &value,
-	                              NULL)) {
-		return NULL;
-	}
-
-	pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (G_OBJECT (config)), NM_IP6_CONFIG_NAMESERVERS);
-	demarshal_ip6_nameserver_array (NM_OBJECT (config), pspec, &value, &priv->nameservers);
-	g_value_unset (&value);
-
-	return priv->nameservers;
+	_nm_object_ensure_inited (NM_OBJECT (config));
+	return NM_IP6_CONFIG_GET_PRIVATE (config)->nameservers;
 }
 
 /**
@@ -227,27 +191,10 @@ nm_ip6_config_get_nameservers (NMIP6Config *config)
 const GPtrArray *
 nm_ip6_config_get_domains (NMIP6Config *config)
 {
-	NMIP6ConfigPrivate *priv;
-	GValue value = {0,};
-
 	g_return_val_if_fail (NM_IS_IP6_CONFIG (config), NULL);
 
-	priv = NM_IP6_CONFIG_GET_PRIVATE (config);
-	if (priv->domains)
-		return handle_ptr_array_return (priv->domains);
-
-	if (!_nm_object_get_property (NM_OBJECT (config),
-	                              NM_DBUS_INTERFACE_IP6_CONFIG,
-	                              "Domains",
-	                              &value,
-	                              NULL)) {
-		return NULL;
-	}
-
-	demarshal_domains (NM_OBJECT (config), NULL, &value, &priv->domains);
-	g_value_unset (&value);
-
-	return handle_ptr_array_return (priv->domains);
+	_nm_object_ensure_inited (NM_OBJECT (config));
+	return handle_ptr_array_return (NM_IP6_CONFIG_GET_PRIVATE (config)->domains);
 }
 
 /**
@@ -263,43 +210,19 @@ nm_ip6_config_get_domains (NMIP6Config *config)
 const GSList *
 nm_ip6_config_get_routes (NMIP6Config *config)
 {
-	NMIP6ConfigPrivate *priv;
-	GValue value = { 0, };
-
 	g_return_val_if_fail (NM_IS_IP6_CONFIG (config), NULL);
 
-	priv = NM_IP6_CONFIG_GET_PRIVATE (config);
-	if (priv->routes)
-		return priv->routes;
-
-	if (!_nm_object_get_property (NM_OBJECT (config),
-	                              NM_DBUS_INTERFACE_IP6_CONFIG,
-	                              "Routes",
-	                              &value,
-	                              NULL)) {
-		return NULL;
-	}
-
-	demarshal_ip6_routes_array (NM_OBJECT (config), NULL, &value, &priv->routes);
-	g_value_unset (&value);
-
-	return priv->routes;
+	_nm_object_ensure_inited (NM_OBJECT (config));
+	return NM_IP6_CONFIG_GET_PRIVATE (config)->routes;
 }
 
-static GObject*
-constructor (GType type,
-             guint n_construct_params,
-             GObjectConstructParam *construct_params)
+static void
+constructed (GObject *object)
 {
-	GObject *object;
 	DBusGConnection *connection;
 	NMIP6ConfigPrivate *priv;
 
-	object = G_OBJECT_CLASS (nm_ip6_config_parent_class)->constructor (type,
-	                                                                   n_construct_params,
-	                                                                   construct_params);
-	if (!object)
-		return NULL;
+	G_OBJECT_CLASS (nm_ip6_config_parent_class)->constructed (object);
 
 	priv = NM_IP6_CONFIG_GET_PRIVATE (object);
 	connection = nm_object_get_connection (NM_OBJECT (object));
@@ -309,9 +232,7 @@ constructor (GType type,
 	                                         nm_object_get_path (NM_OBJECT (object)),
 	                                         NM_DBUS_INTERFACE_IP6_CONFIG);
 
-	register_for_property_changed (NM_IP6_CONFIG (object));
-
-	return object;
+	register_properties (NM_IP6_CONFIG (object));
 }
 
 static void
@@ -379,7 +300,7 @@ nm_ip6_config_class_init (NMIP6ConfigClass *config_class)
 	g_type_class_add_private (config_class, sizeof (NMIP6ConfigPrivate));
 
 	/* virtual methods */
-	object_class->constructor = constructor;
+	object_class->constructed = constructed;
 	object_class->get_property = get_property;
 	object_class->finalize = finalize;
 
diff --git a/libnm-glib/nm-object-cache.c b/libnm-glib/nm-object-cache.c
index c43b4273..741f1291 100644
--- a/libnm-glib/nm-object-cache.c
+++ b/libnm-glib/nm-object-cache.c
@@ -34,18 +34,12 @@ _init_cache (void)
 		cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
 }
 
-void
-_nm_object_cache_remove_by_path (const char *path)
+static void
+_nm_object_cache_remove_by_path (char *path)
 {
 	_init_cache ();
 	g_hash_table_remove (cache, path);
-}
-
-void
-_nm_object_cache_remove_by_object (NMObject *object)
-{
-	_init_cache ();
-	g_hash_table_remove (cache, nm_object_get_path (object));
+	g_free (path);
 }
 
 void
@@ -57,7 +51,7 @@ _nm_object_cache_add (NMObject *object)
 	path = g_strdup (nm_object_get_path (object));
 	g_hash_table_insert (cache, path, object);
 	g_object_set_data_full (G_OBJECT (object), "nm-object-cache-tag",
-	                        path, (GDestroyNotify) _nm_object_cache_remove_by_path);
+	                        g_strdup (path), (GDestroyNotify) _nm_object_cache_remove_by_path);
 }
 
 NMObject *
diff --git a/libnm-glib/nm-object-cache.h b/libnm-glib/nm-object-cache.h
index 2348dcfa..8386591c 100644
--- a/libnm-glib/nm-object-cache.h
+++ b/libnm-glib/nm-object-cache.h
@@ -32,8 +32,6 @@ 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_remove_by_object (NMObject *object);
-void _nm_object_cache_remove_by_path (const char *path);
 
 G_END_DECLS
 
diff --git a/libnm-glib/nm-object-private.h b/libnm-glib/nm-object-private.h
index 4410df22..7ec2162f 100644
--- a/libnm-glib/nm-object-private.h
+++ b/libnm-glib/nm-object-private.h
@@ -23,83 +23,62 @@
 #ifndef NM_OBJECT_PRIVATE_H
 #define NM_OBJECT_PRIVATE_H
 
-#include <glib.h>
-#include <glib-object.h>
+#include <gio/gio.h>
 #include "nm-object.h"
 
-typedef gboolean (*PropChangedMarshalFunc) (NMObject *, GParamSpec *, GValue *, gpointer);
+void _nm_object_ensure_inited (NMObject *object);
+
+typedef gboolean (*PropertyMarshalFunc) (NMObject *, GParamSpec *, GValue *, gpointer);
+
 typedef GObject * (*NMObjectCreatorFunc) (DBusGConnection *, const char *);
 
 typedef struct {
 	const char *name;
-	PropChangedMarshalFunc func;
 	gpointer field;
-} NMPropertiesChangedInfo;
-
-
-void _nm_object_handle_properties_changed (NMObject *object,
-                                           DBusGProxy *proxy,
-                                           const NMPropertiesChangedInfo *info);
-
-void _nm_object_process_properties_changed (NMObject *self, GHashTable *properties);
-
-gboolean _nm_object_demarshal_generic (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field);
+	PropertyMarshalFunc func;
+	GType object_type;
+} NMPropertiesInfo;
+
+
+void _nm_object_register_properties (NMObject *object,
+									 DBusGProxy *proxy,
+									 const NMPropertiesInfo *info);
+
+gboolean _nm_object_reload_properties (NMObject *object, GError **error);
+
+void     _nm_object_reload_properties_async  (NMObject *object,
+                                              GAsyncReadyCallback callback,
+                                              gpointer user_data);
+gboolean _nm_object_reload_properties_finish (NMObject *object,
+                                              GAsyncResult *result,
+                                              GError **error);
+
+typedef void (*NMPseudoPropertyChangedFunc) (NMObject *self, NMObject *changed);
+void _nm_object_register_pseudo_property (NMObject *object,
+                                          DBusGProxy *proxy,
+                                          const char *name,
+                                          gpointer field,
+                                          GType object_type,
+                                          NMPseudoPropertyChangedFunc added_func,
+                                          NMPseudoPropertyChangedFunc removed_func);
+void _nm_object_reload_pseudo_property   (NMObject *object,
+                                          const char *name);
 
 void _nm_object_queue_notify (NMObject *object, const char *property);
 
+void _nm_object_suppress_property_updates (NMObject *object, gboolean suppress);
+
 /* DBus property accessors */
 
-gboolean _nm_object_get_property (NMObject *object,
-                                  const char *interface,
-                                  const char *prop_name,
-                                  GValue *value,
-                                  GError **error);
+void _nm_object_reload_property (NMObject *object,
+                                 const char *interface,
+                                 const char *prop_name);
 
 void _nm_object_set_property (NMObject *object,
                               const char *interface,
                               const char *prop_name,
                               GValue *value);
 
-char *_nm_object_get_string_property (NMObject *object,
-                                      const char *interface,
-                                      const char *prop_name,
-                                      GError **error);
-
-char *_nm_object_get_object_path_property (NMObject *object,
-                                           const char *interface,
-                                           const char *prop_name,
-                                           GError **error);
-
-gint32 _nm_object_get_int_property (NMObject *object,
-                                    const char *interface,
-                                    const char *prop_name,
-                                    GError **error);
-
-guint32 _nm_object_get_uint_property (NMObject *object,
-                                      const char *interface,
-                                      const char *prop_name,
-                                      GError **error);
-
-gboolean _nm_object_get_boolean_property (NMObject *object,
-                                          const char *interface,
-                                          const char *prop_name,
-                                          GError **error);
-
-gint8 _nm_object_get_byte_property (NMObject *object,
-                                    const char *interface,
-                                    const char *prop_name,
-                                    GError **error);
-
-gdouble _nm_object_get_double_property (NMObject *object,
-                                        const char *interface,
-                                        const char *prop_name,
-                                        GError **error);
-
-GByteArray *_nm_object_get_byte_array_property (NMObject *object,
-                                                const char *interface,
-                                                const char *prop_name,
-                                                GError **error);
-
 static inline const GPtrArray *
 handle_ptr_array_return (GPtrArray *array)
 {
@@ -109,4 +88,12 @@ handle_ptr_array_return (GPtrArray *array)
 	return array;
 }
 
+/* object demarshalling support */
+typedef GType (*NMObjectTypeFunc) (DBusGConnection *, const char *);
+typedef void (*NMObjectTypeCallbackFunc) (GType, gpointer);
+typedef void (*NMObjectTypeAsyncFunc) (DBusGConnection *, const char *, NMObjectTypeCallbackFunc, gpointer);
+
+void _nm_object_register_type_func (GType base_type, NMObjectTypeFunc type_func,
+                                    NMObjectTypeAsyncFunc type_async_func);
+
 #endif /* NM_OBJECT_PRIVATE_H */
diff --git a/libnm-glib/nm-object.c b/libnm-glib/nm-object.c
index 9a8a60f7..fc9d7f86 100644
--- a/libnm-glib/nm-object.c
+++ b/libnm-glib/nm-object.c
@@ -22,6 +22,7 @@
  */
 
 #include <string.h>
+#include <gio/gio.h>
 #include <nm-utils.h>
 #include "NetworkManager.h"
 #include "nm-object.h"
@@ -29,28 +30,59 @@
 #include "nm-object-private.h"
 #include "nm-dbus-glib-types.h"
 #include "nm-glib-compat.h"
+#include "nm-types.h"
 
 #define DEBUG 0
 
-G_DEFINE_ABSTRACT_TYPE (NMObject, nm_object, G_TYPE_OBJECT)
+static void nm_object_initable_iface_init (GInitableIface *iface);
+static void nm_object_async_initable_iface_init (GAsyncInitableIface *iface);
+
+G_DEFINE_ABSTRACT_TYPE_WITH_CODE (NMObject, nm_object, G_TYPE_OBJECT,
+                                  G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, nm_object_initable_iface_init);
+                                  G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, nm_object_async_initable_iface_init);
+                                  )
 
 #define NM_OBJECT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_OBJECT, NMObjectPrivate))
 
+static GHashTable *type_funcs, *type_async_funcs;
+
 typedef struct {
-	PropChangedMarshalFunc func;
+	PropertyMarshalFunc func;
+	GType object_type;
+
 	gpointer field;
-} PropChangedInfo;
+} PropertyInfo;
+
+static void reload_complete (NMObject *object);
+
+typedef struct {
+	PropertyInfo pi;
+
+	NMObject *self;
+	DBusGProxy *proxy;
+
+	char *get_method;
+	NMPseudoPropertyChangedFunc added_func;
+	NMPseudoPropertyChangedFunc removed_func;
+} PseudoPropertyInfo;
 
 typedef struct {
 	DBusGConnection *connection;
 	char *path;
 	DBusGProxy *properties_proxy;
-	GSList *pcs;
+	GSList *property_interfaces;
+	GSList *property_tables;
+	GHashTable *pseudo_properties;
 	NMObject *parent;
+	gboolean suppress_property_updates;
 
 	GSList *notify_props;
 	guint32 notify_id;
-	gboolean disposed;
+	gboolean inited, disposed;
+
+	GSList *reload_results;
+	guint reload_remaining;
+	GError *reload_error;
 } NMObjectPrivate;
 
 enum {
@@ -77,8 +109,6 @@ constructor (GType type,
 	object = G_OBJECT_CLASS (nm_object_parent_class)->constructor (type,
 																   n_construct_params,
 																   construct_params);
-	if (!object)
-		return NULL;
 
 	priv = NM_OBJECT_GET_PRIVATE (object);
 
@@ -88,17 +118,78 @@ constructor (GType type,
 		return NULL;
 	}
 
-	priv->properties_proxy = dbus_g_proxy_new_for_name (priv->connection,
-														NM_DBUS_SERVICE,
-														priv->path,
-														"org.freedesktop.DBus.Properties");
-
 	_nm_object_cache_add (NM_OBJECT (object));
 
 	return object;
 }
 
 static void
+constructed (GObject *object)
+{
+	NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
+
+	if (G_OBJECT_CLASS (nm_object_parent_class)->constructed)
+		G_OBJECT_CLASS (nm_object_parent_class)->constructed (object);
+
+	priv->properties_proxy = dbus_g_proxy_new_for_name (priv->connection,
+	                                                    NM_DBUS_SERVICE,
+	                                                    priv->path,
+	                                                    "org.freedesktop.DBus.Properties");
+}
+
+static gboolean
+init_sync (GInitable *initable, GCancellable *cancellable, GError **error)
+{
+	NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (initable);
+
+	priv->inited = TRUE;
+	return _nm_object_reload_properties (NM_OBJECT (initable), error);
+}
+
+static void
+init_async_got_properties (GObject *object, GAsyncResult *result, gpointer user_data)
+{
+	NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
+	GSimpleAsyncResult *simple = user_data;
+	GError *error = NULL;
+
+	priv->inited = TRUE;
+	if (_nm_object_reload_properties_finish (NM_OBJECT (object), result, &error))
+		g_simple_async_result_set_op_res_gboolean (simple, TRUE);
+	else
+		g_simple_async_result_take_error (simple, error);
+
+	g_simple_async_result_complete (simple);
+	g_object_unref (simple);
+}
+
+static void
+init_async (GAsyncInitable *initable, int io_priority,
+            GCancellable *cancellable, GAsyncReadyCallback callback,
+            gpointer user_data)
+{
+	GSimpleAsyncResult *simple;
+
+	simple = g_simple_async_result_new (G_OBJECT (initable), callback, user_data, init_async);
+	_nm_object_reload_properties_async (NM_OBJECT (initable), init_async_got_properties, simple);
+}
+
+static gboolean
+init_finish (GAsyncInitable *initable, GAsyncResult *result, GError **error)
+{
+	GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
+
+	/* This is needed for now because of bug 667375; it can go away
+	 * when we depend on glib >= 2.38
+	 */
+
+	if (g_simple_async_result_propagate_error (simple, error))
+		return FALSE;
+	else
+		return g_simple_async_result_get_op_res_gboolean (simple);
+}
+
+static void
 dispose (GObject *object)
 {
 	NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
@@ -118,6 +209,9 @@ dispose (GObject *object)
 	g_slist_foreach (priv->notify_props, (GFunc) g_free, NULL);
 	g_slist_free (priv->notify_props);
 
+	g_slist_foreach (priv->property_interfaces, (GFunc) g_free, NULL);
+	g_slist_free (priv->property_interfaces);
+
 	g_object_unref (priv->properties_proxy);
 	dbus_g_connection_unref (priv->connection);
 
@@ -129,10 +223,13 @@ finalize (GObject *object)
 {
 	NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
 
-	g_slist_foreach (priv->pcs, (GFunc) g_hash_table_destroy, NULL);
-	g_slist_free (priv->pcs);
+	g_slist_foreach (priv->property_tables, (GFunc) g_hash_table_destroy, NULL);
+	g_slist_free (priv->property_tables);
 	g_free (priv->path);
 
+	if (priv->pseudo_properties)
+		g_hash_table_destroy (priv->pseudo_properties);
+
 	G_OBJECT_CLASS (nm_object_parent_class)->finalize (object);
 }
 
@@ -187,8 +284,14 @@ nm_object_class_init (NMObjectClass *nm_object_class)
 
 	g_type_class_add_private (nm_object_class, sizeof (NMObjectPrivate));
 
+	if (!type_funcs) {
+		type_funcs = g_hash_table_new (NULL, NULL);
+		type_async_funcs = g_hash_table_new (NULL, NULL);
+	}
+
 	/* virtual methods */
 	object_class->constructor = constructor;
+	object_class->constructed = constructed;
 	object_class->set_property = set_property;
 	object_class->get_property = get_property;
 	object_class->dispose = dispose;
@@ -223,6 +326,19 @@ nm_object_class_init (NMObjectClass *nm_object_class)
 							  G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 }
 
+static void
+nm_object_initable_iface_init (GInitableIface *iface)
+{
+	iface->init = init_sync;
+}
+
+static void
+nm_object_async_initable_iface_init (GAsyncInitableIface *iface)
+{
+	iface->init_async = init_async;
+	iface->init_finish = init_finish;
+}
+
 /**
  * nm_object_get_connection:
  * @object: a #NMObject
@@ -306,6 +422,142 @@ _nm_object_queue_notify (NMObject *object, const char *property)
 		priv->notify_props = g_slist_prepend (priv->notify_props, g_strdup (property));
 }
 
+void
+_nm_object_register_type_func (GType base_type, NMObjectTypeFunc type_func,
+                               NMObjectTypeAsyncFunc type_async_func)
+{
+	g_hash_table_insert (type_funcs,
+	                     GSIZE_TO_POINTER (base_type),
+	                     type_func);
+	g_hash_table_insert (type_async_funcs,
+	                     GSIZE_TO_POINTER (base_type),
+	                     type_async_func);
+}
+
+static GObject *
+_nm_object_create (GType type, DBusGConnection *connection, const char *path)
+{
+	NMObjectTypeFunc type_func;
+	GObject *object;
+	GError *error = NULL;
+
+	type_func = g_hash_table_lookup (type_funcs, GSIZE_TO_POINTER (type));
+	if (type_func)
+		type = type_func (connection, path);
+
+	if (type == G_TYPE_INVALID) {
+		g_warning ("Could not create object for %s: unknown object type", path);
+		return NULL;
+	}
+
+	object = g_object_new (type,
+	                       NM_OBJECT_DBUS_CONNECTION, connection,
+	                       NM_OBJECT_DBUS_PATH, path,
+	                       NULL);
+	if (!g_initable_init (G_INITABLE (object), NULL, &error)) {
+		g_object_unref (object);
+		object = NULL;
+		g_warning ("Could not create object for %s: %s", path, error->message);
+		g_error_free (error);
+	}
+
+	return object;
+}
+
+typedef void (*NMObjectCreateCallbackFunc) (GObject *, gpointer);
+typedef struct {
+	DBusGConnection *connection;
+	char *path;
+	NMObjectCreateCallbackFunc callback;
+	gpointer user_data;
+} NMObjectTypeAsyncData;
+
+static void
+create_async_complete (GObject *object, NMObjectTypeAsyncData *async_data)
+{
+	async_data->callback (object, async_data->user_data);
+
+	g_free (async_data->path);
+	g_slice_free (NMObjectTypeAsyncData, async_data);
+}
+
+static void
+async_inited (GObject *source, GAsyncResult *result, gpointer user_data)
+{
+	NMObjectTypeAsyncData *async_data = user_data;
+	GObject *object = G_OBJECT (source);
+	GError *error = NULL;
+
+	if (!g_async_initable_init_finish (G_ASYNC_INITABLE (object), result, &error)) {
+		g_warning ("Could not create object for %s: %s",
+		           nm_object_get_path (NM_OBJECT (object)), error->message);
+		g_error_free (error);
+		g_object_unref (object);
+		object = NULL;
+	}
+
+	create_async_complete (object, async_data);
+}
+
+static void
+async_got_type (GType type, gpointer user_data)
+{
+	NMObjectTypeAsyncData *async_data = user_data;
+	GObject *object;
+
+	/* Ensure we don't have the object already; we may get multiple type
+	 * requests for the same object if there are multiple properties on
+	 * other objects that refer to the object at this path.  One of those
+	 * other requests may have already completed.
+	 */
+	object = (GObject *) _nm_object_cache_get (async_data->path);
+	if (object) {
+		create_async_complete (object, async_data);
+		return;
+	}
+
+	if (type == G_TYPE_INVALID) {
+		/* Don't know how to create this object */
+		create_async_complete (NULL, async_data);
+		return;
+	}
+
+	object = g_object_new (type,
+	                       NM_OBJECT_DBUS_CONNECTION, async_data->connection,
+	                       NM_OBJECT_DBUS_PATH, async_data->path,
+	                       NULL);
+	g_warn_if_fail (object != NULL);
+	g_async_initable_init_async (G_ASYNC_INITABLE (object), G_PRIORITY_DEFAULT,
+	                             NULL, async_inited, async_data);
+}
+
+static void
+_nm_object_create_async (GType type, DBusGConnection *connection, const char *path,
+                         NMObjectCreateCallbackFunc callback, gpointer user_data)
+{
+	NMObjectTypeAsyncFunc type_async_func;
+	NMObjectTypeFunc type_func;
+	NMObjectTypeAsyncData *async_data;
+
+	async_data = g_slice_new (NMObjectTypeAsyncData);
+	async_data->connection = connection;
+	async_data->path = g_strdup (path);
+	async_data->callback = callback;
+	async_data->user_data = user_data;
+
+	type_async_func = g_hash_table_lookup (type_async_funcs, GSIZE_TO_POINTER (type));
+	if (type_async_func) {
+		type_async_func (connection, path, async_got_type, async_data);
+		return;
+	}
+
+	type_func = g_hash_table_lookup (type_funcs, GSIZE_TO_POINTER (type));
+	if (type_func)
+		type = type_func (connection, path);
+
+	async_got_type (type, async_data);
+}
+
 /* Stolen from dbus-glib */
 static char*
 wincaps_to_dash (const char *caps)
@@ -328,19 +580,213 @@ wincaps_to_dash (const char *caps)
 	return g_string_free (str, FALSE);
 }
 
+/* Adds object to array if it's not already there */
+static void
+add_to_object_array_unique (GPtrArray *array, GObject *obj)
+{
+	guint i;
+
+	g_return_if_fail (array != NULL);
+
+	if (obj != NULL) {
+		for (i = 0; i < array->len; i++) {
+			if (g_ptr_array_index (array, i) == obj)
+				return;
+		}
+		g_ptr_array_add (array, obj);
+	}
+}
+
+typedef struct {
+	NMObject *self;
+	PropertyInfo *pi;
+
+	GObject **objects;
+	int length, remaining;
+
+	gboolean array;
+	const char *property_name;
+} ObjectCreatedData;
+
 static void
-handle_property_changed (gpointer key, gpointer data, gpointer user_data)
+object_property_complete (ObjectCreatedData *odata)
+{
+	NMObject *self = odata->self;
+	NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self);
+	PropertyInfo *pi = odata->pi;
+
+	if (odata->array) {
+		GPtrArray **array = pi->field;
+		int i;
+
+		if (*array)
+			g_boxed_free (NM_TYPE_OBJECT_ARRAY, *array);
+		*array = g_ptr_array_sized_new (odata->length);
+		for (i = 0; i < odata->length; i++)
+			add_to_object_array_unique (*array, odata->objects[i]);
+	} else {
+		GObject **obj_p = pi->field;
+
+		if (*obj_p)
+			g_object_unref (*obj_p);
+		*obj_p = odata->objects[0];
+	}
+
+	if (odata->property_name)
+		_nm_object_queue_notify (self, odata->property_name);
+
+	if (priv->reload_results && --priv->reload_remaining == 0)
+		reload_complete (self);
+
+	g_object_unref (self);
+	g_free (odata->objects);
+	g_slice_free (ObjectCreatedData, odata);
+}
+
+static void
+object_created (GObject *obj, gpointer user_data)
+{
+	ObjectCreatedData *odata = user_data;
+
+	/* We assume that on error, the creator_func printed something */
+
+	odata->objects[--odata->remaining] = obj;
+	if (!odata->remaining)
+		object_property_complete (odata);
+}
+
+static gboolean
+handle_object_property (NMObject *self, const char *property_name, GValue *value,
+                        PropertyInfo *pi, gboolean synchronously)
+{
+	NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self);
+	GObject *obj;
+	const char *path;
+	ObjectCreatedData *odata;
+
+	odata = g_slice_new (ObjectCreatedData);
+	odata->self = g_object_ref (self);
+	odata->pi = pi;
+	odata->objects = g_new (GObject *, 1);
+	odata->length = odata->remaining = 1;
+	odata->array = FALSE;
+	odata->property_name = property_name;
+
+	if (priv->reload_results)
+		priv->reload_remaining++;
+
+	path = g_value_get_boxed (value);
+	if (!strcmp (path, "/")) {
+		object_created (NULL, odata);
+		return TRUE;
+	}
+
+	obj = G_OBJECT (_nm_object_cache_get (path));
+	if (obj) {
+		object_created (obj, odata);
+		return TRUE;
+	} else if (synchronously) {
+		obj = _nm_object_create (pi->object_type, priv->connection, path);
+		object_created (obj, odata);
+		return obj != NULL;
+	} else {
+		_nm_object_create_async (pi->object_type, priv->connection, path,
+		                         object_created, odata);
+		/* Assume success */
+		return TRUE;
+	}
+}
+
+static gboolean
+handle_object_array_property (NMObject *self, const char *property_name, GValue *value,
+                              PropertyInfo *pi, gboolean synchronously)
+{
+	NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self);
+	GObject *obj;
+	GPtrArray *paths;
+	GPtrArray **array = pi->field;
+	const char *path;
+	ObjectCreatedData *odata;
+	int i;
+
+	paths = g_value_get_boxed (value);
+
+	odata = g_slice_new (ObjectCreatedData);
+	odata->self = g_object_ref (self);
+	odata->pi = pi;
+	odata->objects = g_new0 (GObject *, paths->len);
+	odata->length = odata->remaining = paths->len;
+	odata->array = TRUE;
+	odata->property_name = property_name;
+
+	if (priv->reload_results)
+		priv->reload_remaining++;
+
+	if (paths->len == 0) {
+		object_property_complete (odata);
+		return TRUE;
+	}
+
+	for (i = 0; i < paths->len; i++) {
+		path = paths->pdata[i];
+		if (!strcmp (path, "/")) {
+			/* FIXME: can't happen? */
+			continue;
+		}
+
+		obj = G_OBJECT (_nm_object_cache_get (path));
+		if (obj) {
+			object_created (obj, odata);
+		} else if (synchronously) {
+			obj = _nm_object_create (pi->object_type, priv->connection, path);
+			object_created (obj, odata);
+		} else {
+			_nm_object_create_async (pi->object_type, priv->connection, path,
+			                         object_created, odata);
+		}
+	}
+
+	if (!synchronously) {
+		/* Assume success */
+		return TRUE;
+	}
+
+	return *array && ((*array)->len == paths->len);
+}
+
+static void
+handle_property_changed (NMObject *self, const char *dbus_name, GValue *value, gboolean synchronously)
 {
-	NMObject *self = NM_OBJECT (user_data);
 	NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self);
 	char *prop_name;
-	PropChangedInfo *pci;
+	PropertyInfo *pi;
 	GParamSpec *pspec;
 	gboolean success = FALSE, found = FALSE;
 	GSList *iter;
-	GValue *value = data;
 
-	prop_name = wincaps_to_dash ((char *) key);
+	prop_name = wincaps_to_dash (dbus_name);
+
+	/* Iterate through the object and its parents to find the property */
+	for (iter = priv->property_tables; iter; iter = g_slist_next (iter)) {
+		pi = g_hash_table_lookup ((GHashTable *) iter->data, prop_name);
+		if (pi) {
+			if (!pi->field) {
+				/* We know about this property but aren't tracking changes on it. */
+				goto out;
+			}
+
+			found = TRUE;
+			break;
+		}
+	}
+
+	if (!found) {
+#if DEBUG
+		g_warning ("Property '%s' unhandled.", prop_name);
+#endif
+		goto out;
+	}
+
 	pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (G_OBJECT (self)), prop_name);
 	if (!pspec) {
 		g_warning ("%s: property '%s' changed but wasn't defined by object type %s.",
@@ -350,29 +796,33 @@ handle_property_changed (gpointer key, gpointer data, gpointer user_data)
 		goto out;
 	}
 
-	/* Iterate through the object and its parents to find the property */
-	for (iter = priv->pcs; iter; iter = g_slist_next (iter)) {
-		pci = g_hash_table_lookup ((GHashTable *) iter->data, prop_name);
-		if (pci) {
-			found = TRUE;
-
-			/* Handle NULL object paths */
-			if (G_VALUE_HOLDS (value, DBUS_TYPE_G_OBJECT_PATH)) {
-				if (g_strcmp0 (g_value_get_boxed (value), "/") == 0)
-					value = NULL;
-			}
-
-			success = (*(pci->func)) (self, pspec, value, pci->field);
-			if (success)
-				break;
-		}
+#if DEBUG
+	{
+		char *s;
+		s = g_strdup_value_contents (value);
+		g_message ("PC: %p (%s) prop (%s) '%s' value (%s) %s",
+		           self, G_OBJECT_TYPE_NAME (self),
+		           g_type_name (pspec->value_type), prop_name,
+		           G_VALUE_TYPE_NAME (value), s);
+		g_free (s);
 	}
-
-	if (!found) {
+#endif
+	if (pi->object_type) {
 #if DEBUG
-		g_warning ("Property '%s' unhandled.", prop_name);
+		g_message ("   Value is object type %s", g_type_name (pi->object_type));
 #endif
-	} else if (!success) {
+		if (G_VALUE_HOLDS (value, DBUS_TYPE_G_OBJECT_PATH))
+			success = handle_object_property (self, pspec->name, value, pi, synchronously);
+		else if (G_VALUE_HOLDS (value, DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH))
+			success = handle_object_array_property (self, pspec->name, value, pi, synchronously);
+		else {
+			g_warn_if_reached ();
+			goto out;
+		}
+	} else
+		success = (*(pi->func)) (self, pspec, value, pi->field);
+
+	if (!success) {
 		g_warning ("%s: failed to update property '%s' of object type %s.",
 		           __func__,
 		           prop_name,
@@ -383,10 +833,19 @@ out:
 	g_free (prop_name);
 }
 
-void
-_nm_object_process_properties_changed (NMObject *self, GHashTable *properties)
+static void
+process_properties_changed (NMObject *self, GHashTable *properties, gboolean synchronously)
 {
-	g_hash_table_foreach (properties, handle_property_changed, self);
+	NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self);
+	GHashTableIter iter;
+	gpointer name, value;
+
+	if (priv->suppress_property_updates)
+		return;
+
+	g_hash_table_iter_init (&iter, properties);
+	while (g_hash_table_iter_next (&iter, &name, &value))
+		handle_property_changed (self, name, value, synchronously);
 }
 
 static void
@@ -394,49 +853,7 @@ properties_changed_proxy (DBusGProxy *proxy,
                           GHashTable *properties,
                           gpointer user_data)
 {
-	_nm_object_process_properties_changed (NM_OBJECT (user_data), properties);
-}
-
-void
-_nm_object_handle_properties_changed (NMObject *object,
-                                     DBusGProxy *proxy,
-                                     const NMPropertiesChangedInfo *info)
-{
-	NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
-	NMPropertiesChangedInfo *tmp;
-	GHashTable *instance;
-
-	g_return_if_fail (NM_IS_OBJECT (object));
-	g_return_if_fail (proxy != NULL);
-	g_return_if_fail (info != NULL);
-
-	dbus_g_proxy_add_signal (proxy, "PropertiesChanged", DBUS_TYPE_G_MAP_OF_VARIANT, G_TYPE_INVALID);
-	dbus_g_proxy_connect_signal (proxy,
-						    "PropertiesChanged",
-						    G_CALLBACK (properties_changed_proxy),
-						    object,
-						    NULL);
-
-	instance = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
-	priv->pcs = g_slist_prepend (priv->pcs, instance);
-
-	for (tmp = (NMPropertiesChangedInfo *) info; tmp->name; tmp++) {
-		PropChangedInfo *pci;
-
-		if (!tmp->name || !tmp->func || !tmp->field) {
-			g_warning ("%s: missing field in NMPropertiesChangedInfo", __func__);
-			continue;
-		}
-
-		pci = g_malloc0 (sizeof (PropChangedInfo));
-		if (!pci) {
-			g_warning ("%s: not enough memory for PropChangedInfo", __func__);
-			continue;
-		}
-		pci->func = tmp->func;
-		pci->field = tmp->field;
-		g_hash_table_insert (instance, g_strdup (tmp->name), pci);
-	}
+	process_properties_changed (NM_OBJECT (user_data), properties, FALSE);
 }
 
 #define HANDLE_TYPE(ucase, lcase, getter) \
@@ -449,11 +866,11 @@ _nm_object_handle_properties_changed (NMObject *object,
 			goto done; \
 		}
 
-gboolean
-_nm_object_demarshal_generic (NMObject *object,
-                             GParamSpec *pspec,
-                             GValue *value,
-                             gpointer field)
+static gboolean
+demarshal_generic (NMObject *object,
+                   GParamSpec *pspec,
+                   GValue *value,
+                   gpointer field)
 {
 	gboolean success = TRUE;
 
@@ -503,34 +920,132 @@ done:
 	return success;
 }
 
+void
+_nm_object_register_properties (NMObject *object,
+                                DBusGProxy *proxy,
+                                const NMPropertiesInfo *info)
+{
+	NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
+	NMPropertiesInfo *tmp;
+	GHashTable *instance;
+
+	g_return_if_fail (NM_IS_OBJECT (object));
+	g_return_if_fail (proxy != NULL);
+	g_return_if_fail (info != NULL);
+
+	priv->property_interfaces = g_slist_prepend (priv->property_interfaces,
+	                                             g_strdup (dbus_g_proxy_get_interface (proxy)));
+
+	dbus_g_proxy_add_signal (proxy, "PropertiesChanged", DBUS_TYPE_G_MAP_OF_VARIANT, G_TYPE_INVALID);
+	dbus_g_proxy_connect_signal (proxy,
+						    "PropertiesChanged",
+						    G_CALLBACK (properties_changed_proxy),
+						    object,
+						    NULL);
+
+	instance = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+	priv->property_tables = g_slist_prepend (priv->property_tables, instance);
+
+	for (tmp = (NMPropertiesInfo *) info; tmp->name; tmp++) {
+		PropertyInfo *pi;
+
+		if (!tmp->name || (tmp->func && !tmp->field)) {
+			g_warning ("%s: missing field in NMPropertiesInfo", __func__);
+			continue;
+		}
+
+		pi = g_malloc0 (sizeof (PropertyInfo));
+		pi->func = tmp->func ? tmp->func : demarshal_generic;
+		pi->object_type = tmp->object_type;
+		pi->field = tmp->field;
+		g_hash_table_insert (instance, g_strdup (tmp->name), pi);
+	}
+}
+
 gboolean
-_nm_object_get_property (NMObject *object,
-                         const char *interface,
-                         const char *prop_name,
-                         GValue *value,
-                         GError **error)
+_nm_object_reload_properties (NMObject *object, GError **error)
 {
+	NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
+	GHashTable *props = NULL;
+	GSList *p;
+	GHashTableIter pp;
+	gpointer name, info;
+
+	if (!priv->property_interfaces)
+		return TRUE;
+
+	for (p = priv->property_interfaces; p; p = p->next) {
+		if (!dbus_g_proxy_call (priv->properties_proxy, "GetAll", error,
+		                        G_TYPE_STRING, p->data,
+		                        G_TYPE_INVALID,
+		                        DBUS_TYPE_G_MAP_OF_VARIANT, &props,
+		                        G_TYPE_INVALID))
+			return FALSE;
+
+		process_properties_changed (object, props, TRUE);
+		g_hash_table_destroy (props);
+	}
+
+	if (priv->pseudo_properties) {
+		g_hash_table_iter_init (&pp, priv->pseudo_properties);
+		while (g_hash_table_iter_next (&pp, &name, &info))
+			_nm_object_reload_pseudo_property (object, name);
+	}
+
+	return TRUE;
+}
+
+void
+_nm_object_suppress_property_updates (NMObject *object, gboolean suppress)
+{
+	NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
+
+	priv->suppress_property_updates = suppress;
+}
+
+
+void
+_nm_object_ensure_inited (NMObject *object)
+{
+	NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
+	GError *error = NULL;
+
+	if (!priv->inited) {
+		if (!g_initable_init (G_INITABLE (object), NULL, &error)) {
+			g_warning ("Could not initialize %s %s: %s",
+			           G_OBJECT_TYPE_NAME (object), priv->path,
+			           error->message);
+			g_error_free (error);
+
+			/* Only warn once */
+			priv->inited = TRUE;
+		}
+	}
+}
+
+void
+_nm_object_reload_property (NMObject *object,
+                            const char *interface,
+                            const char *prop_name)
+{
+	GValue value = { 0, };
 	GError *err = NULL;
 
-	g_return_val_if_fail (NM_IS_OBJECT (object), FALSE);
-	g_return_val_if_fail (interface != NULL, FALSE);
-	g_return_val_if_fail (prop_name != NULL, FALSE);
-	g_return_val_if_fail (value != NULL, FALSE);
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+	g_return_if_fail (NM_IS_OBJECT (object));
+	g_return_if_fail (interface != NULL);
+	g_return_if_fail (prop_name != NULL);
 
 	if (!dbus_g_proxy_call_with_timeout (NM_OBJECT_GET_PRIVATE (object)->properties_proxy,
 							"Get", 15000, &err,
 							G_TYPE_STRING, interface,
 							G_TYPE_STRING, prop_name,
 							G_TYPE_INVALID,
-							G_TYPE_VALUE, value,
+							G_TYPE_VALUE, &value,
 							G_TYPE_INVALID)) {
 		/* Don't warn about D-Bus no reply/timeout errors; it's mostly noise and
 		 * happens for example when NM quits and the applet is still running.
-		 * And don't warn when 'error' is not NULL, rather propagate 'err' so the caller
-		 * can do something with it. */
-		if (   !error
-		    && !(err->domain == DBUS_GERROR && err->code == DBUS_GERROR_NO_REPLY)) {
+		 */
+		if (!g_error_matches (err, DBUS_GERROR, DBUS_GERROR_NO_REPLY)) {
 			g_warning ("%s: Error getting '%s' for %s: (%d) %s\n",
 			           __func__,
 			           prop_name,
@@ -538,11 +1053,12 @@ _nm_object_get_property (NMObject *object,
 			           err->code,
 			           err->message);
 		}
-		g_propagate_error (error, err);
-		return FALSE;
+		g_clear_error (&err);
+		return;
 	}
 
-	return TRUE;
+	handle_property_changed (object, prop_name, &value, TRUE);
+	g_value_unset (&value);
 }
 
 void
@@ -569,157 +1085,305 @@ _nm_object_set_property (NMObject *object,
 	}
 }
 
-char *
-_nm_object_get_string_property (NMObject *object,
-                                const char *interface,
-                                const char *prop_name,
-                                GError **error)
+static void
+pseudo_property_object_created (GObject *obj, gpointer user_data)
 {
-	char *str = NULL;
-	const char *tmp;
-	GValue value = {0,};
+	PseudoPropertyInfo *ppi = user_data;
 
-	if (_nm_object_get_property (object, interface, prop_name, &value, error)) {
-		if (G_VALUE_HOLDS_STRING (&value))
-			str = g_strdup (g_value_get_string (&value));
-		else if (G_VALUE_HOLDS (&value, DBUS_TYPE_G_OBJECT_PATH)) {
-			tmp = g_value_get_boxed (&value);
-			/* Handle "NULL" object paths */
-			if (g_strcmp0 (tmp, "/") != 0)
-				str = g_strdup (tmp);
-		}
-		g_value_unset (&value);
-	}
+	if (obj) {
+		GPtrArray **list_p = (GPtrArray **)ppi->pi.field;
 
-	return str;
+		if (!*list_p)
+			*list_p = g_ptr_array_new ();
+		add_to_object_array_unique (*list_p, obj);
+		ppi->added_func (ppi->self, NM_OBJECT (obj));
+	}
 }
 
-char *
-_nm_object_get_object_path_property (NMObject *object,
-                                     const char *interface,
-                                     const char *prop_name,
-                                     GError **error)
+static void
+pseudo_property_added (DBusGProxy *proxy, const char *path, gpointer user_data)
 {
-	char *path = NULL;
-	const char *tmp;
-	GValue value = {0,};
+	PseudoPropertyInfo *ppi = user_data;
+	NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (ppi->self);
+	NMObject *obj;
 
-	if (_nm_object_get_property (object, interface, prop_name, &value, error)) {
-		tmp = g_value_get_boxed (&value);
-		if (g_strcmp0 (tmp, "/") != 0)
-			path = g_strdup (tmp);
-		g_value_unset (&value);
-	}
+	if (priv->suppress_property_updates)
+		return;
 
-	return path;
+	obj = _nm_object_cache_get (path);
+	if (obj)
+		pseudo_property_object_created (G_OBJECT (obj), ppi);
+	else {
+		_nm_object_create_async (ppi->pi.object_type, priv->connection, path,
+		                         pseudo_property_object_created, ppi);
+	}
 }
 
-gint32
-_nm_object_get_int_property (NMObject *object,
-                             const char *interface,
-                             const char *prop_name,
-                             GError **error)
+static void
+pseudo_property_removed (DBusGProxy *proxy, const char *path, gpointer user_data)
 {
-	gint32 i = 0;
-	GValue value = {0,};
+	PseudoPropertyInfo *ppi = user_data;
+	NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (ppi->self);
+	GPtrArray *list = *(GPtrArray **)ppi->pi.field;
+	NMObject *obj = NULL;
+	int i;
 
-	if (_nm_object_get_property (object, interface, prop_name, &value, error)) {
-		i = g_value_get_int (&value);
-		g_value_unset (&value);
+	if (!list || priv->suppress_property_updates)
+		return;
+
+	for (i = 0; i < list->len; i++) {
+		obj = list->pdata[i];
+		if (!strcmp (path, nm_object_get_path (obj))) {
+			g_ptr_array_remove_index (list, i);
+			ppi->removed_func (ppi->self, obj);
+			g_object_unref (obj);
+			return;
+		}
 	}
+}
 
-	return i;
+static void
+free_pseudo_property (PseudoPropertyInfo *ppi)
+{
+	g_object_unref (ppi->proxy);
+	g_free (ppi->get_method);
+	g_slice_free (PseudoPropertyInfo, ppi);
 }
 
-guint32
-_nm_object_get_uint_property (NMObject *object,
-                              const char *interface,
-                              const char *prop_name,
-                              GError **error)
+void
+_nm_object_register_pseudo_property (NMObject *object,
+                                     DBusGProxy *proxy,
+                                     const char *name,
+                                     gpointer field,
+                                     GType object_type,
+                                     NMPseudoPropertyChangedFunc added_func,
+                                     NMPseudoPropertyChangedFunc removed_func)
 {
-	guint32 i = 0;
-	GValue value = {0,};
+	NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
+	PseudoPropertyInfo *ppi;
+	int basename_len;
+	char *added_signal, *removed_signal;
 
-	if (_nm_object_get_property (object, interface, prop_name, &value, error)) {
-		i = g_value_get_uint (&value);
-		g_value_unset (&value);
-	}
+	g_return_if_fail (NM_IS_OBJECT (object));
+	g_return_if_fail (proxy != NULL);
 
-	return i;
+	ppi = g_slice_new0 (PseudoPropertyInfo);
+	ppi->pi.field = field;
+	ppi->pi.object_type = object_type;
+	ppi->self = object;
+	ppi->proxy = g_object_ref (proxy);
+	ppi->added_func = added_func;
+	ppi->removed_func = removed_func;
+
+	basename_len = strlen (name);
+	if (basename_len > 4 && !strcmp (name + basename_len - 4, "List"))
+		basename_len -= 4;
+	else if (basename_len > 1 && name[basename_len - 1] == 's')
+		basename_len--;
+	else
+		g_assert_not_reached ();
+
+	ppi->get_method = g_strdup_printf ("Get%s", name);
+	added_signal = g_strdup_printf ("%.*sAdded", basename_len, name);
+	removed_signal = g_strdup_printf ("%.*sRemoved", basename_len, name);
+
+	if (!priv->pseudo_properties) {
+		priv->pseudo_properties = g_hash_table_new_full (g_str_hash, g_str_equal,
+		                                                 g_free, (GDestroyNotify) free_pseudo_property);
+	}
+	g_hash_table_insert (priv->pseudo_properties, g_strdup (name), ppi);
+
+	dbus_g_proxy_add_signal (proxy, added_signal,
+	                         DBUS_TYPE_G_OBJECT_PATH,
+	                         G_TYPE_INVALID);
+	dbus_g_proxy_connect_signal (proxy, added_signal,
+	                             G_CALLBACK (pseudo_property_added),
+	                             ppi, NULL);
+
+	dbus_g_proxy_add_signal (proxy, removed_signal,
+	                         DBUS_TYPE_G_OBJECT_PATH,
+	                         G_TYPE_INVALID);
+	dbus_g_proxy_connect_signal (proxy, removed_signal,
+	                             G_CALLBACK (pseudo_property_removed),
+	                             ppi, NULL);
+
+	g_free (added_signal);
+	g_free (removed_signal);
 }
 
-gboolean
-_nm_object_get_boolean_property (NMObject *object,
-                                 const char *interface,
-                                 const char *prop_name,
-                                 GError **error)
+void
+_nm_object_reload_pseudo_property (NMObject *object,
+                                   const char *name)
 {
-	gboolean b = FALSE;
-	GValue value = {0,};
+	NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
+	PseudoPropertyInfo *ppi;
+	GPtrArray *temp;
+	GError *error = NULL;
+	GValue value = { 0, };
 
-	if (_nm_object_get_property (object, interface, prop_name, &value, error)) {
-		b = g_value_get_boolean (&value);
-		g_value_unset (&value);
+	g_return_if_fail (NM_IS_OBJECT (object));
+	g_return_if_fail (name != NULL);
+
+	ppi = g_hash_table_lookup (priv->pseudo_properties, name);
+	g_return_if_fail (ppi != NULL);
+
+	if (!dbus_g_proxy_call (ppi->proxy, ppi->get_method, &error,
+	                        G_TYPE_INVALID,
+	                        DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH, &temp,
+	                        G_TYPE_INVALID)) {
+		g_warning ("%s: error calling %s: %s", __func__, ppi->get_method, error->message);
+		g_error_free (error);
+		return;
 	}
 
-	return b;
+	g_value_init (&value, DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH);
+	g_value_take_boxed (&value, temp);
+	handle_object_array_property (object, NULL, &value, &ppi->pi, TRUE);
+	g_value_unset (&value);
 }
 
-gint8
-_nm_object_get_byte_property (NMObject *object,
-                              const char *interface,
-                              const char *prop_name,
-                              GError **error)
+static void
+reload_complete (NMObject *object)
 {
-	gint8 b = G_MAXINT8;
-	GValue value = {0,};
+	NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
+	GSimpleAsyncResult *simple;
+	GSList *results, *iter;
+	GError *error;
 
-	if (_nm_object_get_property (object, interface, prop_name, &value, error)) {
-		b = g_value_get_uchar (&value);
-		g_value_unset (&value);
-	}
+	results = priv->reload_results;
+	priv->reload_results = NULL;
+	error = priv->reload_error;
+	priv->reload_error = NULL;
+
+	for (iter = results; iter; iter = iter->next) {
+		simple = results->data;
 
-	return b;
+		if (error)
+			g_simple_async_result_set_from_error (simple, error);
+		else
+			g_simple_async_result_set_op_res_gboolean (simple, TRUE);
+
+		g_simple_async_result_complete (simple);
+		g_object_unref (simple);
+	}
+	g_slist_free (results);
+	g_clear_error (&error);
 }
 
-gdouble
-_nm_object_get_double_property (NMObject *object,
-                                const char *interface,
-                                const char *prop_name,
-                                GError **error)
+static void
+reload_got_properties (DBusGProxy *proxy, DBusGProxyCall *call,
+                       gpointer user_data)
 {
-	gdouble d = G_MAXDOUBLE;
-	GValue value = {0,};
+	NMObject *object = user_data;
+	NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
+	GHashTable *props = NULL;
+	GError *error = NULL;
+
+	if (dbus_g_proxy_end_call (proxy, call, &error,
+	                           DBUS_TYPE_G_MAP_OF_VARIANT, &props,
+	                           G_TYPE_INVALID)) {
+		process_properties_changed (object, props, FALSE);
+		g_hash_table_destroy (props);
+	} else {
+		if (priv->reload_error)
+			g_error_free (error);
+		else
+			priv->reload_error = error;
+	}
 
-	if (_nm_object_get_property (object, interface, prop_name, &value, error)) {
-		d = g_value_get_double (&value);
+	if (--priv->reload_remaining == 0)
+		reload_complete (object);
+}
+
+static void
+reload_got_pseudo_property (DBusGProxy *proxy, DBusGProxyCall *call,
+                            gpointer user_data)
+{
+	PseudoPropertyInfo *ppi = user_data;
+	NMObject *object = ppi->self;
+	NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
+	GPtrArray *temp;
+	GValue value = { 0, };
+	GError *error = NULL;
+
+	if (dbus_g_proxy_end_call (proxy, call, &error,
+	                           DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH, &temp,
+	                           G_TYPE_INVALID)) {
+		g_value_init (&value, DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH);
+		g_value_take_boxed (&value, temp);
+		if (!priv->suppress_property_updates)
+			handle_object_array_property (object, NULL, &value, &ppi->pi, FALSE);
 		g_value_unset (&value);
+	} else {
+		if (priv->reload_error)
+			g_error_free (error);
+		else
+			priv->reload_error = error;
 	}
 
-	return d;
+	if (--priv->reload_remaining == 0)
+		reload_complete (object);
 }
 
-GByteArray *
-_nm_object_get_byte_array_property (NMObject *object,
-                                    const char *interface,
-                                    const char *prop_name,
-                                    GError **error)
+void
+_nm_object_reload_properties_async (NMObject *object, GAsyncReadyCallback callback, gpointer user_data)
 {
-	GByteArray *array = NULL;
-	GValue value = {0,};
+	NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
+	GSimpleAsyncResult *simple;
+	GSList *p;
 
-	if (_nm_object_get_property (object, interface, prop_name, &value, error)) {
-		GArray * tmp = g_value_get_boxed (&value);
-		int i;
-		unsigned char byte;
+	simple = g_simple_async_result_new (G_OBJECT (object), callback,
+	                                    user_data, _nm_object_reload_properties_async);
+
+	if (!priv->property_interfaces && !priv->pseudo_properties) {
+		g_simple_async_result_complete_in_idle (simple);
+		return;
+	}
+
+	priv->reload_results = g_slist_prepend (priv->reload_results, simple);
+
+	/* If there was already a reload happening, we don't need to
+	 * re-read the properties again, we just need to wait for the
+	 * existing reload to finish.
+	 */
+	if (priv->reload_results->next)
+		return;
 
-		array = g_byte_array_sized_new (tmp->len);
-		for (i = 0; i < tmp->len; i++) {
-			byte = g_array_index (tmp, unsigned char, i);
-			g_byte_array_append (array, &byte, 1);
+	for (p = priv->property_interfaces; p; p = p->next) {
+		priv->reload_remaining++;
+		dbus_g_proxy_begin_call (priv->properties_proxy, "GetAll",
+		                         reload_got_properties, object, NULL,
+		                         G_TYPE_STRING, p->data,
+		                         G_TYPE_INVALID);
+	}
+
+	if (priv->pseudo_properties) {
+		GHashTableIter iter;
+		gpointer key, value;
+		PseudoPropertyInfo *ppi;
+
+		g_hash_table_iter_init (&iter, priv->pseudo_properties);
+		while (g_hash_table_iter_next (&iter, &key, &value)) {
+			ppi = value;
+			priv->reload_remaining++;
+			dbus_g_proxy_begin_call (ppi->proxy, ppi->get_method,
+			                         reload_got_pseudo_property, ppi, NULL,
+			                         G_TYPE_INVALID);
 		}
-		g_value_unset (&value);
 	}
+}
+
+gboolean
+_nm_object_reload_properties_finish (NMObject *object, GAsyncResult *result, GError **error)
+{
+	GSimpleAsyncResult *simple;
+
+	g_return_val_if_fail (NM_IS_OBJECT (object), FALSE);
+	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (object), _nm_object_reload_properties_async), FALSE);
+
+	simple = G_SIMPLE_ASYNC_RESULT (result);
+	if (g_simple_async_result_propagate_error (simple, error))
+		return FALSE;
 
-	return array;
+	return g_simple_async_result_get_op_res_gboolean (simple);
 }
diff --git a/libnm-glib/nm-remote-connection.c b/libnm-glib/nm-remote-connection.c
index 9e190d9e..c5e38643 100644
--- a/libnm-glib/nm-remote-connection.c
+++ b/libnm-glib/nm-remote-connection.c
@@ -22,6 +22,7 @@
  */
 
 #include <string.h>
+#include <gio/gio.h>
 
 #include <NetworkManager.h>
 #include <nm-utils.h>
@@ -29,16 +30,21 @@
 #include "nm-remote-connection.h"
 #include "nm-remote-connection-private.h"
 #include "nm-dbus-glib-types.h"
-#include "nm-settings-connection-bindings.h"
+#include "nm-glib-compat.h"
 
 #define NM_REMOTE_CONNECTION_BUS "bus"
 
-G_DEFINE_TYPE (NMRemoteConnection, nm_remote_connection, NM_TYPE_CONNECTION)
+static void nm_remote_connection_initable_iface_init (GInitableIface *iface);
+static void nm_remote_connection_async_initable_iface_init (GAsyncInitableIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (NMRemoteConnection, nm_remote_connection, NM_TYPE_CONNECTION,
+                         G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, nm_remote_connection_initable_iface_init);
+                         G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, nm_remote_connection_async_initable_iface_init);
+                         )
 
 enum {
 	PROP_0,
 	PROP_BUS,
-	PROP_INIT_RESULT,
 
 	LAST_PROP
 };
@@ -65,7 +71,6 @@ typedef struct {
 	DBusGProxy *proxy;
 	GSList *calls;
 
-	NMRemoteConnectionInitResult init_result;
 	gboolean visible;
 	gboolean disposed;
 } NMRemoteConnectionPrivate;
@@ -89,13 +94,17 @@ remote_call_complete (NMRemoteConnection *self, RemoteCall *call)
 }
 
 static void
-update_cb (DBusGProxy *proxy, GError *error, gpointer user_data)
+update_cb (DBusGProxy *proxy, DBusGProxyCall *proxy_call, gpointer user_data)
 {
 	RemoteCall *call = user_data;
 	NMRemoteConnectionCommitFunc func = (NMRemoteConnectionCommitFunc) call->callback;
+	GError *error = NULL;
 
+	dbus_g_proxy_end_call (proxy, proxy_call, &error,
+	                       G_TYPE_INVALID);
 	if (func != NULL)
 		(*func)(call->self, error, call->user_data);
+	g_clear_error (&error);
 	remote_call_complete (call->self, call);
 }
 
@@ -131,10 +140,10 @@ nm_remote_connection_commit_changes (NMRemoteConnection *self,
 
 	settings = nm_connection_to_hash (NM_CONNECTION (self), NM_SETTING_HASH_FLAG_ALL);
 
-	call->call = org_freedesktop_NetworkManager_Settings_Connection_update_async (priv->proxy,
-	                                                                              settings,
-	                                                                              update_cb,
-	                                                                              call);
+	call->call = dbus_g_proxy_begin_call (priv->proxy, "Update",
+	                                      update_cb, call, NULL,
+	                                      DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, settings,
+	                                      G_TYPE_INVALID);
 	g_assert (call->call);
 	priv->calls = g_slist_append (priv->calls, call);
 
@@ -142,13 +151,17 @@ nm_remote_connection_commit_changes (NMRemoteConnection *self,
 }
 
 static void
-delete_cb (DBusGProxy *proxy, GError *error, gpointer user_data)
+delete_cb (DBusGProxy *proxy, DBusGProxyCall *proxy_call, gpointer user_data)
 {
 	RemoteCall *call = user_data;
 	NMRemoteConnectionDeleteFunc func = (NMRemoteConnectionDeleteFunc) call->callback;
+	GError *error = NULL;
 
+	dbus_g_proxy_end_call (proxy, proxy_call, &error,
+	                       G_TYPE_INVALID);
 	if (func != NULL)
 		(*func)(call->self, error, call->user_data);
+	g_clear_error (&error);
 	remote_call_complete (call->self, call);
 }
 
@@ -178,20 +191,26 @@ nm_remote_connection_delete (NMRemoteConnection *self,
 	call->callback = (GFunc) callback;
 	call->user_data = user_data;
 
-	call->call = org_freedesktop_NetworkManager_Settings_Connection_delete_async (priv->proxy,
-	                                                                              delete_cb,
-	                                                                              call);
+	call->call = dbus_g_proxy_begin_call (priv->proxy, "Delete",
+	                                      delete_cb, call, NULL,
+	                                      G_TYPE_INVALID);
 	g_assert (call->call);
 	priv->calls = g_slist_append (priv->calls, call);
 }
 
 static void
-get_secrets_cb (DBusGProxy *proxy, GHashTable *secrets, GError *error, gpointer user_data)
+get_secrets_cb (DBusGProxy *proxy, DBusGProxyCall *proxy_call, gpointer user_data)
 {
 	RemoteCall *call = user_data;
 	NMRemoteConnectionGetSecretsFunc func = (NMRemoteConnectionGetSecretsFunc) call->callback;
+	GHashTable *secrets;
+	GError *error = NULL;
 
+	dbus_g_proxy_end_call (proxy, proxy_call, &error,
+	                       DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, &secrets,
+	                       G_TYPE_INVALID);
 	(*func)(call->self, error ? NULL : secrets, error, call->user_data);
+	g_clear_error (&error);
 	remote_call_complete (call->self, call);
 }
 
@@ -225,10 +244,10 @@ nm_remote_connection_get_secrets (NMRemoteConnection *self,
 	call->callback = (GFunc) callback;
 	call->user_data = user_data;
 
-	call->call = org_freedesktop_NetworkManager_Settings_Connection_get_secrets_async (priv->proxy,
-	                                                                                   setting_name,
-	                                                                                   get_secrets_cb,
-	                                                                                   call);
+	call->call = dbus_g_proxy_begin_call (priv->proxy, "GetSecrets",
+	                                      get_secrets_cb, call, NULL,
+	                                      G_TYPE_STRING, setting_name,
+	                                      G_TYPE_INVALID);
 	g_assert (call->call);
 	priv->calls = g_slist_append (priv->calls, call);
 }
@@ -255,43 +274,23 @@ replace_settings (NMRemoteConnection *self, GHashTable *new_settings)
 }
 
 static void
-init_get_settings_cb (DBusGProxy *proxy,
-                      GHashTable *new_settings,
-                      GError *error,
-                      gpointer user_data)
-{
-	NMRemoteConnection *self = user_data;
-	NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (self);
-
-	if (error) {
-		/* Connection doesn't exist, or isn't visible to this user */
-		if (dbus_g_error_has_name (error, "org.freedesktop.NetworkManager.Settings.PermissionDenied"))
-			priv->init_result = NM_REMOTE_CONNECTION_INIT_RESULT_INVISIBLE;
-		else
-			priv->init_result = NM_REMOTE_CONNECTION_INIT_RESULT_ERROR;
-
-		g_object_notify (G_OBJECT (self), NM_REMOTE_CONNECTION_INIT_RESULT);
-	} else {
-		priv->visible = TRUE;
-		replace_settings (self, new_settings);
-		g_hash_table_destroy (new_settings);
-		priv->init_result = NM_REMOTE_CONNECTION_INIT_RESULT_SUCCESS;
-		g_object_notify (G_OBJECT (self), NM_REMOTE_CONNECTION_INIT_RESULT);
-	}
-}
-
-static void
 updated_get_settings_cb (DBusGProxy *proxy,
-                         GHashTable *new_settings,
-                         GError *error,
+                         DBusGProxyCall *call,
                          gpointer user_data)
 {
 	NMRemoteConnection *self = user_data;
 	NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (self);
+	GHashTable *new_settings;
+	GError *error = NULL;
 
+	dbus_g_proxy_end_call (proxy, call, &error,
+	                       DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, &new_settings,
+	                       G_TYPE_INVALID);
 	if (error) {
 		GHashTable *hash;
 
+		g_error_free (error);
+
 		/* Connection is no longer visible to this user.  Let the settings
 		 * service handle this via 'visible'.  The settings service will emit
 		 * the "removed" signal for us since it handles the lifetime of this
@@ -322,9 +321,9 @@ updated_cb (DBusGProxy *proxy, gpointer user_data)
 	NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (self);
 
 	/* The connection got updated; request the replacement settings */
-	org_freedesktop_NetworkManager_Settings_Connection_get_settings_async (priv->proxy,
-	                                                                       updated_get_settings_cb,
-	                                                                       self);
+	dbus_g_proxy_begin_call (priv->proxy, "GetSettings",
+	                         updated_get_settings_cb, self, NULL,
+	                         G_TYPE_INVALID);
 }
 
 static void
@@ -357,18 +356,11 @@ nm_remote_connection_new (DBusGConnection *bus,
 	                                            NULL);
 }
 
-static GObject *
-constructor (GType type,
-             guint n_construct_params,
-             GObjectConstructParam *construct_params)
+static void
+constructed (GObject *object)
 {
-	GObject *object;
 	NMRemoteConnectionPrivate *priv;
 
-	object = G_OBJECT_CLASS (nm_remote_connection_parent_class)->constructor (type, n_construct_params, construct_params);
-	if (!object)
-		return NULL;
-
 	priv = NM_REMOTE_CONNECTION_GET_PRIVATE (object);
 	g_assert (priv->bus);
 	g_assert (nm_connection_get_path (NM_CONNECTION (object)));
@@ -385,11 +377,76 @@ constructor (GType type,
 
 	dbus_g_proxy_add_signal (priv->proxy, "Removed", G_TYPE_INVALID);
 	dbus_g_proxy_connect_signal (priv->proxy, "Removed", G_CALLBACK (removed_cb), object, NULL);
+}
+
+static gboolean
+init_sync (GInitable *initable, GCancellable *cancellable, GError **error)
+{
+	NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (initable);
+	GHashTable *settings;
+
+	if (!dbus_g_proxy_call (priv->proxy, "GetSettings", error,
+	                        G_TYPE_STRING, NM_DBUS_IFACE_SETTINGS,
+	                        G_TYPE_INVALID,
+	                        DBUS_TYPE_G_MAP_OF_VARIANT, &settings,
+	                        G_TYPE_INVALID))
+		return FALSE;
+
+	priv->visible = TRUE;
+	replace_settings (NM_REMOTE_CONNECTION (initable), settings);
+	g_hash_table_destroy (settings);
+	return TRUE;
+}
+
+typedef struct {
+	NMRemoteConnection *connection;
+	GSimpleAsyncResult *result;
+} NMRemoteConnectionInitData;
+
+static void
+init_get_settings_cb (DBusGProxy *proxy,
+                      DBusGProxyCall *call,
+                      gpointer user_data)
+{
+	NMRemoteConnectionInitData *init_data = user_data;
+	NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (init_data->connection);
+	GHashTable *settings;
+	GError *error = NULL;
+
+	dbus_g_proxy_end_call (proxy, call, &error,
+	                       DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, &settings,
+	                       G_TYPE_INVALID);
+	if (error) {
+		g_simple_async_result_take_error (init_data->result, error);
+	} else {
+		priv->visible = TRUE;
+		replace_settings (init_data->connection, settings);
+		g_hash_table_destroy (settings);
+		g_simple_async_result_set_op_res_gboolean (init_data->result, TRUE);
+	}
+
+	g_simple_async_result_complete (init_data->result);
+	g_slice_free (NMRemoteConnectionInitData, init_data);
+}
+
+static void
+init_async (GAsyncInitable *initable, int io_priority,
+			GCancellable *cancellable, GAsyncReadyCallback callback,
+			gpointer user_data)
+{
+	NMRemoteConnectionInitData *init_data;
+	NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (initable);
+
+
+	init_data = g_slice_new0 (NMRemoteConnectionInitData);
+	init_data->connection = NM_REMOTE_CONNECTION (initable);
+	init_data->result = g_simple_async_result_new (G_OBJECT (initable), callback,
+	                                               user_data, init_async);
+
+	dbus_g_proxy_begin_call (priv->proxy, "GetSettings",
+	                         init_get_settings_cb, init_data, NULL,
+	                         G_TYPE_INVALID);
 
-	org_freedesktop_NetworkManager_Settings_Connection_get_settings_async (priv->proxy,
-	                                                                       init_get_settings_cb,
-	                                                                       object);
-	return object;
 }
 
 static void
@@ -415,23 +472,6 @@ set_property (GObject *object, guint prop_id,
 }
 
 static void
-get_property (GObject *object, guint prop_id,
-              GValue *value, GParamSpec *pspec)
-{
-	NMRemoteConnection *self = NM_REMOTE_CONNECTION (object);
-	NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (self);
-
-	switch (prop_id) {
-	case PROP_INIT_RESULT:
-		g_value_set_uint (value, priv->init_result);
-		break;
-	default:
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-		break;
-	}
-}
-
-static void
 dispose (GObject *object)
 {
 	NMRemoteConnection *self = NM_REMOTE_CONNECTION (object);
@@ -459,9 +499,8 @@ nm_remote_connection_class_init (NMRemoteConnectionClass *remote_class)
 
 	/* virtual methods */
 	object_class->set_property = set_property;
-	object_class->get_property = get_property;
 	object_class->dispose = dispose;
-	object_class->constructor = constructor;
+	object_class->constructed = constructed;
 
 	/* Properties */
 	g_object_class_install_property
@@ -472,16 +511,6 @@ nm_remote_connection_class_init (NMRemoteConnectionClass *remote_class)
 						 DBUS_TYPE_G_CONNECTION,
 						 G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
 
-	g_object_class_install_property
-		(object_class, PROP_INIT_RESULT,
-		 g_param_spec_uint (NM_REMOTE_CONNECTION_INIT_RESULT,
-		                    "Initialization result (PRIVATE)",
-		                    "Initialization result (PRIVATE)",
-		                    NM_REMOTE_CONNECTION_INIT_RESULT_UNKNOWN,
-		                    NM_REMOTE_CONNECTION_INIT_RESULT_ERROR,
-		                    NM_REMOTE_CONNECTION_INIT_RESULT_UNKNOWN,
-		                    G_PARAM_READABLE));
-
 	/* Signals */
 	/**
 	 * NMRemoteConnection::updated:
@@ -524,3 +553,15 @@ nm_remote_connection_class_init (NMRemoteConnectionClass *remote_class)
 		              g_cclosure_marshal_VOID__BOOLEAN,
 		              G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
 }
+
+static void
+nm_remote_connection_initable_iface_init (GInitableIface *iface)
+{
+	iface->init = init_sync;
+}
+
+static void
+nm_remote_connection_async_initable_iface_init (GAsyncInitableIface *iface)
+{
+	iface->init_async = init_async;
+}
diff --git a/libnm-glib/nm-remote-settings.c b/libnm-glib/nm-remote-settings.c
index 7658623f..8f213f9e 100644
--- a/libnm-glib/nm-remote-settings.c
+++ b/libnm-glib/nm-remote-settings.c
@@ -18,25 +18,32 @@
  * Boston, MA 02110-1301 USA.
  *
  * Copyright (C) 2008 Novell, Inc.
- * Copyright (C) 2009 - 2011 Red Hat, Inc.
+ * Copyright (C) 2009 - 2012 Red Hat, Inc.
  */
 
 #include <string.h>
 #include <NetworkManager.h>
 #include <nm-connection.h>
 
-#include "nm-marshal.h"
+#include "nm-glib-marshal.h"
 #include "nm-dbus-glib-types.h"
 #include "nm-remote-settings.h"
-#include "nm-settings-bindings.h"
 #include "nm-remote-connection-private.h"
+#include "nm-glib-compat.h"
 
-G_DEFINE_TYPE (NMRemoteSettings, nm_remote_settings, G_TYPE_OBJECT)
+static void nm_remote_settings_initable_iface_init (GInitableIface *iface);
+static void nm_remote_settings_async_initable_iface_init (GAsyncInitableIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (NMRemoteSettings, nm_remote_settings, G_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, nm_remote_settings_initable_iface_init);
+                         G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, nm_remote_settings_async_initable_iface_init);
+                         )
 
 #define NM_REMOTE_SETTINGS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_REMOTE_SETTINGS, NMRemoteSettingsPrivate))
 
 typedef struct {
 	DBusGConnection *bus;
+	gboolean inited;
 
 	DBusGProxy *proxy;
 	GHashTable *connections;
@@ -96,24 +103,27 @@ nm_remote_settings_error_quark (void)
 	return quark;
 }
 
-/* This should really be standard. */
-#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
+/**********************************************************************/
 
-GType
-nm_remote_settings_error_get_type (void)
+static void
+_nm_remote_settings_ensure_inited (NMRemoteSettings *self)
 {
-	static GType etype = 0;
+	NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
+	GError *error;
 
-	if (etype == 0) {
-		static const GEnumValue values[] = {
-			ENUM_ENTRY (NM_REMOTE_SETTINGS_ERROR_UNKNOWN, "UnknownError"),
-			ENUM_ENTRY (NM_REMOTE_SETTINGS_ERROR_CONNECTION_REMOVED, "ConnectionRemoved"),
-			ENUM_ENTRY (NM_REMOTE_SETTINGS_ERROR_CONNECTION_UNAVAILABLE, "ConnectionUnavailable"),
-			{ 0, 0, 0 }
-		};
-		etype = g_enum_register_static ("NMRemoteSettingsError", values);
+	if (!priv->inited) {
+		if (!g_initable_init (G_INITABLE (self), NULL, &error)) {
+			/* Don't warn when the call times out because the settings service can't
+			 * be activated or whatever.
+			 */
+			if (!g_error_matches (error, DBUS_GERROR, DBUS_GERROR_NO_REPLY)) {
+				g_warning ("%s: (NMRemoteSettings) error initializing: %s\n",
+					       __func__, error->message);
+			}
+			g_error_free (error);
+		}
+		priv->inited = TRUE;
 	}
-	return etype;
 }
 
 /**********************************************************************/
@@ -175,11 +185,17 @@ add_connection_info_complete (NMRemoteSettings *self,
 NMRemoteConnection *
 nm_remote_settings_get_connection_by_path (NMRemoteSettings *settings, const char *path)
 {
+	NMRemoteSettingsPrivate *priv;
+
 	g_return_val_if_fail (settings != NULL, NULL);
 	g_return_val_if_fail (NM_IS_REMOTE_SETTINGS (settings), NULL);
 	g_return_val_if_fail (path != NULL, NULL);
 
-	return g_hash_table_lookup (NM_REMOTE_SETTINGS_GET_PRIVATE (settings)->connections, path);
+	priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings);
+
+	_nm_remote_settings_ensure_inited (settings);
+
+	return priv->service_running ? g_hash_table_lookup (priv->connections, path) : NULL;
 }
 
 /**
@@ -195,6 +211,7 @@ nm_remote_settings_get_connection_by_path (NMRemoteSettings *settings, const cha
 NMRemoteConnection *
 nm_remote_settings_get_connection_by_uuid (NMRemoteSettings *settings, const char *uuid)
 {
+	NMRemoteSettingsPrivate *priv;
 	GHashTableIter iter;
 	NMRemoteConnection *candidate;
 
@@ -202,10 +219,16 @@ nm_remote_settings_get_connection_by_uuid (NMRemoteSettings *settings, const cha
 	g_return_val_if_fail (NM_IS_REMOTE_SETTINGS (settings), NULL);
 	g_return_val_if_fail (uuid != NULL, NULL);
 
-	g_hash_table_iter_init (&iter, NM_REMOTE_SETTINGS_GET_PRIVATE (settings)->connections);
-	while (g_hash_table_iter_next (&iter, NULL, (gpointer) &candidate)) {
-		if (g_strcmp0 (uuid, nm_connection_get_uuid (NM_CONNECTION (candidate))) == 0)
-			return candidate;
+	priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings);
+
+	_nm_remote_settings_ensure_inited (settings);
+
+	if (priv->service_running) {
+		g_hash_table_iter_init (&iter, priv->connections);
+		while (g_hash_table_iter_next (&iter, NULL, (gpointer) &candidate)) {
+			if (g_strcmp0 (uuid, nm_connection_get_uuid (NM_CONNECTION (candidate))) == 0)
+				return candidate;
+		}
 	}
 
 	return NULL;
@@ -278,37 +301,20 @@ connection_visible_cb (NMRemoteConnection *remote,
 }
 
 static void
-connection_init_result_cb (NMRemoteConnection *remote,
-                           GParamSpec *pspec,
-                           gpointer user_data)
+connection_inited (GObject *source, GAsyncResult *result, gpointer user_data)
 {
+	NMRemoteConnection *remote = NM_REMOTE_CONNECTION (source);
 	NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data);
 	NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
-	guint32 init_result = NM_REMOTE_CONNECTION_INIT_RESULT_UNKNOWN;
 	AddConnectionInfo *addinfo;
 	const char *path;
-	GError *add_error = NULL;
+	GError *error = NULL;
 	gboolean remove_from_pending = TRUE;
 
-	/* Disconnect from the init-result signal just to be safe */
-	g_signal_handlers_disconnect_matched (remote,
-	                                      G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
-	                                      0,
-	                                      0,
-	                                      NULL,
-	                                      G_CALLBACK (connection_init_result_cb),
-	                                      self);
-
 	path = nm_connection_get_path (NM_CONNECTION (remote));
-
-	g_object_get (G_OBJECT (remote),
-	              NM_REMOTE_CONNECTION_INIT_RESULT, &init_result,
-	              NULL);
-
 	addinfo = add_connection_info_find (self, remote);
 
-	switch (init_result) {
-	case NM_REMOTE_CONNECTION_INIT_RESULT_SUCCESS:
+	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.
 		 */
@@ -324,22 +330,20 @@ connection_init_result_cb (NMRemoteConnection *remote,
 		 * its settings and is valid.
 		 */
 		g_signal_emit (self, signals[NEW_CONNECTION], 0, remote);
-		break;
-	case NM_REMOTE_CONNECTION_INIT_RESULT_INVISIBLE:
-		remove_from_pending = FALSE;
-		/* fall through */
-	case NM_REMOTE_CONNECTION_INIT_RESULT_ERROR:
-		/* Complete pending AddConnection callbacks */
+	} 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) {
-			add_error = 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, add_error);
-			g_error_free (add_error);
+			error = 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);
 		}
-		break;
-	default:
-		break;
 	}
 
 	if (remove_from_pending)
@@ -377,9 +381,9 @@ new_connection_cb (DBusGProxy *proxy, const char *path, gpointer user_data)
 		                  G_CALLBACK (connection_visible_cb),
 		                  self);
 
-		g_signal_connect (connection, "notify::" NM_REMOTE_CONNECTION_INIT_RESULT,
-		                  G_CALLBACK (connection_init_result_cb),
-		                  self);
+		g_async_initable_init_async (G_ASYNC_INITABLE (connection),
+		                             G_PRIORITY_DEFAULT, NULL,
+		                             connection_inited, self);
 
 		/* Add the connection to the pending table to wait for it to retrieve
 		 * it's settings asynchronously over D-Bus.  The connection isn't
@@ -392,15 +396,18 @@ new_connection_cb (DBusGProxy *proxy, const char *path, gpointer user_data)
 
 static void
 fetch_connections_done (DBusGProxy *proxy,
-                        GPtrArray *connections,
-                        GError *error,
+                        DBusGProxyCall *call,
                         gpointer user_data)
 {
 	NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data);
 	NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
+	GPtrArray *connections;
+	GError *error = NULL;
 	int i;
 
-	if (error) {
+	if (!dbus_g_proxy_end_call (proxy, call, &error, 
+	                            DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH, &connections,
+	                            G_TYPE_INVALID)) {
 		/* Ignore settings service spawn errors */
 		if (   !g_error_matches (error, DBUS_GERROR, DBUS_GERROR_SERVICE_UNKNOWN)
 		    && !g_error_matches (error, DBUS_GERROR, DBUS_GERROR_NAME_HAS_NO_OWNER)) {
@@ -440,9 +447,9 @@ fetch_connections (gpointer user_data)
 
 	priv->fetch_id = 0;
 
-	org_freedesktop_NetworkManager_Settings_list_connections_async (priv->proxy,
-	                                                                fetch_connections_done,
-	                                                                self);
+	dbus_g_proxy_begin_call (priv->proxy, "ListConnections",
+	                         fetch_connections_done, self, NULL,
+	                         G_TYPE_INVALID);
 	return FALSE;
 }
 
@@ -470,9 +477,13 @@ nm_remote_settings_list_connections (NMRemoteSettings *settings)
 
 	priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings);
 
-	g_hash_table_iter_init (&iter, priv->connections);
-	while (g_hash_table_iter_next (&iter, NULL, &value))
-		list = g_slist_prepend (list, NM_REMOTE_CONNECTION (value));
+	_nm_remote_settings_ensure_inited (settings);
+
+	if (priv->service_running) {
+		g_hash_table_iter_init (&iter, priv->connections);
+		while (g_hash_table_iter_next (&iter, NULL, &value))
+			list = g_slist_prepend (list, NM_REMOTE_CONNECTION (value));
+	}
 
 	return list;
 }
@@ -525,7 +536,9 @@ nm_remote_settings_add_connection (NMRemoteSettings *settings,
 	g_return_val_if_fail (callback != NULL, FALSE);
 
 	priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings);
-	
+
+	_nm_remote_settings_ensure_inited (settings);
+
 	info = g_malloc0 (sizeof (AddConnectionInfo));
 	info->self = settings;
 	info->callback = callback;
@@ -629,6 +642,8 @@ nm_remote_settings_save_hostname (NMRemoteSettings *settings,
 	
 	priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings);
 
+	_nm_remote_settings_ensure_inited (settings);
+
 	info = g_malloc0 (sizeof (SaveHostnameInfo));
 	info->settings = settings;
 	info->callback = callback;
@@ -696,35 +711,6 @@ properties_changed_cb (DBusGProxy *proxy,
 	}
 }
 
-static void
-get_all_cb  (DBusGProxy *proxy,
-             DBusGProxyCall *call,
-             gpointer user_data)
-{
-	NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data);
-	GHashTable *props = NULL;
-	GError *error = NULL;
-
-	if (!dbus_g_proxy_end_call (proxy, call, &error,
-	                            DBUS_TYPE_G_MAP_OF_VARIANT, &props,
-	                            G_TYPE_INVALID)) {
-		/* Don't warn when the call times out because the settings service can't
-		 * be activated or whatever.
-		 */
-		if (!(error->domain == DBUS_GERROR && error->code == DBUS_GERROR_NO_REPLY)) {
-			g_warning ("%s: couldn't retrieve system settings properties: (%d) %s.",
-			           __func__,
-			           error ? error->code : -1,
-			           (error && error->message) ? error->message : "(unknown)");
-		}
-		g_clear_error (&error);
-		return;
-	}
-
-	properties_changed_cb (NULL, props, self);
-	g_hash_table_destroy (props);
-}
-
 /****************************************************************/
 
 /**
@@ -733,16 +719,84 @@ get_all_cb  (DBusGProxy *proxy,
  *
  * Creates a new object representing the remote settings service.
  *
+ * Note that this will do blocking D-Bus calls to initialize the
+ * settings object. You can use nm_remote_settings_new_async() if you
+ * want to avoid that.
+ *
  * Returns: the new remote settings object on success, or %NULL on failure
  **/
 NMRemoteSettings *
 nm_remote_settings_new (DBusGConnection *bus)
 {
-	return (NMRemoteSettings *) g_object_new (NM_TYPE_REMOTE_SETTINGS,
-	                                          NM_REMOTE_SETTINGS_BUS, bus,
-	                                          NULL);
+	return g_object_new (NM_TYPE_REMOTE_SETTINGS, NM_REMOTE_SETTINGS_BUS, bus, NULL);
+}
+
+static void
+remote_settings_inited (GObject *source, GAsyncResult *result, gpointer user_data)
+{
+	GSimpleAsyncResult *simple = user_data;
+	GError *error = NULL;
+
+	if (!g_async_initable_init_finish (G_ASYNC_INITABLE (source), result, &error))
+		g_simple_async_result_take_error (simple, error);
+	else
+		g_simple_async_result_set_op_res_gpointer (simple, source, g_object_unref);
+	g_simple_async_result_complete (simple);
+	g_object_unref (simple);
+}
+
+/**
+ * nm_remote_settings_new_async:
+ * @bus: (allow-none): a valid and connected D-Bus connection
+ * @cancellable: a #GCancellable, or %NULL
+ * @callback: callback to call when the settings object is created
+ * @user_data: data for @callback
+ *
+ * Creates a new object representing the remote settings service and
+ * begins asynchronously initializing it. @callback will be called
+ * when it is done; use nm_remote_settings_new_finish() to get the
+ * result.
+ **/
+void
+nm_remote_settings_new_async (DBusGConnection *bus, GCancellable *cancellable,
+                              GAsyncReadyCallback callback, gpointer user_data)
+{
+	NMRemoteSettings *self;
+	GSimpleAsyncResult *simple;
+
+	simple = g_simple_async_result_new (NULL, callback, user_data, nm_remote_settings_new_async);
+
+	self = g_object_new (NM_TYPE_REMOTE_SETTINGS,
+	                     NM_REMOTE_SETTINGS_BUS, bus,
+	                     NULL);
+	g_async_initable_init_async (G_ASYNC_INITABLE (self), G_PRIORITY_DEFAULT,
+	                             cancellable, remote_settings_inited, simple);
+}
+
+/**
+ * nm_remote_settings_new_finish:
+ * @result: a #GAsyncResult
+ * @error: location for a #GError, or %NULL
+ *
+ * Gets the result of an nm_remote_settings_new_async() call.
+ *
+ * Returns: a new #NMRemoteSettings object, or %NULL on error
+ **/
+NMRemoteSettings *
+nm_remote_settings_new_finish (GAsyncResult *result, GError **error)
+{
+	GSimpleAsyncResult *simple;
+
+	g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL, nm_remote_settings_new_async), NULL);
+
+	simple = G_SIMPLE_ASYNC_RESULT (result);
+	if (g_simple_async_result_propagate_error (simple, error))
+		return NULL;
+	else
+		return g_object_ref (g_simple_async_result_get_op_res_gpointer (simple));
 }
 
+
 static void
 nm_remote_settings_init (NMRemoteSettings *self)
 {
@@ -752,18 +806,10 @@ nm_remote_settings_init (NMRemoteSettings *self)
 	priv->pending = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
 }
 
-static GObject *
-constructor (GType type,
-             guint n_construct_params,
-             GObjectConstructParam *construct_params)
+static void
+constructed (GObject *object)
 {
-	GObject *object;
 	NMRemoteSettingsPrivate *priv;
-	GError *error = NULL;
-
-	object = G_OBJECT_CLASS (nm_remote_settings_parent_class)->constructor (type, n_construct_params, construct_params);
-	if (!object)
-		return NULL;
 
 	priv = NM_REMOTE_SETTINGS_GET_PRIVATE (object);
 
@@ -774,7 +820,7 @@ constructor (GType type,
 	                                              "org.freedesktop.DBus");
 	g_assert (priv->dbus_proxy);
 
-	dbus_g_object_register_marshaller (_nm_marshal_VOID__STRING_STRING_STRING,
+	dbus_g_object_register_marshaller (_nm_glib_marshal_VOID__STRING_STRING_STRING,
 	                                   G_TYPE_NONE,
 	                                   G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
 	                                   G_TYPE_INVALID);
@@ -786,19 +832,6 @@ constructor (GType type,
 	                             G_CALLBACK (name_owner_changed),
 	                             object, NULL);
 
-	if (!dbus_g_proxy_call (priv->dbus_proxy, "NameHasOwner", &error,
-	                        G_TYPE_STRING, NM_DBUS_SERVICE,
-	                        G_TYPE_INVALID,
-	                        G_TYPE_BOOLEAN, &priv->service_running,
-	                        G_TYPE_INVALID)) {
-		g_warning ("%s (NMRemoteSettings) error getting remote settings service status: (%d) %s\n",
-		           __func__,
-		           error ? error->code : -1,
-		           error && error->message ? error->message : "(unknown)");
-		g_error_free (error);
-		priv->service_running = FALSE;
-	}
-
 	priv->proxy = dbus_g_proxy_new_for_name (priv->bus,
 	                                         NM_DBUS_SERVICE,
 	                                         NM_DBUS_PATH_SETTINGS,
@@ -836,16 +869,136 @@ constructor (GType type,
 	                             G_CALLBACK (properties_changed_cb),
 	                             object,
 	                             NULL);
+}
+
+static gboolean
+init_sync (GInitable *initable, GCancellable *cancellable, GError **error)
+{
+	NMRemoteSettings *settings = NM_REMOTE_SETTINGS (initable);
+	NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings);
+	GHashTable *props;
+
+	if (!dbus_g_proxy_call (priv->dbus_proxy, "NameHasOwner", error,
+	                        G_TYPE_STRING, NM_DBUS_SERVICE,
+	                        G_TYPE_INVALID,
+	                        G_TYPE_BOOLEAN, &priv->service_running,
+	                        G_TYPE_INVALID)) {
+		priv->service_running = FALSE;
+		return FALSE;
+	}
 
 	/* Get properties */
+	if (!dbus_g_proxy_call (priv->props_proxy, "GetAll", error,
+	                        G_TYPE_STRING, NM_DBUS_IFACE_SETTINGS,
+	                        G_TYPE_INVALID,
+	                        DBUS_TYPE_G_MAP_OF_VARIANT, &props,
+	                        G_TYPE_INVALID))
+		return FALSE;
+	properties_changed_cb (priv->props_proxy, props, settings);
+	g_hash_table_destroy (props);
+
+	/* FIXME: need a synchronous fetch_connections too */
+
+	return TRUE;
+}
+
+typedef struct {
+	NMRemoteSettings *settings;
+	GSimpleAsyncResult *result;
+} NMRemoteSettingsInitData;
+
+static void
+init_async_complete (NMRemoteSettingsInitData *init_data)
+{
+	g_simple_async_result_complete (init_data->result);
+	g_object_unref (init_data->result);
+	g_slice_free (NMRemoteSettingsInitData, init_data);
+}
+
+static void
+init_read_connections (NMRemoteSettings *settings, gpointer user_data)
+{
+	NMRemoteSettingsInitData *init_data = user_data;
+
+	g_signal_handlers_disconnect_by_func (settings, G_CALLBACK (init_read_connections), user_data);
+	init_async_complete (init_data);
+}
+
+static void
+init_async_got_properties (DBusGProxy *proxy, DBusGProxyCall *call,
+                           gpointer user_data)
+{
+	NMRemoteSettingsInitData *init_data = user_data;
+	NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (init_data->settings);
+	GHashTable *props;
+	GError *error = NULL;
+
+	if (dbus_g_proxy_end_call (proxy, call, &error,
+	                           DBUS_TYPE_G_MAP_OF_VARIANT, &props,
+	                           G_TYPE_INVALID)) {
+		properties_changed_cb (priv->props_proxy, props, init_data->settings);
+		g_hash_table_destroy (props);
+		g_simple_async_result_set_op_res_gboolean (init_data->result, TRUE);
+	} else
+		g_simple_async_result_take_error (init_data->result, error);
+
+	if (priv->init_left) {
+		/* Still creating initial connections; wait for that to complete */
+		g_signal_connect (init_data->settings, "connections-read",
+		                  G_CALLBACK (init_read_connections), init_data);
+		return;
+	}
+
+	init_async_complete (init_data);
+}
+
+static void
+init_async_got_manager_running (DBusGProxy *proxy, DBusGProxyCall *call,
+                                gpointer user_data)
+{
+	NMRemoteSettingsInitData *init_data = user_data;
+	NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (init_data->settings);
+	GError *error = NULL;
+
+	if (!dbus_g_proxy_end_call (proxy, call, &error,
+	                            G_TYPE_BOOLEAN, &priv->service_running,
+	                            G_TYPE_INVALID)) {
+		g_simple_async_result_take_error (init_data->result, error);
+		init_async_complete (init_data);
+		return;
+	}
+
+	if (!priv->service_running) {
+		g_simple_async_result_set_op_res_gboolean (init_data->result, TRUE);
+		init_async_complete (init_data);
+		return;
+	}
+
 	dbus_g_proxy_begin_call (priv->props_proxy, "GetAll",
-	                         get_all_cb,
-	                         object,
-	                         NULL,
+	                         init_async_got_properties, init_data, NULL,
 	                         G_TYPE_STRING, NM_DBUS_IFACE_SETTINGS,
-	                         G_TYPE_INVALID);	
+	                         G_TYPE_INVALID);
+}
 
-	return object;
+static void
+init_async (GAsyncInitable *initable, int io_priority,
+			GCancellable *cancellable, GAsyncReadyCallback callback,
+			gpointer user_data)
+{
+	NMRemoteSettingsInitData *init_data;
+	NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (initable);
+
+	init_data = g_slice_new0 (NMRemoteSettingsInitData);
+	init_data->settings = NM_REMOTE_SETTINGS (initable);
+	init_data->result = g_simple_async_result_new (G_OBJECT (initable), callback,
+	                                               user_data, init_async);
+
+	/* Check if NM is running */
+	dbus_g_proxy_begin_call (priv->dbus_proxy, "NameHasOwner",
+	                         init_async_got_manager_running,
+	                         init_data, NULL,
+	                         G_TYPE_STRING, NM_DBUS_SERVICE,
+	                         G_TYPE_INVALID);
 }
 
 static void
@@ -935,7 +1088,7 @@ nm_remote_settings_class_init (NMRemoteSettingsClass *class)
 	g_type_class_add_private (class, sizeof (NMRemoteSettingsPrivate));
 
 	/* Virtual methods */
-	object_class->constructor = constructor;
+	object_class->constructed = constructed;
 	object_class->set_property = set_property;
 	object_class->get_property = get_property;
 	object_class->dispose = dispose;
@@ -993,3 +1146,14 @@ nm_remote_settings_class_init (NMRemoteSettingsClass *class)
 	                              G_TYPE_NONE, 0);
 }
 
+static void
+nm_remote_settings_initable_iface_init (GInitableIface *iface)
+{
+	iface->init = init_sync;
+}
+
+static void
+nm_remote_settings_async_initable_iface_init (GAsyncInitableIface *iface)
+{
+	iface->init_async = init_async;
+}
diff --git a/libnm-glib/nm-remote-settings.h b/libnm-glib/nm-remote-settings.h
index e882e4fa..dd6c5a34 100644
--- a/libnm-glib/nm-remote-settings.h
+++ b/libnm-glib/nm-remote-settings.h
@@ -24,7 +24,7 @@
 #ifndef NM_REMOTE_SETTINGS_H
 #define NM_REMOTE_SETTINGS_H
 
-#include <glib.h>
+#include <gio/gio.h>
 #include <dbus/dbus-glib.h>
 #include <nm-connection.h>
 #include <nm-remote-connection.h>
@@ -50,14 +50,11 @@ G_BEGIN_DECLS
  *
  **/
 typedef enum {
-	NM_REMOTE_SETTINGS_ERROR_UNKNOWN = 0,
-	NM_REMOTE_SETTINGS_ERROR_CONNECTION_REMOVED,
-	NM_REMOTE_SETTINGS_ERROR_CONNECTION_UNAVAILABLE,
+	NM_REMOTE_SETTINGS_ERROR_UNKNOWN = 0,            /*< nick=UnknownError >*/
+	NM_REMOTE_SETTINGS_ERROR_CONNECTION_REMOVED,     /*< nick=ConnectionRemoved >*/
+	NM_REMOTE_SETTINGS_ERROR_CONNECTION_UNAVAILABLE, /*< nick=ConnectionUnavailable >*/
 } NMRemoteSettingsError;
 
-#define NM_TYPE_REMOTE_SETTINGS_ERROR (nm_remote_settings_error_get_type ()) 
-GType nm_remote_settings_error_get_type (void);
-
 #define NM_REMOTE_SETTINGS_ERROR nm_remote_settings_error_quark ()
 GQuark nm_remote_settings_error_quark (void);
 
@@ -110,6 +107,13 @@ GType nm_remote_settings_get_type (void);
 
 NMRemoteSettings *nm_remote_settings_new (DBusGConnection *bus);
 
+void              nm_remote_settings_new_async  (DBusGConnection      *bus,
+                                                 GCancellable         *cancellable,
+                                                 GAsyncReadyCallback   callback,
+                                                 gpointer              user_data);
+NMRemoteSettings *nm_remote_settings_new_finish (GAsyncResult         *result,
+                                                 GError              **error);
+
 GSList *nm_remote_settings_list_connections (NMRemoteSettings *settings);
 
 NMRemoteConnection * nm_remote_settings_get_connection_by_path (NMRemoteSettings *settings,
diff --git a/libnm-glib/nm-secret-agent.c b/libnm-glib/nm-secret-agent.c
index 1b413171..19f55c0e 100644
--- a/libnm-glib/nm-secret-agent.c
+++ b/libnm-glib/nm-secret-agent.c
@@ -25,7 +25,8 @@
 #include <dbus/dbus-glib-lowlevel.h>
 
 #include "nm-secret-agent.h"
-#include "nm-marshal.h"
+#include "nm-glib-enum-types.h"
+#include "nm-glib-marshal.h"
 #include "NetworkManager.h"
 
 static void impl_secret_agent_get_secrets (NMSecretAgent *self,
@@ -86,6 +87,7 @@ enum {
 	PROP_0,
 	PROP_IDENTIFIER,
 	PROP_AUTO_REGISTER,
+	PROP_REGISTERED,
 
 	LAST_PROP
 };
@@ -111,34 +113,6 @@ nm_secret_agent_error_quark (void)
 	return ret;
 }
 
-#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
-
-GType
-nm_secret_agent_error_get_type (void)
-{
-	static GType etype = 0;
-
-	if (etype == 0) {
-		static const GEnumValue values[] = {
-			/* Sender is not authorized to make this request */
-			ENUM_ENTRY (NM_SECRET_AGENT_ERROR_NOT_AUTHORIZED, "NotAuthorized"),
-			/* Given connection details do not make a valid connection */
-			ENUM_ENTRY (NM_SECRET_AGENT_ERROR_INVALID_CONNECTION, "InvalidConnection"),
-			/* The request was canceled explicitly by the user */
-			ENUM_ENTRY (NM_SECRET_AGENT_ERROR_USER_CANCELED, "UserCanceled"),
-			/* The request was canceled, but not by the user */
-			ENUM_ENTRY (NM_SECRET_AGENT_ERROR_AGENT_CANCELED, "AgentCanceled"),
-			/* Some internal error prevented returning secrets */
-			ENUM_ENTRY (NM_SECRET_AGENT_ERROR_INTERNAL_ERROR, "InternalError"),
-			/* No secrets could be found to fulfill the request */
-			ENUM_ENTRY (NM_SECRET_AGENT_ERROR_NO_SECRETS, "NoSecrets"),
-			{ 0, 0, 0 }
-		};
-		etype = g_enum_register_static ("NMSecretAgentError", values);
-	}
-	return etype;
-}
-
 /*************************************************************/
 
 static const char *
@@ -172,6 +146,7 @@ _internal_unregister (NMSecretAgent *self)
 	if (priv->registered) {
 		dbus_g_connection_unregister_g_object (priv->bus, G_OBJECT (self));
 		priv->registered = FALSE;
+		g_object_notify (G_OBJECT (self), NM_SECRET_AGENT_REGISTERED);
 	}
 }
 
@@ -536,9 +511,10 @@ reg_request_cb (DBusGProxy *proxy,
 
 	priv->reg_call = NULL;
 
-	if (dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INVALID))
+	if (dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INVALID)) {
 		priv->registered = TRUE;
-	else {
+		g_object_notify (G_OBJECT (self), NM_SECRET_AGENT_REGISTERED);
+	} else {
 		/* If registration failed we shouldn't expose ourselves on the bus */
 		_internal_unregister (self);
 	}
@@ -634,6 +610,21 @@ nm_secret_agent_unregister (NMSecretAgent *self)
 	return TRUE;
 }
 
+/**
+ * nm_secret_agent_get_registered:
+ * @self: a #NMSecretAgent
+ *
+ * Returns: a %TRUE if the agent is registered, %FALSE if it is not.
+ **/
+gboolean
+nm_secret_agent_get_registered (NMSecretAgent *self)
+{
+	g_return_val_if_fail (self != NULL, FALSE);
+	g_return_val_if_fail (NM_IS_SECRET_AGENT (self), FALSE);
+
+	return NM_SECRET_AGENT_GET_PRIVATE (self)->registered;
+}
+
 static gboolean
 auto_register_cb (gpointer user_data)
 {
@@ -655,7 +646,7 @@ auto_register_cb (gpointer user_data)
  * @setting_name: the name of the secret setting
  * @hints: (array zero-terminated=1): hints to the agent
  * @flags: flags that modify the behavior of the request
- * @callback: (scope async): a callback, invoked when the operation is done
+ * @callback: (scope async): a callback, to be invoked when the operation is done
  * @user_data: (closure): caller-specific data to be passed to @callback
  *
  * Asyncronously retrieve secrets belonging to @connection for the
@@ -698,7 +689,7 @@ nm_secret_agent_get_secrets (NMSecretAgent *self,
  * nm_secret_agent_save_secrets:
  * @self: a #NMSecretAgent
  * @connection: a #NMConnection
- * @callback: (scope async): a callback, invoked when the operation is done
+ * @callback: (scope async): a callback, to be invoked when the operation is done
  * @user_data: (closure): caller-specific data to be passed to @callback
  *
  * Asyncronously ensure that all secrets inside @connection
@@ -729,7 +720,7 @@ nm_secret_agent_save_secrets (NMSecretAgent *self,
  * nm_secret_agent_delete_secrets:
  * @self: a #NMSecretAgent
  * @connection: a #NMConnection
- * @callback: (scope async): a callback, invoked when the operation is done
+ * @callback: (scope async): a callback, to be invoked when the operation is done
  * @user_data: (closure): caller-specific data to be passed to @callback
  *
  * Asynchronously ask the agent to delete all saved secrets belonging to
@@ -806,7 +797,7 @@ nm_secret_agent_init (NMSecretAgent *self)
 		return;
 	}
 
-	dbus_g_object_register_marshaller (_nm_marshal_VOID__STRING_STRING_STRING,
+	dbus_g_object_register_marshaller (_nm_glib_marshal_VOID__STRING_STRING_STRING,
 	                                   G_TYPE_NONE,
 	                                   G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
 	                                   G_TYPE_INVALID);
@@ -845,6 +836,9 @@ get_property (GObject *object,
 	case PROP_AUTO_REGISTER:
 		g_value_set_boolean (value, priv->auto_register);
 		break;
+	case PROP_REGISTERED:
+		g_value_set_boolean (value, priv->registered);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -963,6 +957,19 @@ nm_secret_agent_class_init (NMSecretAgentClass *class)
 						       G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
 	/**
+	 * NMSecretAgent:registered:
+	 *
+	 * %TRUE if the agent is registered with NetworkManager, %FALSE if not.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_REGISTERED,
+		 g_param_spec_boolean (NM_SECRET_AGENT_REGISTERED,
+		                       "Registered",
+		                       "Registered",
+		                       FALSE,
+		                       G_PARAM_READABLE));
+
+	/**
 	 * NMSecretAgent::registration-result:
 	 * @agent: the agent that received the signal
 	 * @error: the error, if any, that occured while registering
diff --git a/libnm-glib/nm-secret-agent.h b/libnm-glib/nm-secret-agent.h
index 2e0cce40..c367f916 100644
--- a/libnm-glib/nm-secret-agent.h
+++ b/libnm-glib/nm-secret-agent.h
@@ -26,18 +26,16 @@
 G_BEGIN_DECLS
 
 #define NM_SECRET_AGENT_ERROR         (nm_secret_agent_error_quark ())
-#define NM_TYPE_SECRET_AGENT_ERROR    (nm_secret_agent_error_get_type ())
 
 GQuark nm_secret_agent_error_quark (void);
-GType nm_secret_agent_error_get_type (void);
 
 typedef enum {
-	NM_SECRET_AGENT_ERROR_NOT_AUTHORIZED = 0,
-	NM_SECRET_AGENT_ERROR_INVALID_CONNECTION,
-	NM_SECRET_AGENT_ERROR_USER_CANCELED,
-	NM_SECRET_AGENT_ERROR_AGENT_CANCELED,
-	NM_SECRET_AGENT_ERROR_INTERNAL_ERROR,
-	NM_SECRET_AGENT_ERROR_NO_SECRETS,
+	NM_SECRET_AGENT_ERROR_NOT_AUTHORIZED = 0, /*< nick=NotAuthorized >*/
+	NM_SECRET_AGENT_ERROR_INVALID_CONNECTION, /*< nick=InvalidConnection >*/
+	NM_SECRET_AGENT_ERROR_USER_CANCELED,      /*< nick=UserCanceled >*/
+	NM_SECRET_AGENT_ERROR_AGENT_CANCELED,     /*< nick=AgentCanceled >*/
+	NM_SECRET_AGENT_ERROR_INTERNAL_ERROR,     /*< nick=InternalError >*/
+	NM_SECRET_AGENT_ERROR_NO_SECRETS,         /*< nick=NoSecrets >*/
 } NMSecretAgentError;
 
 /**
@@ -70,6 +68,7 @@ typedef enum {
 
 #define NM_SECRET_AGENT_IDENTIFIER          "identifier"
 #define NM_SECRET_AGENT_AUTO_REGISTER       "auto-register"
+#define NM_SECRET_AGENT_REGISTERED          "registered"
 
 #define NM_SECRET_AGENT_REGISTRATION_RESULT "registration-result"
 
@@ -77,17 +76,82 @@ typedef struct {
 	GObject parent;
 } NMSecretAgent;
 
+/**
+ * NMSecretAgentGetSecretsFunc:
+ * @agent: the secret agent object
+ * @connection: the connection for which secrets were requested
+ * @secrets: (element-type utf8 GLib.HashTable): the #GHashTable containing
+ * the requested secrets in the same format as an #NMConnection hash (as
+ * created by nm_connection_to_hash() for example).  Each key in @secrets
+ * should be the name of a #NMSetting object (like "802-11-wireless-security")
+ * and each value should be a #GHashTable.  The sub-hashes map string:#GValue
+ * where the string is the setting property name (like "psk") and the value
+ * is the secret
+ * @error: if the secrets request failed, give a descriptive error here 
+ * @user_data: caller-specific data to be passed to the function
+ *
+ * Called as a result of a request by NM to retrieve secrets.  When the
+ * #NMSecretAgent subclass has finished retrieving secrets and is ready to
+ * return them, or to return an error, this function should be called with
+ * those secrets or the error.
+ *
+ * To easily create the hash table to return the WiFi PSK, you could do
+ * something like this:
+ * <example>
+ *  <title>Creating a secrets hash</title>
+ *  <programlisting>
+ *   NMConnection *secrets;
+ *   NMSettingWirelessSecurity *s_wsec;
+ *   GHashTable *secrets_hash;
+ *
+ *   secrets = nm_connection_new ();
+ *   s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
+ *   g_object_set (G_OBJECT (s_wsec),
+ *                 NM_SETTING_WIRELESS_SECURITY_PSK, "my really cool PSK",
+ *                 NULL);
+ *   nm_connection_add_setting (secrets, NM_SETTING (s_wsec));
+ *   secrets_hash = nm_connection_to_hash (secrets);
+ *
+ *   (call the NMSecretAgentGetSecretsFunc with secrets_hash)
+ *
+ *   g_object_unref (secrets);
+ *   g_hash_table_unref (secrets_hash);
+ *  </programlisting>
+ * </example>
+ */
 typedef void (*NMSecretAgentGetSecretsFunc) (NMSecretAgent *agent,
                                              NMConnection *connection,
                                              GHashTable *secrets,
                                              GError *error,
                                              gpointer user_data);
 
+/**
+ * NMSecretAgentSaveSecretsFunc:
+ * @agent: the secret agent object
+ * @connection: the connection for which secrets were to be saved
+ * @error: if the saving secrets failed, give a descriptive error here 
+ * @user_data: caller-specific data to be passed to the function
+ *
+ * Called as a result of a request by NM to save secrets.  When the
+ * #NMSecretAgent subclass has finished saving the secrets, this function
+ * should be called.
+ */
 typedef void (*NMSecretAgentSaveSecretsFunc) (NMSecretAgent *agent,
                                               NMConnection *connection,
                                               GError *error,
                                               gpointer user_data);
 
+/**
+ * NMSecretAgentDeleteSecretsFunc:
+ * @agent: the secret agent object
+ * @connection: the connection for which secrets were to be deleted
+ * @error: if the deleting secrets failed, give a descriptive error here 
+ * @user_data: caller-specific data to be passed to the function
+ *
+ * Called as a result of a request by NM to delete secrets.  When the
+ * #NMSecretAgent subclass has finished deleting the secrets, this function
+ * should be called.
+ */
 typedef void (*NMSecretAgentDeleteSecretsFunc) (NMSecretAgent *agent,
                                                 NMConnection *connection,
                                                 GError *error,
@@ -166,6 +230,8 @@ gboolean nm_secret_agent_register (NMSecretAgent *self);
 
 gboolean nm_secret_agent_unregister (NMSecretAgent *self);
 
+gboolean nm_secret_agent_get_registered (NMSecretAgent *self);
+
 void nm_secret_agent_get_secrets (NMSecretAgent *self,
                                   NMConnection *connection,
                                   const char *setting_name,
diff --git a/libnm-glib/nm-types.c b/libnm-glib/nm-types.c
index 6d76787d..098af8d8 100644
--- a/libnm-glib/nm-types.c
+++ b/libnm-glib/nm-types.c
@@ -172,9 +172,9 @@ nm_string_array_get_type (void)
 gboolean
 _nm_string_array_demarshal (GValue *value, GPtrArray **dest)
 {
-	GPtrArray *array;
+	char **array;
 
-	if (!G_VALUE_HOLDS (value, DBUS_TYPE_G_ARRAY_OF_STRING))
+	if (!G_VALUE_HOLDS (value, G_TYPE_STRV))
 		return FALSE;
 
 	if (*dest) {
@@ -182,13 +182,13 @@ _nm_string_array_demarshal (GValue *value, GPtrArray **dest)
 		*dest = NULL;
 	}
 
-	array = (GPtrArray *) g_value_get_boxed (value);
-	if (array && array->len) {
+	array = (char **) g_value_get_boxed (value);
+	if (array && array[0]) {
 		int i;
 
-		*dest = g_ptr_array_sized_new (array->len);
-		for (i = 0; i < array->len; i++)
-			g_ptr_array_add (*dest, g_strdup (g_ptr_array_index (array, i)));
+		*dest = g_ptr_array_new ();
+		for (i = 0; array[i]; i++)
+			g_ptr_array_add (*dest, g_strdup (array[i]));
 	}
 
 	return TRUE;
@@ -323,11 +323,11 @@ _nm_ip6_address_array_copy (GPtrArray *src)
 	dest = g_ptr_array_sized_new (src->len);
 	for (i = 0; i < src->len; i++) {
 		struct in6_addr *addr = g_ptr_array_index (src, i);
-		struct in6_addr *dup;
+		struct in6_addr *copy;
 
-		dup = g_malloc0 (sizeof (struct in6_addr));
-		memcpy (dup, addr, sizeof (struct in6_addr));
-		g_ptr_array_add (dest, dup);
+		copy = g_malloc0 (sizeof (struct in6_addr));
+		memcpy (copy, addr, sizeof (struct in6_addr));
+		g_ptr_array_add (dest, copy);
 	}
 	return dest;
 }
diff --git a/libnm-glib/nm-types.h b/libnm-glib/nm-types.h
index cb1bf872..adccafb7 100644
--- a/libnm-glib/nm-types.h
+++ b/libnm-glib/nm-types.h
@@ -26,6 +26,8 @@
 #include <glib.h>
 #include <glib-object.h>
 
+#include <nm-glib-enum-types.h>
+
 G_BEGIN_DECLS
 
 #define NM_TYPE_SSID  (nm_ssid_get_type ())
diff --git a/libnm-glib/nm-vpn-connection.c b/libnm-glib/nm-vpn-connection.c
index dd219b2a..53934216 100644
--- a/libnm-glib/nm-vpn-connection.c
+++ b/libnm-glib/nm-vpn-connection.c
@@ -18,15 +18,14 @@
  * 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>
 #include "nm-vpn-connection.h"
 #include "NetworkManager.h"
 #include "nm-utils.h"
-#include "nm-vpn-connection-bindings.h"
-#include "nm-marshal.h"
+#include "nm-glib-marshal.h"
 #include "nm-object-private.h"
 #include "nm-active-connection.h"
 
@@ -81,6 +80,15 @@ nm_vpn_connection_new (DBusGConnection *connection, const char *path)
 	                     NULL);
 }
 
+/**
+ * nm_vpn_connection_get_banner:
+ * @vpn: a #NMVPNConnection
+ *
+ * Gets the VPN login banner of the active #NMVPNConnection.
+ *
+ * Returns: the VPN login banner of the VPN connection. This is the internal
+ * string used by the connection, and must not be modified.
+ **/
 const char *
 nm_vpn_connection_get_banner (NMVPNConnection *vpn)
 {
@@ -89,37 +97,31 @@ nm_vpn_connection_get_banner (NMVPNConnection *vpn)
 	g_return_val_if_fail (NM_IS_VPN_CONNECTION (vpn), NULL);
 
 	priv = NM_VPN_CONNECTION_GET_PRIVATE (vpn);
+
+	/* We need to update vpn_state first in case it's unknown. */
+	_nm_object_ensure_inited (NM_OBJECT (vpn));
+
 	if (priv->vpn_state != NM_VPN_CONNECTION_STATE_ACTIVATED)
 		return NULL;
 
-	if (!priv->banner) {
-		priv->banner = _nm_object_get_string_property (NM_OBJECT (vpn),
-		                                               NM_DBUS_INTERFACE_VPN_CONNECTION,
-		                                               DBUS_PROP_BANNER,
-		                                               NULL);
-		if (priv->banner && !strlen (priv->banner)) {
-			g_free (priv->banner);
-			priv->banner = NULL;
-		}
-	}
 	return priv->banner;
 }
 
+/**
+ * nm_vpn_connection_get_vpn_state:
+ * @vpn: a #NMVPNConnection
+ *
+ * Gets the current #NMVPNConnection state.
+ *
+ * Returns: the VPN state of the active VPN connection.
+ **/
 NMVPNConnectionState
 nm_vpn_connection_get_vpn_state (NMVPNConnection *vpn)
 {
-	NMVPNConnectionPrivate *priv;
-
 	g_return_val_if_fail (NM_IS_VPN_CONNECTION (vpn), NM_VPN_CONNECTION_STATE_UNKNOWN);
 
-	priv = NM_VPN_CONNECTION_GET_PRIVATE (vpn);
-	if (priv->vpn_state == NM_VPN_CONNECTION_STATE_UNKNOWN) {
-		priv->vpn_state = _nm_object_get_uint_property (NM_OBJECT (vpn),
-		                                                NM_DBUS_INTERFACE_VPN_CONNECTION,
-		                                                DBUS_PROP_VPN_STATE,
-		                                                NULL);
-	}
-	return priv->vpn_state;
+	_nm_object_ensure_inited (NM_OBJECT (vpn));
+	return NM_VPN_CONNECTION_GET_PRIVATE (vpn)->vpn_state;
 }
 
 static void
@@ -147,28 +149,36 @@ nm_vpn_connection_init (NMVPNConnection *connection)
 	priv->vpn_state = NM_VPN_CONNECTION_STATE_UNKNOWN;
 }
 
-static GObject*
-constructor (GType type,
-		   guint n_construct_params,
-		   GObjectConstructParam *construct_params)
+static void
+register_properties (NMVPNConnection *connection)
+{
+	NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection);
+	const NMPropertiesInfo property_info[] = {
+		{ NM_VPN_CONNECTION_BANNER,    &priv->banner },
+		{ NM_VPN_CONNECTION_VPN_STATE, &priv->vpn_state },
+		{ NULL },
+	};
+
+	_nm_object_register_properties (NM_OBJECT (connection),
+	                                priv->proxy,
+	                                property_info);
+}
+
+static void
+constructed (GObject *object)
 {
-	NMObject *object;
 	NMVPNConnectionPrivate *priv;
 
-	object = (NMObject *) G_OBJECT_CLASS (nm_vpn_connection_parent_class)->constructor (type,
-																	    n_construct_params,
-																	    construct_params);
-	if (!object)
-		return NULL;
+	G_OBJECT_CLASS (nm_vpn_connection_parent_class)->constructed (object);
 
 	priv = NM_VPN_CONNECTION_GET_PRIVATE (object);
 
-	priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (object),
+	priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (NM_OBJECT (object)),
 									 NM_DBUS_SERVICE,
-									 nm_object_get_path (object),
+									 nm_object_get_path (NM_OBJECT (object)),
 									 NM_DBUS_INTERFACE_VPN_CONNECTION);
 
-	dbus_g_object_register_marshaller (_nm_marshal_VOID__UINT_UINT,
+	dbus_g_object_register_marshaller (_nm_glib_marshal_VOID__UINT_UINT,
 	                                   G_TYPE_NONE,
 	                                   G_TYPE_UINT, G_TYPE_UINT,
 	                                   G_TYPE_INVALID);
@@ -178,7 +188,8 @@ constructor (GType type,
 						    G_CALLBACK (vpn_state_changed_proxy),
 						    object,
 						    NULL);
-	return G_OBJECT (object);
+
+	register_properties (NM_VPN_CONNECTION (object));
 }
 
 static void
@@ -221,7 +232,7 @@ nm_vpn_connection_class_init (NMVPNConnectionClass *connection_class)
 	g_type_class_add_private (connection_class, sizeof (NMVPNConnectionPrivate));
 
 	/* virtual methods */
-	object_class->constructor = constructor;
+	object_class->constructed = constructed;
 	object_class->get_property = get_property;
 	object_class->finalize = finalize;
 
@@ -260,7 +271,7 @@ nm_vpn_connection_class_init (NMVPNConnectionClass *connection_class)
 				    G_SIGNAL_RUN_FIRST,
 				    G_STRUCT_OFFSET (NMVPNConnectionClass, vpn_state_changed),
 				    NULL, NULL,
-				    _nm_marshal_VOID__UINT_UINT,
+				    _nm_glib_marshal_VOID__UINT_UINT,
 				    G_TYPE_NONE, 2,
 				    G_TYPE_UINT, G_TYPE_UINT);
 }
diff --git a/libnm-glib/nm-vpn-enum-types.c b/libnm-glib/nm-vpn-enum-types.c
new file mode 100644
index 00000000..fb0de17c
--- /dev/null
+++ b/libnm-glib/nm-vpn-enum-types.c
@@ -0,0 +1,61 @@
+
+
+
+/* Generated by glib-mkenums. Do not edit */
+
+#include "nm-vpn-enum-types.h"
+
+#include "nm-vpn-plugin.h" 
+#include "nm-vpn-plugin-ui-interface.h" 
+#include "nm-vpn-plugin-utils.h"
+
+GType
+nm_vpn_plugin_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_VPN_PLUGIN_ERROR_GENERAL, "NM_VPN_PLUGIN_ERROR_GENERAL", "General" },
+        { NM_VPN_PLUGIN_ERROR_STARTING_IN_PROGRESS, "NM_VPN_PLUGIN_ERROR_STARTING_IN_PROGRESS", "StartingInProgress" },
+        { NM_VPN_PLUGIN_ERROR_ALREADY_STARTED, "NM_VPN_PLUGIN_ERROR_ALREADY_STARTED", "AlreadyStarted" },
+        { NM_VPN_PLUGIN_ERROR_STOPPING_IN_PROGRESS, "NM_VPN_PLUGIN_ERROR_STOPPING_IN_PROGRESS", "StoppingInProgress" },
+        { NM_VPN_PLUGIN_ERROR_ALREADY_STOPPED, "NM_VPN_PLUGIN_ERROR_ALREADY_STOPPED", "AlreadyStopped" },
+        { NM_VPN_PLUGIN_ERROR_WRONG_STATE, "NM_VPN_PLUGIN_ERROR_WRONG_STATE", "WrongState" },
+        { NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, "NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS", "BadArguments" },
+        { NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED, "NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED", "LaunchFailed" },
+        { NM_VPN_PLUGIN_ERROR_CONNECTION_INVALID, "NM_VPN_PLUGIN_ERROR_CONNECTION_INVALID", "ConnectionInvalid" },
+        { 0, NULL, NULL }
+      };
+      GType g_define_type_id =
+        g_enum_register_static (g_intern_static_string ("NMVPNPluginError"), values);
+      g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+    }
+
+  return g_define_type_id__volatile;
+}
+GType
+nm_vpn_plugin_ui_interface_prop_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_VPN_PLUGIN_UI_INTERFACE_PROP_FIRST, "NM_VPN_PLUGIN_UI_INTERFACE_PROP_FIRST", "first" },
+        { NM_VPN_PLUGIN_UI_INTERFACE_PROP_NAME, "NM_VPN_PLUGIN_UI_INTERFACE_PROP_NAME", "name" },
+        { NM_VPN_PLUGIN_UI_INTERFACE_PROP_DESC, "NM_VPN_PLUGIN_UI_INTERFACE_PROP_DESC", "desc" },
+        { NM_VPN_PLUGIN_UI_INTERFACE_PROP_SERVICE, "NM_VPN_PLUGIN_UI_INTERFACE_PROP_SERVICE", "service" },
+        { 0, NULL, NULL }
+      };
+      GType g_define_type_id =
+        g_enum_register_static (g_intern_static_string ("NMVpnPluginUiInterfaceProp"), values);
+      g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+    }
+
+  return g_define_type_id__volatile;
+}
+
+
+
diff --git a/libnm-glib/nm-vpn-enum-types.h b/libnm-glib/nm-vpn-enum-types.h
new file mode 100644
index 00000000..86bb97f1
--- /dev/null
+++ b/libnm-glib/nm-vpn-enum-types.h
@@ -0,0 +1,21 @@
+
+
+
+/* Generated by glib-mkenums. Do not edit */
+
+#ifndef __NM_VPN_ENUM_TYPES_H__
+#define __NM_VPN_ENUM_TYPES_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+GType nm_vpn_plugin_error_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_VPN_PLUGIN_ERROR (nm_vpn_plugin_error_get_type ())
+GType nm_vpn_plugin_ui_interface_prop_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_VPN_PLUGIN_UI_INTERFACE_PROP (nm_vpn_plugin_ui_interface_prop_get_type ())
+G_END_DECLS
+
+#endif /* __NM_VPN_ENUM_TYPES_H__ */
+
+
+
diff --git a/libnm-glib/nm-vpn-plugin.c b/libnm-glib/nm-vpn-plugin.c
index 4c3813e3..23685384 100644
--- a/libnm-glib/nm-vpn-plugin.c
+++ b/libnm-glib/nm-vpn-plugin.c
@@ -24,6 +24,7 @@
 #include <signal.h>
 #include "nm-glib-compat.h"
 #include "nm-vpn-plugin.h"
+#include "nm-vpn-enum-types.h"
 #include "nm-utils.h"
 #include "nm-connection.h"
 #include "nm-dbus-glib-types.h"
@@ -107,33 +108,6 @@ nm_vpn_plugin_error_quark (void)
 	return quark;
 }
 
-#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
-
-GType
-nm_vpn_plugin_error_get_type (void)
-{
-	static GType etype = 0;
-
-	if (etype == 0) {
-		static const GEnumValue values[] = {
-			ENUM_ENTRY (NM_VPN_PLUGIN_ERROR_GENERAL,              "General"),
-			ENUM_ENTRY (NM_VPN_PLUGIN_ERROR_STARTING_IN_PROGRESS, "StartingInProgress"),
-			ENUM_ENTRY (NM_VPN_PLUGIN_ERROR_ALREADY_STARTED,      "AlreadyStarted"),
-			ENUM_ENTRY (NM_VPN_PLUGIN_ERROR_STOPPING_IN_PROGRESS, "StoppingInProgress"),
-			ENUM_ENTRY (NM_VPN_PLUGIN_ERROR_ALREADY_STOPPED,      "AlreadyStopped"),
-			ENUM_ENTRY (NM_VPN_PLUGIN_ERROR_WRONG_STATE,          "WrongState"),
-			ENUM_ENTRY (NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,        "BadArguments"),
-			ENUM_ENTRY (NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED,        "LaunchFailed"),
-			ENUM_ENTRY (NM_VPN_PLUGIN_ERROR_CONNECTION_INVALID,   "ConnectionInvalid"),
-			{ 0, 0, 0 }
-		};
-
-		etype = g_enum_register_static ("NMVPNPluginError", values);
-	}
-
-	return etype;
-}
-
 
 static void
 nm_vpn_plugin_set_connection (NMVPNPlugin *plugin,
diff --git a/libnm-glib/nm-vpn-plugin.h b/libnm-glib/nm-vpn-plugin.h
index 8a3c2f1d..15cbf686 100644
--- a/libnm-glib/nm-vpn-plugin.h
+++ b/libnm-glib/nm-vpn-plugin.h
@@ -43,19 +43,18 @@ G_BEGIN_DECLS
 #define NM_VPN_PLUGIN_STATE             "state"
 
 typedef enum {
-	NM_VPN_PLUGIN_ERROR_GENERAL,
-	NM_VPN_PLUGIN_ERROR_STARTING_IN_PROGRESS,
-	NM_VPN_PLUGIN_ERROR_ALREADY_STARTED,
-	NM_VPN_PLUGIN_ERROR_STOPPING_IN_PROGRESS,
-	NM_VPN_PLUGIN_ERROR_ALREADY_STOPPED,
-	NM_VPN_PLUGIN_ERROR_WRONG_STATE,
-	NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
-	NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED,
-	NM_VPN_PLUGIN_ERROR_CONNECTION_INVALID,
+	NM_VPN_PLUGIN_ERROR_GENERAL,              /*< nick=General >*/
+	NM_VPN_PLUGIN_ERROR_STARTING_IN_PROGRESS, /*< nick=StartingInProgress >*/
+	NM_VPN_PLUGIN_ERROR_ALREADY_STARTED,      /*< nick=AlreadyStarted >*/
+	NM_VPN_PLUGIN_ERROR_STOPPING_IN_PROGRESS, /*< nick=StoppingInProgress >*/
+	NM_VPN_PLUGIN_ERROR_ALREADY_STOPPED,      /*< nick=AlreadyStopped >*/
+	NM_VPN_PLUGIN_ERROR_WRONG_STATE,          /*< nick=WrongState >*/
+	NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,        /*< nick=BadArguments >*/
+	NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED,        /*< nick=LaunchFailed >*/
+	NM_VPN_PLUGIN_ERROR_CONNECTION_INVALID,   /*< nick=ConnectionInvalid >*/
 } NMVPNPluginError;
 
 #define NM_VPN_PLUGIN_ERROR      (nm_vpn_plugin_error_quark ())
-#define NM_TYPE_VPN_PLUGIN_ERROR (nm_vpn_plugin_error_get_type ()) 
 
 typedef struct {
 	GObject parent;
diff --git a/libnm-glib/nm-wimax-nsp.c b/libnm-glib/nm-wimax-nsp.c
index 21478499..c3b222df 100644
--- a/libnm-glib/nm-wimax-nsp.c
+++ b/libnm-glib/nm-wimax-nsp.c
@@ -90,18 +90,10 @@ nm_wimax_nsp_new (DBusGConnection *connection, const char *path)
 const char *
 nm_wimax_nsp_get_name (NMWimaxNsp *nsp)
 {
-	NMWimaxNspPrivate *priv;
-
 	g_return_val_if_fail (NM_IS_WIMAX_NSP (nsp), NULL);
 
-	priv = NM_WIMAX_NSP_GET_PRIVATE (nsp);
-	if (!priv->name)
-		priv->name = _nm_object_get_string_property (NM_OBJECT (nsp),
-		                                             NM_DBUS_INTERFACE_WIMAX_NSP,
-		                                             DBUS_PROP_NAME,
-		                                             NULL);
-
-	return priv->name;
+	_nm_object_ensure_inited (NM_OBJECT (nsp));
+	return NM_WIMAX_NSP_GET_PRIVATE (nsp)->name;
 }
 
 /**
@@ -115,19 +107,10 @@ nm_wimax_nsp_get_name (NMWimaxNsp *nsp)
 guint32
 nm_wimax_nsp_get_signal_quality (NMWimaxNsp *nsp)
 {
-	NMWimaxNspPrivate *priv;
-
 	g_return_val_if_fail (NM_IS_WIMAX_NSP (nsp), 0);
 
-	priv = NM_WIMAX_NSP_GET_PRIVATE (nsp);
-	if (!priv->signal_quality) {
-		priv->signal_quality = _nm_object_get_uint_property (NM_OBJECT (nsp),
-		                                                     NM_DBUS_INTERFACE_WIMAX_NSP,
-		                                                     DBUS_PROP_SIGNAL_QUALITY,
-		                                                     NULL);
-	}
-
-	return priv->signal_quality;
+	_nm_object_ensure_inited (NM_OBJECT (nsp));
+	return NM_WIMAX_NSP_GET_PRIVATE (nsp)->signal_quality;
 }
 
 /**
@@ -141,19 +124,10 @@ nm_wimax_nsp_get_signal_quality (NMWimaxNsp *nsp)
 NMWimaxNspNetworkType
 nm_wimax_nsp_get_network_type (NMWimaxNsp *nsp)
 {
-	NMWimaxNspPrivate *priv;
-
 	g_return_val_if_fail (NM_IS_WIMAX_NSP (nsp), NM_WIMAX_NSP_NETWORK_TYPE_UNKNOWN);
 
-	priv = NM_WIMAX_NSP_GET_PRIVATE (nsp);
-	if (!priv->network_type) {
-		priv->network_type = _nm_object_get_uint_property (NM_OBJECT (nsp),
-		                                                   NM_DBUS_INTERFACE_WIMAX_NSP,
-		                                                   DBUS_PROP_NETWORK_TYPE,
-		                                                   NULL);
-	}
-
-	return priv->network_type;
+	_nm_object_ensure_inited (NM_OBJECT (nsp));
+	return NM_WIMAX_NSP_GET_PRIVATE (nsp)->network_type;
 }
 
 /**
@@ -290,43 +264,36 @@ get_property (GObject *object,
 }
 
 static void
-register_for_property_changed (NMWimaxNsp *nsp)
+register_properties (NMWimaxNsp *nsp)
 {
 	NMWimaxNspPrivate *priv = NM_WIMAX_NSP_GET_PRIVATE (nsp);
-	const NMPropertiesChangedInfo property_changed_info[] = {
-		{ NM_WIMAX_NSP_SIGNAL_QUALITY, _nm_object_demarshal_generic, &priv->signal_quality },
+	const NMPropertiesInfo property_info[] = {
+		{ NM_WIMAX_NSP_NAME,           &priv->name },
+		{ NM_WIMAX_NSP_SIGNAL_QUALITY, &priv->signal_quality },
+		{ NM_WIMAX_NSP_NETWORK_TYPE,   &priv->network_type },
 		{ NULL },
 	};
 
-	_nm_object_handle_properties_changed (NM_OBJECT (nsp),
-										  priv->proxy,
-										  property_changed_info);
+	_nm_object_register_properties (NM_OBJECT (nsp),
+	                                priv->proxy,
+	                                property_info);
 }
 
-static GObject*
-constructor (GType type,
-			 guint n_construct_params,
-			 GObjectConstructParam *construct_params)
+static void
+constructed (GObject *object)
 {
-	NMObject *object;
 	NMWimaxNspPrivate *priv;
 
-	object = (NMObject *) G_OBJECT_CLASS (nm_wimax_nsp_parent_class)->constructor (type,
-																				   n_construct_params,
-																				   construct_params);
-	if (!object)
-		return NULL;
+	G_OBJECT_CLASS (nm_wimax_nsp_parent_class)->constructed (object);
 
 	priv = NM_WIMAX_NSP_GET_PRIVATE (object);
 
-	priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (object),
+	priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (NM_OBJECT (object)),
 											 NM_DBUS_SERVICE,
-											 nm_object_get_path (object),
+											 nm_object_get_path (NM_OBJECT (object)),
 											 NM_DBUS_INTERFACE_WIMAX_NSP);
 
-	register_for_property_changed (NM_WIMAX_NSP (object));
-
-	return G_OBJECT (object);
+	register_properties (NM_WIMAX_NSP (object));
 }
 
 
@@ -338,7 +305,7 @@ nm_wimax_nsp_class_init (NMWimaxNspClass *nsp_class)
 	g_type_class_add_private (nsp_class, sizeof (NMWimaxNspPrivate));
 
 	/* virtual methods */
-	object_class->constructor = constructor;
+	object_class->constructed = constructed;
 	object_class->get_property = get_property;
 	object_class->dispose = dispose;
 	object_class->finalize = finalize;
diff --git a/libnm-glib/tests/Makefile.am b/libnm-glib/tests/Makefile.am
index 06aee712..0dba0793 100644
--- a/libnm-glib/tests/Makefile.am
+++ b/libnm-glib/tests/Makefile.am
@@ -1,6 +1,8 @@
 INCLUDES = \
 	-I$(top_srcdir)/include \
+	-I$(top_builddir)/include \
 	-I$(top_srcdir)/libnm-util \
+	-I$(top_builddir)/libnm-util \
 	-I$(top_srcdir)/libnm-glib
 
 noinst_PROGRAMS = test-remote-settings-client
diff --git a/libnm-glib/tests/Makefile.in b/libnm-glib/tests/Makefile.in
index 0fcd5f86..ad4d1c44 100644
--- a/libnm-glib/tests/Makefile.in
+++ b/libnm-glib/tests/Makefile.in
@@ -143,6 +143,8 @@ GIO_LIBS = @GIO_LIBS@
 GLIB_CFLAGS = @GLIB_CFLAGS@
 GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
 GLIB_LIBS = @GLIB_LIBS@
+GLIB_MAKEFILE = @GLIB_MAKEFILE@
+GLIB_MKENUMS = @GLIB_MKENUMS@
 GMODULE_CFLAGS = @GMODULE_CFLAGS@
 GMODULE_LIBS = @GMODULE_LIBS@
 GMSGFMT = @GMSGFMT@
@@ -197,11 +199,15 @@ LIBNL2_LIBS = @LIBNL2_LIBS@
 LIBNL3_CFLAGS = @LIBNL3_CFLAGS@
 LIBNL3_LIBS = @LIBNL3_LIBS@
 LIBNL_CFLAGS = @LIBNL_CFLAGS@
+LIBNL_GENL3_CFLAGS = @LIBNL_GENL3_CFLAGS@
+LIBNL_GENL3_LIBS = @LIBNL_GENL3_LIBS@
 LIBNL_LIBS = @LIBNL_LIBS@
 LIBNL_ROUTE3_CFLAGS = @LIBNL_ROUTE3_CFLAGS@
 LIBNL_ROUTE3_LIBS = @LIBNL_ROUTE3_LIBS@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
+LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@
+LIBSOUP_LIBS = @LIBSOUP_LIBS@
 LIBTOOL = @LIBTOOL@
 LIPO = @LIPO@
 LN_S = @LN_S@
@@ -212,6 +218,7 @@ MAINT = @MAINT@
 MAKEINFO = @MAKEINFO@
 MANIFEST_TOOL = @MANIFEST_TOOL@
 MKDIR_P = @MKDIR_P@
+MOC = @MOC@
 MSGFMT = @MSGFMT@
 MSGFMT_015 = @MSGFMT_015@
 MSGMERGE = @MSGMERGE@
@@ -251,6 +258,8 @@ SED = @SED@
 SET_MAKE = @SET_MAKE@
 SHELL = @SHELL@
 STRIP = @STRIP@
+SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@
+SYSTEMD_LIBS = @SYSTEMD_LIBS@
 SYSTEM_CA_PATH = @SYSTEM_CA_PATH@
 UDEV_BASE_DIR = @UDEV_BASE_DIR@
 USE_NLS = @USE_NLS@
@@ -316,7 +325,9 @@ top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
 INCLUDES = \
 	-I$(top_srcdir)/include \
+	-I$(top_builddir)/include \
 	-I$(top_srcdir)/libnm-util \
+	-I$(top_builddir)/libnm-util \
 	-I$(top_srcdir)/libnm-glib