summary refs log tree commit diff
path: root/libnm-glib
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2010-11-29 00:47:11 +0100
committerMichael Biebl <biebl@debian.org>2010-11-29 00:47:11 +0100
commit9fae01fa351805b2903e535736e06971bc0b925e (patch)
treec19bccf84c9f894e50fae678ba6ee2b2044e2d30 /libnm-glib
Imported Upstream version 0.8.1 upstream/0.8.1
Diffstat (limited to 'libnm-glib')
-rw-r--r--libnm-glib/Makefile.am212
-rw-r--r--libnm-glib/Makefile.in1183
-rw-r--r--libnm-glib/libnm-glib-test.c419
-rw-r--r--libnm-glib/libnm-glib-vpn.pc.in13
-rw-r--r--libnm-glib/libnm-glib-vpn.ver26
-rw-r--r--libnm-glib/libnm-glib.pc.in13
-rw-r--r--libnm-glib/libnm-glib.ver161
-rw-r--r--libnm-glib/libnm_glib.c600
-rw-r--r--libnm-glib/libnm_glib.h60
-rw-r--r--libnm-glib/nm-access-point.c597
-rw-r--r--libnm-glib/nm-access-point.h83
-rw-r--r--libnm-glib/nm-active-connection.c570
-rw-r--r--libnm-glib/nm-active-connection.h81
-rw-r--r--libnm-glib/nm-cdma-device.c130
-rw-r--r--libnm-glib/nm-cdma-device.h60
-rw-r--r--libnm-glib/nm-client.c1160
-rw-r--r--libnm-glib/nm-client.h110
-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-bt.c307
-rw-r--r--libnm-glib/nm-device-bt.h71
-rw-r--r--libnm-glib/nm-device-ethernet.c315
-rw-r--r--libnm-glib/nm-device-ethernet.h68
-rw-r--r--libnm-glib/nm-device-private.h36
-rw-r--r--libnm-glib/nm-device-wifi.c759
-rw-r--r--libnm-glib/nm-device-wifi.h82
-rw-r--r--libnm-glib/nm-device.c1246
-rw-r--r--libnm-glib/nm-device.h107
-rw-r--r--libnm-glib/nm-dhcp4-config.c248
-rw-r--r--libnm-glib/nm-dhcp4-config.h68
-rw-r--r--libnm-glib/nm-dhcp6-config.c248
-rw-r--r--libnm-glib/nm-dhcp6-config.h68
-rw-r--r--libnm-glib/nm-exported-connection.c281
-rw-r--r--libnm-glib/nm-exported-connection.h75
-rw-r--r--libnm-glib/nm-gsm-device.c130
-rw-r--r--libnm-glib/nm-gsm-device.h61
-rw-r--r--libnm-glib/nm-ip4-config.c526
-rw-r--r--libnm-glib/nm-ip4-config.h77
-rw-r--r--libnm-glib/nm-ip6-config.c438
-rw-r--r--libnm-glib/nm-ip6-config.h73
-rw-r--r--libnm-glib/nm-object-cache.c72
-rw-r--r--libnm-glib/nm-object-cache.h39
-rw-r--r--libnm-glib/nm-object-private.h101
-rw-r--r--libnm-glib/nm-object.c675
-rw-r--r--libnm-glib/nm-object.h66
-rw-r--r--libnm-glib/nm-remote-connection-private.h35
-rw-r--r--libnm-glib/nm-remote-connection.c439
-rw-r--r--libnm-glib/nm-remote-connection.h65
-rw-r--r--libnm-glib/nm-remote-settings-system.c375
-rw-r--r--libnm-glib/nm-remote-settings-system.h64
-rw-r--r--libnm-glib/nm-remote-settings.c540
-rw-r--r--libnm-glib/nm-remote-settings.h67
-rw-r--r--libnm-glib/nm-serial-device.c207
-rw-r--r--libnm-glib/nm-serial-device.h63
-rw-r--r--libnm-glib/nm-settings-connection-interface.c192
-rw-r--r--libnm-glib/nm-settings-connection-interface.h116
-rw-r--r--libnm-glib/nm-settings-interface.c206
-rw-r--r--libnm-glib/nm-settings-interface.h109
-rw-r--r--libnm-glib/nm-settings-service.c372
-rw-r--r--libnm-glib/nm-settings-service.h82
-rw-r--r--libnm-glib/nm-settings-system-interface.c150
-rw-r--r--libnm-glib/nm-settings-system-interface.h108
-rw-r--r--libnm-glib/nm-types-private.h39
-rw-r--r--libnm-glib/nm-types.c423
-rw-r--r--libnm-glib/nm-types.h54
-rw-r--r--libnm-glib/nm-vpn-connection.c257
-rw-r--r--libnm-glib/nm-vpn-connection.h75
-rw-r--r--libnm-glib/nm-vpn-plugin-ui-interface.c245
-rw-r--r--libnm-glib/nm-vpn-plugin-ui-interface.h204
-rw-r--r--libnm-glib/nm-vpn-plugin.c807
-rw-r--r--libnm-glib/nm-vpn-plugin.h127
71 files changed, 17408 insertions, 0 deletions
diff --git a/libnm-glib/Makefile.am b/libnm-glib/Makefile.am
new file mode 100644
index 00000000..de25df4c
--- /dev/null
+++ b/libnm-glib/Makefile.am
@@ -0,0 +1,212 @@
+INCLUDES = \
+	-I$(top_srcdir)/include \
+	-I$(top_srcdir)/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-exported-connection-glue.h \
+	nm-exported-connection-bindings.h \
+	nm-settings-glue.h \
+	nm-settings-bindings.h \
+	nm-settings-system-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
+
+#####################################################
+# Deprecated original libnm_glib bits
+#####################################################
+
+noinst_LTLIBRARIES = libdeprecated-nm-glib.la
+
+libdeprecated_nm_glib_la_SOURCES = \
+	libnm_glib.h \
+	libnm_glib.c
+
+libdeprecated_nm_glib_la_CPPFLAGS = \
+	$(DBUS_CFLAGS) \
+	$(GLIB_CFLAGS) \
+	-Wno-deprecated-declarations \
+	-Wno-deprecated
+
+libdeprecated_nm_glib_la_LIBADD = \
+	$(DBUS_LIBS) \
+	$(GLIB_LIBS)
+
+#####################################################
+# Real libnm-glib stuff
+#####################################################
+
+lib_LTLIBRARIES = libnm-glib.la libnm-glib-vpn.la
+
+libnm_glib_la_CFLAGS = \
+	$(GLIB_CFLAGS) \
+	$(DBUS_CFLAGS) \
+	$(GCONF_CFLAGS) \
+	$(GUDEV_CFLAGS)
+
+libnmincludedir = $(includedir)/libnm-glib
+
+libnminclude_HEADERS = \
+	libnm_glib.h \
+	nm-object.h \
+	nm-client.h \
+	nm-device.h \
+	nm-device-ethernet.h \
+	nm-device-wifi.h \
+	nm-device-bt.h \
+	nm-access-point.h \
+	nm-ip4-config.h \
+	nm-gsm-device.h \
+	nm-cdma-device.h \
+	nm-serial-device.h \
+	nm-vpn-connection.h \
+	nm-vpn-plugin.h \
+	nm-vpn-plugin-ui-interface.h \
+	nm-types.h \
+	nm-active-connection.h \
+	nm-dhcp4-config.h \
+	nm-ip6-config.h \
+	nm-dhcp6-config.h \
+	nm-remote-connection.h \
+	nm-settings-interface.h \
+	nm-settings-system-interface.h \
+	nm-remote-settings.h \
+	nm-remote-settings-system.h \
+	nm-settings-connection-interface.h \
+	nm-exported-connection.h \
+	nm-settings-service.h
+
+libnm_glib_la_SOURCES = \
+	nm-object.c \
+	nm-object-private.h \
+	nm-client.c \
+	nm-dbus-utils.c \
+	nm-dbus-utils.h \
+	nm-device.c \
+	nm-device-private.h \
+	nm-device-ethernet.c \
+	nm-device-wifi.c \
+	nm-device-bt.c \
+	nm-access-point.c \
+	nm-ip4-config.c \
+	nm-gsm-device.c \
+	nm-cdma-device.c \
+	nm-serial-device.c \
+	nm-vpn-connection.c \
+	nm-types.c \
+	nm-types-private.h \
+	nm-object-cache.c \
+	nm-object-cache.h \
+	nm-active-connection.c \
+	nm-dhcp4-config.c \
+	nm-ip6-config.c \
+	nm-dhcp6-config.c \
+	nm-remote-connection.c \
+	nm-remote-connection-private.h \
+	nm-settings-interface.c \
+	nm-settings-system-interface.c \
+	nm-remote-settings.c \
+	nm-remote-settings-system.c \
+	nm-settings-connection-interface.c \
+	nm-exported-connection.c \
+	nm-settings-service.c
+
+libnm_glib_la_LIBADD = \
+	$(top_builddir)/libnm-util/libnm-util.la \
+	$(top_builddir)/marshallers/libmarshallers.la \
+	$(builddir)/libdeprecated-nm-glib.la \
+	$(GLIB_LIBS) \
+	$(DBUS_LIBS) \
+	$(GCONF_LIBS) \
+	$(GUDEV_LIBS)
+
+libnm_glib_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libnm-glib.ver \
+	-version-info "4:3:2"
+
+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_vpn_la_SOURCES = nm-vpn-plugin.c nm-vpn-plugin-ui-interface.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)
+libnm_glib_vpn_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libnm-glib-vpn.ver \
+	-version-info "1:0:0"
+
+
+nm-client-bindings.h: $(top_srcdir)/introspection/nm-manager-client.xml
+	dbus-binding-tool --prefix=nm_client --mode=glib-client --output=$@ $<
+
+nm-device-bindings.h: $(top_srcdir)/introspection/nm-device.xml
+	dbus-binding-tool --prefix=nm_device --mode=glib-client --output=$@ $<
+
+nm-device-ethernet-bindings.h: $(top_srcdir)/introspection/nm-device-ethernet.xml
+	dbus-binding-tool --prefix=nm_device_ethernet --mode=glib-client --output=$@ $<
+
+nm-device-wifi-bindings.h: $(top_srcdir)/introspection/nm-device-wifi.xml
+	dbus-binding-tool --prefix=nm_device_wifi --mode=glib-client --output=$@ $<
+
+nm-device-bt-bindings.h: $(top_srcdir)/introspection/nm-device-bt.xml
+	dbus-binding-tool --prefix=nm_device_bt --mode=glib-client --output=$@ $<
+
+nm-access-point-bindings.h: $(top_srcdir)/introspection/nm-access-point.xml
+	dbus-binding-tool --prefix=nm_access_point --mode=glib-client --output=$@ $<
+
+nm-settings-glue.h: $(top_srcdir)/introspection/nm-settings.xml
+	dbus-binding-tool --prefix=nm_settings --mode=glib-server --output=$@ $<
+
+nm-settings-bindings.h: $(top_srcdir)/introspection/nm-settings.xml
+	dbus-binding-tool --prefix=nm_settings --mode=glib-client --output=$@ $<
+
+nm-settings-system-bindings.h: $(top_srcdir)/introspection/nm-settings-system.xml
+	dbus-binding-tool --prefix=nm_settings_system --mode=glib-client --output=$@ $<
+
+nm-exported-connection-glue.h: $(top_srcdir)/introspection/nm-exported-connection.xml
+	dbus-binding-tool --prefix=nm_exported_connection --mode=glib-server --output=$@ $<
+
+nm-exported-connection-bindings.h: $(top_srcdir)/introspection/nm-exported-connection.xml
+	dbus-binding-tool --prefix=nm_exported_connection --mode=glib-client --output=$@ $<
+
+nm-vpn-connection-bindings.h: $(top_srcdir)/introspection/nm-vpn-connection.xml
+	dbus-binding-tool --prefix=nm_vpn_connection --mode=glib-client --output=$@ $<
+
+nm-vpn-plugin-glue.h: $(top_srcdir)/introspection/nm-vpn-plugin.xml
+	dbus-binding-tool --prefix=nm_vpn_plugin --mode=glib-server --output=$@ $<
+
+nm-active-connection-bindings.h: $(top_srcdir)/introspection/nm-active-connection.xml
+	dbus-binding-tool --prefix=nm_active_connection --mode=glib-client --output=$@ $<
+
+nm-ip4-config-bindings.h: $(top_srcdir)/introspection/nm-ip4-config.xml
+	dbus-binding-tool --prefix=nm_ip4_config --mode=glib-client --output=$@ $<
+
+nm-dhcp4-config-bindings.h: $(top_srcdir)/introspection/nm-dhcp4-config.xml
+	dbus-binding-tool --prefix=nm_dhcp4_config --mode=glib-client --output=$@ $<
+
+nm-ip6-config-bindings.h: $(top_srcdir)/introspection/nm-ip6-config.xml
+	dbus-binding-tool --prefix=nm_ip6_config --mode=glib-client --output=$@ $<
+
+nm-dhcp6-config-bindings.h: $(top_srcdir)/introspection/nm-dhcp6-config.xml
+	dbus-binding-tool --prefix=nm_dhcp6_config --mode=glib-client --output=$@ $<
+
+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)
diff --git a/libnm-glib/Makefile.in b/libnm-glib/Makefile.in
new file mode 100644
index 00000000..b7e933d1
--- /dev/null
+++ b/libnm-glib/Makefile.in
@@ -0,0 +1,1183 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009  Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+noinst_PROGRAMS = libnm-glib-test$(EXEEXT)
+subdir = libnm-glib
+DIST_COMMON = $(libnminclude_HEADERS) $(srcdir)/Makefile.am \
+	$(srcdir)/Makefile.in $(srcdir)/libnm-glib-vpn.pc.in \
+	$(srcdir)/libnm-glib.pc.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \
+	$(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/intltool.m4 \
+	$(top_srcdir)/m4/libnl-check.m4 $(top_srcdir)/m4/libtool.m4 \
+	$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+	$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES = libnm-glib.pc libnm-glib-vpn.pc
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+  srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+  for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+  for p in $$list; do echo "$$p $$p"; done | \
+  sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+  $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+    if (++n[$$2] == $(am__install_max)) \
+      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+    END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+  sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgconfigdir)" \
+	"$(DESTDIR)$(libnmincludedir)"
+LTLIBRARIES = $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libdeprecated_nm_glib_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1)
+am_libdeprecated_nm_glib_la_OBJECTS =  \
+	libdeprecated_nm_glib_la-libnm_glib.lo
+libdeprecated_nm_glib_la_OBJECTS =  \
+	$(am_libdeprecated_nm_glib_la_OBJECTS)
+libnm_glib_vpn_la_DEPENDENCIES =  \
+	$(top_builddir)/libnm-util/libnm-util.la $(am__DEPENDENCIES_1) \
+	$(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_OBJECTS = $(am_libnm_glib_vpn_la_OBJECTS)
+libnm_glib_vpn_la_LINK = $(LIBTOOL) --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_libnm_glib_la_OBJECTS = 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-wifi.lo libnm_glib_la-nm-device-bt.lo \
+	libnm_glib_la-nm-access-point.lo \
+	libnm_glib_la-nm-ip4-config.lo libnm_glib_la-nm-gsm-device.lo \
+	libnm_glib_la-nm-cdma-device.lo \
+	libnm_glib_la-nm-serial-device.lo \
+	libnm_glib_la-nm-vpn-connection.lo libnm_glib_la-nm-types.lo \
+	libnm_glib_la-nm-object-cache.lo \
+	libnm_glib_la-nm-active-connection.lo \
+	libnm_glib_la-nm-dhcp4-config.lo \
+	libnm_glib_la-nm-ip6-config.lo \
+	libnm_glib_la-nm-dhcp6-config.lo \
+	libnm_glib_la-nm-remote-connection.lo \
+	libnm_glib_la-nm-settings-interface.lo \
+	libnm_glib_la-nm-settings-system-interface.lo \
+	libnm_glib_la-nm-remote-settings.lo \
+	libnm_glib_la-nm-remote-settings-system.lo \
+	libnm_glib_la-nm-settings-connection-interface.lo \
+	libnm_glib_la-nm-exported-connection.lo \
+	libnm_glib_la-nm-settings-service.lo
+libnm_glib_la_OBJECTS = $(am_libnm_glib_la_OBJECTS)
+libnm_glib_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(libnm_glib_la_CFLAGS) \
+	$(CFLAGS) $(libnm_glib_la_LDFLAGS) $(LDFLAGS) -o $@
+PROGRAMS = $(noinst_PROGRAMS)
+am_libnm_glib_test_OBJECTS =  \
+	libnm_glib_test-libnm-glib-test.$(OBJEXT)
+libnm_glib_test_OBJECTS = $(am_libnm_glib_test_OBJECTS)
+libnm_glib_test_DEPENDENCIES = libnm-glib.la \
+	$(top_builddir)/libnm-util/libnm-util.la $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1)
+libnm_glib_test_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(libnm_glib_test_CFLAGS) \
+	$(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+	$(LDFLAGS) -o $@
+SOURCES = $(libdeprecated_nm_glib_la_SOURCES) \
+	$(libnm_glib_vpn_la_SOURCES) $(libnm_glib_la_SOURCES) \
+	$(libnm_glib_test_SOURCES)
+DIST_SOURCES = $(libdeprecated_nm_glib_la_SOURCES) \
+	$(libnm_glib_vpn_la_SOURCES) $(libnm_glib_la_SOURCES) \
+	$(libnm_glib_test_SOURCES)
+DATA = $(pkgconfig_DATA)
+HEADERS = $(libnminclude_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@
+ALL_LINGUAS = @ALL_LINGUAS@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DBUS_CFLAGS = @DBUS_CFLAGS@
+DBUS_LIBS = @DBUS_LIBS@
+DBUS_SYS_DIR = @DBUS_SYS_DIR@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DHCLIENT_PATH = @DHCLIENT_PATH@
+DHCPCD_PATH = @DHCPCD_PATH@
+DISABLE_DEPRECATED = @DISABLE_DEPRECATED@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GIO_CFLAGS = @GIO_CFLAGS@
+GIO_LIBS = @GIO_LIBS@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GLIB_LIBS = @GLIB_LIBS@
+GMODULE_CFLAGS = @GMODULE_CFLAGS@
+GMODULE_LIBS = @GMODULE_LIBS@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GTKDOC_CHECK = @GTKDOC_CHECK@
+GTKDOC_MKPDF = @GTKDOC_MKPDF@
+GTKDOC_REBASE = @GTKDOC_REBASE@
+GUDEV_CFLAGS = @GUDEV_CFLAGS@
+GUDEV_LIBS = @GUDEV_LIBS@
+HTML_DIR = @HTML_DIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTOBJEXT = @INSTOBJEXT@
+INTLLIBS = @INTLLIBS@
+INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+INTLTOOL_MERGE = @INTLTOOL_MERGE@
+INTLTOOL_PERL = @INTLTOOL_PERL@
+INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+IPTABLES_PATH = @IPTABLES_PATH@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBDL = @LIBDL@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBM = @LIBM@
+LIBNL_CFLAGS = @LIBNL_CFLAGS@
+LIBNL_LIBS = @LIBNL_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+MSGFMT_OPTS = @MSGFMT_OPTS@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NSS_CFLAGS = @NSS_CFLAGS@
+NSS_LIBS = @NSS_LIBS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+POFILES = @POFILES@
+POLKIT_CFLAGS = @POLKIT_CFLAGS@
+POLKIT_LIBS = @POLKIT_LIBS@
+POSUB = @POSUB@
+PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@
+RANLIB = @RANLIB@
+RESOLVCONF_PATH = @RESOLVCONF_PATH@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+SYSTEM_CA_PATH = @SYSTEM_CA_PATH@
+UDEV_BASE_DIR = @UDEV_BASE_DIR@
+USE_NLS = @USE_NLS@
+UUID_CFLAGS = @UUID_CFLAGS@
+UUID_LIBS = @UUID_LIBS@
+VERSION = @VERSION@
+XGETTEXT = @XGETTEXT@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+INCLUDES = \
+	-I$(top_srcdir)/include \
+	-I$(top_srcdir)/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-exported-connection-glue.h \
+	nm-exported-connection-bindings.h \
+	nm-settings-glue.h \
+	nm-settings-bindings.h \
+	nm-settings-system-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
+
+
+#####################################################
+# Deprecated original libnm_glib bits
+#####################################################
+noinst_LTLIBRARIES = libdeprecated-nm-glib.la
+libdeprecated_nm_glib_la_SOURCES = \
+	libnm_glib.h \
+	libnm_glib.c
+
+libdeprecated_nm_glib_la_CPPFLAGS = \
+	$(DBUS_CFLAGS) \
+	$(GLIB_CFLAGS) \
+	-Wno-deprecated-declarations \
+	-Wno-deprecated
+
+libdeprecated_nm_glib_la_LIBADD = \
+	$(DBUS_LIBS) \
+	$(GLIB_LIBS)
+
+
+#####################################################
+# Real libnm-glib stuff
+#####################################################
+lib_LTLIBRARIES = libnm-glib.la libnm-glib-vpn.la
+libnm_glib_la_CFLAGS = \
+	$(GLIB_CFLAGS) \
+	$(DBUS_CFLAGS) \
+	$(GCONF_CFLAGS) \
+	$(GUDEV_CFLAGS)
+
+libnmincludedir = $(includedir)/libnm-glib
+libnminclude_HEADERS = \
+	libnm_glib.h \
+	nm-object.h \
+	nm-client.h \
+	nm-device.h \
+	nm-device-ethernet.h \
+	nm-device-wifi.h \
+	nm-device-bt.h \
+	nm-access-point.h \
+	nm-ip4-config.h \
+	nm-gsm-device.h \
+	nm-cdma-device.h \
+	nm-serial-device.h \
+	nm-vpn-connection.h \
+	nm-vpn-plugin.h \
+	nm-vpn-plugin-ui-interface.h \
+	nm-types.h \
+	nm-active-connection.h \
+	nm-dhcp4-config.h \
+	nm-ip6-config.h \
+	nm-dhcp6-config.h \
+	nm-remote-connection.h \
+	nm-settings-interface.h \
+	nm-settings-system-interface.h \
+	nm-remote-settings.h \
+	nm-remote-settings-system.h \
+	nm-settings-connection-interface.h \
+	nm-exported-connection.h \
+	nm-settings-service.h
+
+libnm_glib_la_SOURCES = \
+	nm-object.c \
+	nm-object-private.h \
+	nm-client.c \
+	nm-dbus-utils.c \
+	nm-dbus-utils.h \
+	nm-device.c \
+	nm-device-private.h \
+	nm-device-ethernet.c \
+	nm-device-wifi.c \
+	nm-device-bt.c \
+	nm-access-point.c \
+	nm-ip4-config.c \
+	nm-gsm-device.c \
+	nm-cdma-device.c \
+	nm-serial-device.c \
+	nm-vpn-connection.c \
+	nm-types.c \
+	nm-types-private.h \
+	nm-object-cache.c \
+	nm-object-cache.h \
+	nm-active-connection.c \
+	nm-dhcp4-config.c \
+	nm-ip6-config.c \
+	nm-dhcp6-config.c \
+	nm-remote-connection.c \
+	nm-remote-connection-private.h \
+	nm-settings-interface.c \
+	nm-settings-system-interface.c \
+	nm-remote-settings.c \
+	nm-remote-settings-system.c \
+	nm-settings-connection-interface.c \
+	nm-exported-connection.c \
+	nm-settings-service.c
+
+libnm_glib_la_LIBADD = \
+	$(top_builddir)/libnm-util/libnm-util.la \
+	$(top_builddir)/marshallers/libmarshallers.la \
+	$(builddir)/libdeprecated-nm-glib.la \
+	$(GLIB_LIBS) \
+	$(DBUS_LIBS) \
+	$(GCONF_LIBS) \
+	$(GUDEV_LIBS)
+
+libnm_glib_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libnm-glib.ver \
+	-version-info "4:3:2"
+
+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_vpn_la_SOURCES = nm-vpn-plugin.c nm-vpn-plugin-ui-interface.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)
+libnm_glib_vpn_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libnm-glib-vpn.ver \
+	-version-info "1:0:0"
+
+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)
+all: $(BUILT_SOURCES)
+	$(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libnm-glib/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu libnm-glib/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+libnm-glib.pc: $(top_builddir)/config.status $(srcdir)/libnm-glib.pc.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+libnm-glib-vpn.pc: $(top_builddir)/config.status $(srcdir)/libnm-glib-vpn.pc.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+	@$(NORMAL_INSTALL)
+	test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
+	@list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+	list2=; for p in $$list; do \
+	  if test -f $$p; then \
+	    list2="$$list2 $$p"; \
+	  else :; fi; \
+	done; \
+	test -z "$$list2" || { \
+	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
+	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
+	}
+
+uninstall-libLTLIBRARIES:
+	@$(NORMAL_UNINSTALL)
+	@list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+	for p in $$list; do \
+	  $(am__strip_dir) \
+	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
+	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
+	done
+
+clean-libLTLIBRARIES:
+	-test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+	@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+	  dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+	  test "$$dir" != "$$p" || dir=.; \
+	  echo "rm -f \"$${dir}/so_locations\""; \
+	  rm -f "$${dir}/so_locations"; \
+	done
+
+clean-noinstLTLIBRARIES:
+	-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+	@list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+	  dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+	  test "$$dir" != "$$p" || dir=.; \
+	  echo "rm -f \"$${dir}/so_locations\""; \
+	  rm -f "$${dir}/so_locations"; \
+	done
+libdeprecated-nm-glib.la: $(libdeprecated_nm_glib_la_OBJECTS) $(libdeprecated_nm_glib_la_DEPENDENCIES) 
+	$(LINK)  $(libdeprecated_nm_glib_la_OBJECTS) $(libdeprecated_nm_glib_la_LIBADD) $(LIBS)
+libnm-glib-vpn.la: $(libnm_glib_vpn_la_OBJECTS) $(libnm_glib_vpn_la_DEPENDENCIES) 
+	$(libnm_glib_vpn_la_LINK) -rpath $(libdir) $(libnm_glib_vpn_la_OBJECTS) $(libnm_glib_vpn_la_LIBADD) $(LIBS)
+libnm-glib.la: $(libnm_glib_la_OBJECTS) $(libnm_glib_la_DEPENDENCIES) 
+	$(libnm_glib_la_LINK) -rpath $(libdir) $(libnm_glib_la_OBJECTS) $(libnm_glib_la_LIBADD) $(LIBS)
+
+clean-noinstPROGRAMS:
+	@list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \
+	echo " rm -f" $$list; \
+	rm -f $$list || exit $$?; \
+	test -n "$(EXEEXT)" || exit 0; \
+	list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+	echo " rm -f" $$list; \
+	rm -f $$list
+libnm-glib-test$(EXEEXT): $(libnm_glib_test_OBJECTS) $(libnm_glib_test_DEPENDENCIES) 
+	@rm -f libnm-glib-test$(EXEEXT)
+	$(libnm_glib_test_LINK) $(libnm_glib_test_OBJECTS) $(libnm_glib_test_LDADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdeprecated_nm_glib_la-libnm_glib.Plo@am__quote@
+@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-cdma-device.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-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-wifi.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-exported-connection.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_la-nm-gsm-device.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@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_la-nm-object.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_la-nm-remote-connection.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_la-nm-remote-settings-system.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_la-nm-remote-settings.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_la-nm-serial-device.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_la-nm-settings-connection-interface.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_la-nm-settings-interface.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_la-nm-settings-service.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_la-nm-settings-system-interface.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_la-nm-types.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_la-nm-vpn-connection.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_test-libnm-glib-test.Po@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.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@	depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@	depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@	depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@	$(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LTCOMPILE) -c -o $@ $<
+
+libdeprecated_nm_glib_la-libnm_glib.lo: libnm_glib.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdeprecated_nm_glib_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libdeprecated_nm_glib_la-libnm_glib.lo -MD -MP -MF $(DEPDIR)/libdeprecated_nm_glib_la-libnm_glib.Tpo -c -o libdeprecated_nm_glib_la-libnm_glib.lo `test -f 'libnm_glib.c' || echo '$(srcdir)/'`libnm_glib.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libdeprecated_nm_glib_la-libnm_glib.Tpo $(DEPDIR)/libdeprecated_nm_glib_la-libnm_glib.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='libnm_glib.c' object='libdeprecated_nm_glib_la-libnm_glib.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdeprecated_nm_glib_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libdeprecated_nm_glib_la-libnm_glib.lo `test -f 'libnm_glib.c' || echo '$(srcdir)/'`libnm_glib.c
+
+libnm_glib_vpn_la-nm-vpn-plugin.lo: nm-vpn-plugin.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --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__mv) $(DEPDIR)/libnm_glib_vpn_la-nm-vpn-plugin.Tpo $(DEPDIR)/libnm_glib_vpn_la-nm-vpn-plugin.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-vpn-plugin.c' object='libnm_glib_vpn_la-nm-vpn-plugin.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --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.lo `test -f 'nm-vpn-plugin.c' || echo '$(srcdir)/'`nm-vpn-plugin.c
+
+libnm_glib_vpn_la-nm-vpn-plugin-ui-interface.lo: nm-vpn-plugin-ui-interface.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --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-ui-interface.lo -MD -MP -MF $(DEPDIR)/libnm_glib_vpn_la-nm-vpn-plugin-ui-interface.Tpo -c -o libnm_glib_vpn_la-nm-vpn-plugin-ui-interface.lo `test -f 'nm-vpn-plugin-ui-interface.c' || echo '$(srcdir)/'`nm-vpn-plugin-ui-interface.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libnm_glib_vpn_la-nm-vpn-plugin-ui-interface.Tpo $(DEPDIR)/libnm_glib_vpn_la-nm-vpn-plugin-ui-interface.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-vpn-plugin-ui-interface.c' object='libnm_glib_vpn_la-nm-vpn-plugin-ui-interface.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --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-ui-interface.lo `test -f 'nm-vpn-plugin-ui-interface.c' || echo '$(srcdir)/'`nm-vpn-plugin-ui-interface.c
+
+libnm_glib_la-nm-object.lo: nm-object.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --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__mv) $(DEPDIR)/libnm_glib_la-nm-object.Tpo $(DEPDIR)/libnm_glib_la-nm-object.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-object.c' object='libnm_glib_la-nm-object.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --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-object.lo `test -f 'nm-object.c' || echo '$(srcdir)/'`nm-object.c
+
+libnm_glib_la-nm-client.lo: nm-client.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --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-client.lo -MD -MP -MF $(DEPDIR)/libnm_glib_la-nm-client.Tpo -c -o libnm_glib_la-nm-client.lo `test -f 'nm-client.c' || echo '$(srcdir)/'`nm-client.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libnm_glib_la-nm-client.Tpo $(DEPDIR)/libnm_glib_la-nm-client.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-client.c' object='libnm_glib_la-nm-client.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --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@	$(LIBTOOL)  --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__mv) $(DEPDIR)/libnm_glib_la-nm-dbus-utils.Tpo $(DEPDIR)/libnm_glib_la-nm-dbus-utils.Plo
+@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)  --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@	$(LIBTOOL)  --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__mv) $(DEPDIR)/libnm_glib_la-nm-device.Tpo $(DEPDIR)/libnm_glib_la-nm-device.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-device.c' object='libnm_glib_la-nm-device.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --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.lo `test -f 'nm-device.c' || echo '$(srcdir)/'`nm-device.c
+
+libnm_glib_la-nm-device-ethernet.lo: nm-device-ethernet.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --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-ethernet.lo -MD -MP -MF $(DEPDIR)/libnm_glib_la-nm-device-ethernet.Tpo -c -o libnm_glib_la-nm-device-ethernet.lo `test -f 'nm-device-ethernet.c' || echo '$(srcdir)/'`nm-device-ethernet.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libnm_glib_la-nm-device-ethernet.Tpo $(DEPDIR)/libnm_glib_la-nm-device-ethernet.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-device-ethernet.c' object='libnm_glib_la-nm-device-ethernet.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --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-wifi.lo: nm-device-wifi.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --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__mv) $(DEPDIR)/libnm_glib_la-nm-device-wifi.Tpo $(DEPDIR)/libnm_glib_la-nm-device-wifi.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-device-wifi.c' object='libnm_glib_la-nm-device-wifi.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --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-wifi.lo `test -f 'nm-device-wifi.c' || echo '$(srcdir)/'`nm-device-wifi.c
+
+libnm_glib_la-nm-device-bt.lo: nm-device-bt.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --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-bt.lo -MD -MP -MF $(DEPDIR)/libnm_glib_la-nm-device-bt.Tpo -c -o libnm_glib_la-nm-device-bt.lo `test -f 'nm-device-bt.c' || echo '$(srcdir)/'`nm-device-bt.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libnm_glib_la-nm-device-bt.Tpo $(DEPDIR)/libnm_glib_la-nm-device-bt.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-device-bt.c' object='libnm_glib_la-nm-device-bt.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --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-access-point.lo: nm-access-point.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --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__mv) $(DEPDIR)/libnm_glib_la-nm-access-point.Tpo $(DEPDIR)/libnm_glib_la-nm-access-point.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-access-point.c' object='libnm_glib_la-nm-access-point.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --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-access-point.lo `test -f 'nm-access-point.c' || echo '$(srcdir)/'`nm-access-point.c
+
+libnm_glib_la-nm-ip4-config.lo: nm-ip4-config.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --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-ip4-config.lo -MD -MP -MF $(DEPDIR)/libnm_glib_la-nm-ip4-config.Tpo -c -o libnm_glib_la-nm-ip4-config.lo `test -f 'nm-ip4-config.c' || echo '$(srcdir)/'`nm-ip4-config.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libnm_glib_la-nm-ip4-config.Tpo $(DEPDIR)/libnm_glib_la-nm-ip4-config.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-ip4-config.c' object='libnm_glib_la-nm-ip4-config.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --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-ip4-config.lo `test -f 'nm-ip4-config.c' || echo '$(srcdir)/'`nm-ip4-config.c
+
+libnm_glib_la-nm-gsm-device.lo: nm-gsm-device.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --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-gsm-device.lo -MD -MP -MF $(DEPDIR)/libnm_glib_la-nm-gsm-device.Tpo -c -o libnm_glib_la-nm-gsm-device.lo `test -f 'nm-gsm-device.c' || echo '$(srcdir)/'`nm-gsm-device.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libnm_glib_la-nm-gsm-device.Tpo $(DEPDIR)/libnm_glib_la-nm-gsm-device.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-gsm-device.c' object='libnm_glib_la-nm-gsm-device.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --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-gsm-device.lo `test -f 'nm-gsm-device.c' || echo '$(srcdir)/'`nm-gsm-device.c
+
+libnm_glib_la-nm-cdma-device.lo: nm-cdma-device.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --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-cdma-device.lo -MD -MP -MF $(DEPDIR)/libnm_glib_la-nm-cdma-device.Tpo -c -o libnm_glib_la-nm-cdma-device.lo `test -f 'nm-cdma-device.c' || echo '$(srcdir)/'`nm-cdma-device.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libnm_glib_la-nm-cdma-device.Tpo $(DEPDIR)/libnm_glib_la-nm-cdma-device.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-cdma-device.c' object='libnm_glib_la-nm-cdma-device.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --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-cdma-device.lo `test -f 'nm-cdma-device.c' || echo '$(srcdir)/'`nm-cdma-device.c
+
+libnm_glib_la-nm-serial-device.lo: nm-serial-device.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --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-serial-device.lo -MD -MP -MF $(DEPDIR)/libnm_glib_la-nm-serial-device.Tpo -c -o libnm_glib_la-nm-serial-device.lo `test -f 'nm-serial-device.c' || echo '$(srcdir)/'`nm-serial-device.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libnm_glib_la-nm-serial-device.Tpo $(DEPDIR)/libnm_glib_la-nm-serial-device.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-serial-device.c' object='libnm_glib_la-nm-serial-device.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --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-serial-device.lo `test -f 'nm-serial-device.c' || echo '$(srcdir)/'`nm-serial-device.c
+
+libnm_glib_la-nm-vpn-connection.lo: nm-vpn-connection.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --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-vpn-connection.lo -MD -MP -MF $(DEPDIR)/libnm_glib_la-nm-vpn-connection.Tpo -c -o libnm_glib_la-nm-vpn-connection.lo `test -f 'nm-vpn-connection.c' || echo '$(srcdir)/'`nm-vpn-connection.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libnm_glib_la-nm-vpn-connection.Tpo $(DEPDIR)/libnm_glib_la-nm-vpn-connection.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-vpn-connection.c' object='libnm_glib_la-nm-vpn-connection.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --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-vpn-connection.lo `test -f 'nm-vpn-connection.c' || echo '$(srcdir)/'`nm-vpn-connection.c
+
+libnm_glib_la-nm-types.lo: nm-types.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --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-types.lo -MD -MP -MF $(DEPDIR)/libnm_glib_la-nm-types.Tpo -c -o libnm_glib_la-nm-types.lo `test -f 'nm-types.c' || echo '$(srcdir)/'`nm-types.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libnm_glib_la-nm-types.Tpo $(DEPDIR)/libnm_glib_la-nm-types.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-types.c' object='libnm_glib_la-nm-types.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --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-types.lo `test -f 'nm-types.c' || echo '$(srcdir)/'`nm-types.c
+
+libnm_glib_la-nm-object-cache.lo: nm-object-cache.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --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-cache.lo -MD -MP -MF $(DEPDIR)/libnm_glib_la-nm-object-cache.Tpo -c -o libnm_glib_la-nm-object-cache.lo `test -f 'nm-object-cache.c' || echo '$(srcdir)/'`nm-object-cache.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libnm_glib_la-nm-object-cache.Tpo $(DEPDIR)/libnm_glib_la-nm-object-cache.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-object-cache.c' object='libnm_glib_la-nm-object-cache.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --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-object-cache.lo `test -f 'nm-object-cache.c' || echo '$(srcdir)/'`nm-object-cache.c
+
+libnm_glib_la-nm-active-connection.lo: nm-active-connection.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --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-active-connection.lo -MD -MP -MF $(DEPDIR)/libnm_glib_la-nm-active-connection.Tpo -c -o libnm_glib_la-nm-active-connection.lo `test -f 'nm-active-connection.c' || echo '$(srcdir)/'`nm-active-connection.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libnm_glib_la-nm-active-connection.Tpo $(DEPDIR)/libnm_glib_la-nm-active-connection.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-active-connection.c' object='libnm_glib_la-nm-active-connection.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --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-active-connection.lo `test -f 'nm-active-connection.c' || echo '$(srcdir)/'`nm-active-connection.c
+
+libnm_glib_la-nm-dhcp4-config.lo: nm-dhcp4-config.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --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-dhcp4-config.lo -MD -MP -MF $(DEPDIR)/libnm_glib_la-nm-dhcp4-config.Tpo -c -o libnm_glib_la-nm-dhcp4-config.lo `test -f 'nm-dhcp4-config.c' || echo '$(srcdir)/'`nm-dhcp4-config.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libnm_glib_la-nm-dhcp4-config.Tpo $(DEPDIR)/libnm_glib_la-nm-dhcp4-config.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-dhcp4-config.c' object='libnm_glib_la-nm-dhcp4-config.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --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-dhcp4-config.lo `test -f 'nm-dhcp4-config.c' || echo '$(srcdir)/'`nm-dhcp4-config.c
+
+libnm_glib_la-nm-ip6-config.lo: nm-ip6-config.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --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-ip6-config.lo -MD -MP -MF $(DEPDIR)/libnm_glib_la-nm-ip6-config.Tpo -c -o libnm_glib_la-nm-ip6-config.lo `test -f 'nm-ip6-config.c' || echo '$(srcdir)/'`nm-ip6-config.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libnm_glib_la-nm-ip6-config.Tpo $(DEPDIR)/libnm_glib_la-nm-ip6-config.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-ip6-config.c' object='libnm_glib_la-nm-ip6-config.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --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-ip6-config.lo `test -f 'nm-ip6-config.c' || echo '$(srcdir)/'`nm-ip6-config.c
+
+libnm_glib_la-nm-dhcp6-config.lo: nm-dhcp6-config.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --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-dhcp6-config.lo -MD -MP -MF $(DEPDIR)/libnm_glib_la-nm-dhcp6-config.Tpo -c -o libnm_glib_la-nm-dhcp6-config.lo `test -f 'nm-dhcp6-config.c' || echo '$(srcdir)/'`nm-dhcp6-config.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libnm_glib_la-nm-dhcp6-config.Tpo $(DEPDIR)/libnm_glib_la-nm-dhcp6-config.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-dhcp6-config.c' object='libnm_glib_la-nm-dhcp6-config.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --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-dhcp6-config.lo `test -f 'nm-dhcp6-config.c' || echo '$(srcdir)/'`nm-dhcp6-config.c
+
+libnm_glib_la-nm-remote-connection.lo: nm-remote-connection.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --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-remote-connection.lo -MD -MP -MF $(DEPDIR)/libnm_glib_la-nm-remote-connection.Tpo -c -o libnm_glib_la-nm-remote-connection.lo `test -f 'nm-remote-connection.c' || echo '$(srcdir)/'`nm-remote-connection.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libnm_glib_la-nm-remote-connection.Tpo $(DEPDIR)/libnm_glib_la-nm-remote-connection.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-remote-connection.c' object='libnm_glib_la-nm-remote-connection.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --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-remote-connection.lo `test -f 'nm-remote-connection.c' || echo '$(srcdir)/'`nm-remote-connection.c
+
+libnm_glib_la-nm-settings-interface.lo: nm-settings-interface.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --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-settings-interface.lo -MD -MP -MF $(DEPDIR)/libnm_glib_la-nm-settings-interface.Tpo -c -o libnm_glib_la-nm-settings-interface.lo `test -f 'nm-settings-interface.c' || echo '$(srcdir)/'`nm-settings-interface.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libnm_glib_la-nm-settings-interface.Tpo $(DEPDIR)/libnm_glib_la-nm-settings-interface.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-settings-interface.c' object='libnm_glib_la-nm-settings-interface.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --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-settings-interface.lo `test -f 'nm-settings-interface.c' || echo '$(srcdir)/'`nm-settings-interface.c
+
+libnm_glib_la-nm-settings-system-interface.lo: nm-settings-system-interface.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --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-settings-system-interface.lo -MD -MP -MF $(DEPDIR)/libnm_glib_la-nm-settings-system-interface.Tpo -c -o libnm_glib_la-nm-settings-system-interface.lo `test -f 'nm-settings-system-interface.c' || echo '$(srcdir)/'`nm-settings-system-interface.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libnm_glib_la-nm-settings-system-interface.Tpo $(DEPDIR)/libnm_glib_la-nm-settings-system-interface.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-settings-system-interface.c' object='libnm_glib_la-nm-settings-system-interface.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --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-settings-system-interface.lo `test -f 'nm-settings-system-interface.c' || echo '$(srcdir)/'`nm-settings-system-interface.c
+
+libnm_glib_la-nm-remote-settings.lo: nm-remote-settings.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --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-remote-settings.lo -MD -MP -MF $(DEPDIR)/libnm_glib_la-nm-remote-settings.Tpo -c -o libnm_glib_la-nm-remote-settings.lo `test -f 'nm-remote-settings.c' || echo '$(srcdir)/'`nm-remote-settings.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libnm_glib_la-nm-remote-settings.Tpo $(DEPDIR)/libnm_glib_la-nm-remote-settings.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-remote-settings.c' object='libnm_glib_la-nm-remote-settings.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --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-remote-settings.lo `test -f 'nm-remote-settings.c' || echo '$(srcdir)/'`nm-remote-settings.c
+
+libnm_glib_la-nm-remote-settings-system.lo: nm-remote-settings-system.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --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-remote-settings-system.lo -MD -MP -MF $(DEPDIR)/libnm_glib_la-nm-remote-settings-system.Tpo -c -o libnm_glib_la-nm-remote-settings-system.lo `test -f 'nm-remote-settings-system.c' || echo '$(srcdir)/'`nm-remote-settings-system.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libnm_glib_la-nm-remote-settings-system.Tpo $(DEPDIR)/libnm_glib_la-nm-remote-settings-system.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-remote-settings-system.c' object='libnm_glib_la-nm-remote-settings-system.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --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-remote-settings-system.lo `test -f 'nm-remote-settings-system.c' || echo '$(srcdir)/'`nm-remote-settings-system.c
+
+libnm_glib_la-nm-settings-connection-interface.lo: nm-settings-connection-interface.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --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-settings-connection-interface.lo -MD -MP -MF $(DEPDIR)/libnm_glib_la-nm-settings-connection-interface.Tpo -c -o libnm_glib_la-nm-settings-connection-interface.lo `test -f 'nm-settings-connection-interface.c' || echo '$(srcdir)/'`nm-settings-connection-interface.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libnm_glib_la-nm-settings-connection-interface.Tpo $(DEPDIR)/libnm_glib_la-nm-settings-connection-interface.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-settings-connection-interface.c' object='libnm_glib_la-nm-settings-connection-interface.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --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-settings-connection-interface.lo `test -f 'nm-settings-connection-interface.c' || echo '$(srcdir)/'`nm-settings-connection-interface.c
+
+libnm_glib_la-nm-exported-connection.lo: nm-exported-connection.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --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-exported-connection.lo -MD -MP -MF $(DEPDIR)/libnm_glib_la-nm-exported-connection.Tpo -c -o libnm_glib_la-nm-exported-connection.lo `test -f 'nm-exported-connection.c' || echo '$(srcdir)/'`nm-exported-connection.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libnm_glib_la-nm-exported-connection.Tpo $(DEPDIR)/libnm_glib_la-nm-exported-connection.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-exported-connection.c' object='libnm_glib_la-nm-exported-connection.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --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-exported-connection.lo `test -f 'nm-exported-connection.c' || echo '$(srcdir)/'`nm-exported-connection.c
+
+libnm_glib_la-nm-settings-service.lo: nm-settings-service.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --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-settings-service.lo -MD -MP -MF $(DEPDIR)/libnm_glib_la-nm-settings-service.Tpo -c -o libnm_glib_la-nm-settings-service.lo `test -f 'nm-settings-service.c' || echo '$(srcdir)/'`nm-settings-service.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libnm_glib_la-nm-settings-service.Tpo $(DEPDIR)/libnm_glib_la-nm-settings-service.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-settings-service.c' object='libnm_glib_la-nm-settings-service.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --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-settings-service.lo `test -f 'nm-settings-service.c' || echo '$(srcdir)/'`nm-settings-service.c
+
+libnm_glib_test-libnm-glib-test.o: libnm-glib-test.c
+@am__fastdepCC_TRUE@	$(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__mv) $(DEPDIR)/libnm_glib_test-libnm-glib-test.Tpo $(DEPDIR)/libnm_glib_test-libnm-glib-test.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='libnm-glib-test.c' object='libnm_glib_test-libnm-glib-test.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnm_glib_test_CFLAGS) $(CFLAGS) -c -o libnm_glib_test-libnm-glib-test.o `test -f 'libnm-glib-test.c' || echo '$(srcdir)/'`libnm-glib-test.c
+
+libnm_glib_test-libnm-glib-test.obj: libnm-glib-test.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnm_glib_test_CFLAGS) $(CFLAGS) -MT libnm_glib_test-libnm-glib-test.obj -MD -MP -MF $(DEPDIR)/libnm_glib_test-libnm-glib-test.Tpo -c -o libnm_glib_test-libnm-glib-test.obj `if test -f 'libnm-glib-test.c'; then $(CYGPATH_W) 'libnm-glib-test.c'; else $(CYGPATH_W) '$(srcdir)/libnm-glib-test.c'; fi`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libnm_glib_test-libnm-glib-test.Tpo $(DEPDIR)/libnm_glib_test-libnm-glib-test.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='libnm-glib-test.c' object='libnm_glib_test-libnm-glib-test.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnm_glib_test_CFLAGS) $(CFLAGS) -c -o libnm_glib_test-libnm-glib-test.obj `if test -f 'libnm-glib-test.c'; then $(CYGPATH_W) 'libnm-glib-test.c'; else $(CYGPATH_W) '$(srcdir)/libnm-glib-test.c'; fi`
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+install-pkgconfigDATA: $(pkgconfig_DATA)
+	@$(NORMAL_INSTALL)
+	test -z "$(pkgconfigdir)" || $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)"
+	@list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \
+	done
+
+uninstall-pkgconfigDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	test -n "$$files" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(pkgconfigdir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(pkgconfigdir)" && rm -f $$files
+install-libnmincludeHEADERS: $(libnminclude_HEADERS)
+	@$(NORMAL_INSTALL)
+	test -z "$(libnmincludedir)" || $(MKDIR_P) "$(DESTDIR)$(libnmincludedir)"
+	@list='$(libnminclude_HEADERS)'; test -n "$(libnmincludedir)" || list=; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libnmincludedir)'"; \
+	  $(INSTALL_HEADER) $$files "$(DESTDIR)$(libnmincludedir)" || exit $$?; \
+	done
+
+uninstall-libnmincludeHEADERS:
+	@$(NORMAL_UNINSTALL)
+	@list='$(libnminclude_HEADERS)'; test -n "$(libnmincludedir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	test -n "$$files" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(libnmincludedir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(libnmincludedir)" && rm -f $$files
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	set x; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	shift; \
+	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  if test $$# -gt 0; then \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      "$$@" $$unique; \
+	  else \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      $$unique; \
+	  fi; \
+	fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	test -z "$(CTAGS_ARGS)$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && $(am__cd) $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d "$(distdir)/$$file"; then \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+	  else \
+	    test -f "$(distdir)/$$file" \
+	    || cp -p $$d/$$file "$(distdir)/$$file" \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: $(BUILT_SOURCES)
+	$(MAKE) $(AM_MAKEFLAGS) check-am
+all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) $(HEADERS)
+installdirs:
+	for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(libnmincludedir)"; do \
+	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+	done
+install: $(BUILT_SOURCES)
+	$(MAKE) $(AM_MAKEFLAGS) install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+	-test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+	-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+clean: clean-am
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+	clean-noinstLTLIBRARIES clean-noinstPROGRAMS mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-libnmincludeHEADERS install-pkgconfigDATA
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-libLTLIBRARIES
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-libLTLIBRARIES uninstall-libnmincludeHEADERS \
+	uninstall-pkgconfigDATA
+
+.MAKE: all check install install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+	clean-libLTLIBRARIES clean-libtool clean-noinstLTLIBRARIES \
+	clean-noinstPROGRAMS ctags distclean distclean-compile \
+	distclean-generic distclean-libtool distclean-tags distdir dvi \
+	dvi-am html html-am info info-am install install-am \
+	install-data install-data-am install-dvi install-dvi-am \
+	install-exec install-exec-am install-html install-html-am \
+	install-info install-info-am install-libLTLIBRARIES \
+	install-libnmincludeHEADERS install-man install-pdf \
+	install-pdf-am install-pkgconfigDATA install-ps install-ps-am \
+	install-strip installcheck installcheck-am installdirs \
+	maintainer-clean maintainer-clean-generic mostlyclean \
+	mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+	pdf pdf-am ps ps-am tags uninstall uninstall-am \
+	uninstall-libLTLIBRARIES uninstall-libnmincludeHEADERS \
+	uninstall-pkgconfigDATA
+
+
+nm-client-bindings.h: $(top_srcdir)/introspection/nm-manager-client.xml
+	dbus-binding-tool --prefix=nm_client --mode=glib-client --output=$@ $<
+
+nm-device-bindings.h: $(top_srcdir)/introspection/nm-device.xml
+	dbus-binding-tool --prefix=nm_device --mode=glib-client --output=$@ $<
+
+nm-device-ethernet-bindings.h: $(top_srcdir)/introspection/nm-device-ethernet.xml
+	dbus-binding-tool --prefix=nm_device_ethernet --mode=glib-client --output=$@ $<
+
+nm-device-wifi-bindings.h: $(top_srcdir)/introspection/nm-device-wifi.xml
+	dbus-binding-tool --prefix=nm_device_wifi --mode=glib-client --output=$@ $<
+
+nm-device-bt-bindings.h: $(top_srcdir)/introspection/nm-device-bt.xml
+	dbus-binding-tool --prefix=nm_device_bt --mode=glib-client --output=$@ $<
+
+nm-access-point-bindings.h: $(top_srcdir)/introspection/nm-access-point.xml
+	dbus-binding-tool --prefix=nm_access_point --mode=glib-client --output=$@ $<
+
+nm-settings-glue.h: $(top_srcdir)/introspection/nm-settings.xml
+	dbus-binding-tool --prefix=nm_settings --mode=glib-server --output=$@ $<
+
+nm-settings-bindings.h: $(top_srcdir)/introspection/nm-settings.xml
+	dbus-binding-tool --prefix=nm_settings --mode=glib-client --output=$@ $<
+
+nm-settings-system-bindings.h: $(top_srcdir)/introspection/nm-settings-system.xml
+	dbus-binding-tool --prefix=nm_settings_system --mode=glib-client --output=$@ $<
+
+nm-exported-connection-glue.h: $(top_srcdir)/introspection/nm-exported-connection.xml
+	dbus-binding-tool --prefix=nm_exported_connection --mode=glib-server --output=$@ $<
+
+nm-exported-connection-bindings.h: $(top_srcdir)/introspection/nm-exported-connection.xml
+	dbus-binding-tool --prefix=nm_exported_connection --mode=glib-client --output=$@ $<
+
+nm-vpn-connection-bindings.h: $(top_srcdir)/introspection/nm-vpn-connection.xml
+	dbus-binding-tool --prefix=nm_vpn_connection --mode=glib-client --output=$@ $<
+
+nm-vpn-plugin-glue.h: $(top_srcdir)/introspection/nm-vpn-plugin.xml
+	dbus-binding-tool --prefix=nm_vpn_plugin --mode=glib-server --output=$@ $<
+
+nm-active-connection-bindings.h: $(top_srcdir)/introspection/nm-active-connection.xml
+	dbus-binding-tool --prefix=nm_active_connection --mode=glib-client --output=$@ $<
+
+nm-ip4-config-bindings.h: $(top_srcdir)/introspection/nm-ip4-config.xml
+	dbus-binding-tool --prefix=nm_ip4_config --mode=glib-client --output=$@ $<
+
+nm-dhcp4-config-bindings.h: $(top_srcdir)/introspection/nm-dhcp4-config.xml
+	dbus-binding-tool --prefix=nm_dhcp4_config --mode=glib-client --output=$@ $<
+
+nm-ip6-config-bindings.h: $(top_srcdir)/introspection/nm-ip6-config.xml
+	dbus-binding-tool --prefix=nm_ip6_config --mode=glib-client --output=$@ $<
+
+nm-dhcp6-config-bindings.h: $(top_srcdir)/introspection/nm-dhcp6-config.xml
+	dbus-binding-tool --prefix=nm_dhcp6_config --mode=glib-client --output=$@ $<
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/libnm-glib/libnm-glib-test.c b/libnm-glib/libnm-glib-test.c
new file mode 100644
index 00000000..3ac0a24c
--- /dev/null
+++ b/libnm-glib/libnm-glib-test.c
@@ -0,0 +1,419 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * libnm_glib -- Access network status & information from glib applications
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2007 - 2008 Novell, Inc.
+ * Copyright (C) 2007 - 2008 Red Hat, Inc.
+ */
+
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+
+#include <sys/socket.h>
+#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"
+#include "nm-device-wifi.h"
+#include "nm-utils.h"
+#include "nm-active-connection.h"
+#include "nm-vpn-connection.h"
+#include "nm-setting-ip4-config.h"
+
+static gboolean
+test_wireless_enabled (NMClient *client)
+{
+	gboolean wireless;
+
+	wireless = nm_client_wireless_get_enabled (client);
+	g_print ("Wireless enabled? %s\n", wireless ? "yes" : "no");
+
+//	nm_client_wireless_set_enabled (client, !wireless);
+
+	wireless = nm_client_wireless_hardware_get_enabled (client);
+	g_print ("Wireless HW enabled? %s\n", wireless ? "yes" : "no");
+
+//	nm_client_wireless_set_enabled (client, !wireless);
+
+	return TRUE;
+}
+
+static gboolean
+test_get_state (NMClient *client)
+{
+	guint state;
+
+	state = nm_client_get_state (client);
+	g_print ("Current state: %d\n", state);
+
+	return TRUE;
+}
+
+static gchar *
+ip4_address_as_string (guint32 ip)
+{
+	char buf[INET_ADDRSTRLEN+1];
+	struct in_addr tmp_addr;
+
+	memset (&buf, '\0', sizeof (buf));
+	tmp_addr.s_addr = ip;
+
+	if (inet_ntop (AF_INET, &tmp_addr, buf, INET_ADDRSTRLEN)) {
+		return g_strdup (buf);
+	} else {
+		nm_warning ("%s: error converting IP4 address 0x%X",
+		            __func__, ntohl (tmp_addr.s_addr));
+		return NULL;
+	}
+}
+
+static void
+dump_ip4_config (NMIP4Config *cfg)
+{
+	char *tmp;
+	const GArray *array;
+	const GPtrArray *ptr_array;
+	GSList *iter;
+	int i;
+
+	for (iter = (GSList *) nm_ip4_config_get_addresses (cfg); iter; iter = g_slist_next (iter)) {
+		NMIP4Address *addr = iter->data;
+		guint32 u;
+
+		tmp = ip4_address_as_string (nm_ip4_address_get_address (addr));
+		g_print ("IP4 address: %s\n", tmp);
+		g_free (tmp);
+
+		u = nm_ip4_address_get_prefix (addr);
+		tmp = ip4_address_as_string (nm_utils_ip4_prefix_to_netmask (u));
+		g_print ("IP4 prefix: %d (%s)\n", u, tmp);
+		g_free (tmp);
+
+		tmp = ip4_address_as_string (nm_ip4_address_get_gateway (addr));
+		g_print ("IP4 gateway: %s\n\n", tmp);
+		g_free (tmp);
+	}
+
+	array = nm_ip4_config_get_nameservers (cfg);
+	if (array) {
+		g_print ("IP4 DNS:\n");
+		for (i = 0; i < array->len; i++) {
+			tmp = ip4_address_as_string (g_array_index (array, guint32, i));
+			g_print ("\t%s\n", tmp);
+			g_free (tmp);
+		}
+	}
+
+	ptr_array = nm_ip4_config_get_domains (cfg);
+	if (ptr_array) {
+		g_print ("IP4 domains:\n");
+		for (i = 0; i < ptr_array->len; i++)
+			g_print ("\t%s\n", (const char *) g_ptr_array_index (ptr_array, i));
+	}
+
+	array = nm_ip4_config_get_wins_servers (cfg);
+	if (array) {
+		g_print ("IP4 WINS:\n");
+		for (i = 0; i < array->len; i++) {
+			tmp = ip4_address_as_string (g_array_index (array, guint32, i));
+			g_print ("\t%s\n", tmp);
+			g_free (tmp);
+		}
+	}
+}
+
+static void
+print_one_dhcp4_option (gpointer key, gpointer data, gpointer user_data)
+{
+	const char *option = (const char *) key;
+	const char *value = (const char *) data;
+
+	g_print ("  %s:   %s\n", option, value);
+}
+
+static void
+dump_dhcp4_config (NMDHCP4Config *config)
+{
+	GHashTable *options = NULL;
+
+	if (!config)
+		return;
+
+	g_print ("\nDHCP4 Options:\n");
+	g_print ("-------------------------------------\n");
+
+	g_object_get (G_OBJECT (config), NM_DHCP4_CONFIG_OPTIONS, &options, NULL);
+	g_hash_table_foreach (options, print_one_dhcp4_option, NULL);
+}
+
+static void
+dump_access_point (NMAccessPoint *ap)
+{
+	const GByteArray * ssid;
+	const char * str;
+
+	ssid = nm_access_point_get_ssid (ap);
+	g_print ("\tSsid: %s\n",
+	         ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "(none)");
+
+	str = nm_access_point_get_hw_address (ap);
+	g_print ("\tMAC Address: %s\n", str);
+
+	g_print ("\tFlags: 0x%X\n", nm_access_point_get_flags (ap));
+	g_print ("\tWPA Flags: 0x%X\n", nm_access_point_get_wpa_flags (ap));
+	g_print ("\tRSN Flags: 0x%X\n", nm_access_point_get_rsn_flags (ap));
+	g_print ("\tFrequency: %u\n", nm_access_point_get_frequency (ap));
+
+	g_print ("\tMode: %d\n", nm_access_point_get_mode (ap));
+	g_print ("\tRate: %d\n", nm_access_point_get_max_bitrate (ap));
+	g_print ("\tStrength: %d\n", nm_access_point_get_strength (ap));
+}
+
+static void
+dump_wireless (NMDeviceWifi *device)
+{
+	const char *str;
+	const GPtrArray *aps;
+	int i;
+
+	g_print ("Mode: %d\n", nm_device_wifi_get_mode (device));
+	g_print ("Bitrate: %d\n", nm_device_wifi_get_bitrate (device));
+
+	str = nm_device_wifi_get_hw_address (device);
+	g_print ("MAC: %s\n", str);
+
+	g_print ("AccessPoints:\n");
+	aps = nm_device_wifi_get_access_points (device);
+	for (i = 0; i < aps->len; i++) {
+		dump_access_point (NM_ACCESS_POINT (g_ptr_array_index (aps, i)));
+		g_print ("\n");
+	}
+}
+
+static void
+dump_wired (NMDeviceEthernet *device)
+{
+	const char *str;
+
+	g_print ("Speed: %d\n", nm_device_ethernet_get_speed (device));
+
+	str = nm_device_ethernet_get_hw_address (device);
+	g_print ("MAC: %s\n", str);
+}
+
+static void
+dump_device (NMDevice *device)
+{
+	const char *str;
+	NMDeviceState state;
+
+	str = nm_device_get_iface (device);
+	g_print ("Interface: %s\n", str);
+
+	str = nm_device_get_udi (device);
+	g_print ("Udi: %s\n", str);
+
+	str = nm_device_get_driver (device);
+	g_print ("Driver: %s\n", str);
+
+	str = nm_device_get_vendor (device);
+	g_print ("Vendor: %s\n", str);
+
+	str = nm_device_get_product (device);
+	g_print ("Product: %s\n", str);
+
+	state = nm_device_get_state (device);
+	g_print ("State: %d\n", state);
+
+	if (state == NM_DEVICE_STATE_ACTIVATED)
+		dump_ip4_config (nm_device_get_ip4_config (device));
+
+	if (NM_IS_DEVICE_ETHERNET (device))
+		dump_wired (NM_DEVICE_ETHERNET (device));
+	else if (NM_IS_DEVICE_WIFI (device))
+		dump_wireless (NM_DEVICE_WIFI (device));
+
+	dump_dhcp4_config (nm_device_get_dhcp4_config (device));
+}
+
+static gboolean
+test_devices (NMClient *client)
+{
+	const GPtrArray *devices;
+	int i;
+
+	devices = nm_client_get_devices (client);
+	g_print ("Got devices:\n");
+	if (!devices) {
+		g_print ("  NONE\n");
+		return TRUE;
+	}
+
+	for (i = 0; i < devices->len; i++) {
+		NMDevice *device = g_ptr_array_index (devices, i);
+		dump_device (device);
+		g_print ("\n");
+	}
+
+	return TRUE;
+}
+
+static void
+active_connections_changed (NMClient *client, GParamSpec *pspec, gpointer user_data)
+{
+	const GPtrArray *connections;
+	int i, j;
+
+	g_print ("Active connections changed:\n");
+	connections = nm_client_get_active_connections (client);
+	for (i = 0; connections && (i < connections->len); i++) {
+		NMActiveConnection *connection;
+		const GPtrArray *devices;
+
+		connection = g_ptr_array_index (connections, i);
+		g_print ("    %s\n", nm_object_get_path (NM_OBJECT (connection)));
+		devices = nm_active_connection_get_devices (connection);
+		for (j = 0; devices && j < devices->len; j++)
+			g_print ("           %s\n", nm_device_get_udi (g_ptr_array_index (devices, j)));
+		if (NM_IS_VPN_CONNECTION (connection))
+			g_print ("           VPN base connection: %s\n", nm_active_connection_get_specific_object (connection));
+	}
+}
+
+static void
+show_active_connection_device (gpointer data, gpointer user_data)
+{
+	NMDevice *device = NM_DEVICE (data);
+
+	g_print ("           %s\n", nm_device_get_udi (device));
+}
+
+static void
+test_get_active_connections (NMClient *client)
+{
+	const GPtrArray *connections;
+	int i;
+
+	g_print ("Active connections:\n");
+	connections = nm_client_get_active_connections (client);
+	for (i = 0; connections && (i < connections->len); i++) {
+		const GPtrArray *devices;
+
+		g_print ("    %s\n", nm_object_get_path (g_ptr_array_index (connections, i)));
+		devices = nm_active_connection_get_devices (g_ptr_array_index (connections, i));
+		g_ptr_array_foreach ((GPtrArray *) devices, show_active_connection_device, NULL);
+	}
+}
+
+static void
+device_state_changed (NMDevice *device, GParamSpec *pspec, gpointer user_data)
+{
+	g_print ("Device state changed: %s %d\n",
+	         nm_device_get_iface (device),
+	         nm_device_get_state (device));
+}
+
+static void
+device_added_cb (NMClient *client, NMDevice *device, gpointer user_data)
+{
+	g_print ("New device added\n");
+	dump_device (device);
+	g_signal_connect (G_OBJECT (device), "notify::state",
+	                  (GCallback) device_state_changed, NULL);
+}
+
+static void
+device_removed_cb (NMClient *client, NMDevice *device, gpointer user_data)
+{
+	g_print ("Device removed\n");
+	dump_device (device);
+}
+
+static void
+manager_running (NMClient *client, GParamSpec *pspec, gpointer user_data)
+{
+	if (nm_client_get_manager_running (client)) {
+		g_print ("NM appeared\n");
+		test_wireless_enabled (client);
+		test_get_state (client);
+		test_get_active_connections (client);
+		test_devices (client);
+	} else
+		g_print ("NM disappeared\n");
+}
+
+static GMainLoop *loop = NULL;
+
+static void
+signal_handler (int signo)
+{
+	if (signo == SIGINT || signo == SIGTERM) {
+		g_message ("Caught signal %d, shutting down...", signo);
+		g_main_loop_quit (loop);
+	}
+}
+
+static void
+setup_signals (void)
+{
+	struct sigaction action;
+	sigset_t mask;
+
+	sigemptyset (&mask);
+	action.sa_handler = signal_handler;
+	action.sa_mask = mask;
+	action.sa_flags = 0;
+	sigaction (SIGTERM,  &action, NULL);
+	sigaction (SIGINT,  &action, NULL);
+}
+
+int
+main (int argc, char *argv[])
+{
+	NMClient *client;
+
+	g_type_init ();
+
+	client = nm_client_new ();
+	if (!client) {
+		exit (1);
+	}
+
+	g_signal_connect (client, "notify::" NM_CLIENT_MANAGER_RUNNING,
+	                  G_CALLBACK (manager_running), NULL);
+	g_signal_connect (client, "notify::" NM_CLIENT_ACTIVE_CONNECTIONS,
+	                  G_CALLBACK (active_connections_changed), NULL);
+	manager_running (client, NULL, NULL);
+
+	g_signal_connect (client, "device-added",
+					  G_CALLBACK (device_added_cb), NULL);
+	g_signal_connect (client, "device-removed",
+					  G_CALLBACK (device_removed_cb), NULL);
+
+	loop = g_main_loop_new (NULL, FALSE);
+	setup_signals ();
+	g_main_loop_run (loop);
+
+	g_object_unref (client);
+
+	return 0;
+}
diff --git a/libnm-glib/libnm-glib-vpn.pc.in b/libnm-glib/libnm-glib-vpn.pc.in
new file mode 100644
index 00000000..73b7a9c7
--- /dev/null
+++ b/libnm-glib/libnm-glib-vpn.pc.in
@@ -0,0 +1,13 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libnm-glib-vpn
+Description: Convenience library for NetworkManager VPN plugins
+Version: @VERSION@
+Requires: NetworkManager >= 0.7.999 glib-2.0 dbus-glib-1
+Cflags: -I${includedir}/libnm-glib
+Libs: -L${libdir} -lnm-glib-vpn
+
+
diff --git a/libnm-glib/libnm-glib-vpn.ver b/libnm-glib/libnm-glib-vpn.ver
new file mode 100644
index 00000000..16643d2e
--- /dev/null
+++ b/libnm-glib/libnm-glib-vpn.ver
@@ -0,0 +1,26 @@
+{
+global:
+	nm_vpn_plugin_disconnect;
+	nm_vpn_plugin_error_get_type;
+	nm_vpn_plugin_error_quark;
+	nm_vpn_plugin_failure;
+	nm_vpn_plugin_get_connection;
+	nm_vpn_plugin_get_state;
+	nm_vpn_plugin_get_type;
+	nm_vpn_plugin_set_ip4_config;
+	nm_vpn_plugin_set_login_banner;
+	nm_vpn_plugin_set_state;
+	nm_vpn_plugin_ui_interface_delete_connection;
+	nm_vpn_plugin_ui_interface_export;
+	nm_vpn_plugin_ui_interface_get_capabilities;
+	nm_vpn_plugin_ui_interface_get_suggested_name;
+	nm_vpn_plugin_ui_interface_get_type;
+	nm_vpn_plugin_ui_interface_import;
+	nm_vpn_plugin_ui_interface_ui_factory;
+	nm_vpn_plugin_ui_widget_interface_get_type;
+	nm_vpn_plugin_ui_widget_interface_get_widget;
+	nm_vpn_plugin_ui_widget_interface_save_secrets;
+	nm_vpn_plugin_ui_widget_interface_update_connection;
+local:
+	*;
+};
diff --git a/libnm-glib/libnm-glib.pc.in b/libnm-glib/libnm-glib.pc.in
new file mode 100644
index 00000000..5c3471b1
--- /dev/null
+++ b/libnm-glib/libnm-glib.pc.in
@@ -0,0 +1,13 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libnm-glib
+Description: Convenience library for clients of NetworkManager
+Version: @VERSION@
+Requires: NetworkManager >= 0.7.999 glib-2.0 dbus-glib-1
+Cflags: -I${includedir}/libnm-glib
+Libs: -L${libdir} -lnm-glib
+
+
diff --git a/libnm-glib/libnm-glib.ver b/libnm-glib/libnm-glib.ver
new file mode 100644
index 00000000..6d48fb38
--- /dev/null
+++ b/libnm-glib/libnm-glib.ver
@@ -0,0 +1,161 @@
+{
+global:
+	libnm_glib_get_network_state;
+	libnm_glib_init;
+	libnm_glib_register_callback;
+	libnm_glib_shutdown;
+	libnm_glib_unregister_callback;
+	nm_access_point_get_flags;
+	nm_access_point_get_frequency;
+	nm_access_point_get_hw_address;
+	nm_access_point_get_max_bitrate;
+	nm_access_point_get_mode;
+	nm_access_point_get_rsn_flags;
+	nm_access_point_get_ssid;
+	nm_access_point_get_strength;
+	nm_access_point_get_type;
+	nm_access_point_get_wpa_flags;
+	nm_access_point_new;
+	nm_active_connection_get_connection;
+	nm_active_connection_get_default;
+	nm_active_connection_get_default6;
+	nm_active_connection_get_devices;
+	nm_active_connection_get_scope;
+	nm_active_connection_get_service_name;
+	nm_active_connection_get_specific_object;
+	nm_active_connection_get_state;
+	nm_active_connection_get_type;
+	nm_active_connection_new;
+	nm_cdma_device_get_type;
+	nm_cdma_device_new;
+	nm_client_activate_connection;
+	nm_client_deactivate_connection;
+	nm_client_get_active_connections;
+	nm_client_get_device_by_path;
+	nm_client_get_devices;
+	nm_client_get_manager_running;
+	nm_client_get_state;
+	nm_client_get_type;
+	nm_client_networking_get_enabled;
+	nm_client_networking_set_enabled;
+	nm_client_new;
+	nm_client_sleep;
+	nm_client_wireless_get_enabled;
+	nm_client_wireless_hardware_get_enabled;
+	nm_client_wireless_set_enabled;
+	nm_client_wwan_get_enabled;
+	nm_client_wwan_hardware_get_enabled;
+	nm_client_wwan_set_enabled;
+	nm_dbus_settings_get_connection_by_path;
+	nm_dbus_settings_get_type;
+	nm_dbus_settings_new;
+	nm_dbus_settings_system_add_connection;
+	nm_dbus_settings_system_get_can_modify;
+	nm_dbus_settings_system_get_type;
+	nm_dbus_settings_system_get_unmanaged_devices;
+	nm_dbus_settings_system_new;
+	nm_device_disconnect;
+	nm_device_bt_new;
+	nm_device_bt_get_capabilities;
+	nm_device_bt_get_hw_address;
+	nm_device_bt_get_name;
+	nm_device_bt_get_type;
+	nm_device_ethernet_get_carrier;
+	nm_device_ethernet_get_hw_address;
+	nm_device_ethernet_get_speed;
+	nm_device_ethernet_get_type;
+	nm_device_ethernet_new;
+	nm_device_get_capabilities;
+	nm_device_get_dhcp4_config;
+	nm_device_get_driver;
+	nm_device_get_iface;
+	nm_device_get_ip4_config;
+	nm_device_get_ip6_config;
+	nm_device_get_managed;
+	nm_device_get_product;
+	nm_device_get_state;
+	nm_device_get_type;
+	nm_device_get_udi;
+	nm_device_get_vendor;
+	nm_device_new;
+	nm_device_wifi_get_access_point_by_path;
+	nm_device_wifi_get_access_points;
+	nm_device_wifi_get_active_access_point;
+	nm_device_wifi_get_bitrate;
+	nm_device_wifi_get_capabilities;
+	nm_device_wifi_get_hw_address;
+	nm_device_wifi_get_mode;
+	nm_device_wifi_get_type;
+	nm_device_wifi_new;
+	nm_dhcp4_config_get_one_option;
+	nm_dhcp4_config_get_options;
+	nm_dhcp4_config_get_type;
+	nm_dhcp4_config_new;
+	nm_exported_connection_export;
+	nm_exported_connection_get_type;
+	nm_exported_connection_new;
+	nm_gsm_device_get_type;
+	nm_gsm_device_new;
+	nm_ip4_config_get_addresses;
+	nm_ip4_config_get_domains;
+	nm_ip4_config_get_hostname;
+	nm_ip4_config_get_nameservers;
+	nm_ip4_config_get_wins_servers;
+	nm_ip4_config_get_routes;
+	nm_ip4_config_get_type;
+	nm_ip4_config_new;
+	nm_ip6_address_array_get_type;
+	nm_ip6_address_object_array_get_type;
+	nm_ip6_config_get_addresses;
+	nm_ip6_config_get_domains;
+	nm_ip6_config_get_nameservers;
+	nm_ip6_config_get_routes;
+	nm_ip6_config_get_type;
+	nm_ip6_config_new;
+	nm_ip6_route_object_array_get_type;
+	nm_object_array_get_type;
+	nm_object_get_connection;
+	nm_object_get_path;
+	nm_object_get_type;
+	nm_remote_connection_get_type;
+	nm_remote_connection_new;
+	nm_remote_settings_get_type;
+	nm_remote_settings_new;
+	nm_remote_settings_system_get_type;
+	nm_remote_settings_system_new;
+	nm_serial_device_get_bytes_received;
+	nm_serial_device_get_bytes_sent;
+	nm_serial_device_get_type;
+	nm_settings_connection_interface_delete;
+	nm_settings_connection_interface_emit_updated;
+	nm_settings_connection_interface_get_secrets;
+	nm_settings_connection_interface_get_type;
+	nm_settings_connection_interface_update;
+	nm_settings_interface_add_connection;
+	nm_settings_interface_error_get_type;
+	nm_settings_interface_error_quark;
+	nm_settings_interface_get_connection_by_path;
+	nm_settings_interface_get_type;
+	nm_settings_interface_list_connections;
+	nm_settings_service_export;
+	nm_settings_service_export_connection;
+	nm_settings_service_get_connection_by_path;
+	nm_settings_service_get_type;
+	nm_settings_system_interface_get_type;
+	nm_settings_system_interface_add_connection;
+	nm_settings_system_interface_get_permissions;
+	nm_settings_system_interface_save_hostname;
+	nm_settings_error_quark;
+	nm_settings_get_type;
+	nm_settings_list_connections;
+	nm_settings_signal_new_connection;
+	nm_ssid_get_type;
+	nm_string_array_get_type;
+	nm_uint_array_get_type;
+	nm_vpn_connection_get_banner;
+	nm_vpn_connection_get_type;
+	nm_vpn_connection_get_vpn_state;
+	nm_vpn_connection_new;
+local:
+	*;
+};
diff --git a/libnm-glib/libnm_glib.c b/libnm-glib/libnm_glib.c
new file mode 100644
index 00000000..5e0e5cf5
--- /dev/null
+++ b/libnm-glib/libnm_glib.c
@@ -0,0 +1,600 @@
+/* -*- 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) 2005 - 2008 Red Hat, Inc.
+ * Copyright (C) 2005 - 2008 Novell, Inc.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib-lowlevel.h>
+#include "NetworkManager.h"
+#include "libnm_glib.h"
+
+#define	DBUS_NO_SERVICE_ERROR			"org.freedesktop.DBus.Error.ServiceDoesNotExist"
+#define NM_DBUS_SIGNAL_STATE_CHANGE	"StateChange"
+
+
+struct libnm_glib_ctx
+{
+	unsigned char		check;
+
+	GMainContext *		g_main_ctx;
+	GMainLoop *		g_main_loop;
+	DBusConnection	*	dbus_con;
+	guint			dbus_watcher;
+	guint			dbus_watch_interval;
+
+	gboolean			thread_done;
+	gboolean			thread_inited;
+	GThread *			thread;
+
+	GSList *			callbacks;
+	GMutex *			callbacks_lock;
+	guint			callback_id_last;
+
+	libnm_glib_state	nm_state;
+};
+
+typedef struct libnm_glib_callback
+{
+	guint				id;
+	GMainContext *			gmain_ctx;
+	libnm_glib_ctx *		libnm_glib_ctx;
+	libnm_glib_callback_func	func;
+	gpointer				user_data;
+} libnm_glib_callback;
+
+
+static void libnm_glib_schedule_dbus_watcher (libnm_glib_ctx *ctx);
+static DBusConnection * libnm_glib_dbus_init (gpointer *user_data, GMainContext *context);
+static void libnm_glib_update_state (libnm_glib_ctx *ctx, NMState state);
+
+
+static void
+libnm_glib_nm_state_cb (DBusPendingCall *pcall,
+                        void *user_data)
+{
+	DBusMessage *		reply;
+	libnm_glib_ctx *	ctx = (libnm_glib_ctx *) user_data;
+	NMState			nm_state;
+
+	g_return_if_fail (pcall != NULL);
+	g_return_if_fail (ctx != NULL);
+
+	if (!(reply = dbus_pending_call_steal_reply (pcall)))
+		goto out;
+
+	if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR)
+	{
+		DBusError err;
+
+		dbus_error_init (&err);
+		dbus_set_error_from_message (&err, reply);
+		fprintf (stderr, "%s: dbus returned an error.\n  (%s) %s\n", __func__, err.name, err.message);
+		dbus_error_free (&err);
+		dbus_message_unref (reply);
+		goto out;
+	}
+
+	if (dbus_message_get_args (reply, NULL, DBUS_TYPE_UINT32, &nm_state, DBUS_TYPE_INVALID))
+		libnm_glib_update_state (ctx, nm_state);
+
+	dbus_message_unref (reply);
+
+out:
+	dbus_pending_call_unref (pcall);
+}
+
+static void
+libnm_glib_get_nm_state (libnm_glib_ctx *ctx)
+{
+	DBusMessage *		message;
+	DBusPendingCall *	pcall = NULL;
+
+	g_return_if_fail (ctx != NULL);
+
+	if ((message = dbus_message_new_method_call (NM_DBUS_SERVICE, NM_DBUS_PATH, NM_DBUS_INTERFACE, "state")))
+	{
+		dbus_connection_send_with_reply (ctx->dbus_con, message, &pcall, -1);
+		if (pcall)
+			dbus_pending_call_set_notify (pcall, libnm_glib_nm_state_cb, ctx, NULL);
+		dbus_message_unref (message);
+	}
+}
+
+static gboolean
+libnm_glib_callback_helper (gpointer user_data)
+{
+	libnm_glib_callback	*cb_data = (libnm_glib_callback *)user_data;
+
+	g_return_val_if_fail (cb_data != NULL, FALSE);
+	g_return_val_if_fail (cb_data->func != NULL, FALSE);
+	g_return_val_if_fail (cb_data->libnm_glib_ctx != NULL, FALSE);
+
+	(*(cb_data->func)) (cb_data->libnm_glib_ctx, cb_data->user_data);
+
+	return FALSE;
+}
+
+static void
+libnm_glib_schedule_single_callback (libnm_glib_ctx *ctx,
+                                     libnm_glib_callback *callback)
+{
+	GSource				*source;
+
+	g_return_if_fail (ctx != NULL);
+	g_return_if_fail (callback != NULL);
+
+	callback->libnm_glib_ctx = ctx;
+
+	source = g_idle_source_new ();
+	g_source_set_callback (source, libnm_glib_callback_helper, callback, NULL);
+	g_source_attach (source, callback->gmain_ctx);
+	g_source_unref (source);
+}
+
+static void
+libnm_glib_unschedule_single_callback (libnm_glib_ctx *ctx,
+                                       libnm_glib_callback *callback)
+{
+	GSource *source;
+
+	g_return_if_fail (ctx != NULL);
+	g_return_if_fail (callback != NULL);
+
+	source = g_main_context_find_source_by_user_data (callback->gmain_ctx, callback);
+	if (source)
+		g_source_destroy (source);
+}
+
+static void
+libnm_glib_call_callbacks (libnm_glib_ctx *ctx)
+{
+	GSList	*elem;
+
+	g_return_if_fail (ctx != NULL);
+
+	g_mutex_lock (ctx->callbacks_lock);
+	for (elem = ctx->callbacks; elem; elem = g_slist_next (elem))
+	{
+		libnm_glib_callback *callback = (libnm_glib_callback *)(elem->data);
+		if (callback)
+			libnm_glib_schedule_single_callback (ctx, callback);
+	}
+	g_mutex_unlock (ctx->callbacks_lock);
+}
+
+
+static void
+libnm_glib_update_state (libnm_glib_ctx *ctx,
+                         NMState state)
+{
+	libnm_glib_state	old_state;
+
+	g_return_if_fail (ctx != NULL);
+
+	old_state = ctx->nm_state;
+	switch (state)
+	{
+		case NM_STATE_CONNECTED:
+			ctx->nm_state = LIBNM_ACTIVE_NETWORK_CONNECTION;
+			break;
+
+		case NM_STATE_ASLEEP:
+		case NM_STATE_CONNECTING:
+		case NM_STATE_DISCONNECTED:
+			ctx->nm_state = LIBNM_NO_NETWORK_CONNECTION;
+			break;
+
+		case NM_STATE_UNKNOWN:
+		default:
+			ctx->nm_state = LIBNM_NO_NETWORKMANAGER;
+			break;
+	}
+
+	if (old_state != ctx->nm_state)
+		libnm_glib_call_callbacks (ctx);
+}
+
+
+static DBusHandlerResult
+libnm_glib_dbus_filter (DBusConnection *connection,
+                        DBusMessage *message,
+                        void *user_data)
+{
+	libnm_glib_ctx		*ctx = (libnm_glib_ctx *)user_data;
+	gboolean		 handled = TRUE;
+	DBusError	 	 error;
+
+	g_return_val_if_fail (ctx != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
+	g_return_val_if_fail (connection != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
+	g_return_val_if_fail (message != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
+
+	dbus_error_init (&error);
+	if (dbus_message_is_signal (message, DBUS_INTERFACE_LOCAL, "Disconnected"))
+	{
+		/* Try to reactivate our connection to dbus on the next pass through the event loop */
+		ctx->nm_state = LIBNM_NO_DBUS;
+		dbus_connection_close (ctx->dbus_con);
+		dbus_connection_unref (ctx->dbus_con);
+		ctx->dbus_con = NULL;
+		libnm_glib_schedule_dbus_watcher (ctx);
+	}
+	else if (dbus_message_is_signal (message, DBUS_INTERFACE_DBUS, "NameOwnerChanged"))
+	{
+		/* New signal for dbus 0.23... */
+		char 	*service;
+		char		*old_owner;
+		char		*new_owner;
+
+		if (    dbus_message_get_args (message, &error,
+									DBUS_TYPE_STRING, &service,
+									DBUS_TYPE_STRING, &old_owner,
+									DBUS_TYPE_STRING, &new_owner,
+									DBUS_TYPE_INVALID))
+		{
+			if (strcmp (service, NM_DBUS_SERVICE) == 0)
+			{
+				gboolean old_owner_good = (old_owner && (strlen (old_owner) > 0));
+				gboolean new_owner_good = (new_owner && (strlen (new_owner) > 0));
+
+				if (!old_owner_good && new_owner_good)	/* Equivalent to old ServiceCreated signal */
+					libnm_glib_get_nm_state (ctx);
+				else if (old_owner_good && !new_owner_good)	/* Equivalent to old ServiceDeleted signal */
+					ctx->nm_state = LIBNM_NO_NETWORKMANAGER;
+			}
+		}
+	}
+	else if (    dbus_message_is_signal (message, NM_DBUS_INTERFACE, "DeviceNowActive")
+			|| dbus_message_is_signal (message, NM_DBUS_INTERFACE, "DeviceNoLongerActive")
+			|| dbus_message_is_signal (message, NM_DBUS_INTERFACE, "DeviceActivating")
+			|| dbus_message_is_signal (message, NM_DBUS_INTERFACE, "DevicesChanged"))
+	{
+		libnm_glib_get_nm_state (ctx);
+	}
+	else if (dbus_message_is_signal (message, NM_DBUS_INTERFACE, NM_DBUS_SIGNAL_STATE_CHANGE))
+	{
+		NMState	state = NM_STATE_UNKNOWN;
+
+		dbus_message_get_args (message, &error, DBUS_TYPE_UINT32, &state, DBUS_TYPE_INVALID);
+		libnm_glib_update_state (ctx, state);
+	}
+	else
+		handled = FALSE;
+
+	if (dbus_error_is_set (&error))
+		dbus_error_free (&error);
+
+	return (handled ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
+}
+
+
+/*
+ * libnm_glib_dbus_init
+ *
+ * Initialize a connection to dbus and set up our callbacks.
+ *
+ */
+static DBusConnection *
+libnm_glib_dbus_init (gpointer *user_data,
+                      GMainContext *context)
+{
+	DBusConnection	*connection = NULL;
+	DBusError		 error;
+
+	dbus_error_init (&error);
+	connection = dbus_bus_get_private (DBUS_BUS_SYSTEM, &error);
+	if (dbus_error_is_set (&error))
+	{
+		fprintf (stderr, "%s: error, %s raised:\n %s\n\n", __func__, error.name, error.message);
+		dbus_error_free (&error);
+		return (NULL);
+	}
+	if (!connection)
+		return NULL;
+
+	if (!dbus_connection_add_filter (connection, libnm_glib_dbus_filter, user_data, NULL))
+		return (NULL);
+
+	dbus_connection_set_exit_on_disconnect (connection, FALSE);
+	dbus_connection_setup_with_g_main (connection, context);
+
+	dbus_error_init (&error);
+	dbus_bus_add_match (connection,
+				"type='signal',"
+				"interface='" DBUS_INTERFACE_DBUS "',"
+				"sender='" DBUS_SERVICE_DBUS "'",
+				&error);
+	if (dbus_error_is_set (&error))
+		dbus_error_free (&error);
+
+	dbus_error_init (&error);
+	dbus_bus_add_match (connection,
+				"type='signal',"
+				"interface='" NM_DBUS_INTERFACE "',"
+				"path='" NM_DBUS_PATH "',"
+				"sender='" NM_DBUS_SERVICE "'",
+				&error);
+	if (dbus_error_is_set (&error))
+		dbus_error_free (&error);
+
+	return (connection);
+}
+
+
+/*
+ * libnm_glib_dbus_watcher
+ *
+ * Repeatedly try to re-activate the connection to dbus.
+ *
+ */
+static gboolean
+libnm_glib_dbus_watcher (gpointer user_data)
+{
+	libnm_glib_ctx	*ctx = (libnm_glib_ctx *)user_data;
+
+	g_return_val_if_fail (ctx != NULL, FALSE);
+
+	ctx->dbus_watcher = 0;
+
+	if (!ctx->dbus_con)
+		ctx->dbus_con = libnm_glib_dbus_init ((gpointer)ctx, ctx->g_main_ctx);
+
+	if (ctx->dbus_con)
+	{
+		/* Get NM's state right away after we reconnect */
+		libnm_glib_get_nm_state (ctx);
+		ctx->dbus_watch_interval = 1000;
+	}
+	else
+	{
+		/* Wait 3 seconds longer each time we fail to reconnect to dbus,
+		 * with a maximum wait of one minute.
+		 */
+		ctx->dbus_watch_interval = MIN(ctx->dbus_watch_interval + 3000, 60000); 
+
+		/* Reschule ourselves if we _still_ don't have a connection to dbus */
+		libnm_glib_schedule_dbus_watcher (ctx);
+	}
+
+	return FALSE;
+}
+
+
+/*
+ * libnm_glib_schedule_dbus_watcher
+ *
+ * Schedule an idle handler in our main loop to repeatedly
+ * attempt to re-activate the dbus connection until connected.
+ *
+ */
+static void
+libnm_glib_schedule_dbus_watcher (libnm_glib_ctx *ctx)
+{
+	g_return_if_fail (ctx != NULL);
+
+	if (ctx->dbus_watcher == 0)
+	{
+		GSource *	source = g_timeout_source_new (ctx->dbus_watch_interval);
+		g_source_set_callback (source, libnm_glib_dbus_watcher, (gpointer) ctx, NULL);
+		ctx->dbus_watcher = g_source_attach (source, ctx->g_main_ctx);
+		g_source_unref (source);
+	}
+}
+
+
+/*
+ * libnm_glib_dbus_worker
+ *
+ * Main thread for libnm
+ *
+ */
+static gpointer
+libnm_glib_dbus_worker (gpointer user_data)
+{
+	libnm_glib_ctx	*ctx = (libnm_glib_ctx *)user_data;
+
+	g_return_val_if_fail (ctx != NULL, NULL);
+
+	/* If dbus isn't up yet, schedule an idle handler to check for dbus.
+	 * We also need a way to reconnect to dbus if the connection ever goes
+	 * down.  Should probably be done by a timeout polling dbus_connection_is_connected()
+	 * or by getting connection status out of libdbus or something.
+	 */
+	if (!(ctx->dbus_con = libnm_glib_dbus_init ((gpointer) ctx, ctx->g_main_ctx)))
+		libnm_glib_schedule_dbus_watcher (ctx);
+	else
+		libnm_glib_get_nm_state (ctx);
+
+	ctx->thread_inited = TRUE;
+	g_main_loop_run (ctx->g_main_loop);
+	ctx->thread_done = TRUE;
+
+	return NULL;
+}
+
+
+static void
+libnm_glib_ctx_free (libnm_glib_ctx *ctx)
+{
+	g_return_if_fail (ctx != NULL);
+
+	if (ctx->check == 0xDD)
+	{
+		fprintf (stderr, "%s: context %p already freed!\n", __func__, ctx);
+		return;
+	}
+
+	if (ctx->g_main_ctx)
+		g_main_context_unref (ctx->g_main_ctx);
+	if (ctx->g_main_loop)
+		g_main_loop_unref (ctx->g_main_loop);
+
+	if (ctx->dbus_con)
+	{
+		dbus_connection_close (ctx->dbus_con);
+		dbus_connection_unref (ctx->dbus_con);
+		ctx->dbus_con = NULL;
+	}
+
+	if (ctx->callbacks_lock)
+		g_mutex_free (ctx->callbacks_lock);
+
+	g_slist_foreach (ctx->callbacks, (GFunc)g_free, NULL);
+	g_slist_free (ctx->callbacks);
+
+	if (ctx->thread)
+		g_thread_join (ctx->thread);
+
+	memset (ctx, 0, sizeof (libnm_glib_ctx));
+	memset (&(ctx->check), 0xDD, sizeof (ctx->check));
+	g_free (ctx);
+}
+
+
+static libnm_glib_ctx *
+libnm_glib_ctx_new (void)
+{
+	libnm_glib_ctx *ctx = g_malloc0 (sizeof (libnm_glib_ctx));
+
+	if (!(ctx->g_main_ctx = g_main_context_new ()))
+		goto error;
+	if (!(ctx->g_main_loop = g_main_loop_new (ctx->g_main_ctx, FALSE)))
+		goto error;
+	if (!(ctx->callbacks_lock = g_mutex_new ()))
+		goto error;
+	ctx->dbus_watch_interval = 1000;
+
+	return ctx;
+
+error:
+	libnm_glib_ctx_free (ctx);
+	return NULL;
+}
+
+
+libnm_glib_ctx *
+libnm_glib_init (void)
+{
+	libnm_glib_ctx	*ctx = NULL;
+
+	g_type_init ();
+	if (!g_thread_supported ())
+		g_thread_init (NULL);
+	dbus_g_thread_init ();
+
+	if (!(ctx = libnm_glib_ctx_new ()))
+		return NULL;
+
+	ctx->thread = g_thread_create (libnm_glib_dbus_worker, ctx, TRUE, NULL);
+	if (!ctx->thread)
+		goto error;	
+
+	/* Wait until initialization of the thread */
+	while (!ctx->thread_inited)
+		g_usleep (G_USEC_PER_SEC / 20);
+
+	return ctx;
+
+error:
+	libnm_glib_ctx_free (ctx);
+	return NULL;
+}
+
+
+void
+libnm_glib_shutdown (libnm_glib_ctx *ctx)
+{
+	g_return_if_fail (ctx != NULL);
+
+	g_main_loop_quit (ctx->g_main_loop);
+	while (!ctx->thread_done)
+		g_usleep (G_USEC_PER_SEC / 20);
+
+	libnm_glib_ctx_free (ctx);
+}
+
+
+libnm_glib_state
+libnm_glib_get_network_state (const libnm_glib_ctx *ctx)
+{
+	if (!ctx)
+		return LIBNM_INVALID_CONTEXT;
+
+	return ctx->nm_state;
+}
+
+
+guint
+libnm_glib_register_callback	(libnm_glib_ctx *ctx,
+                               libnm_glib_callback_func func,
+                               gpointer user_data,
+                               GMainContext *g_main_ctx)
+{
+	libnm_glib_callback		*callback = NULL;
+
+	g_return_val_if_fail (ctx != NULL, 0);
+	g_return_val_if_fail (func != NULL, 0);
+
+	callback = g_malloc0 (sizeof (libnm_glib_callback));
+
+	callback->id = ++ (ctx->callback_id_last);
+	callback->func = func;
+	callback->gmain_ctx = g_main_ctx;
+	callback->libnm_glib_ctx = ctx;
+	callback->user_data = user_data;
+
+	g_mutex_lock (ctx->callbacks_lock);
+	ctx->callbacks = g_slist_append (ctx->callbacks, callback);
+	libnm_glib_schedule_single_callback (ctx, callback);
+	g_mutex_unlock (ctx->callbacks_lock);
+
+	return (callback->id);
+}
+
+
+void
+libnm_glib_unregister_callback (libnm_glib_ctx *ctx,
+                                guint id)
+{
+	GSList *elem;
+
+	g_return_if_fail (ctx != NULL);
+	g_return_if_fail (id > 0);
+
+	g_mutex_lock (ctx->callbacks_lock);
+	elem = ctx->callbacks;
+	while (elem)
+	{
+		libnm_glib_callback *callback = (libnm_glib_callback *)(elem->data);
+		if (callback && (callback->id == id))
+		{
+			libnm_glib_unschedule_single_callback (ctx, callback);
+			ctx->callbacks = g_slist_remove_link (ctx->callbacks, elem);
+			break;
+		}
+
+		elem = g_slist_next (elem);
+	}
+	g_mutex_unlock (ctx->callbacks_lock);
+}
diff --git a/libnm-glib/libnm_glib.h b/libnm-glib/libnm_glib.h
new file mode 100644
index 00000000..01c055d0
--- /dev/null
+++ b/libnm-glib/libnm_glib.h
@@ -0,0 +1,60 @@
+/* -*- 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) 2005 - 2008 Red Hat, Inc.
+ * Copyright (C) 2005 - 2008 Novell, Inc.
+ */
+
+#ifndef _LIB_NM_H_
+#define _LIB_NM_H_
+
+#ifndef NM_DISABLE_DEPRECATED
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef enum libnm_glib_state
+{
+	LIBNM_NO_DBUS = 0,
+	LIBNM_NO_NETWORKMANAGER,
+	LIBNM_NO_NETWORK_CONNECTION,
+	LIBNM_ACTIVE_NETWORK_CONNECTION,
+	LIBNM_INVALID_CONTEXT
+} libnm_glib_state G_GNUC_DEPRECATED;
+
+typedef struct libnm_glib_ctx libnm_glib_ctx G_GNUC_DEPRECATED;
+
+
+typedef void (*libnm_glib_callback_func) (libnm_glib_ctx *libnm_ctx, gpointer user_data) G_GNUC_DEPRECATED;
+
+
+G_GNUC_DEPRECATED libnm_glib_ctx *  libnm_glib_init                (void);
+G_GNUC_DEPRECATED void              libnm_glib_shutdown            (libnm_glib_ctx *ctx);
+
+G_GNUC_DEPRECATED libnm_glib_state  libnm_glib_get_network_state   (const libnm_glib_ctx *ctx);
+
+G_GNUC_DEPRECATED guint             libnm_glib_register_callback   (libnm_glib_ctx *ctx, libnm_glib_callback_func func, gpointer user_data, GMainContext *g_main_ctx);
+G_GNUC_DEPRECATED void              libnm_glib_unregister_callback (libnm_glib_ctx *ctx, guint id);
+
+G_END_DECLS
+
+#endif /* NM_DISABLE_DEPRECATED */
+
+#endif /* _LIB_NM_H_ */
diff --git a/libnm-glib/nm-access-point.c b/libnm-glib/nm-access-point.c
new file mode 100644
index 00000000..777e41de
--- /dev/null
+++ b/libnm-glib/nm-access-point.c
@@ -0,0 +1,597 @@
+/* -*- 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.
+ * Copyright (C) 2007 - 2008 Red Hat, Inc.
+ */
+
+#include <string.h>
+
+#include "nm-access-point.h"
+#include "NetworkManager.h"
+#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))
+
+typedef struct {
+	gboolean disposed;
+	DBusGProxy *proxy;
+
+	guint32 flags;
+	guint32 wpa_flags;
+	guint32 rsn_flags;
+	GByteArray *ssid;
+	guint32 frequency;
+	char *hw_address;
+	NM80211Mode mode;
+	guint32 max_bitrate;
+	guint8 strength;
+} NMAccessPointPrivate;
+
+enum {
+	PROP_0,
+	PROP_FLAGS,
+	PROP_WPA_FLAGS,
+	PROP_RSN_FLAGS,
+	PROP_SSID,
+	PROP_FREQUENCY,
+	PROP_HW_ADDRESS,
+	PROP_MODE,
+	PROP_MAX_BITRATE,
+	PROP_STRENGTH,
+
+	LAST_PROP
+};
+
+#define DBUS_PROP_FLAGS "Flags"
+#define DBUS_PROP_WPA_FLAGS "WpaFlags"
+#define DBUS_PROP_RSN_FLAGS "RsnFlags"
+#define DBUS_PROP_SSID "Ssid"
+#define DBUS_PROP_FREQUENCY "Frequency"
+#define DBUS_PROP_HW_ADDRESS "HwAddress"
+#define DBUS_PROP_MODE "Mode"
+#define DBUS_PROP_MAX_BITRATE "MaxBitrate"
+#define DBUS_PROP_STRENGTH "Strength"
+
+/**
+ * nm_access_point_new:
+ * @connection: the #DBusGConnection
+ * @path: the DBusobject path of the access point
+ *
+ * Creates a new #NMAccessPoint.
+ *
+ * Returns: a new access point
+ **/
+GObject *
+nm_access_point_new (DBusGConnection *connection, const char *path)
+{
+	g_return_val_if_fail (connection != NULL, NULL);
+	g_return_val_if_fail (path != NULL, NULL);
+
+	return (GObject *) g_object_new (NM_TYPE_ACCESS_POINT,
+								    NM_OBJECT_DBUS_CONNECTION, connection,
+								    NM_OBJECT_DBUS_PATH, path,
+								    NULL);
+}
+
+/**
+ * nm_access_point_get_flags:
+ * @ap: a #NMAccessPoint
+ *
+ * Gets the flags of the access point
+ *
+ * Returns: the flags
+ **/
+guint32
+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);
+	}
+
+	return priv->flags;
+}
+
+/**
+ * nm_access_point_get_wpa_flags:
+ * @ap: a #NMAccessPoint
+ *
+ * Gets the WPA flags of the access point.
+ *
+ * Returns: the WPA flags
+ **/
+guint32
+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);
+	}
+
+	return priv->wpa_flags;
+}
+
+/**
+ * nm_access_point_get_rsn_flags:
+ * @ap: a #NMAccessPoint
+ *
+ * Gets the RSN flags of the access point.
+ *
+ * Returns: the RSN flags
+ **/
+guint32
+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);
+	}
+
+	return priv->rsn_flags;
+}
+
+/**
+ * nm_access_point_get_ssid:
+ * @ap: a #NMAccessPoint
+ *
+ * Gets the SSID of the access point.
+ *
+ * Returns: the #GByteArray containing the SSID. This is the internal copy used by the
+ * access point, and must not be modified.
+ **/
+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);
+	}
+
+	return priv->ssid;
+}
+
+/**
+ * nm_access_point_get_frequency:
+ * @ap: a #NMAccessPoint
+ *
+ * Gets the frequency of the access point.
+ *
+ * Returns: the frequency
+ **/
+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);
+	}
+
+	return priv->frequency;
+}
+
+/**
+ * nm_access_point_get_hw_address:
+ * @ap: a #NMAccessPoint
+ *
+ * Gets the hardware (MAC) address of the access point.
+ *
+ * Returns: the hardware address of the access point. This is the internal string used by the
+ * access point and must not be modified.
+ **/
+const char *
+nm_access_point_get_hw_address (NMAccessPoint *ap)
+{
+	NMAccessPointPrivate *priv;
+
+	g_return_val_if_fail (NM_IS_ACCESS_POINT (ap), NULL);
+
+	priv = NM_ACCESS_POINT_GET_PRIVATE (ap);
+	if (!priv->hw_address) {
+		priv->hw_address = _nm_object_get_string_property (NM_OBJECT (ap),
+		                                                  NM_DBUS_INTERFACE_ACCESS_POINT,
+		                                                  DBUS_PROP_HW_ADDRESS);
+	}
+
+	return priv->hw_address;
+}
+
+/**
+ * nm_access_point_get_mode:
+ * @ap: a #NMAccessPoint
+ *
+ * Gets the mode of the access point.
+ *
+ * Returns: the mode
+ **/
+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);
+	}
+
+	return priv->mode;
+}
+
+/**
+ * nm_access_point_get_max_bitrate:
+ * @ap: a #NMAccessPoint
+ *
+ * Gets the maximum bit rate of the access point.
+ *
+ * Returns: the maximum bit rate
+ **/
+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);
+	}
+
+	return priv->max_bitrate;
+}
+
+/**
+ * nm_access_point_get_strength:
+ * @ap: a #NMAccessPoint
+ *
+ * Gets the current signal strength of the access point.
+ *
+ * Returns: the signal strength
+ **/
+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);
+	}
+
+	return priv->strength;
+}
+
+/************************************************************/
+
+static void
+nm_access_point_init (NMAccessPoint *ap)
+{
+}
+
+static void
+dispose (GObject *object)
+{
+	NMAccessPointPrivate *priv = NM_ACCESS_POINT_GET_PRIVATE (object);
+
+	if (priv->disposed) {
+		G_OBJECT_CLASS (nm_access_point_parent_class)->dispose (object);
+		return;
+	}
+
+	priv->disposed = TRUE;
+
+	g_object_unref (priv->proxy);
+
+	G_OBJECT_CLASS (nm_access_point_parent_class)->dispose (object);
+}
+
+static void
+finalize (GObject *object)
+{
+	NMAccessPointPrivate *priv = NM_ACCESS_POINT_GET_PRIVATE (object);
+
+	if (priv->ssid)
+		g_byte_array_free (priv->ssid, TRUE);
+
+	if (priv->hw_address)
+		g_free (priv->hw_address);
+
+	G_OBJECT_CLASS (nm_access_point_parent_class)->finalize (object);
+}
+
+static void
+get_property (GObject *object,
+              guint prop_id,
+              GValue *value,
+              GParamSpec *pspec)
+{
+	NMAccessPoint *ap = NM_ACCESS_POINT (object);
+
+	switch (prop_id) {
+	case PROP_FLAGS:
+		g_value_set_uint (value, nm_access_point_get_flags (ap));
+		break;
+	case PROP_WPA_FLAGS:
+		g_value_set_uint (value, nm_access_point_get_wpa_flags (ap));
+		break;
+	case PROP_RSN_FLAGS:
+		g_value_set_uint (value, nm_access_point_get_rsn_flags (ap));
+		break;
+	case PROP_SSID:
+		g_value_set_boxed (value, nm_access_point_get_ssid (ap));
+		break;
+	case PROP_FREQUENCY:
+		g_value_set_uint (value, nm_access_point_get_frequency (ap));
+		break;
+	case PROP_HW_ADDRESS:
+		g_value_set_string (value, nm_access_point_get_hw_address (ap));
+		break;
+	case PROP_MODE:
+		g_value_set_uint (value, nm_access_point_get_mode (ap));
+		break;
+	case PROP_MAX_BITRATE:
+		g_value_set_uint (value, nm_access_point_get_max_bitrate (ap));
+		break;
+	case PROP_STRENGTH:
+		g_value_set_uchar (value, nm_access_point_get_strength (ap));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static gboolean
+demarshal_ssid (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field)
+{
+	if (!_nm_ssid_demarshal (value, (GByteArray **) field))
+		return FALSE;
+
+	_nm_object_queue_notify (object, NM_ACCESS_POINT_SSID);
+	return TRUE;
+}
+
+static void
+register_for_property_changed (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->hw_address },
+		{ 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 },
+		{ NULL },
+	};
+
+	_nm_object_handle_properties_changed (NM_OBJECT (ap),
+	                                     priv->proxy,
+	                                     property_changed_info);
+}
+
+static GObject*
+constructor (GType type,
+			 guint n_construct_params,
+			 GObjectConstructParam *construct_params)
+{
+	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;
+
+	priv = NM_ACCESS_POINT_GET_PRIVATE (object);
+
+	priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (object),
+									    NM_DBUS_SERVICE,
+									    nm_object_get_path (object),
+									    NM_DBUS_INTERFACE_ACCESS_POINT);
+
+	register_for_property_changed (NM_ACCESS_POINT (object));
+
+	return G_OBJECT (object);
+}
+
+
+static void
+nm_access_point_class_init (NMAccessPointClass *ap_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (ap_class);
+
+	g_type_class_add_private (ap_class, sizeof (NMAccessPointPrivate));
+
+	/* virtual methods */
+	object_class->constructor = constructor;
+	object_class->get_property = get_property;
+	object_class->dispose = dispose;
+	object_class->finalize = finalize;
+
+	/* properties */
+
+	/**
+	 * NMAccessPoint:flags:
+	 *
+	 * The flags of the access point.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_FLAGS,
+		 g_param_spec_uint (NM_ACCESS_POINT_FLAGS,
+		                    "Flags",
+		                    "Flags",
+		                    NM_802_11_AP_FLAGS_NONE,
+		                    NM_802_11_AP_FLAGS_PRIVACY,
+		                    NM_802_11_AP_FLAGS_NONE,
+		                    G_PARAM_READABLE));
+
+	/**
+	 * NMAccessPoint:wpa-flags:
+	 *
+	 * The WPA flags of the access point.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_WPA_FLAGS,
+		 g_param_spec_uint (NM_ACCESS_POINT_WPA_FLAGS,
+		                    "WPA Flags",
+		                    "WPA Flags",
+		                    0, G_MAXUINT32, 0,
+		                    G_PARAM_READABLE));
+
+	/**
+	 * NMAccessPoint:rsn-flags:
+	 *
+	 * The RSN flags of the access point.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_RSN_FLAGS,
+		 g_param_spec_uint (NM_ACCESS_POINT_RSN_FLAGS,
+		                    "RSN Flags",
+		                    "RSN Flags",
+		                    0, G_MAXUINT32, 0,
+		                    G_PARAM_READABLE));
+
+	/**
+	 * NMAccessPoint:ssid:
+	 *
+	 * The SSID of the access point.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_SSID,
+		 g_param_spec_boxed (NM_ACCESS_POINT_SSID,
+						 "SSID",
+						 "SSID",
+						 NM_TYPE_SSID,
+						 G_PARAM_READABLE));
+
+	/**
+	 * NMAccessPoint:frequency:
+	 *
+	 * The frequency of the access point.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_FREQUENCY,
+		 g_param_spec_uint (NM_ACCESS_POINT_FREQUENCY,
+						"Frequency",
+						"Frequency",
+						0, 10000, 0,
+						G_PARAM_READABLE));
+
+	/**
+	 * NMAccessPoint:hw-address:
+	 *
+	 * The hardware address of the access point.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_HW_ADDRESS,
+		 g_param_spec_string (NM_ACCESS_POINT_HW_ADDRESS,
+						  "MAC Address",
+						  "Hardware MAC address",
+						  NULL,
+						  G_PARAM_READABLE));
+	
+	/**
+	 * NMAccessPoint:mode:
+	 *
+	 * The mode of the access point.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_MODE,
+		 g_param_spec_uint (NM_ACCESS_POINT_MODE,
+					    "Mode",
+					    "Mode",
+					    NM_802_11_MODE_ADHOC, NM_802_11_MODE_INFRA, NM_802_11_MODE_INFRA,
+					    G_PARAM_READABLE));
+
+	/**
+	 * NMAccessPoint:max-bitrate:
+	 *
+	 * The maximum bit rate of the access point.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_MAX_BITRATE,
+		 g_param_spec_uint (NM_ACCESS_POINT_MAX_BITRATE,
+						"Max Bitrate",
+						"Max Bitrate",
+						0, G_MAXUINT32, 0,
+						G_PARAM_READABLE));
+
+	/**
+	 * NMAccessPoint:strength:
+	 *
+	 * The current signal strength of the access point.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_STRENGTH,
+		 g_param_spec_uchar (NM_ACCESS_POINT_STRENGTH,
+						"Strength",
+						"Strength",
+						0, G_MAXUINT8, 0,
+						G_PARAM_READABLE));
+}
diff --git a/libnm-glib/nm-access-point.h b/libnm-glib/nm-access-point.h
new file mode 100644
index 00000000..77024815
--- /dev/null
+++ b/libnm-glib/nm-access-point.h
@@ -0,0 +1,83 @@
+/* -*- 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.
+ * Copyright (C) 2007 - 2008 Red Hat, Inc.
+ */
+
+#ifndef NM_ACCESS_POINT_H
+#define NM_ACCESS_POINT_H
+
+#include <glib.h>
+#include <glib-object.h>
+#include <NetworkManager.h>
+#include "nm-object.h"
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_ACCESS_POINT            (nm_access_point_get_type ())
+#define NM_ACCESS_POINT(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_ACCESS_POINT, NMAccessPoint))
+#define NM_ACCESS_POINT_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_ACCESS_POINT, NMAccessPointClass))
+#define NM_IS_ACCESS_POINT(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_ACCESS_POINT))
+#define NM_IS_ACCESS_POINT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_ACCESS_POINT))
+#define NM_ACCESS_POINT_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_ACCESS_POINT, NMAccessPointClass))
+
+#define NM_ACCESS_POINT_FLAGS       "flags"
+#define NM_ACCESS_POINT_WPA_FLAGS   "wpa-flags"
+#define NM_ACCESS_POINT_RSN_FLAGS   "rsn-flags"
+#define NM_ACCESS_POINT_SSID        "ssid"
+#define NM_ACCESS_POINT_FREQUENCY   "frequency"
+#define NM_ACCESS_POINT_HW_ADDRESS  "hw-address"
+#define NM_ACCESS_POINT_MODE        "mode"
+#define NM_ACCESS_POINT_MAX_BITRATE "max-bitrate"
+#define NM_ACCESS_POINT_STRENGTH    "strength"
+
+typedef struct {
+	NMObject parent;
+} NMAccessPoint;
+
+typedef struct {
+	NMObjectClass parent;
+
+	/* Padding for future expansion */
+	void (*_reserved1) (void);
+	void (*_reserved2) (void);
+	void (*_reserved3) (void);
+	void (*_reserved4) (void);
+	void (*_reserved5) (void);
+	void (*_reserved6) (void);
+} NMAccessPointClass;
+
+GType nm_access_point_get_type (void);
+
+GObject *nm_access_point_new (DBusGConnection *connection, const char *path);
+
+guint32      nm_access_point_get_flags        (NMAccessPoint *ap);
+guint32      nm_access_point_get_wpa_flags    (NMAccessPoint *ap);
+guint32      nm_access_point_get_rsn_flags    (NMAccessPoint *ap);
+const GByteArray * nm_access_point_get_ssid   (NMAccessPoint *ap);
+guint32      nm_access_point_get_frequency    (NMAccessPoint *ap);
+const char * nm_access_point_get_hw_address   (NMAccessPoint *ap);
+NM80211Mode  nm_access_point_get_mode         (NMAccessPoint *ap);
+guint32      nm_access_point_get_max_bitrate  (NMAccessPoint *ap);
+guint8       nm_access_point_get_strength     (NMAccessPoint *ap);
+
+G_END_DECLS
+
+#endif /* NM_ACCESS_POINT_H */
diff --git a/libnm-glib/nm-active-connection.c b/libnm-glib/nm-active-connection.c
new file mode 100644
index 00000000..2468da09
--- /dev/null
+++ b/libnm-glib/nm-active-connection.c
@@ -0,0 +1,570 @@
+/* -*- 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 - 2010 Red Hat, Inc.
+ * Copyright (C) 2008 Novell, Inc.
+ */
+
+#include <string.h>
+
+#include "NetworkManager.h"
+#include "nm-active-connection.h"
+#include "nm-object-private.h"
+#include "nm-types-private.h"
+#include "nm-device.h"
+#include "nm-connection.h"
+
+#include "nm-active-connection-bindings.h"
+
+G_DEFINE_TYPE (NMActiveConnection, nm_active_connection, NM_TYPE_OBJECT)
+
+#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;
+
+	char *service_name;
+	NMConnectionScope scope;
+	char *connection;
+	char *specific_object;
+	GPtrArray *devices;
+	NMActiveConnectionState state;
+	gboolean is_default;
+	gboolean is_default6;
+} NMActiveConnectionPrivate;
+
+enum {
+	PROP_0,
+	PROP_SERVICE_NAME,
+	PROP_CONNECTION,
+	PROP_SPECIFIC_OBJECT,
+	PROP_DEVICES,
+	PROP_STATE,
+	PROP_DEFAULT,
+	PROP_DEFAULT6,
+
+	LAST_PROP
+};
+
+#define DBUS_PROP_SERVICE_NAME "ServiceName"
+#define DBUS_PROP_CONNECTION "Connection"
+#define DBUS_PROP_SPECIFIC_OBJECT "SpecificObject"
+#define DBUS_PROP_DEVICES "Devices"
+#define DBUS_PROP_STATE "State"
+#define DBUS_PROP_DEFAULT "Default"
+#define DBUS_PROP_DEFAULT6 "Default6"
+
+/**
+ * nm_active_connection_new:
+ * @connection: the #DBusGConnection
+ * @path: the DBus object path of the device
+ *
+ * Creates a new #NMActiveConnection.
+ *
+ * Returns: a new active connection
+ **/
+GObject *
+nm_active_connection_new (DBusGConnection *connection, const char *path)
+{
+	g_return_val_if_fail (connection != NULL, NULL);
+	g_return_val_if_fail (path != NULL, NULL);
+
+	return g_object_new (NM_TYPE_ACTIVE_CONNECTION,
+						 NM_OBJECT_DBUS_CONNECTION, connection,
+						 NM_OBJECT_DBUS_PATH, path,
+						 NULL);
+}
+
+static NMConnectionScope
+get_scope_for_service_name (const char *service_name)
+{
+	if (service_name && !strcmp (service_name, NM_DBUS_SERVICE_USER_SETTINGS))
+		return NM_CONNECTION_SCOPE_USER;
+	else if (service_name && !strcmp (service_name, NM_DBUS_SERVICE_SYSTEM_SETTINGS))
+		return NM_CONNECTION_SCOPE_SYSTEM;
+
+	return NM_CONNECTION_SCOPE_UNKNOWN;
+}
+
+/**
+ * nm_active_connection_get_service_name:
+ * @connection: a #NMActiveConnection
+ *
+ * Gets the service name of the active connection.
+ *
+ * Returns: the service name. This is the internal string used by the
+ * connection, and must not be modified.
+ **/
+const char *
+nm_active_connection_get_service_name (NMActiveConnection *connection)
+{
+	NMActiveConnectionPrivate *priv;
+
+	g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), NULL);
+
+	priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (connection);
+	if (!priv->service_name) {
+		priv->service_name = _nm_object_get_string_property (NM_OBJECT (connection),
+		                                                    NM_DBUS_INTERFACE_ACTIVE_CONNECTION,
+		                                                    DBUS_PROP_SERVICE_NAME);
+		priv->scope = get_scope_for_service_name (priv->service_name);
+	}
+
+	return priv->service_name;
+}
+
+/**
+ * nm_active_connection_get_scope:
+ * @connection: a #NMActiveConnection
+ *
+ * Gets the scope of the active connection.
+ *
+ * Returns: the connection's scope
+ **/
+NMConnectionScope
+nm_active_connection_get_scope (NMActiveConnection *connection)
+{
+	g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), NM_CONNECTION_SCOPE_UNKNOWN);
+
+	/* Make sure service_name and scope are up-to-date */
+	nm_active_connection_get_service_name (connection);
+	return NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->scope;
+}
+
+/**
+ * nm_active_connection_get_connection:
+ * @connection: a #NMActiveConnection
+ *
+ * Gets the #NMConnection<!-- -->'s DBus object path.
+ *
+ * Returns: the object path of the #NMConnection inside of #NMActiveConnection.
+ * This is the internal string used by the connection, and must not be modified.
+ **/
+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);
+	}
+
+	return priv->connection;
+}
+
+/**
+ * nm_active_connection_get_specific_object:
+ * @connection: a #NMActiveConnection
+ *
+ * Gets the "specific object" used at the activation.
+ *
+ * Returns: the specific object's DBus path. This is the internal string used by the
+ * connection, and must not be modified.
+ **/
+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);
+	}
+
+	return priv->specific_object;
+}
+
+/**
+ * nm_active_connection_get_devices:
+ * @connection: a #NMActiveConnection
+ *
+ * Gets the #NMDevice<!-- -->s used for the active connections.
+ *
+ * Returns: the #GPtrArray containing #NMDevice<!-- -->s.
+ * This is the internal copy used by the connection, and must not be modified.
+ **/
+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)) {
+		return NULL;
+	}
+
+	demarshal_devices (NM_OBJECT (connection), NULL, &value, &priv->devices);
+	g_value_unset (&value);
+
+	return handle_ptr_array_return (priv->devices);
+}
+
+/**
+ * nm_active_connection_get_state:
+ * @connection: a #NMActiveConnection
+ *
+ * Gets the active connection's state.
+ *
+ * Returns: the state
+ **/
+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);
+	}
+
+	return priv->state;
+}
+
+/**
+ * nm_active_connection_get_default:
+ * @connection: a #NMActiveConnection
+ *
+ * Whether the active connection is the default IPv4 one (that is, is used for
+ * the default IPv4 route and DNS information).
+ *
+ * Returns: %TRUE if the active connection is the default IPv4 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);
+	}
+
+	return priv->is_default;
+}
+
+/**
+ * nm_active_connection_get_default6:
+ * @connection: a #NMActiveConnection
+ *
+ * Whether the active connection is the default IPv6 one (that is, is used for
+ * the default IPv6 route and DNS information).
+ *
+ * Returns: %TRUE if the active connection is the default IPv6 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);
+	}
+
+	return priv->is_default6;
+}
+
+static void
+nm_active_connection_init (NMActiveConnection *ap)
+{
+}
+
+static void
+dispose (GObject *object)
+{
+	NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (object);
+
+	if (priv->disposed) {
+		G_OBJECT_CLASS (nm_active_connection_parent_class)->dispose (object);
+		return;
+	}
+
+	priv->disposed = TRUE;
+
+	if (priv->devices) {
+		g_ptr_array_foreach (priv->devices, (GFunc) g_object_unref, NULL);
+		g_ptr_array_free (priv->devices, TRUE);
+	}
+	g_object_unref (priv->proxy);
+
+	G_OBJECT_CLASS (nm_active_connection_parent_class)->dispose (object);
+}
+
+static void
+finalize (GObject *object)
+{
+	NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (object);
+
+	g_free (priv->service_name);
+	g_free (priv->connection);
+	g_free (priv->specific_object);
+
+	G_OBJECT_CLASS (nm_active_connection_parent_class)->finalize (object);
+}
+
+static void
+get_property (GObject *object,
+              guint prop_id,
+              GValue *value,
+              GParamSpec *pspec)
+{
+	NMActiveConnection *self = NM_ACTIVE_CONNECTION (object);
+
+	switch (prop_id) {
+	case PROP_SERVICE_NAME:
+		g_value_set_string (value, nm_active_connection_get_service_name (self));
+		break;
+	case PROP_CONNECTION:
+		g_value_set_boxed (value, nm_active_connection_get_connection (self));
+		break;
+	case PROP_SPECIFIC_OBJECT:
+		g_value_set_boxed (value, nm_active_connection_get_specific_object (self));
+		break;
+	case PROP_DEVICES:
+		g_value_set_boxed (value, nm_active_connection_get_devices (self));
+		break;
+	case PROP_STATE:
+		g_value_set_uint (value, nm_active_connection_get_state (self));
+		break;
+	case PROP_DEFAULT:
+		g_value_set_boolean (value, nm_active_connection_get_default (self));
+		break;
+	case PROP_DEFAULT6:
+		g_value_set_boolean (value, nm_active_connection_get_default6 (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 gboolean
+demarshal_service (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field)
+{
+	NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (object);
+
+	if (_nm_object_demarshal_generic (object, pspec, value, field)) {
+		priv->scope = get_scope_for_service_name (priv->service_name);
+		return TRUE;
+	}
+	return FALSE;
+}
+
+static void
+register_for_property_changed (NMActiveConnection *connection)
+{
+	NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (connection);
+	const NMPropertiesChangedInfo property_changed_info[] = {
+		{ NM_ACTIVE_CONNECTION_SERVICE_NAME,        demarshal_service,           &priv->service_name },
+		{ 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 },
+		{ NULL },
+	};
+
+	_nm_object_handle_properties_changed (NM_OBJECT (connection),
+	                                     priv->proxy,
+	                                     property_changed_info);
+}
+
+static GObject*
+constructor (GType type,
+			 guint n_construct_params,
+			 GObjectConstructParam *construct_params)
+{
+	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;
+
+	priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (object);
+
+	priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (object),
+									    NM_DBUS_SERVICE,
+									    nm_object_get_path (object),
+									    NM_DBUS_INTERFACE_ACTIVE_CONNECTION);
+
+	register_for_property_changed (NM_ACTIVE_CONNECTION (object));
+
+	return G_OBJECT (object);
+}
+
+
+static void
+nm_active_connection_class_init (NMActiveConnectionClass *ap_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (ap_class);
+
+	g_type_class_add_private (ap_class, sizeof (NMActiveConnectionPrivate));
+
+	/* virtual methods */
+	object_class->constructor = constructor;
+	object_class->get_property = get_property;
+	object_class->dispose = dispose;
+	object_class->finalize = finalize;
+
+	/* properties */
+
+	/**
+	 * NMActiveConnection:service-name:
+	 *
+	 * The service name of the active connection.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_SERVICE_NAME,
+		 g_param_spec_string (NM_ACTIVE_CONNECTION_SERVICE_NAME,
+						  "Service Name",
+						  "Service Name",
+						  NULL,
+						  G_PARAM_READABLE));
+
+	/**
+	 * NMActiveConnection:connection:
+	 *
+	 * The connection's path of the active connection.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_CONNECTION,
+		 g_param_spec_string (NM_ACTIVE_CONNECTION_CONNECTION,
+						      "Connection",
+						      "Connection",
+						      NULL,
+						      G_PARAM_READABLE));
+
+	/**
+	 * NMActiveConnection:specific-object:
+	 *
+	 * The specific object's path of the active connection.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_SPECIFIC_OBJECT,
+		 g_param_spec_string (NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT,
+						      "Specific object",
+						      "Specific object",
+						      NULL,
+						      G_PARAM_READABLE));
+
+	/**
+	 * NMActiveConnection:device:
+	 *
+	 * The devices (#NMDevice) of the active connection.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_DEVICES,
+		 g_param_spec_boxed (NM_ACTIVE_CONNECTION_DEVICES,
+						       "Devices",
+						       "Devices",
+						       NM_TYPE_OBJECT_ARRAY,
+						       G_PARAM_READABLE));
+
+	/**
+	 * NMActiveConnection:state:
+	 *
+	 * The state of the active connection.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_STATE,
+		 g_param_spec_uint (NM_ACTIVE_CONNECTION_STATE,
+							  "State",
+							  "State",
+							  NM_ACTIVE_CONNECTION_STATE_UNKNOWN,
+							  NM_ACTIVE_CONNECTION_STATE_ACTIVATED,
+							  NM_ACTIVE_CONNECTION_STATE_UNKNOWN,
+							  G_PARAM_READABLE));
+
+	/**
+	 * NMActiveConnection:default:
+	 *
+	 * Whether the active connection is the default IPv4 one.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_DEFAULT,
+		 g_param_spec_boolean (NM_ACTIVE_CONNECTION_DEFAULT,
+							   "Default",
+							   "Is the default IPv4 active connection",
+							   FALSE,
+							   G_PARAM_READABLE));
+
+	/**
+	 * NMActiveConnection:default6:
+	 *
+	 * Whether the active connection is the default IPv6 one.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_DEFAULT6,
+		 g_param_spec_boolean (NM_ACTIVE_CONNECTION_DEFAULT6,
+							   "Default6",
+							   "Is the default IPv6 active connection",
+							   FALSE,
+							   G_PARAM_READABLE));
+}
diff --git a/libnm-glib/nm-active-connection.h b/libnm-glib/nm-active-connection.h
new file mode 100644
index 00000000..30edf047
--- /dev/null
+++ b/libnm-glib/nm-active-connection.h
@@ -0,0 +1,81 @@
+/* -*- 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 - 2010 Red Hat, Inc.
+ * Copyright (C) 2008 Novell, Inc.
+ */
+
+#ifndef NM_ACTIVE_CONNECTION_H
+#define NM_ACTIVE_CONNECTION_H
+
+#include <glib.h>
+#include <glib-object.h>
+#include "nm-object.h"
+#include <nm-connection.h>
+#include <NetworkManager.h>
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_ACTIVE_CONNECTION            (nm_active_connection_get_type ())
+#define NM_ACTIVE_CONNECTION(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_ACTIVE_CONNECTION, NMActiveConnection))
+#define NM_ACTIVE_CONNECTION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_ACTIVE_CONNECTION, NMActiveConnectionClass))
+#define NM_IS_ACTIVE_CONNECTION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_ACTIVE_CONNECTION))
+#define NM_IS_ACTIVE_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_ACTIVE_CONNECTION))
+#define NM_ACTIVE_CONNECTION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_ACTIVE_CONNECTION, NMActiveConnectionClass))
+
+#define NM_ACTIVE_CONNECTION_SERVICE_NAME        "service-name"
+#define NM_ACTIVE_CONNECTION_CONNECTION          "connection"
+#define NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT     "specific-object"
+#define NM_ACTIVE_CONNECTION_DEVICES             "devices"
+#define NM_ACTIVE_CONNECTION_STATE               "state"
+#define NM_ACTIVE_CONNECTION_DEFAULT             "default"
+#define NM_ACTIVE_CONNECTION_DEFAULT6            "default6"
+
+typedef struct {
+	NMObject parent;
+} NMActiveConnection;
+
+typedef struct {
+	NMObjectClass parent;
+
+	/* Padding for future expansion */
+	void (*_reserved1) (void);
+	void (*_reserved2) (void);
+	void (*_reserved3) (void);
+	void (*_reserved4) (void);
+	void (*_reserved5) (void);
+	void (*_reserved6) (void);
+} NMActiveConnectionClass;
+
+GType nm_active_connection_get_type (void);
+
+GObject *nm_active_connection_new (DBusGConnection *connection, const char *path);
+
+const char * nm_active_connection_get_service_name        (NMActiveConnection *connection);
+NMConnectionScope nm_active_connection_get_scope          (NMActiveConnection *connection);
+const char * nm_active_connection_get_connection          (NMActiveConnection *connection);
+const char * nm_active_connection_get_specific_object     (NMActiveConnection *connection);
+const GPtrArray *nm_active_connection_get_devices         (NMActiveConnection *connection);
+NMActiveConnectionState nm_active_connection_get_state    (NMActiveConnection *connection);
+gboolean nm_active_connection_get_default                 (NMActiveConnection *connection);
+gboolean nm_active_connection_get_default6                (NMActiveConnection *connection);
+
+G_END_DECLS
+
+#endif /* NM_ACTIVE_CONNECTION_H */
diff --git a/libnm-glib/nm-cdma-device.c b/libnm-glib/nm-cdma-device.c
new file mode 100644
index 00000000..31b2e99c
--- /dev/null
+++ b/libnm-glib/nm-cdma-device.c
@@ -0,0 +1,130 @@
+/* -*- 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) 2008 Red Hat, Inc.
+ * Copyright (C) 2008 Novell, Inc.
+ */
+
+#include "nm-cdma-device.h"
+#include "nm-device-private.h"
+#include "nm-object-private.h"
+
+G_DEFINE_TYPE (NMCdmaDevice, nm_cdma_device, NM_TYPE_SERIAL_DEVICE)
+
+#define NM_CDMA_DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_CDMA_DEVICE, NMCdmaDevicePrivate))
+
+typedef struct {
+	DBusGProxy *proxy;
+
+	gboolean disposed;
+} NMCdmaDevicePrivate;
+
+static void
+nm_cdma_device_init (NMCdmaDevice *device)
+{
+}
+
+static void
+register_for_property_changed (NMCdmaDevice *device)
+{
+	NMCdmaDevicePrivate *priv = NM_CDMA_DEVICE_GET_PRIVATE (device);
+	const NMPropertiesChangedInfo property_changed_info[] = {
+		{ NULL },
+	};
+
+	_nm_object_handle_properties_changed (NM_OBJECT (device),
+	                                     priv->proxy,
+	                                     property_changed_info);
+}
+
+static GObject*
+constructor (GType type,
+             guint n_construct_params,
+             GObjectConstructParam *construct_params)
+{
+	GObject *object;
+	NMCdmaDevicePrivate *priv;
+
+	object = G_OBJECT_CLASS (nm_cdma_device_parent_class)->constructor (type,
+														  n_construct_params,
+														  construct_params);
+	if (!object)
+		return NULL;
+
+	priv = NM_CDMA_DEVICE_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_CDMA_DEVICE);
+
+	register_for_property_changed (NM_CDMA_DEVICE (object));
+
+	return object;
+}
+
+static void
+dispose (GObject *object)
+{
+	NMCdmaDevicePrivate *priv = NM_CDMA_DEVICE_GET_PRIVATE (object);
+
+	if (priv->disposed) {
+		G_OBJECT_CLASS (nm_cdma_device_parent_class)->dispose (object);
+		return;
+	}
+
+	priv->disposed = TRUE;
+
+	g_object_unref (priv->proxy);
+
+	G_OBJECT_CLASS (nm_cdma_device_parent_class)->dispose (object);
+}
+
+static void
+nm_cdma_device_class_init (NMCdmaDeviceClass *device_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (device_class);
+
+	g_type_class_add_private (device_class, sizeof (NMCdmaDevicePrivate));
+
+	/* virtual methods */
+	object_class->constructor = constructor;
+	object_class->dispose = dispose;
+}
+
+/**
+ * nm_cdma_device_new:
+ * @connection: the #DBusGConnection
+ * @path: the DBus object path of the device
+ *
+ * Creates a new #NMCdmaDevice.
+ *
+ * Returns: a new device
+ **/
+GObject *
+nm_cdma_device_new (DBusGConnection *connection, const char *path)
+{
+	g_return_val_if_fail (connection != NULL, NULL);
+	g_return_val_if_fail (path != NULL, NULL);
+
+	return g_object_new (NM_TYPE_CDMA_DEVICE,
+	                     NM_OBJECT_DBUS_CONNECTION, connection,
+	                     NM_OBJECT_DBUS_PATH, path,
+	                     NULL);
+}
diff --git a/libnm-glib/nm-cdma-device.h b/libnm-glib/nm-cdma-device.h
new file mode 100644
index 00000000..f40124ac
--- /dev/null
+++ b/libnm-glib/nm-cdma-device.h
@@ -0,0 +1,60 @@
+/* -*- 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) 2008 Red Hat, Inc.
+ * Copyright (C) 2008 Novell, Inc.
+ */
+
+#ifndef NM_CDMA_DEVICE_H
+#define NM_CDMA_DEVICE_H
+
+#include "nm-serial-device.h"
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_CDMA_DEVICE            (nm_cdma_device_get_type ())
+#define NM_CDMA_DEVICE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_CDMA_DEVICE, NMCdmaDevice))
+#define NM_CDMA_DEVICE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_CDMA_DEVICE, NMCdmaDeviceClass))
+#define NM_IS_CDMA_DEVICE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_CDMA_DEVICE))
+#define NM_IS_CDMA_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_CDMA_DEVICE))
+#define NM_CDMA_DEVICE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_CDMA_DEVICE, NMCdmaDeviceClass))
+
+typedef struct {
+	NMSerialDevice parent;
+} NMCdmaDevice;
+
+typedef struct {
+	NMSerialDeviceClass parent;
+
+	/* Padding for future expansion */
+	void (*_reserved1) (void);
+	void (*_reserved2) (void);
+	void (*_reserved3) (void);
+	void (*_reserved4) (void);
+	void (*_reserved5) (void);
+	void (*_reserved6) (void);
+} NMCdmaDeviceClass;
+
+GType        nm_cdma_device_get_type (void);
+
+GObject *nm_cdma_device_new (DBusGConnection *connection, const char *path);
+
+G_END_DECLS
+
+#endif /* NM_CDMA_DEVICE_H */
diff --git a/libnm-glib/nm-client.c b/libnm-glib/nm-client.c
new file mode 100644
index 00000000..00d729a2
--- /dev/null
+++ b/libnm-glib/nm-client.c
@@ -0,0 +1,1160 @@
+/* -*- 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.
+ * Copyright (C) 2007 - 2010 Red Hat, Inc.
+ */
+
+#include <dbus/dbus-glib.h>
+#include <string.h>
+#include <nm-utils.h>
+
+#include "nm-client.h"
+#include "nm-device-ethernet.h"
+#include "nm-device-wifi.h"
+#include "nm-gsm-device.h"
+#include "nm-cdma-device.h"
+#include "nm-device-private.h"
+#include "nm-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"
+
+void _nm_device_wifi_set_wireless_enabled (NMDeviceWifi *device, gboolean enabled);
+
+
+G_DEFINE_TYPE (NMClient, nm_client, NM_TYPE_OBJECT)
+
+#define NM_CLIENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_CLIENT, NMClientPrivate))
+
+typedef struct {
+	gboolean disposed;
+
+	DBusGProxy *client_proxy;
+	DBusGProxy *bus_proxy;
+	gboolean manager_running;
+	NMState state;
+	GPtrArray *devices;
+	GPtrArray *active_connections;
+
+	gboolean have_networking_enabled;
+	gboolean networking_enabled;
+	gboolean wireless_enabled;
+	gboolean wireless_hw_enabled;
+
+	gboolean wwan_enabled;
+	gboolean wwan_hw_enabled;
+} NMClientPrivate;
+
+enum {
+	PROP_0,
+	PROP_STATE,
+	PROP_MANAGER_RUNNING,
+	PROP_NETWORKING_ENABLED,
+	PROP_WIRELESS_ENABLED,
+	PROP_WIRELESS_HARDWARE_ENABLED,
+	PROP_WWAN_ENABLED,
+	PROP_WWAN_HARDWARE_ENABLED,
+	PROP_ACTIVE_CONNECTIONS,
+
+	LAST_PROP
+};
+
+enum {
+	DEVICE_ADDED,
+	DEVICE_REMOVED,
+
+	LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static void proxy_name_owner_changed (DBusGProxy *proxy,
+									  const char *name,
+									  const char *old_owner,
+									  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
+nm_client_init (NMClient *client)
+{
+	NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client);
+
+	priv->state = NM_STATE_UNKNOWN;
+
+	g_signal_connect (client,
+	                  "notify::" NM_CLIENT_NETWORKING_ENABLED,
+	                  G_CALLBACK (handle_net_enabled_changed),
+	                  client);
+}
+
+static void
+poke_wireless_devices_with_rf_status (NMClient *client)
+{
+	NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client);
+	int i;
+
+	for (i = 0; priv->devices && (i < priv->devices->len); i++) {
+		NMDevice *device = g_ptr_array_index (priv->devices, i);
+
+		if (NM_IS_DEVICE_WIFI (device))
+			_nm_device_wifi_set_wireless_enabled (NM_DEVICE_WIFI (device), priv->wireless_enabled);
+	}
+}
+
+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");
+	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");
+	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");
+	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");
+	}
+
+	if (val != priv->wwan_enabled) {
+		priv->wwan_enabled = val;
+		if (notify)
+			_nm_object_queue_notify (NM_OBJECT (client), NM_CLIENT_WWAN_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_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_ACTIVE_CONNECTIONS,        demarshal_active_connections, &priv->active_connections },
+		{ NULL },
+	};
+
+	_nm_object_handle_properties_changed (NM_OBJECT (client),
+	                                     priv->client_proxy,
+	                                     property_changed_info);
+}
+
+static GObject*
+constructor (GType type,
+		   guint n_construct_params,
+		   GObjectConstructParam *construct_params)
+{
+	NMObject *object;
+	DBusGConnection *connection;
+	NMClientPrivate *priv;
+	GError *err = NULL;
+
+	object = (NMObject *) G_OBJECT_CLASS (nm_client_parent_class)->constructor (type,
+																 n_construct_params,
+																 construct_params);
+	if (!object)
+		return NULL;
+
+	priv = NM_CLIENT_GET_PRIVATE (object);
+	connection = nm_object_get_connection (object);
+
+	priv->client_proxy = dbus_g_proxy_new_for_name (connection,
+										   NM_DBUS_SERVICE,
+										   nm_object_get_path (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);
+
+	priv->bus_proxy = dbus_g_proxy_new_for_name (connection,
+										"org.freedesktop.DBus",
+										"/org/freedesktop/DBus",
+										"org.freedesktop.DBus");
+
+	dbus_g_proxy_add_signal (priv->bus_proxy, "NameOwnerChanged",
+						G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
+						G_TYPE_INVALID);
+	dbus_g_proxy_connect_signal (priv->bus_proxy,
+						    "NameOwnerChanged",
+						    G_CALLBACK (proxy_name_owner_changed),
+						    object, NULL);
+
+	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);
+	}
+
+	if (priv->manager_running) {
+		update_wireless_status (NM_CLIENT (object), FALSE);
+		update_wwan_status (NM_CLIENT (object), FALSE);
+		nm_client_get_state (NM_CLIENT (object));
+	}
+
+	g_signal_connect (G_OBJECT (object), "notify::" NM_CLIENT_WIRELESS_ENABLED,
+	                  G_CALLBACK (wireless_enabled_cb), NULL);
+
+	return G_OBJECT (object);
+}
+
+static void
+free_object_array (GPtrArray **array)
+{
+	g_return_if_fail (array != NULL);
+
+	if (*array) {
+		g_ptr_array_foreach (*array, (GFunc) g_object_unref, NULL);
+		g_ptr_array_free (*array, TRUE);
+		*array = NULL;
+	}
+}
+
+static void
+dispose (GObject *object)
+{
+	NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (object);
+
+	if (priv->disposed) {
+		G_OBJECT_CLASS (nm_client_parent_class)->dispose (object);
+		return;
+	}
+
+	g_object_unref (priv->client_proxy);
+	g_object_unref (priv->bus_proxy);
+
+	free_object_array (&priv->devices);
+	free_object_array (&priv->active_connections);
+
+	G_OBJECT_CLASS (nm_client_parent_class)->dispose (object);
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+		    const GValue *value, GParamSpec *pspec)
+{
+	NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (object);
+	gboolean b;
+
+	switch (prop_id) {
+	case PROP_WIRELESS_ENABLED:
+		b = g_value_get_boolean (value);
+		if (priv->wireless_enabled != b) {
+			priv->wireless_enabled = b;
+			_nm_object_queue_notify (NM_OBJECT (object), NM_CLIENT_WIRELESS_ENABLED);
+		}
+		break;
+	case PROP_WIRELESS_HARDWARE_ENABLED:
+		b = g_value_get_boolean (value);
+		if (priv->wireless_hw_enabled != b) {
+			priv->wireless_hw_enabled = b;
+			_nm_object_queue_notify (NM_OBJECT (object), NM_CLIENT_WIRELESS_HARDWARE_ENABLED);
+		}
+		break;
+	case PROP_WWAN_ENABLED:
+		b = g_value_get_boolean (value);
+		if (priv->wwan_enabled != b) {
+			priv->wwan_enabled = b;
+			_nm_object_queue_notify (NM_OBJECT (object), NM_CLIENT_WWAN_ENABLED);
+		}
+		break;
+	case PROP_WWAN_HARDWARE_ENABLED:
+		b = g_value_get_boolean (value);
+		if (priv->wwan_hw_enabled != b) {
+			priv->wwan_hw_enabled = b;
+			_nm_object_queue_notify (NM_OBJECT (object), NM_CLIENT_WWAN_HARDWARE_ENABLED);
+		}
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+get_property (GObject *object,
+              guint prop_id,
+              GValue *value,
+              GParamSpec *pspec)
+{
+	NMClient *self = NM_CLIENT (object);
+	NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self);
+
+	switch (prop_id) {
+	case PROP_STATE:
+		g_value_set_uint (value, nm_client_get_state (self));
+		break;
+	case PROP_MANAGER_RUNNING:
+		g_value_set_boolean (value, priv->manager_running);
+		break;
+	case PROP_NETWORKING_ENABLED:
+		g_value_set_boolean (value, priv->networking_enabled);
+		break;
+	case PROP_WIRELESS_ENABLED:
+		g_value_set_boolean (value, priv->wireless_enabled);
+		break;
+	case PROP_WIRELESS_HARDWARE_ENABLED:
+		g_value_set_boolean (value, priv->wireless_hw_enabled);
+		break;
+	case PROP_WWAN_ENABLED:
+		g_value_set_boolean (value, priv->wwan_enabled);
+		break;
+	case PROP_WWAN_HARDWARE_ENABLED:
+		g_value_set_boolean (value, priv->wwan_hw_enabled);
+		break;
+	case PROP_ACTIVE_CONNECTIONS:
+		g_value_set_boxed (value, nm_client_get_active_connections (self));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+nm_client_class_init (NMClientClass *client_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (client_class);
+
+	g_type_class_add_private (client_class, sizeof (NMClientPrivate));
+
+	/* virtual methods */
+	object_class->constructor = constructor;
+	object_class->set_property = set_property;
+	object_class->get_property = get_property;
+	object_class->dispose = dispose;
+
+	/* properties */
+
+	/**
+	 * NMClient:state:
+	 *
+	 * The current daemon state.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_STATE,
+		 g_param_spec_uint (NM_CLIENT_STATE,
+						    "State",
+						    "NetworkManager state",
+						    NM_STATE_UNKNOWN, NM_STATE_DISCONNECTED, NM_STATE_UNKNOWN,
+						    G_PARAM_READABLE));
+
+	/**
+	 * NMClient::manager-running:
+	 *
+	 * Whether the daemon is running.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_MANAGER_RUNNING,
+		 g_param_spec_boolean (NM_CLIENT_MANAGER_RUNNING,
+						       "ManagerRunning",
+						       "Whether NetworkManager is running",
+						       FALSE,
+						       G_PARAM_READABLE));
+
+	/**
+	 * NMClient::networking-enabled:
+	 *
+	 * Whether networking is enabled.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_NETWORKING_ENABLED,
+		 g_param_spec_boolean (NM_CLIENT_NETWORKING_ENABLED,
+						   "NetworkingEnabled",
+						   "Is networking enabled",
+						   TRUE,
+						   G_PARAM_READABLE));
+
+	/**
+	 * NMClient::wireless-enabled:
+	 *
+	 * Whether wireless is enabled.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_WIRELESS_ENABLED,
+		 g_param_spec_boolean (NM_CLIENT_WIRELESS_ENABLED,
+						   "WirelessEnabled",
+						   "Is wireless enabled",
+						   TRUE,
+						   G_PARAM_READWRITE));
+
+	/**
+	 * NMClient::wireless-hardware-enabled:
+	 *
+	 * Whether the wireless hardware is enabled.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_WIRELESS_HARDWARE_ENABLED,
+		 g_param_spec_boolean (NM_CLIENT_WIRELESS_HARDWARE_ENABLED,
+						   "WirelessHardwareEnabled",
+						   "Is wireless hardware enabled",
+						   TRUE,
+						   G_PARAM_READABLE));
+
+	/**
+	 * NMClient::wwan-enabled:
+	 *
+	 * Whether WWAN functionality is enabled.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_WWAN_ENABLED,
+		 g_param_spec_boolean (NM_CLIENT_WWAN_ENABLED,
+		                       "WwanEnabled",
+		                       "Is WWAN enabled",
+		                       TRUE,
+		                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+	/**
+	 * NMClient::wwan-hardware-enabled:
+	 *
+	 * Whether the WWAN hardware is enabled.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_WWAN_HARDWARE_ENABLED,
+		 g_param_spec_boolean (NM_CLIENT_WWAN_HARDWARE_ENABLED,
+		                       "WwanHardwareEnabled",
+		                       "Is WWAN hardware enabled",
+		                       TRUE,
+		                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+	/**
+	 * NMClient::active-connections:
+	 *
+	 * The active connections.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_ACTIVE_CONNECTIONS,
+		 g_param_spec_boxed (NM_CLIENT_ACTIVE_CONNECTIONS,
+						   "Active connections",
+						   "Active connections",
+						   NM_TYPE_OBJECT_ARRAY,
+						   G_PARAM_READABLE));
+
+	/* signals */
+
+	/**
+	 * NMClient::device-added:
+	 * @client: the client that received the signal
+	 * @device: the new device
+	 *
+	 * Notifies that a #NMDevice is added.
+	 **/
+	signals[DEVICE_ADDED] =
+		g_signal_new ("device-added",
+					  G_OBJECT_CLASS_TYPE (object_class),
+					  G_SIGNAL_RUN_FIRST,
+					  G_STRUCT_OFFSET (NMClientClass, device_added),
+					  NULL, NULL,
+					  g_cclosure_marshal_VOID__OBJECT,
+					  G_TYPE_NONE, 1,
+					  G_TYPE_OBJECT);
+
+	/**
+	 * NMClient::device-removed:
+	 * @widget: the client that received the signal
+	 * @device: the removed device
+	 *
+	 * Notifies that a #NMDevice is removed.
+	 **/
+	signals[DEVICE_REMOVED] =
+		g_signal_new ("device-removed",
+					  G_OBJECT_CLASS_TYPE (object_class),
+					  G_SIGNAL_RUN_FIRST,
+					  G_STRUCT_OFFSET (NMClientClass, device_removed),
+					  NULL, NULL,
+					  g_cclosure_marshal_VOID__OBJECT,
+					  G_TYPE_NONE, 1,
+					  G_TYPE_OBJECT);
+}
+
+/**
+ * nm_client_new:
+ *
+ * Creates a new #NMClient.
+ *
+ * Returns: a new #NMClient
+ **/
+NMClient *
+nm_client_new (void)
+{
+	DBusGConnection *connection;
+	GError *err = NULL;
+
+	connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &err);
+	if (!connection) {
+		g_warning ("Couldn't connect to system bus: %s", err->message);
+		g_error_free (err);
+		return NULL;
+	}
+
+	return (NMClient *) g_object_new (NM_TYPE_CLIENT,
+									  NM_OBJECT_DBUS_CONNECTION, connection,
+									  NM_OBJECT_DBUS_PATH, NM_DBUS_PATH,
+									  NULL);
+}
+
+static void
+proxy_name_owner_changed (DBusGProxy *proxy,
+						  const char *name,
+						  const char *old_owner,
+						  const char *new_owner,
+						  gpointer user_data)
+{
+	NMClient *client = NM_CLIENT (user_data);
+	NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client);
+	gboolean old_good = (old_owner && strlen (old_owner));
+	gboolean new_good = (new_owner && strlen (new_owner));
+	gboolean new_running = FALSE;
+
+	if (!name || strcmp (name, NM_DBUS_SERVICE))
+		return;
+
+	if (!old_good && new_good)
+		new_running = TRUE;
+	else if (old_good && !new_good)
+		new_running = FALSE;
+
+	if (new_running == priv->manager_running)
+		return;
+
+	priv->manager_running = new_running;
+	if (!priv->manager_running) {
+		priv->state = NM_STATE_UNKNOWN;
+		_nm_object_queue_notify (NM_OBJECT (client), NM_CLIENT_MANAGER_RUNNING);
+		poke_wireless_devices_with_rf_status (client);
+		free_object_array (&priv->devices);
+		free_object_array (&priv->active_connections);
+		priv->wireless_enabled = FALSE;
+		priv->wireless_hw_enabled = FALSE;
+		priv->wwan_enabled = FALSE;
+		priv->wwan_hw_enabled = FALSE;
+	} else {
+		_nm_object_queue_notify (NM_OBJECT (client), NM_CLIENT_MANAGER_RUNNING);
+		update_wireless_status (client, TRUE);
+		update_wwan_status (client, TRUE);
+	}
+}
+
+static void
+client_device_added_proxy (DBusGProxy *proxy, char *path, gpointer user_data)
+{
+	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, g_object_ref (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);
+}
+
+static void
+client_device_removed_proxy (DBusGProxy *proxy, char *path, gpointer user_data)
+{
+	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);
+	}
+}
+
+/**
+ * nm_client_get_devices:
+ * @client: a #NMClient
+ *
+ * Gets all the detected devices.
+ *
+ * Returns: a #GPtrArray containing all the #NMDevice<!-- -->s.
+ * The returned array is owned by the client and should not be modified.
+ **/
+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);
+
+	return handle_ptr_array_return (priv->devices);
+}
+
+/**
+ * nm_client_get_device_by_path:
+ * @client: a #NMClient
+ * @object_path: the object path to search for
+ *
+ * Gets a #NMDevice from a #NMClient.
+ *
+ * Returns: the #NMDevice for the given @object_path or %NULL if none is found.
+ **/
+NMDevice *
+nm_client_get_device_by_path (NMClient *client, const char *object_path)
+{
+	const GPtrArray *devices;
+	int i;
+	NMDevice *device = NULL;
+
+	g_return_val_if_fail (NM_IS_CLIENT (client), NULL);
+	g_return_val_if_fail (object_path, NULL);
+
+	devices = nm_client_get_devices (client);
+	if (!devices)
+		return NULL;
+
+	for (i = 0; i < devices->len; i++) {
+		NMDevice *candidate = g_ptr_array_index (devices, i);
+		if (!strcmp (nm_object_get_path (NM_OBJECT (candidate)), object_path)) {
+			device = candidate;
+			break;
+		}
+	}
+
+	return device;
+}
+
+typedef struct {
+	NMClientActivateDeviceFn fn;
+	gpointer user_data;
+} ActivateDeviceInfo;
+
+static void
+activate_cb (DBusGProxy *proxy,
+             char *path,
+             GError *error,
+             gpointer user_data)
+{
+	ActivateDeviceInfo *info = (ActivateDeviceInfo *) user_data;
+
+	if (info->fn)
+		info->fn (info->user_data, path, error);
+	else if (error)
+		nm_warning ("Device activation failed: (%d) %s", error->code, error->message);
+
+	g_slice_free (ActivateDeviceInfo, info);
+}
+
+/**
+ * nm_client_activate_connection:
+ * @client: a #NMClient
+ * @service_name: the connection's service name
+ * @connection_path: the connection's DBus path
+ * @device: the #NMDevice
+ * @specific_object: the device specific object (currently used only for
+ * activating wireless devices and should be the #NMAccessPoint<!-- -->'s path.
+ * @callback: the function to call when the call is done
+ * @user_data: user data to pass to the callback function
+ *
+ * Activates a connection with the given #NMDevice.
+ **/
+void
+nm_client_activate_connection (NMClient *client,
+					  const char *service_name,
+					  const char *connection_path,
+					  NMDevice *device,
+					  const char *specific_object,
+					  NMClientActivateDeviceFn callback,
+					  gpointer user_data)
+{
+	ActivateDeviceInfo *info;
+	char *internal_so = (char *) specific_object;
+
+	g_return_if_fail (NM_IS_CLIENT (client));
+	g_return_if_fail (NM_IS_DEVICE (device));
+	g_return_if_fail (service_name != NULL);
+	g_return_if_fail (connection_path != NULL);
+
+	/* NULL specific object must be translated into "/" because D-Bus does
+	 * not have any idea of NULL object paths.
+	 */
+	if (internal_so == NULL)
+		internal_so = "/";
+
+	info = g_slice_new (ActivateDeviceInfo);
+	info->fn = callback;
+	info->user_data = user_data;
+
+	org_freedesktop_NetworkManager_activate_connection_async (NM_CLIENT_GET_PRIVATE (client)->client_proxy,
+											    service_name,
+											    connection_path,
+											    nm_object_get_path (NM_OBJECT (device)),
+											    internal_so,
+											    activate_cb,
+											    info);
+}
+
+/**
+ * nm_client_deactivate_connection:
+ * @client: a #NMClient
+ * @active: the #NMActiveConnection to deactivate
+ *
+ * Deactivates an active #NMActiveConnection.
+ **/
+void
+nm_client_deactivate_connection (NMClient *client, NMActiveConnection *active)
+{
+	NMClientPrivate *priv;
+	const char *path;
+	GError *error = NULL;
+
+	g_return_if_fail (NM_IS_CLIENT (client));
+	g_return_if_fail (NM_IS_ACTIVE_CONNECTION (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)) {
+		g_warning ("Could not deactivate connection '%s': %s", path, error->message);
+		g_error_free (error);
+	}
+}
+
+/**
+ * nm_client_get_active_connections:
+ * @client: a #NMClient
+ *
+ * Gets the active connections.
+ *
+ * Returns: a #GPtrArray containing all the active #NMActiveConnection<!-- -->s.
+ * The returned array is owned by the client and should not be modified.
+ **/
+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);
+
+	if (!priv->manager_running)
+		return NULL;
+
+	if (!_nm_object_get_property (NM_OBJECT (client),
+	                             "org.freedesktop.NetworkManager",
+	                             "ActiveConnections",
+	                             &value)) {
+		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);
+}
+
+/**
+ * nm_client_wireless_get_enabled:
+ * @client: a #NMClient
+ *
+ * Determines whether the wireless is enabled.
+ *
+ * Returns: %TRUE if wireless is enabled
+ **/
+gboolean
+nm_client_wireless_get_enabled (NMClient *client)
+{
+	g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
+
+	return NM_CLIENT_GET_PRIVATE (client)->wireless_enabled;
+}
+
+/**
+ * nm_client_wireless_set_enabled:
+ * @client: a #NMClient
+ * @enabled: %TRUE to enable wireless
+ *
+ * Enables or disables wireless devices.
+ **/
+void
+nm_client_wireless_set_enabled (NMClient *client, gboolean enabled)
+{
+	GValue value = {0,};
+
+	g_return_if_fail (NM_IS_CLIENT (client));
+
+	g_value_init (&value, G_TYPE_BOOLEAN);
+	g_value_set_boolean (&value, enabled);
+
+	_nm_object_set_property (NM_OBJECT (client),
+					    NM_DBUS_INTERFACE,
+					    "WirelessEnabled",
+					    &value);
+}
+
+/**
+ * nm_client_wireless_hardware_get_enabled:
+ * @client: a #NMClient
+ *
+ * Determines whether the wireless hardware is enabled.
+ *
+ * Returns: %TRUE if the wireless hardware is enabled
+ **/
+gboolean
+nm_client_wireless_hardware_get_enabled (NMClient *client)
+{
+	g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
+
+	return NM_CLIENT_GET_PRIVATE (client)->wireless_hw_enabled;
+}
+
+/**
+ * nm_client_wwan_get_enabled:
+ * @client: a #NMClient
+ *
+ * Determines whether WWAN is enabled.
+ *
+ * Returns: %TRUE if WWAN is enabled
+ **/
+gboolean
+nm_client_wwan_get_enabled (NMClient *client)
+{
+	g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
+
+	return NM_CLIENT_GET_PRIVATE (client)->wwan_enabled;
+}
+
+/**
+ * nm_client_wwan_set_enabled:
+ * @client: a #NMClient
+ * @enabled: %TRUE to enable WWAN
+ *
+ * Enables or disables WWAN devices.
+ **/
+void
+nm_client_wwan_set_enabled (NMClient *client, gboolean enabled)
+{
+	GValue value = {0,};
+
+	g_return_if_fail (NM_IS_CLIENT (client));
+
+	g_value_init (&value, G_TYPE_BOOLEAN);
+	g_value_set_boolean (&value, enabled);
+
+	_nm_object_set_property (NM_OBJECT (client),
+	                         NM_DBUS_INTERFACE,
+	                         "WwanEnabled",
+	                         &value);
+}
+
+/**
+ * nm_client_wwan_hardware_get_enabled:
+ * @client: a #NMClient
+ *
+ * Determines whether the WWAN hardware is enabled.
+ *
+ * Returns: %TRUE if the WWAN hardware is enabled
+ **/
+gboolean
+nm_client_wwan_hardware_get_enabled (NMClient *client)
+{
+	g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
+
+	return NM_CLIENT_GET_PRIVATE (client)->wwan_hw_enabled;
+}
+
+/**
+ * nm_client_get_state:
+ * @client: a #NMClient
+ *
+ * Gets the current daemon state.
+ *
+ * Returns: the current %NMState
+ **/
+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");
+
+	return priv->state;
+}
+
+/**
+ * nm_client_networking_get_enabled:
+ * @client: a #NMClient
+ *
+ * Whether networking is enabled or disabled.
+ *
+ * Returns: %TRUE if networking is disabled, %FALSE if networking is enabled
+ **/
+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");
+			priv->have_networking_enabled = TRUE;
+		}
+	}
+
+	return priv->networking_enabled;
+}
+
+/**
+ * nm_client_networking_set_enabled:
+ * @client: a #NMClient
+ * @enabled: %TRUE to set networking enabled, %FALSE to set networking disabled
+ *
+ * Enables or disables networking.  When networking is disabled, all controlled
+ * interfaces are disconnected and deactivated.  When networking is enabled,
+ * all controlled interfaces are available for activation.
+ **/
+void
+nm_client_networking_set_enabled (NMClient *client, gboolean enable)
+{
+	GError *err = NULL;
+
+	g_return_if_fail (NM_IS_CLIENT (client));
+
+	if (!org_freedesktop_NetworkManager_enable (NM_CLIENT_GET_PRIVATE (client)->client_proxy, enable, &err)) {
+		g_warning ("Error enabling/disabling networking: %s", err->message);
+		g_error_free (err);
+	}
+}
+
+/**
+ * nm_client_sleep:
+ * @client: a #NMClient
+ * @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_networking_set_enabled (client, !sleep);
+}
+
+/**
+ * nm_client_get_manager_running:
+ * @client: a #NMClient
+ *
+ * Determines whether the daemon is running.
+ *
+ * Returns: %TRUE if the daemon is running
+ **/
+gboolean
+nm_client_get_manager_running (NMClient *client)
+{
+	g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
+
+	return NM_CLIENT_GET_PRIVATE (client)->manager_running;
+}
+
diff --git a/libnm-glib/nm-client.h b/libnm-glib/nm-client.h
new file mode 100644
index 00000000..6b912e05
--- /dev/null
+++ b/libnm-glib/nm-client.h
@@ -0,0 +1,110 @@
+/* -*- 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.
+ * Copyright (C) 2007 - 2010 Red Hat, Inc.
+ */
+
+#ifndef NM_CLIENT_H
+#define NM_CLIENT_H
+
+#include <glib.h>
+#include <glib-object.h>
+#include <dbus/dbus-glib.h>
+#include <NetworkManager.h>
+#include "nm-object.h"
+#include "nm-device.h"
+#include "nm-active-connection.h"
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_CLIENT            (nm_client_get_type ())
+#define NM_CLIENT(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_CLIENT, NMClient))
+#define NM_CLIENT_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_CLIENT, NMClientClass))
+#define NM_IS_CLIENT(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_CLIENT))
+#define NM_IS_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_CLIENT))
+#define NM_CLIENT_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_CLIENT, NMClientClass))
+
+#define NM_CLIENT_STATE "state"
+#define NM_CLIENT_MANAGER_RUNNING "manager-running"
+#define NM_CLIENT_NETWORKING_ENABLED "networking-enabled"
+#define NM_CLIENT_WIRELESS_ENABLED "wireless-enabled"
+#define NM_CLIENT_WIRELESS_HARDWARE_ENABLED "wireless-hardware-enabled"
+#define NM_CLIENT_WWAN_ENABLED "wwan-enabled"
+#define NM_CLIENT_WWAN_HARDWARE_ENABLED "wwan-hardware-enabled"
+#define NM_CLIENT_ACTIVE_CONNECTIONS "active-connections"
+
+typedef struct {
+	NMObject parent;
+} NMClient;
+
+typedef struct {
+	NMObjectClass parent;
+
+	/* Signals */
+	void (*device_added) (NMClient *client, NMDevice *device);
+	void (*device_removed) (NMClient *client, NMDevice *device);
+
+	/* Padding for future expansion */
+	void (*_reserved1) (void);
+	void (*_reserved2) (void);
+	void (*_reserved3) (void);
+	void (*_reserved4) (void);
+	void (*_reserved5) (void);
+	void (*_reserved6) (void);
+} NMClientClass;
+
+GType nm_client_get_type (void);
+
+NMClient *nm_client_new (void);
+
+const GPtrArray *nm_client_get_devices    (NMClient *client);
+NMDevice *nm_client_get_device_by_path    (NMClient *client, const char *object_path);
+
+typedef void (*NMClientActivateDeviceFn) (gpointer user_data, const char *object_path, GError *error);
+
+void nm_client_activate_connection (NMClient *client,
+						  const char *service_name,
+						  const char *connection_path,
+						  NMDevice *device,
+						  const char *specific_object,
+						  NMClientActivateDeviceFn callback,
+						  gpointer user_data);
+
+void nm_client_deactivate_connection (NMClient *client, NMActiveConnection *active);
+
+gboolean  nm_client_networking_get_enabled (NMClient *client);
+void      nm_client_networking_set_enabled (NMClient *client, gboolean enabled);
+
+gboolean  nm_client_wireless_get_enabled (NMClient *client);
+void      nm_client_wireless_set_enabled (NMClient *client, gboolean enabled);
+gboolean  nm_client_wireless_hardware_get_enabled (NMClient *client);
+
+gboolean  nm_client_wwan_get_enabled (NMClient *client);
+void      nm_client_wwan_set_enabled (NMClient *client, gboolean enabled);
+gboolean  nm_client_wwan_hardware_get_enabled (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);
+
+G_END_DECLS
+
+#endif /* NM_CLIENT_H */
diff --git a/libnm-glib/nm-dbus-utils.c b/libnm-glib/nm-dbus-utils.c
new file mode 100644
index 00000000..f641f185
--- /dev/null
+++ b/libnm-glib/nm-dbus-utils.c
@@ -0,0 +1,215 @@
+/* -*- 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
new file mode 100644
index 00000000..4002c3a0
--- /dev/null
+++ b/libnm-glib/nm-dbus-utils.h
@@ -0,0 +1,57 @@
+/* -*- 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-bt.c b/libnm-glib/nm-device-bt.c
new file mode 100644
index 00000000..0451f2b0
--- /dev/null
+++ b/libnm-glib/nm-device-bt.c
@@ -0,0 +1,307 @@
+/* -*- 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.
+ * Copyright (C) 2007 - 2009 Red Hat, Inc.
+ */
+
+#include "nm-device-bt.h"
+#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))
+
+typedef struct {
+	DBusGProxy *proxy;
+
+	char *hw_address;
+	char *name;
+	guint32 bt_capabilities;
+	gboolean bt_capabilities_valid;
+
+	gboolean disposed;
+} NMDeviceBtPrivate;
+
+enum {
+	PROP_0,
+	PROP_HW_ADDRESS,
+	PROP_NAME,
+	PROP_BT_CAPABILITIES,
+
+	LAST_PROP
+};
+
+#define DBUS_PROP_HW_ADDRESS      "HwAddress"
+#define DBUS_PROP_NAME            "Name"
+#define DBUS_PROP_BT_CAPABILITIES "BtCapabilities"
+
+/**
+ * nm_device_bt_new:
+ * @connection: the #DBusGConnection
+ * @path: the DBus object path of the device
+ *
+ * Creates a new #NMDeviceBt.
+ *
+ * Returns: a new device
+ **/
+GObject *
+nm_device_bt_new (DBusGConnection *connection, const char *path)
+{
+	g_return_val_if_fail (connection != NULL, NULL);
+	g_return_val_if_fail (path != NULL, NULL);
+
+	return g_object_new (NM_TYPE_DEVICE_BT,
+	                     NM_OBJECT_DBUS_CONNECTION, connection,
+	                     NM_OBJECT_DBUS_PATH, path,
+	                     NULL);
+}
+
+/**
+ * nm_device_bt_get_hw_address:
+ * @device: a #NMDeviceBt
+ *
+ * Gets the hardware (MAC) address of the #NMDeviceBt
+ *
+ * Returns: the hardware address. This is the internal string used by the
+ * device, and must not be modified.
+ **/
+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);
+	}
+
+	return priv->hw_address;
+}
+
+/**
+ * nm_device_bt_get_name:
+ * @device: a #NMDeviceBt
+ *
+ * Gets the name of the #NMDeviceBt.
+ *
+ * Returns: the name of the 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);
+	}
+
+	return priv->name;
+}
+
+/**
+ * nm_device_bt_get_capabilities:
+ * @device: a #NMDeviceBt
+ *
+ * Returns the Bluetooth device's usable capabilities.
+ *
+ * Returns: a combination of #NMBluetoothCapabilities
+ **/
+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);
+		priv->bt_capabilities_valid = TRUE;
+	}
+
+	return priv->bt_capabilities;
+}
+
+static void
+nm_device_bt_init (NMDeviceBt *device)
+{
+}
+
+static void
+register_for_property_changed (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 },
+		{ NULL },
+	};
+
+	_nm_object_handle_properties_changed (NM_OBJECT (device),
+	                                     priv->proxy,
+	                                     property_changed_info);
+}
+
+static GObject*
+constructor (GType type,
+			 guint n_construct_params,
+			 GObjectConstructParam *construct_params)
+{
+	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);
+
+		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);
+
+		register_for_property_changed (NM_DEVICE_BT (object));
+	}
+
+	return object;
+}
+
+static void
+dispose (GObject *object)
+{
+	NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (object);
+
+	if (priv->disposed) {
+		G_OBJECT_CLASS (nm_device_bt_parent_class)->dispose (object);
+		return;
+	}
+	priv->disposed = TRUE;
+
+	g_object_unref (priv->proxy);
+
+	G_OBJECT_CLASS (nm_device_bt_parent_class)->dispose (object);
+}
+
+static void
+finalize (GObject *object)
+{
+	NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (object);
+
+	g_free (priv->hw_address);
+	g_free (priv->name);
+
+	G_OBJECT_CLASS (nm_device_bt_parent_class)->finalize (object);
+}
+
+static void
+get_property (GObject *object,
+              guint prop_id,
+              GValue *value,
+              GParamSpec *pspec)
+{
+	NMDeviceBt *device = NM_DEVICE_BT (object);
+
+	switch (prop_id) {
+	case PROP_HW_ADDRESS:
+		g_value_set_string (value, nm_device_bt_get_hw_address (device));
+		break;
+	case PROP_NAME:
+		g_value_set_string (value, nm_device_bt_get_name (device));
+		break;
+	case PROP_BT_CAPABILITIES:
+		g_value_set_uint (value, nm_device_bt_get_capabilities (device));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+nm_device_bt_class_init (NMDeviceBtClass *device_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (device_class);
+
+	g_type_class_add_private (device_class, sizeof (NMDeviceBtPrivate));
+
+	/* virtual methods */
+	object_class->constructor = constructor;
+	object_class->dispose = dispose;
+	object_class->finalize = finalize;
+	object_class->get_property = get_property;
+
+	/* properties */
+
+	/**
+	 * NMDeviceBt: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_BT_HW_ADDRESS,
+		                      "MAC Address",
+		                      "Hardware MAC address",
+		                      NULL,
+		                      G_PARAM_READABLE));
+
+	/**
+	 * NMDeviceBt:name:
+	 *
+	 * The name of the bluetooth device.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_NAME,
+		 g_param_spec_string (NM_DEVICE_BT_NAME,
+		                      "Name",
+		                      "Device name",
+		                      NULL,
+		                      G_PARAM_READABLE));
+
+	/**
+	 * NMDeviceBt:bt-capabilities:
+	 *
+	 * The device's bluetooth capabilities, a combination of #NMBluetoothCapabilities.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_BT_CAPABILITIES,
+		 g_param_spec_uint (NM_DEVICE_BT_CAPABILITIES,
+		                    "BtCapabilities",
+		                    "Bluetooth capabilities",
+		                    NM_BT_CAPABILITY_NONE, G_MAXUINT32, NM_BT_CAPABILITY_NONE,
+		                    G_PARAM_READABLE));
+
+}
+
diff --git a/libnm-glib/nm-device-bt.h b/libnm-glib/nm-device-bt.h
new file mode 100644
index 00000000..71817f84
--- /dev/null
+++ b/libnm-glib/nm-device-bt.h
@@ -0,0 +1,71 @@
+/* -*- 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) 2008 - 2009 Red Hat, Inc.
+ * Copyright (C) 2008 Novell, Inc.
+ */
+
+#ifndef NM_DEVICE_BT_H
+#define NM_DEVICE_BT_H
+
+#include "NetworkManager.h"
+#include "nm-device.h"
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_DEVICE_BT            (nm_device_bt_get_type ())
+#define NM_DEVICE_BT(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_BT, NMDeviceBt))
+#define NM_DEVICE_BT_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_BT, NMDeviceBtClass))
+#define NM_IS_DEVICE_BT(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_BT))
+#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))
+
+#define NM_DEVICE_BT_HW_ADDRESS   "hw-address"
+#define NM_DEVICE_BT_NAME         "name"
+#define NM_DEVICE_BT_CAPABILITIES "bt-capabilities"
+
+typedef struct {
+	NMDevice parent;
+} NMDeviceBt;
+
+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);
+} NMDeviceBtClass;
+
+GType nm_device_bt_get_type (void);
+
+GObject *nm_device_bt_new (DBusGConnection *connection, const char *path);
+
+const char *nm_device_bt_get_hw_address   (NMDeviceBt *device);
+
+const char *nm_device_bt_get_name         (NMDeviceBt *device);
+
+NMBluetoothCapabilities nm_device_bt_get_capabilities (NMDeviceBt *device);
+
+G_END_DECLS
+
+#endif /* NM_DEVICE_BT_H */
diff --git a/libnm-glib/nm-device-ethernet.c b/libnm-glib/nm-device-ethernet.c
new file mode 100644
index 00000000..7a0cd925
--- /dev/null
+++ b/libnm-glib/nm-device-ethernet.c
@@ -0,0 +1,315 @@
+/* -*- 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.
+ * Copyright (C) 2007 - 2008 Red Hat, Inc.
+ */
+
+#include "nm-device-ethernet.h"
+#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))
+
+typedef struct {
+	DBusGProxy *proxy;
+
+	char * hw_address;
+	guint32 speed;
+	gboolean carrier;
+	gboolean carrier_valid;
+
+	gboolean disposed;
+} NMDeviceEthernetPrivate;
+
+enum {
+	PROP_0,
+	PROP_HW_ADDRESS,
+	PROP_SPEED,
+	PROP_CARRIER,
+
+	LAST_PROP
+};
+
+#define DBUS_PROP_HW_ADDRESS "HwAddress"
+#define DBUS_PROP_SPEED "Speed"
+#define DBUS_PROP_CARRIER "Carrier"
+
+/**
+ * nm_device_ethernet_new:
+ * @connection: the #DBusGConnection
+ * @path: the DBus object path of the device
+ *
+ * Creates a new #NMDeviceEthernet.
+ *
+ * Returns: a new device
+ **/
+GObject *
+nm_device_ethernet_new (DBusGConnection *connection, const char *path)
+{
+	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);
+}
+
+/**
+ * nm_device_ethernet_get_hw_address:
+ * @device: a #NMDeviceEthernet
+ *
+ * Gets the hardware (MAC) address of the #NMDeviceEthernet
+ *
+ * Returns: the hardware address. This is the internal string used by the
+ * device, and must not be modified.
+ **/
+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);
+	}
+
+	return priv->hw_address;
+}
+
+/**
+ * nm_device_ethernet_get_speed:
+ * @device: a #NMDeviceEthernet
+ *
+ * Gets the speed of the #NMDeviceEthernet.
+ *
+ * Returns: the speed of the 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);
+	}
+
+	return priv->speed;
+}
+
+/**
+ * nm_device_ethernet_get_carrier:
+ * @device: a #NMDeviceEthernet
+ *
+ * Whether the device has carrier.
+ *
+ * Returns: %TRUE if the device has carrier
+ **/
+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);
+		priv->carrier_valid = TRUE;
+	}
+
+	return priv->carrier;
+}
+
+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;
+}
+
+static void
+register_for_property_changed (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_SPEED,      _nm_object_demarshal_generic, &priv->speed },
+		{ NM_DEVICE_ETHERNET_CARRIER,    _nm_object_demarshal_generic, &priv->carrier },
+		{ NULL },
+	};
+
+	_nm_object_handle_properties_changed (NM_OBJECT (device),
+	                                     priv->proxy,
+	                                     property_changed_info);
+}
+
+static GObject*
+constructor (GType type,
+			 guint n_construct_params,
+			 GObjectConstructParam *construct_params)
+{
+	GObject *object;
+	NMDeviceEthernetPrivate *priv;
+
+	object = G_OBJECT_CLASS (nm_device_ethernet_parent_class)->constructor (type,
+																				  n_construct_params,
+																				  construct_params);
+	if (!object)
+		return NULL;
+
+	priv = NM_DEVICE_ETHERNET_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_WIRED);
+
+	register_for_property_changed (NM_DEVICE_ETHERNET (object));
+
+	return object;
+}
+
+static void
+dispose (GObject *object)
+{
+	NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (object);
+
+	if (priv->disposed) {
+		G_OBJECT_CLASS (nm_device_ethernet_parent_class)->dispose (object);
+		return;
+	}
+
+	priv->disposed = TRUE;
+
+	g_object_unref (priv->proxy);
+
+	G_OBJECT_CLASS (nm_device_ethernet_parent_class)->dispose (object);
+}
+
+static void
+finalize (GObject *object)
+{
+	NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (object);
+
+	if (priv->hw_address)
+		g_free (priv->hw_address);
+
+	G_OBJECT_CLASS (nm_device_ethernet_parent_class)->finalize (object);
+}
+
+static void
+get_property (GObject *object,
+              guint prop_id,
+              GValue *value,
+              GParamSpec *pspec)
+{
+	NMDeviceEthernet *device = NM_DEVICE_ETHERNET (object);
+
+	switch (prop_id) {
+	case PROP_HW_ADDRESS:
+		g_value_set_string (value, nm_device_ethernet_get_hw_address (device));
+		break;
+	case PROP_SPEED:
+		g_value_set_uint (value, nm_device_ethernet_get_speed (device));
+		break;
+	case PROP_CARRIER:
+		g_value_set_boolean (value, nm_device_ethernet_get_carrier (device));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+nm_device_ethernet_class_init (NMDeviceEthernetClass *device_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (device_class);
+
+	g_type_class_add_private (device_class, sizeof (NMDeviceEthernetPrivate));
+
+	/* virtual methods */
+	object_class->constructor = constructor;
+	object_class->dispose = dispose;
+	object_class->finalize = finalize;
+	object_class->get_property = get_property;
+
+	/* properties */
+
+	/**
+	 * NMDeviceEthernet: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_ETHERNET_HW_ADDRESS,
+						  "MAC Address",
+						  "Hardware MAC address",
+						  NULL,
+						  G_PARAM_READABLE));
+
+	/**
+	 * NMDeviceEthernet:speed:
+	 *
+	 * The speed of the device.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_SPEED,
+		 g_param_spec_uint (NM_DEVICE_ETHERNET_SPEED,
+					    "Speed",
+					    "Speed",
+					    0, G_MAXUINT32, 0,
+					    G_PARAM_READABLE));
+
+	/**
+	 * NMDeviceEthernet:carrier:
+	 *
+	 * Whether the device has carrier.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_CARRIER,
+		 g_param_spec_boolean (NM_DEVICE_ETHERNET_CARRIER,
+					    "Carrier",
+					    "Carrier",
+					    FALSE,
+					    G_PARAM_READABLE));
+
+}
+
diff --git a/libnm-glib/nm-device-ethernet.h b/libnm-glib/nm-device-ethernet.h
new file mode 100644
index 00000000..565e3e7e
--- /dev/null
+++ b/libnm-glib/nm-device-ethernet.h
@@ -0,0 +1,68 @@
+/* -*- 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.
+ * Copyright (C) 2007 - 2008 Red Hat, Inc.
+ */
+
+#ifndef NM_DEVICE_ETHERNET_H
+#define NM_DEVICE_ETHERNET_H
+
+#include "nm-device.h"
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_DEVICE_ETHERNET            (nm_device_ethernet_get_type ())
+#define NM_DEVICE_ETHERNET(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_ETHERNET, NMDeviceEthernet))
+#define NM_DEVICE_ETHERNET_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_ETHERNET, NMDeviceEthernetClass))
+#define NM_IS_DEVICE_ETHERNET(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_ETHERNET))
+#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))
+
+#define NM_DEVICE_ETHERNET_HW_ADDRESS  "hw-address"
+#define NM_DEVICE_ETHERNET_SPEED       "speed"
+#define NM_DEVICE_ETHERNET_CARRIER     "carrier"
+
+typedef struct {
+	NMDevice parent;
+} NMDeviceEthernet;
+
+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);
+} NMDeviceEthernetClass;
+
+GType nm_device_ethernet_get_type (void);
+
+GObject *nm_device_ethernet_new (DBusGConnection *connection, const char *path);
+
+const char * nm_device_ethernet_get_hw_address (NMDeviceEthernet *device);
+guint32      nm_device_ethernet_get_speed   (NMDeviceEthernet *device);
+gboolean     nm_device_ethernet_get_carrier (NMDeviceEthernet *device);
+
+G_END_DECLS
+
+#endif /* NM_DEVICE_ETHERNET_H */
diff --git a/libnm-glib/nm-device-private.h b/libnm-glib/nm-device-private.h
new file mode 100644
index 00000000..2c56a0e6
--- /dev/null
+++ b/libnm-glib/nm-device-private.h
@@ -0,0 +1,36 @@
+/* -*- 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 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);
+
+#endif /* NM_DEVICE_PRIVATE_H */
diff --git a/libnm-glib/nm-device-wifi.c b/libnm-glib/nm-device-wifi.c
new file mode 100644
index 00000000..1729c8aa
--- /dev/null
+++ b/libnm-glib/nm-device-wifi.c
@@ -0,0 +1,759 @@
+/* -*- 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.
+ * Copyright (C) 2007 - 2008 Red Hat, Inc.
+ */
+
+#include <string.h>
+
+#include "nm-device-wifi.h"
+#include "nm-device-private.h"
+#include "nm-object-private.h"
+#include "nm-object-cache.h"
+#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 {
+	gboolean disposed;
+	DBusGProxy *proxy;
+
+	char *hw_address;
+	NM80211Mode mode;
+	guint32 rate;
+	NMAccessPoint *active_ap;
+	gboolean null_active_ap;
+	guint32 wireless_caps;
+	GPtrArray *aps;
+
+	gboolean wireless_enabled;
+} NMDeviceWifiPrivate;
+
+enum {
+	PROP_0,
+	PROP_HW_ADDRESS,
+	PROP_MODE,
+	PROP_BITRATE,
+	PROP_ACTIVE_ACCESS_POINT,
+	PROP_WIRELESS_CAPABILITIES,
+
+	LAST_PROP
+};
+
+#define DBUS_PROP_HW_ADDRESS "HwAddress"
+#define DBUS_PROP_MODE "Mode"
+#define DBUS_PROP_BITRATE "Bitrate"
+#define DBUS_PROP_ACTIVE_ACCESS_POINT "ActiveAccessPoint"
+#define DBUS_PROP_WIRELESS_CAPABILITIES "WirelessCapabilities"
+
+enum {
+	ACCESS_POINT_ADDED,
+	ACCESS_POINT_REMOVED,
+
+	LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+/**
+ * nm_device_wifi_new:
+ * @connection: the #DBusGConnection
+ * @path: the DBus object path of the device
+ *
+ * Creates a new #NMDeviceWifi.
+ *
+ * Returns: a new device
+ **/
+GObject *
+nm_device_wifi_new (DBusGConnection *connection, const char *path)
+{
+	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);
+}
+
+/**
+ * nm_device_wifi_get_hw_address:
+ * @device: a #NMDeviceWifi
+ *
+ * Gets the hardware (MAC) address of the #NMDeviceWifi
+ *
+ * Returns: the hardware address. This is the internal string used by the
+ * device, and must not be modified.
+ **/
+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);
+	}
+
+	return priv->hw_address;
+}
+
+/**
+ * nm_device_wifi_get_mode:
+ * @device: a #NMDeviceWifi
+ *
+ * Gets the #NMDeviceWifi mode.
+ *
+ * Returns: the mode
+ **/
+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);
+	}
+
+	return priv->mode;
+}
+
+/**
+ * nm_device_wifi_get_bitrate:
+ * @device: a #NMDeviceWifi
+ *
+ * Gets the bit rate of the #NMDeviceWifi.
+ *
+ * Returns: the bit rate
+ **/
+guint32
+nm_device_wifi_get_bitrate (NMDeviceWifi *device)
+{
+	NMDeviceWifiPrivate *priv;
+	NMDeviceState state;
+
+	g_return_val_if_fail (NM_IS_DEVICE_WIFI (device), 0);
+
+	state = nm_device_get_state (NM_DEVICE (device));
+	switch (state) {
+	case NM_DEVICE_STATE_PREPARE:
+	case NM_DEVICE_STATE_CONFIG:
+	case NM_DEVICE_STATE_NEED_AUTH:
+	case NM_DEVICE_STATE_IP_CONFIG:
+	case NM_DEVICE_STATE_ACTIVATED:
+		break;
+	default:
+		return 0;
+		break;
+	}
+
+	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);
+	}
+
+	return priv->rate;
+}
+
+/**
+ * nm_device_wifi_get_capabilities:
+ * @device: a #NMDeviceWifi
+ *
+ * Gets the WIFI capabilities of the #NMDeviceWifi.
+ *
+ * Returns: the capabilities
+ **/
+guint32
+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);
+	}
+
+	return priv->wireless_caps;
+}
+
+/**
+ * nm_device_wifi_get_active_access_point:
+ * @device: a #NMDeviceWifi
+ *
+ * Gets the active #NMAccessPoint.
+ *
+ * Returns: the access point or %NULL if none is active
+ **/
+NMAccessPoint *
+nm_device_wifi_get_active_access_point (NMDeviceWifi *device)
+{
+	NMDeviceWifiPrivate *priv;
+	NMDeviceState state;
+	char *path;
+	GValue value = { 0, };
+
+	g_return_val_if_fail (NM_IS_DEVICE_WIFI (device), NULL);
+
+	state = nm_device_get_state (NM_DEVICE (device));
+	switch (state) {
+	case NM_DEVICE_STATE_PREPARE:
+	case NM_DEVICE_STATE_CONFIG:
+	case NM_DEVICE_STATE_NEED_AUTH:
+	case NM_DEVICE_STATE_IP_CONFIG:
+	case NM_DEVICE_STATE_ACTIVATED:
+		break;
+	default:
+		return NULL;
+		break;
+	}
+
+	priv = NM_DEVICE_WIFI_GET_PRIVATE (device);
+	if (priv->active_ap)
+		return priv->active_ap;
+	if (priv->null_active_ap)
+		return NULL;
+
+	path = _nm_object_get_object_path_property (NM_OBJECT (device),
+	                                           NM_DBUS_INTERFACE_DEVICE_WIRELESS,
+	                                           DBUS_PROP_ACTIVE_ACCESS_POINT);
+	if (path) {
+		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);
+	}
+
+	return priv->active_ap;
+}
+
+/**
+ * nm_device_wifi_get_access_points:
+ * @device: a #NMDeviceWifi
+ *
+ * Gets all the scanned access points of the #NMDeviceWifi.
+ *
+ * Returns: a #GPtrArray containing all the scanned #NMAccessPoint<!-- -->s.
+ * The returned array is owned by the client and should not be modified.
+ **/
+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_device_wifi_get_access_point_by_path:
+ * @device: a #NMDeviceWifi
+ * @path: the object path of the access point
+ *
+ * Gets a #NMAccessPoint by path.
+ *
+ * Returns: the access point or %NULL if none is found.
+ **/
+NMAccessPoint *
+nm_device_wifi_get_access_point_by_path (NMDeviceWifi *device,
+                                         const char *path)
+{
+	const GPtrArray *aps;
+	int i;
+	NMAccessPoint *ap = NULL;
+
+	g_return_val_if_fail (NM_IS_DEVICE_WIFI (device), NULL);
+	g_return_val_if_fail (path != NULL, NULL);
+
+	aps = nm_device_wifi_get_access_points (device);
+	if (!aps)
+		return NULL;
+
+	for (i = 0; i < aps->len; i++) {
+		NMAccessPoint *candidate = g_ptr_array_index (aps, i);
+		if (!strcmp (nm_object_get_path (NM_OBJECT (candidate)), path)) {
+			ap = candidate;
+			break;
+		}
+	}
+
+	return ap;
+}
+
+static void
+access_point_added_proxy (DBusGProxy *proxy, char *path, gpointer user_data)
+{
+	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, g_object_ref (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));
+}
+
+static void
+access_point_removed_proxy (DBusGProxy *proxy, char *path, gpointer user_data)
+{
+	NMDeviceWifi *self = NM_DEVICE_WIFI (user_data);
+	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
+	NMAccessPoint *ap;
+
+	g_return_if_fail (self != NULL);
+
+	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;
+			priv->null_active_ap = FALSE;
+
+			_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);
+		}
+
+		g_signal_emit (self, signals[ACCESS_POINT_REMOVED], 0, ap);
+		g_ptr_array_remove (priv->aps, ap);
+		g_object_unref (G_OBJECT (ap));
+	}
+}
+
+static void
+clean_up_aps (NMDeviceWifi *self, gboolean notify)
+{
+	NMDeviceWifiPrivate *priv;
+
+	g_return_if_fail (NM_IS_DEVICE_WIFI (self));
+
+	priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
+
+	if (priv->active_ap) {
+		g_object_unref (priv->active_ap);
+		priv->active_ap = NULL;
+	}
+
+	if (priv->aps) {
+		while (priv->aps->len) {
+			NMAccessPoint *ap = NM_ACCESS_POINT (g_ptr_array_index (priv->aps, 0));
+
+			if (notify)
+				g_signal_emit (self, signals[ACCESS_POINT_REMOVED], 0, ap);
+			g_ptr_array_remove (priv->aps, ap);
+			g_object_unref (ap);
+		}
+		g_ptr_array_free (priv->aps, TRUE);
+		priv->aps = NULL;
+	}
+}
+
+/**
+ * _nm_device_wifi_set_wireless_enabled:
+ * @device: a #NMDeviceWifi
+ * @enabled: %TRUE to enable the device
+ *
+ * Enables or disables the wireless device.
+ **/
+void
+_nm_device_wifi_set_wireless_enabled (NMDeviceWifi *device,
+                                                gboolean enabled)
+{
+	g_return_if_fail (NM_IS_DEVICE_WIFI (device));
+
+	if (!enabled)
+		clean_up_aps (device, TRUE);
+}
+
+
+/**************************************************************/
+
+static void
+nm_device_wifi_init (NMDeviceWifi *device)
+{
+	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (device);
+
+	priv->disposed = FALSE;
+}
+
+static void
+get_property (GObject *object,
+              guint prop_id,
+              GValue *value,
+              GParamSpec *pspec)
+{
+	NMDeviceWifi *self = NM_DEVICE_WIFI (object);
+
+	switch (prop_id) {
+	case PROP_HW_ADDRESS:
+		g_value_set_string (value, nm_device_wifi_get_hw_address (self));
+		break;
+	case PROP_MODE:
+		g_value_set_uint (value, nm_device_wifi_get_mode (self));
+		break;
+	case PROP_BITRATE:
+		g_value_set_uint (value, nm_device_wifi_get_bitrate (self));
+		break;
+	case PROP_ACTIVE_ACCESS_POINT:
+		g_value_set_object (value, nm_device_wifi_get_active_access_point (self));
+		break;
+	case PROP_WIRELESS_CAPABILITIES:
+		g_value_set_uint (value, nm_device_wifi_get_capabilities (self));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+state_changed_cb (NMDevice *device, GParamSpec *pspec, gpointer user_data)
+{
+	NMDeviceWifi *self = NM_DEVICE_WIFI (device);
+	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
+
+	switch (nm_device_get_state (device)) {
+	case NM_DEVICE_STATE_UNKNOWN:
+	case NM_DEVICE_STATE_UNMANAGED:
+	case NM_DEVICE_STATE_UNAVAILABLE:
+	case NM_DEVICE_STATE_DISCONNECTED:
+	case NM_DEVICE_STATE_FAILED:
+		/* Just clear active AP; don't clear the AP list unless wireless is disabled completely */
+		if (priv->active_ap) {
+			g_object_unref (priv->active_ap);
+			priv->active_ap = NULL;
+			priv->null_active_ap = FALSE;
+		}
+		_nm_object_queue_notify (NM_OBJECT (device), NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT);
+		priv->rate = 0;
+		_nm_object_queue_notify (NM_OBJECT (device), NM_DEVICE_WIFI_BITRATE);
+		break;
+	default:
+		break;
+	}
+}
+
+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 (!G_VALUE_HOLDS (value, DBUS_TYPE_G_OBJECT_PATH))
+		return FALSE;
+
+	priv->null_active_ap = FALSE;
+
+	path = g_value_get_boxed (value);
+	if (path) {
+		if (!strcmp (path, "/"))
+			priv->null_active_ap = TRUE;
+		else {
+			ap = NM_ACCESS_POINT (_nm_object_cache_get (path));
+			if (ap)
+				ap = g_object_ref (ap);
+			else {
+				connection = nm_object_get_connection (object);
+				ap = NM_ACCESS_POINT (nm_access_point_new (connection, path));
+			}
+		}
+	}
+
+	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)
+{
+	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_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 },
+		{ NULL },
+	};
+
+	_nm_object_handle_properties_changed (NM_OBJECT (device),
+	                                     priv->proxy,
+	                                     property_changed_info);
+}
+
+static GObject*
+constructor (GType type,
+		   guint n_construct_params,
+		   GObjectConstructParam *construct_params)
+{
+	GObject *object;
+	NMDeviceWifiPrivate *priv;
+
+	object = G_OBJECT_CLASS (nm_device_wifi_parent_class)->constructor (type,
+																    n_construct_params,
+																    construct_params);
+	if (!object)
+		return NULL;
+
+	priv = NM_DEVICE_WIFI_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_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));
+
+	g_signal_connect (NM_DEVICE (object),
+	                  "notify::" NM_DEVICE_STATE,
+	                  G_CALLBACK (state_changed_cb),
+	                  NULL);
+
+	return object;
+}
+
+static void
+dispose (GObject *object)
+{
+	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (object);
+
+	if (priv->disposed) {
+		G_OBJECT_CLASS (nm_device_wifi_parent_class)->dispose (object);
+		return;
+	}
+
+	priv->disposed = TRUE;
+
+	clean_up_aps (NM_DEVICE_WIFI (object), FALSE);
+	g_object_unref (priv->proxy);
+
+	G_OBJECT_CLASS (nm_device_wifi_parent_class)->dispose (object);
+}
+
+static void
+finalize (GObject *object)
+{
+	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (object);
+
+	if (priv->hw_address)
+		g_free (priv->hw_address);
+
+	G_OBJECT_CLASS (nm_device_wifi_parent_class)->finalize (object);
+}
+
+static void
+nm_device_wifi_class_init (NMDeviceWifiClass *device_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (device_class);
+
+	g_type_class_add_private (device_class, sizeof (NMDeviceWifiPrivate));
+
+	/* virtual methods */
+	object_class->constructor = constructor;
+	object_class->get_property = get_property;
+	object_class->dispose = dispose;
+	object_class->finalize = finalize;
+
+	/* properties */
+
+	/**
+	 * NMDeviceWifi: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_WIFI_HW_ADDRESS,
+						  "MAC Address",
+						  "Hardware MAC address",
+						  NULL,
+						  G_PARAM_READABLE));
+
+	/**
+	 * NMDeviceWifi:mode:
+	 *
+	 * The mode of the device.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_MODE,
+		 g_param_spec_uint (NM_DEVICE_WIFI_MODE,
+					    "Mode",
+					    "Mode",
+					    NM_802_11_MODE_UNKNOWN, NM_802_11_MODE_INFRA, NM_802_11_MODE_INFRA,
+					    G_PARAM_READABLE));
+
+	/**
+	 * NMDeviceWifi:bitrate:
+	 *
+	 * The bit rate of the device.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_BITRATE,
+		 g_param_spec_uint (NM_DEVICE_WIFI_BITRATE,
+					    "Bit Rate",
+					    "Bit Rate",
+					    0, G_MAXUINT32, 0,
+					    G_PARAM_READABLE));
+
+	/**
+	 * NMDeviceWifi:active-access-point:
+	 *
+	 * The active #NMAccessPoint of the device.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_ACTIVE_ACCESS_POINT,
+		 g_param_spec_object (NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT,
+						 "Active Access Point",
+						 "Active Access Point",
+						 NM_TYPE_ACCESS_POINT,
+						 G_PARAM_READABLE));
+
+	/**
+	 * NMDeviceWifi:wireless-capabilities:
+	 *
+	 * The wireless capabilities of the device.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_WIRELESS_CAPABILITIES,
+		 g_param_spec_uint (NM_DEVICE_WIFI_CAPABILITIES,
+		                    "Wireless Capabilities",
+		                    "Wireless Capabilities",
+		                    0, G_MAXUINT32, 0,
+		                    G_PARAM_READABLE));
+
+	/* signals */
+
+	/**
+	 * NMDeviceWifi::access-point-added:
+	 * @device: the wifi device that received the signal
+	 * @ap: the new access point
+	 *
+	 * Notifies that a #NMAccessPoint is added to the wifi device.
+	 **/
+	signals[ACCESS_POINT_ADDED] =
+		g_signal_new ("access-point-added",
+				    G_OBJECT_CLASS_TYPE (object_class),
+				    G_SIGNAL_RUN_FIRST,
+				    G_STRUCT_OFFSET (NMDeviceWifiClass, access_point_added),
+				    NULL, NULL,
+				    g_cclosure_marshal_VOID__OBJECT,
+				    G_TYPE_NONE, 1,
+				    G_TYPE_OBJECT);
+
+	/**
+	 * NMDeviceWifi::access-point-removed:
+	 * @device: the wifi device that received the signal
+	 * @ap: the removed access point
+	 *
+	 * Notifies that a #NMAccessPoint is removed from the wifi device.
+	 **/
+	signals[ACCESS_POINT_REMOVED] =
+		g_signal_new ("access-point-removed",
+				    G_OBJECT_CLASS_TYPE (object_class),
+				    G_SIGNAL_RUN_FIRST,
+				    G_STRUCT_OFFSET (NMDeviceWifiClass, access_point_removed),
+				    NULL, NULL,
+				    g_cclosure_marshal_VOID__OBJECT,
+				    G_TYPE_NONE, 1,
+				    G_TYPE_OBJECT);
+}
diff --git a/libnm-glib/nm-device-wifi.h b/libnm-glib/nm-device-wifi.h
new file mode 100644
index 00000000..9152ab29
--- /dev/null
+++ b/libnm-glib/nm-device-wifi.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) 2007 - 2008 Novell, Inc.
+ * Copyright (C) 2007 - 2008 Red Hat, Inc.
+ */
+
+#ifndef NM_DEVICE_WIFI_H
+#define NM_DEVICE_WIFI_H
+
+#include "nm-device.h"
+#include "nm-access-point.h"
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_DEVICE_WIFI            (nm_device_wifi_get_type ())
+#define NM_DEVICE_WIFI(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_WIFI, NMDeviceWifi))
+#define NM_DEVICE_WIFI_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_WIFI, NMDeviceWifiClass))
+#define NM_IS_DEVICE_WIFI(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_WIFI))
+#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))
+
+#define NM_DEVICE_WIFI_HW_ADDRESS          "hw-address"
+#define NM_DEVICE_WIFI_MODE                "mode"
+#define NM_DEVICE_WIFI_BITRATE             "bitrate"
+#define NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT "active-access-point"
+#define NM_DEVICE_WIFI_CAPABILITIES        "wireless-capabilities"
+
+typedef struct {
+	NMDevice parent;
+} NMDeviceWifi;
+
+typedef struct {
+	NMDeviceClass parent;
+
+	/* Signals */
+	void (*access_point_added) (NMDeviceWifi *device, NMAccessPoint *ap);
+	void (*access_point_removed) (NMDeviceWifi *device, NMAccessPoint *ap);
+
+	/* Padding for future expansion */
+	void (*_reserved1) (void);
+	void (*_reserved2) (void);
+	void (*_reserved3) (void);
+	void (*_reserved4) (void);
+	void (*_reserved5) (void);
+	void (*_reserved6) (void);
+} NMDeviceWifiClass;
+
+GType nm_device_wifi_get_type (void);
+
+GObject *nm_device_wifi_new (DBusGConnection *connection, const char *path);
+
+const char *    nm_device_wifi_get_hw_address           (NMDeviceWifi *device);
+NM80211Mode     nm_device_wifi_get_mode                 (NMDeviceWifi *device);
+guint32         nm_device_wifi_get_bitrate              (NMDeviceWifi *device);
+guint32         nm_device_wifi_get_capabilities         (NMDeviceWifi *device);
+NMAccessPoint * nm_device_wifi_get_active_access_point  (NMDeviceWifi *device);
+
+NMAccessPoint * nm_device_wifi_get_access_point_by_path (NMDeviceWifi *device,
+                                                         const char *path);
+
+const GPtrArray *nm_device_wifi_get_access_points       (NMDeviceWifi *device);
+
+G_END_DECLS
+
+#endif /* NM_DEVICE_WIFI_H */
diff --git a/libnm-glib/nm-device.c b/libnm-glib/nm-device.c
new file mode 100644
index 00000000..5e9eb506
--- /dev/null
+++ b/libnm-glib/nm-device.c
@@ -0,0 +1,1246 @@
+/* -*- 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.
+ * Copyright (C) 2007 - 2008 Red Hat, Inc.
+ */
+
+#include <string.h>
+
+#define G_UDEV_API_IS_SUBJECT_TO_CHANGE
+#include <gudev/gudev.h>
+
+#include "NetworkManager.h"
+#include "nm-device-ethernet.h"
+#include "nm-device-wifi.h"
+#include "nm-gsm-device.h"
+#include "nm-cdma-device.h"
+#include "nm-device-bt.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-device-bindings.h"
+
+G_DEFINE_TYPE (NMDevice, nm_device, NM_TYPE_OBJECT)
+
+#define NM_DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE, NMDevicePrivate))
+
+typedef struct {
+	gboolean disposed;
+	DBusGProxy *proxy;
+
+	char *iface;
+	char *udi;
+	char *driver;
+	guint32 capabilities;
+	gboolean managed;
+	NMIP4Config *ip4_config;
+	gboolean null_ip4_config;
+	NMDHCP4Config *dhcp4_config;
+	gboolean null_dhcp4_config;
+	NMIP6Config *ip6_config;
+	gboolean null_ip6_config;
+	NMDHCP6Config *dhcp6_config;
+	gboolean null_dhcp6_config;
+	NMDeviceState state;
+
+	GUdevClient *client;
+	char *product;
+	char *vendor;
+} NMDevicePrivate;
+
+enum {
+	PROP_0,
+	PROP_INTERFACE,
+	PROP_UDI,
+	PROP_DRIVER,
+	PROP_CAPABILITIES,
+	PROP_MANAGED,
+	PROP_IP4_CONFIG,
+	PROP_DHCP4_CONFIG,
+	PROP_IP6_CONFIG,
+	PROP_STATE,
+	PROP_PRODUCT,
+	PROP_VENDOR,
+	PROP_DHCP6_CONFIG,
+
+	LAST_PROP
+};
+
+enum {
+	STATE_CHANGED,
+
+	LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+
+static void
+nm_device_init (NMDevice *device)
+{
+	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
+
+	priv->state = NM_DEVICE_STATE_UNKNOWN;
+}
+
+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 (!G_VALUE_HOLDS (value, DBUS_TYPE_G_OBJECT_PATH))
+		return FALSE;
+
+	priv->null_ip4_config = FALSE;
+
+	path = g_value_get_boxed (value);
+	if (path) {
+		if (!strcmp (path, "/"))
+			priv->null_ip4_config = TRUE;
+		else {
+			config = NM_IP4_CONFIG (_nm_object_cache_get (path));
+			if (config)
+				config = g_object_ref (config);
+			else {
+				connection = nm_object_get_connection (object);
+				config = NM_IP4_CONFIG (nm_ip4_config_new (connection, path));
+			}
+		}
+	}
+
+	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 (!G_VALUE_HOLDS (value, DBUS_TYPE_G_OBJECT_PATH))
+		return FALSE;
+
+	priv->null_dhcp4_config = FALSE;
+
+	path = g_value_get_boxed (value);
+	if (path) {
+		if (!strcmp (path, "/"))
+			priv->null_dhcp4_config = TRUE;
+		else {
+			config = NM_DHCP4_CONFIG (_nm_object_cache_get (path));
+			if (config)
+				config = g_object_ref (config);
+			else {
+				connection = nm_object_get_connection (object);
+				config = NM_DHCP4_CONFIG (nm_dhcp4_config_new (connection, path));
+			}
+		}
+	}
+
+	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 (!G_VALUE_HOLDS (value, DBUS_TYPE_G_OBJECT_PATH))
+		return FALSE;
+
+	priv->null_ip6_config = FALSE;
+
+	path = g_value_get_boxed (value);
+	if (path) {
+		if (!strcmp (path, "/"))
+			priv->null_ip6_config = TRUE;
+		else {
+			config = NM_IP6_CONFIG (_nm_object_cache_get (path));
+			if (config)
+				config = g_object_ref (config);
+			else {
+				connection = nm_object_get_connection (object);
+				config = NM_IP6_CONFIG (nm_ip6_config_new (connection, path));
+			}
+		}
+	}
+
+	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)
+{
+	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (object);
+	const char *path;
+	NMDHCP6Config *config = NULL;
+	DBusGConnection *connection;
+
+	if (!G_VALUE_HOLDS (value, DBUS_TYPE_G_OBJECT_PATH))
+		return FALSE;
+
+	priv->null_dhcp6_config = FALSE;
+
+	path = g_value_get_boxed (value);
+	if (path) {
+		if (!strcmp (path, "/"))
+			priv->null_dhcp6_config = TRUE;
+		else {
+			config = NM_DHCP6_CONFIG (_nm_object_cache_get (path));
+			if (config)
+				config = g_object_ref (config);
+			else {
+				connection = nm_object_get_connection (object);
+				config = NM_DHCP6_CONFIG (nm_dhcp6_config_new (connection, path));
+			}
+		}
+	}
+
+	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 void
+register_for_property_changed (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_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_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 },
+		{ NULL },
+	};
+
+	_nm_object_handle_properties_changed (NM_OBJECT (device),
+	                                     priv->proxy,
+	                                     property_changed_info);
+}
+
+static void
+device_state_changed (DBusGProxy *proxy,
+                      NMDeviceState new_state,
+                      NMDeviceState old_state,
+                      NMDeviceStateReason reason,
+                      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;
+		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)
+{
+	NMObject *object;
+	NMDevicePrivate *priv;
+
+	object = (NMObject *) G_OBJECT_CLASS (nm_device_parent_class)->constructor (type,
+																				n_construct_params,
+																				construct_params);
+	if (!object)
+		return NULL;
+
+	priv = NM_DEVICE_GET_PRIVATE (object);
+
+	priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (object),
+											 NM_DBUS_SERVICE,
+											 nm_object_get_path (object),
+											 NM_DBUS_INTERFACE_DEVICE);
+
+	register_for_property_changed (NM_DEVICE (object));
+
+	dbus_g_object_register_marshaller (_nm_marshal_VOID__UINT_UINT_UINT,
+									   G_TYPE_NONE,
+									   G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT,
+									   G_TYPE_INVALID);
+
+	dbus_g_proxy_add_signal (priv->proxy,
+	                         "StateChanged",
+	                         G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT,
+	                         G_TYPE_INVALID);
+
+	dbus_g_proxy_connect_signal (priv->proxy, "StateChanged",
+								 G_CALLBACK (device_state_changed),
+								 NM_DEVICE (object),
+								 NULL);
+
+	return G_OBJECT (object);
+}
+
+static void
+dispose (GObject *object)
+{
+	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (object);
+
+	if (priv->disposed) {
+		G_OBJECT_CLASS (nm_device_parent_class)->dispose (object);
+		return;
+	}
+
+	priv->disposed = TRUE;
+
+	g_object_unref (priv->proxy);
+	if (priv->ip4_config)
+		g_object_unref (priv->ip4_config);
+	if (priv->dhcp4_config)
+		g_object_unref (priv->dhcp4_config);
+	if (priv->ip6_config)
+		g_object_unref (priv->ip6_config);
+	if (priv->dhcp6_config)
+		g_object_unref (priv->dhcp6_config);
+	if (priv->client)
+		g_object_unref (priv->client);
+
+	G_OBJECT_CLASS (nm_device_parent_class)->dispose (object);
+}
+
+static void
+finalize (GObject *object)
+{
+	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (object);
+
+	g_free (priv->iface);
+	g_free (priv->udi);
+	g_free (priv->driver);
+	g_free (priv->product);
+	g_free (priv->vendor);
+
+	G_OBJECT_CLASS (nm_device_parent_class)->finalize (object);
+}
+
+static void
+get_property (GObject *object,
+              guint prop_id,
+              GValue *value,
+              GParamSpec *pspec)
+{
+	NMDevice *device = NM_DEVICE (object);
+
+	switch (prop_id) {
+	case PROP_UDI:
+		g_value_set_string (value, nm_device_get_udi (device));
+		break;
+	case PROP_INTERFACE:
+		g_value_set_string (value, nm_device_get_iface (device));
+		break;
+	case PROP_DRIVER:
+		g_value_set_string (value, nm_device_get_driver (device));
+		break;
+	case PROP_CAPABILITIES:
+		g_value_set_uint (value, nm_device_get_capabilities (device));
+		break;
+	case PROP_MANAGED:
+		g_value_set_boolean (value, nm_device_get_managed (device));
+		break;
+	case PROP_IP4_CONFIG:
+		g_value_set_object (value, nm_device_get_ip4_config (device));
+		break;
+	case PROP_DHCP4_CONFIG:
+		g_value_set_object (value, nm_device_get_dhcp4_config (device));
+		break;
+	case PROP_IP6_CONFIG:
+		g_value_set_object (value, nm_device_get_ip6_config (device));
+		break;
+	case PROP_DHCP6_CONFIG:
+		g_value_set_object (value, nm_device_get_dhcp6_config (device));
+		break;
+	case PROP_STATE:
+		g_value_set_uint (value, nm_device_get_state (device));
+		break;
+	case PROP_PRODUCT:
+		g_value_set_string (value, nm_device_get_product (device));
+		break;
+	case PROP_VENDOR:
+		g_value_set_string (value, nm_device_get_vendor (device));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+nm_device_class_init (NMDeviceClass *device_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (device_class);
+
+	g_type_class_add_private (device_class, sizeof (NMDevicePrivate));
+
+	/* virtual methods */
+	object_class->constructor = constructor;
+	object_class->get_property = get_property;
+	object_class->dispose = dispose;
+	object_class->finalize = finalize;
+
+	/* properties */
+
+	/**
+	 * NMDevice:interface:
+	 *
+	 * The interface of the device.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_INTERFACE,
+		 g_param_spec_string (NM_DEVICE_INTERFACE,
+						  "Interface",
+						  "Interface name",
+						  NULL,
+						  G_PARAM_READABLE));
+
+	/**
+	 * NMDevice:udi:
+	 *
+	 * The Unique Device Identifier of the device.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_UDI,
+		 g_param_spec_string (NM_DEVICE_UDI,
+						  "UDI",
+						  "Unique Device Identifier",
+						  NULL,
+						  G_PARAM_READABLE));
+
+	/**
+	 * NMDevice:driver:
+	 *
+	 * The driver of the device.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_DRIVER,
+		 g_param_spec_string (NM_DEVICE_DRIVER,
+						  "Driver",
+						  "Driver",
+						  NULL,
+						  G_PARAM_READABLE));
+
+	/**
+	 * NMDevice:capabilities:
+	 *
+	 * The capabilities of the device.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_CAPABILITIES,
+		 g_param_spec_uint (NM_DEVICE_CAPABILITIES,
+						  "Capabilities",
+						  "Capabilities",
+						  0, G_MAXUINT32, 0,
+						  G_PARAM_READABLE));
+
+	/**
+	 * NMDevice:managed:
+	 *
+	 * Whether the device is managed by NetworkManager.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_MANAGED,
+		 g_param_spec_boolean (NM_DEVICE_MANAGED,
+						  "Managed",
+						  "Managed",
+						  FALSE,
+						  G_PARAM_READABLE));
+
+	/**
+	 * NMDevice:ip4-config:
+	 *
+	 * The #NMIP4Config of the device.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_IP4_CONFIG,
+		 g_param_spec_object (NM_DEVICE_IP4_CONFIG,
+						  "IP4 Config",
+						  "IP4 Config",
+						  NM_TYPE_IP4_CONFIG,
+						  G_PARAM_READABLE));
+
+	/**
+	 * NMDevice:dhcp4-config:
+	 *
+	 * The #NMDHCP4Config of the device.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_DHCP4_CONFIG,
+		 g_param_spec_object (NM_DEVICE_DHCP4_CONFIG,
+						  "DHCP4 Config",
+						  "DHCP4 Config",
+						  NM_TYPE_DHCP4_CONFIG,
+						  G_PARAM_READABLE));
+
+	/**
+	 * NMDevice:ip6-config:
+	 *
+	 * The #NMIP6Config of the device.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_IP6_CONFIG,
+		 g_param_spec_object (NM_DEVICE_IP6_CONFIG,
+		                      "IP6 Config",
+		                      "IP6 Config",
+		                      NM_TYPE_IP6_CONFIG,
+		                      G_PARAM_READABLE));
+
+	/**
+	 * NMDevice:dhcp6-config:
+	 *
+	 * The #NMDHCP6Config of the device.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_DHCP6_CONFIG,
+		 g_param_spec_object (NM_DEVICE_DHCP6_CONFIG,
+						  "DHCP6 Config",
+						  "DHCP6 Config",
+						  NM_TYPE_DHCP6_CONFIG,
+						  G_PARAM_READABLE));
+
+	/**
+	 * NMDevice:state:
+	 *
+	 * The state of the device.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_STATE,
+		 g_param_spec_uint (NM_DEVICE_STATE,
+						  "State",
+						  "State",
+						  0, G_MAXUINT32, 0,
+						  G_PARAM_READABLE));
+
+	/**
+	 * NMDevice:vendor:
+	 *
+	 * The vendor string of the device.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_VENDOR,
+		 g_param_spec_string (NM_DEVICE_VENDOR,
+						  "Vendor",
+						  "Vendor string",
+						  NULL,
+						  G_PARAM_READABLE));
+
+	/**
+	 * NMDevice:product:
+	 *
+	 * The product string of the device.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_PRODUCT,
+		 g_param_spec_string (NM_DEVICE_PRODUCT,
+						  "Product",
+						  "Product string",
+						  NULL,
+						  G_PARAM_READABLE));
+
+	/* signals */
+
+	/**
+	 * NMDevice::state-changed:
+	 * @device: the client that received the signal
+	 * @state: the new state of the device
+	 *
+	 * Notifies the state change of a #NMDevice.
+	 **/
+	signals[STATE_CHANGED] =
+		g_signal_new ("state-changed",
+				    G_OBJECT_CLASS_TYPE (object_class),
+				    G_SIGNAL_RUN_FIRST,
+				    G_STRUCT_OFFSET (NMDeviceClass, state_changed),
+				    NULL, NULL,
+				    _nm_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.
+ *
+ * Returns: a new device
+ **/
+GObject *
+nm_device_new (DBusGConnection *connection, const char *path)
+{
+	DBusGProxy *proxy;
+	GError *err = NULL;
+	GValue value = {0,};
+	GType dtype = 0;
+	NMDevice *device = NULL;
+
+	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;
+	}
+
+	if (!dbus_g_proxy_call (proxy,
+						    "Get", &err,
+						    G_TYPE_STRING, NM_DBUS_INTERFACE_DEVICE,
+						    G_TYPE_STRING, "DeviceType",
+						    G_TYPE_INVALID,
+						    G_TYPE_VALUE, &value, G_TYPE_INVALID)) {
+		g_warning ("Error in get_property: %s\n", err->message);
+		g_error_free (err);
+		goto out;
+	}
+
+	switch (g_value_get_uint (&value)) {
+	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_GSM:
+		dtype = NM_TYPE_GSM_DEVICE;
+		break;
+	case NM_DEVICE_TYPE_CDMA:
+		dtype = NM_TYPE_CDMA_DEVICE;
+		break;
+	case NM_DEVICE_TYPE_BT:
+		dtype = NM_TYPE_DEVICE_BT;
+		break;
+	default:
+		g_warning ("Unknown device type %d", g_value_get_uint (&value));
+		break;
+	}
+
+	if (dtype) {
+		device = (NMDevice *) g_object_new (dtype,
+											NM_OBJECT_DBUS_CONNECTION, connection,
+											NM_OBJECT_DBUS_PATH, path,
+											NULL);
+	}
+
+out:
+	g_object_unref (proxy);
+	return G_OBJECT (device);
+}
+
+/**
+ * nm_device_get_iface:
+ * @device: a #NMDevice
+ *
+ * Gets the interface name of the #NMDevice.
+ *
+ * Returns: the interface of the device. This is the internal string used by the
+ * device, and must not be modified.
+ **/
+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");
+	}
+
+	return priv->iface;
+}
+
+/**
+ * nm_device_get_udi:
+ * @device: a #NMDevice
+ *
+ * Gets the Unique Device Identifier of the #NMDevice.
+ *
+ * Returns: the Unique Device Identifier of the device.  This identifier may be
+ * used to gather more information about the device from various operating
+ * system services like udev or sysfs.
+ **/
+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");
+	}
+
+	return priv->udi;
+}
+
+/**
+ * nm_device_get_driver:
+ * @device: a #NMDevice
+ *
+ * Gets the driver of the #NMDevice.
+ *
+ * Returns: the driver of the device. This is the internal string used by the
+ * device, and must not be modified.
+ **/
+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");
+	}
+
+	return priv->driver;
+}
+
+/**
+ * nm_device_get_capabilities:
+ * @device: a #NMDevice
+ *
+ * Gets the device' capabilities.
+ *
+ * Returns: the capabilities
+ **/
+guint32
+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");
+	}
+
+	return priv->capabilities;
+}
+
+/**
+ * nm_device_get_managed:
+ * @device: a #NMDevice
+ *
+ * Whether the #NMDevice is managed by NetworkManager.
+ *
+ * Returns: %TRUE if the device is managed by NetworkManager
+ **/
+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");
+	}
+
+	return priv->managed;
+}
+
+/**
+ * nm_device_get_ip4_config:
+ * @device: a #NMDevice
+ *
+ * Gets the current #NMIP4Config associated with the #NMDevice.
+ *
+ * Returns: the #NMIP4Config or %NULL if the device is not activated.
+ **/
+NMIP4Config *
+nm_device_get_ip4_config (NMDevice *device)
+{
+	NMDevicePrivate *priv;
+	char *path;
+	GValue value = { 0, };
+
+	g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
+
+	priv = NM_DEVICE_GET_PRIVATE (device);
+	if (priv->ip4_config)
+		return priv->ip4_config;
+	if (priv->null_ip4_config)
+		return NULL;
+
+	path = _nm_object_get_object_path_property (NM_OBJECT (device), NM_DBUS_INTERFACE_DEVICE, "Ip4Config");
+	if (path) {
+		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);
+	}
+
+	return priv->ip4_config;
+}
+
+/**
+ * nm_device_get_dhcp4_config:
+ * @device: a #NMDevice
+ *
+ * Gets the current #NMDHCP4Config associated with the #NMDevice.
+ *
+ * Returns: the #NMDHCPConfig or %NULL if the device is not activated or not
+ * using DHCP.
+ **/
+NMDHCP4Config *
+nm_device_get_dhcp4_config (NMDevice *device)
+{
+	NMDevicePrivate *priv;
+	char *path;
+	GValue value = { 0, };
+
+	g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
+
+	priv = NM_DEVICE_GET_PRIVATE (device);
+	if (priv->dhcp4_config)
+		return priv->dhcp4_config;
+	if (priv->null_dhcp4_config)
+		return NULL;
+
+	path = _nm_object_get_object_path_property (NM_OBJECT (device), NM_DBUS_INTERFACE_DEVICE, "Dhcp4Config");
+	if (path) {
+		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);
+	}
+
+	return priv->dhcp4_config;
+}
+
+/**
+ * nm_device_get_ip6_config:
+ * @device: a #NMDevice
+ *
+ * Gets the current #NMIP6Config associated with the #NMDevice.
+ *
+ * Returns: the #NMIP6Config or %NULL if the device is not activated.
+ **/
+NMIP6Config *
+nm_device_get_ip6_config (NMDevice *device)
+{
+	NMDevicePrivate *priv;
+	char *path;
+	GValue value = { 0, };
+
+	g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
+
+	priv = NM_DEVICE_GET_PRIVATE (device);
+	if (priv->ip6_config)
+		return priv->ip6_config;
+	if (priv->null_ip6_config)
+		return NULL;
+
+	path = _nm_object_get_object_path_property (NM_OBJECT (device), NM_DBUS_INTERFACE_DEVICE, "Ip6Config");
+	if (path) {
+		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);
+	}
+
+	return priv->ip6_config;
+}
+
+/**
+ * nm_device_get_dhcp6_config:
+ * @device: a #NMDevice
+ *
+ * Gets the current #NMDHCP6Config associated with the #NMDevice.
+ *
+ * Returns: the #NMDHCPConfig or %NULL if the device is not activated or not
+ * using DHCP.
+ **/
+NMDHCP6Config *
+nm_device_get_dhcp6_config (NMDevice *device)
+{
+	NMDevicePrivate *priv;
+	char *path;
+	GValue value = { 0, };
+
+	g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
+
+	priv = NM_DEVICE_GET_PRIVATE (device);
+	if (priv->dhcp6_config)
+		return priv->dhcp6_config;
+	if (priv->null_dhcp6_config)
+		return NULL;
+
+	path = _nm_object_get_object_path_property (NM_OBJECT (device), NM_DBUS_INTERFACE_DEVICE, "Dhcp6Config");
+	if (path) {
+		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);
+	}
+
+	return priv->dhcp6_config;
+}
+
+/**
+ * nm_device_get_state:
+ * @device: a #NMDevice
+ *
+ * Gets the current #NMDevice state.
+ *
+ * Returns: the current device state
+ **/
+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");
+	}
+
+	return priv->state;
+}
+
+/* From hostap, Copyright (c) 2002-2005, Jouni Malinen <jkmaline@cc.hut.fi> */
+
+static int hex2num (char c)
+{
+	if (c >= '0' && c <= '9')
+		return c - '0';
+	if (c >= 'a' && c <= 'f')
+		return c - 'a' + 10;
+	if (c >= 'A' && c <= 'F')
+		return c - 'A' + 10;
+	return -1;
+}
+
+static int hex2byte (const char *hex)
+{
+	int a, b;
+	a = hex2num(*hex++);
+	if (a < 0)
+		return -1;
+	b = hex2num(*hex++);
+	if (b < 0)
+		return -1;
+	return (a << 4) | b;
+}
+
+/* End from hostap */
+
+static char *
+get_decoded_property (GUdevDevice *device, const char *property)
+{
+	const char *orig, *p;
+	char *unescaped, *n;
+	guint len;
+
+	p = orig = g_udev_device_get_property (device, property);
+	if (!orig)
+		return NULL;
+
+	len = strlen (orig);
+	n = unescaped = g_malloc0 (len + 1);
+	while (*p) {
+		if ((len >= 4) && (*p == '\\') && (*(p+1) == 'x')) {
+			*n++ = (char) hex2byte (p + 2);
+			p += 4;
+			len -= 4;
+		} else {
+			*n++ = *p++;
+			len--;
+		}
+	}
+
+	return unescaped;
+}
+
+static void
+nm_device_update_description (NMDevice *device)
+{
+	NMDevicePrivate *priv;
+	const char *subsys[3] = { "net", "tty", NULL };
+	GUdevDevice *udev_device = NULL, *tmpdev, *olddev;
+	const char *ifname;
+	guint32 count = 0;
+	const char *vendor, *model;
+
+	g_return_if_fail (NM_IS_DEVICE (device));
+	priv = NM_DEVICE_GET_PRIVATE (device);
+
+	if (!priv->client) {
+		priv->client = g_udev_client_new (subsys);
+		if (!priv->client)
+			return;
+	}
+
+	ifname = nm_device_get_iface (device);
+	if (!ifname)
+		return;
+
+	udev_device = g_udev_client_query_by_subsystem_and_name (priv->client, "net", ifname);
+	if (!udev_device)
+		udev_device = g_udev_client_query_by_subsystem_and_name (priv->client, "tty", ifname);
+	if (!udev_device)
+		return;
+
+	g_free (priv->product);
+	priv->product = NULL;
+	g_free (priv->vendor);
+	priv->vendor = NULL;
+
+	/* Walk up the chain of the device and its parents a few steps to grab
+	 * vendor and device ID information off it.
+	 */
+
+	/* Ref the device again becuase we have to unref it each iteration,
+	 * as g_udev_device_get_parent() returns a ref-ed object.
+	 */
+	tmpdev = g_object_ref (udev_device);
+	while ((count++ < 3) && tmpdev && (!priv->vendor || !priv->product)) {
+		if (!priv->vendor)
+			priv->vendor = get_decoded_property (tmpdev, "ID_VENDOR_ENC");
+
+		if (!priv->product)
+			priv->product = get_decoded_property (tmpdev, "ID_MODEL_ENC");
+
+		olddev = tmpdev;
+		tmpdev = g_udev_device_get_parent (tmpdev);
+		g_object_unref (olddev);
+	}
+
+	/* Unref the last device if we found what we needed before running out
+	 * of parents.
+	 */
+	if (tmpdev)
+		g_object_unref (tmpdev);
+
+	/* If we didn't get strings directly from the device, try database strings */
+
+	/* Again, ref the original device as we need to unref it every iteration
+	 * since g_udev_device_get_parent() returns a refed object.
+	 */
+	tmpdev = g_object_ref (udev_device);
+	count = 0;
+	while ((count++ < 3) && tmpdev && (!priv->vendor || !priv->product)) {
+		if (!priv->vendor) {
+			vendor = g_udev_device_get_property (tmpdev, "ID_VENDOR_FROM_DATABASE");
+			if (vendor)
+				priv->vendor = g_strdup (vendor);
+		}
+
+		if (!priv->product) {
+			model = g_udev_device_get_property (tmpdev, "ID_MODEL_FROM_DATABASE");
+			if (model)
+				priv->product = g_strdup (model);
+		}
+
+		olddev = tmpdev;
+		tmpdev = g_udev_device_get_parent (tmpdev);
+		g_object_unref (olddev);
+	}
+
+	/* Unref the last device if we found what we needed before running out
+	 * of parents.
+	 */
+	if (tmpdev)
+		g_object_unref (tmpdev);
+
+	/* Balance the initial g_udev_client_query_by_subsystem_and_name() */
+	g_object_unref (udev_device);
+
+	_nm_object_queue_notify (NM_OBJECT (device), NM_DEVICE_VENDOR);
+	_nm_object_queue_notify (NM_OBJECT (device), NM_DEVICE_PRODUCT);
+}
+
+/**
+ * nm_device_get_product:
+ * @device: a #NMDevice
+ *
+ * Gets the product string of the #NMDevice.
+ *
+ * Returns: the product name of the device. This is the internal string used by the
+ * device, and must not be modified.
+ **/
+const char *
+nm_device_get_product (NMDevice *device)
+{
+	NMDevicePrivate *priv;
+
+	g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
+
+	priv = NM_DEVICE_GET_PRIVATE (device);
+	if (!priv->product)
+		nm_device_update_description (device);
+	return priv->product;
+}
+
+/**
+ * nm_device_get_vendor:
+ * @device: a #NMDevice
+ *
+ * Gets the vendor string of the #NMDevice.
+ *
+ * Returns: the vendor name of the device. This is the internal string used by the
+ * device, and must not be modified.
+ **/
+const char *
+nm_device_get_vendor (NMDevice *device)
+{
+	NMDevicePrivate *priv;
+
+	g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
+
+	priv = NM_DEVICE_GET_PRIVATE (device);
+	if (!priv->vendor)
+		nm_device_update_description (device);
+	return priv->vendor;
+}
+
+typedef struct {
+	NMDevice *device;
+	NMDeviceDeactivateFn fn;
+	gpointer user_data;
+} DeactivateInfo;
+
+static void
+deactivate_cb (DBusGProxy *proxy,
+               GError *error,
+               gpointer user_data)
+{
+	DeactivateInfo *info = user_data;
+
+	if (info->fn)
+		info->fn (info->device, error, info->user_data);
+	else if (error) {
+		g_warning ("%s: device %s deactivation failed: (%d) %s",
+		           __func__,
+		           nm_object_get_path (NM_OBJECT (info->device)),
+		           error ? error->code : -1,
+		           error && error->message ? error->message : "(unknown)");
+	}
+
+	g_object_unref (info->device);
+	g_slice_free (DeactivateInfo, info);
+}
+
+/**
+ * nm_device_disconnect:
+ * @device: a #NMDevice
+ * @callback: callback to be called when disconnect operation completes
+ * @user_data: caller-specific data passed to @callback
+ *
+ * Disconnects the device if currently connected, and prevents the device from
+ * automatically connecting to networks until the next manual network connection
+ * request.
+ **/
+void
+nm_device_disconnect (NMDevice *device,
+                      NMDeviceDeactivateFn callback,
+                      gpointer user_data)
+{
+	DeactivateInfo *info;
+
+	g_return_if_fail (NM_IS_DEVICE (device));
+
+	info = g_slice_new (DeactivateInfo);
+	info->fn = callback;
+	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);
+}
+
diff --git a/libnm-glib/nm-device.h b/libnm-glib/nm-device.h
new file mode 100644
index 00000000..64694ec8
--- /dev/null
+++ b/libnm-glib/nm-device.h
@@ -0,0 +1,107 @@
+/* -*- 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.
+ * Copyright (C) 2007 - 2008 Red Hat, Inc.
+ */
+
+#ifndef NM_DEVICE_H
+#define NM_DEVICE_H
+
+#include <glib.h>
+#include <glib-object.h>
+#include <dbus/dbus-glib.h>
+#include "nm-object.h"
+#include "NetworkManager.h"
+#include "nm-ip4-config.h"
+#include "nm-dhcp4-config.h"
+#include "nm-ip6-config.h"
+#include "nm-dhcp6-config.h"
+#include "nm-connection.h"
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_DEVICE            (nm_device_get_type ())
+#define NM_DEVICE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE, NMDevice))
+#define NM_DEVICE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE, NMDeviceClass))
+#define NM_IS_DEVICE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE))
+#define NM_IS_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_DEVICE))
+#define NM_DEVICE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE, NMDeviceClass))
+
+#define NM_DEVICE_UDI "udi"
+#define NM_DEVICE_INTERFACE "interface"
+#define NM_DEVICE_DRIVER "driver"
+#define NM_DEVICE_CAPABILITIES "capabilities"
+#define NM_DEVICE_MANAGED "managed"
+#define NM_DEVICE_IP4_CONFIG "ip4-config"
+#define NM_DEVICE_DHCP4_CONFIG "dhcp4-config"
+#define NM_DEVICE_IP6_CONFIG "ip6-config"
+#define NM_DEVICE_DHCP6_CONFIG "dhcp6-config"
+#define NM_DEVICE_STATE "state"
+#define NM_DEVICE_VENDOR "vendor"
+#define NM_DEVICE_PRODUCT "product"
+
+typedef struct {
+	NMObject parent;
+} NMDevice;
+
+typedef struct {
+	NMObjectClass parent;
+
+	/* Signals */
+	void (*state_changed) (NMDevice *device,
+	                       NMDeviceState new_state,
+	                       NMDeviceState old_state,
+	                       NMDeviceStateReason reason);
+
+	/* Padding for future expansion */
+	void (*_reserved1) (void);
+	void (*_reserved2) (void);
+	void (*_reserved3) (void);
+	void (*_reserved4) (void);
+	void (*_reserved5) (void);
+	void (*_reserved6) (void);
+} NMDeviceClass;
+
+GType nm_device_get_type (void);
+
+GObject * nm_device_new (DBusGConnection *connection, const char *path);
+
+const char *  nm_device_get_iface          (NMDevice *device);
+const char *  nm_device_get_udi            (NMDevice *device);
+const char *  nm_device_get_driver         (NMDevice *device);
+guint32       nm_device_get_capabilities   (NMDevice *device);
+gboolean      nm_device_get_managed        (NMDevice *device);
+NMIP4Config * nm_device_get_ip4_config     (NMDevice *device);
+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);
+const char *  nm_device_get_product        (NMDevice *device);
+const char *  nm_device_get_vendor         (NMDevice *device);
+
+typedef void (*NMDeviceDeactivateFn) (NMDevice *device, GError *error, gpointer user_data);
+
+void          nm_device_disconnect         (NMDevice *device,
+                                            NMDeviceDeactivateFn callback,
+                                            gpointer user_data);
+
+G_END_DECLS
+
+#endif /* NM_DEVICE_H */
diff --git a/libnm-glib/nm-dhcp4-config.c b/libnm-glib/nm-dhcp4-config.c
new file mode 100644
index 00000000..c87feedf
--- /dev/null
+++ b/libnm-glib/nm-dhcp4-config.c
@@ -0,0 +1,248 @@
+/* -*- 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) 2008 Red Hat, Inc.
+ * Copyright (C) 2008 Novell, Inc.
+ */
+
+#include <string.h>
+
+#include "nm-dhcp4-config.h"
+#include "NetworkManager.h"
+#include "nm-types-private.h"
+#include "nm-object-private.h"
+#include "nm-utils.h"
+
+G_DEFINE_TYPE (NMDHCP4Config, nm_dhcp4_config, NM_TYPE_OBJECT)
+
+#define NM_DHCP4_CONFIG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DHCP4_CONFIG, NMDHCP4ConfigPrivate))
+
+typedef struct {
+	DBusGProxy *proxy;
+
+	GHashTable *options;
+} NMDHCP4ConfigPrivate;
+
+enum {
+	PROP_0,
+	PROP_OPTIONS,
+
+	LAST_PROP
+};
+
+static void
+nm_dhcp4_config_init (NMDHCP4Config *config)
+{
+}
+
+static void
+copy_options (gpointer key, gpointer data, gpointer user_data)
+{
+	GHashTable *options = (GHashTable *) user_data;
+	GValue *value = (GValue *) data;
+
+	g_hash_table_insert (options, g_strdup (key), g_value_dup_string (value));
+}
+
+static gboolean
+demarshal_dhcp4_options (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field)
+{
+	NMDHCP4ConfigPrivate *priv = NM_DHCP4_CONFIG_GET_PRIVATE (object);
+	GHashTable *new_options;
+
+	g_hash_table_remove_all (priv->options);
+
+	new_options = g_value_get_boxed (value);
+	if (new_options)
+		g_hash_table_foreach (new_options, copy_options, priv->options);
+
+	_nm_object_queue_notify (object, NM_DHCP4_CONFIG_OPTIONS);
+	return TRUE;
+}
+
+static void
+register_for_property_changed (NMDHCP4Config *config)
+{
+	NMDHCP4ConfigPrivate *priv = NM_DHCP4_CONFIG_GET_PRIVATE (config);
+	const NMPropertiesChangedInfo property_changed_info[] = {
+		{ NM_DHCP4_CONFIG_OPTIONS,   demarshal_dhcp4_options,  &priv->options },
+		{ NULL },
+	};
+
+	_nm_object_handle_properties_changed (NM_OBJECT (config),
+	                                     priv->proxy,
+	                                     property_changed_info);
+}
+
+static GObject*
+constructor (GType type,
+		   guint n_construct_params,
+		   GObjectConstructParam *construct_params)
+{
+	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;
+
+	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);
+
+	priv->proxy = dbus_g_proxy_new_for_name (connection,
+										   NM_DBUS_SERVICE,
+										   nm_object_get_path (object),
+										   NM_DBUS_INTERFACE_DHCP4_CONFIG);
+
+	register_for_property_changed (NM_DHCP4_CONFIG (object));
+
+	return G_OBJECT (object);
+}
+
+static void
+finalize (GObject *object)
+{
+	NMDHCP4ConfigPrivate *priv = NM_DHCP4_CONFIG_GET_PRIVATE (object);
+
+	if (priv->options)
+		g_hash_table_destroy (priv->options);
+
+	g_object_unref (priv->proxy);
+
+	G_OBJECT_CLASS (nm_dhcp4_config_parent_class)->finalize (object);
+}
+
+static void
+get_property (GObject *object,
+              guint prop_id,
+              GValue *value,
+              GParamSpec *pspec)
+{
+	NMDHCP4Config *self = NM_DHCP4_CONFIG (object);
+
+	switch (prop_id) {
+	case PROP_OPTIONS:
+		g_value_set_boxed (value, nm_dhcp4_config_get_options (self));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+nm_dhcp4_config_class_init (NMDHCP4ConfigClass *config_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (config_class);
+
+	g_type_class_add_private (config_class, sizeof (NMDHCP4ConfigPrivate));
+
+	/* virtual methods */
+	object_class->constructor = constructor;
+	object_class->get_property = get_property;
+	object_class->finalize = finalize;
+
+	/* properties */
+
+	/**
+	 * NMDHCP4Config:options:
+	 *
+	 * The #GHashTable containing options of the configuration.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_OPTIONS,
+		 g_param_spec_boxed (NM_DHCP4_CONFIG_OPTIONS,
+						       "Options",
+						       "Options",
+						       G_TYPE_HASH_TABLE,
+						       G_PARAM_READABLE));
+}
+
+/**
+ * nm_dhcp4_config_new:
+ * @connection: the #DBusGConnection
+ * @object_path: the DBus object path of the device
+ *
+ * Creates a new #NMDHCP4Config.
+ *
+ * Returns: a new configuration
+ **/
+GObject *
+nm_dhcp4_config_new (DBusGConnection *connection, const char *object_path)
+{
+	return (GObject *) g_object_new (NM_TYPE_DHCP4_CONFIG,
+									 NM_OBJECT_DBUS_CONNECTION, connection,
+									 NM_OBJECT_DBUS_PATH, object_path,
+									 NULL);
+}
+
+/**
+ * nm_dhcp4_config_get_options:
+ * @config: a #NMDHCP4Config
+ *
+ * Gets all the options contained in the configuration.
+ *
+ * Returns: the #GHashTable containing strings for keys and values.
+ * This is the internal copy used by the configuration, and must not be modified.
+ **/
+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),
+	                             "org.freedesktop.DBus.Properties",
+	                             "Options",
+	                             &value))
+		goto out;
+
+	demarshal_dhcp4_options (NM_OBJECT (config), NULL, &value, &priv->options);	
+	g_value_unset (&value);
+
+out:
+	return priv->options;
+}
+
+/**
+ * nm_dhcp4_config_get_one_option:
+ * @config: a #NMDHCP4Config
+ * @option: the option to retrieve
+ *
+ * Gets one option by option name.
+ *
+ * Returns: the configuration option's value. This is the internal string used by the
+ * configuration, and must not be modified.
+ **/
+const char *
+nm_dhcp4_config_get_one_option (NMDHCP4Config *config, const char *option)
+{
+	g_return_val_if_fail (NM_IS_DHCP4_CONFIG (config), NULL);
+
+	return g_hash_table_lookup (nm_dhcp4_config_get_options (config), option);
+}
+
diff --git a/libnm-glib/nm-dhcp4-config.h b/libnm-glib/nm-dhcp4-config.h
new file mode 100644
index 00000000..da5b57b3
--- /dev/null
+++ b/libnm-glib/nm-dhcp4-config.h
@@ -0,0 +1,68 @@
+/* -*- 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) 2008 Red Hat, Inc.
+ * Copyright (C) 2008 Novell, Inc.
+ */
+
+#ifndef NM_DHCP4_CONFIG_H
+#define NM_DHCP4_CONFIG_H
+
+#include <glib.h>
+#include <glib-object.h>
+#include <dbus/dbus-glib.h>
+#include "nm-object.h"
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_DHCP4_CONFIG            (nm_dhcp4_config_get_type ())
+#define NM_DHCP4_CONFIG(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DHCP4_CONFIG, NMDHCP4Config))
+#define NM_DHCP4_CONFIG_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DHCP4_CONFIG, NMDHCP4ConfigClass))
+#define NM_IS_DHCP4_CONFIG(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DHCP4_CONFIG))
+#define NM_IS_DHCP4_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_DHCP4_CONFIG))
+
+typedef struct {
+	NMObject parent;
+} NMDHCP4Config;
+
+typedef struct {
+	NMObjectClass parent;
+
+	/* Padding for future expansion */
+	void (*_reserved1) (void);
+	void (*_reserved2) (void);
+	void (*_reserved3) (void);
+	void (*_reserved4) (void);
+	void (*_reserved5) (void);
+	void (*_reserved6) (void);
+} NMDHCP4ConfigClass;
+
+#define NM_DHCP4_CONFIG_OPTIONS "options"
+
+GType nm_dhcp4_config_get_type (void);
+
+GObject *nm_dhcp4_config_new (DBusGConnection *connection, const char *object_path);
+
+GHashTable * nm_dhcp4_config_get_options (NMDHCP4Config *config);
+
+const char * nm_dhcp4_config_get_one_option (NMDHCP4Config *config, const char *option);
+
+G_END_DECLS
+
+#endif /* NM_DHCP4_CONFIG_H */
diff --git a/libnm-glib/nm-dhcp6-config.c b/libnm-glib/nm-dhcp6-config.c
new file mode 100644
index 00000000..49eeda39
--- /dev/null
+++ b/libnm-glib/nm-dhcp6-config.c
@@ -0,0 +1,248 @@
+/* -*- 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) 2008 - 2010 Red Hat, Inc.
+ * Copyright (C) 2008 Novell, Inc.
+ */
+
+#include <string.h>
+
+#include "nm-dhcp6-config.h"
+#include "NetworkManager.h"
+#include "nm-types-private.h"
+#include "nm-object-private.h"
+#include "nm-utils.h"
+
+G_DEFINE_TYPE (NMDHCP6Config, nm_dhcp6_config, NM_TYPE_OBJECT)
+
+#define NM_DHCP6_CONFIG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DHCP6_CONFIG, NMDHCP6ConfigPrivate))
+
+typedef struct {
+	DBusGProxy *proxy;
+
+	GHashTable *options;
+} NMDHCP6ConfigPrivate;
+
+enum {
+	PROP_0,
+	PROP_OPTIONS,
+
+	LAST_PROP
+};
+
+static void
+nm_dhcp6_config_init (NMDHCP6Config *config)
+{
+}
+
+static void
+copy_options (gpointer key, gpointer data, gpointer user_data)
+{
+	GHashTable *options = (GHashTable *) user_data;
+	GValue *value = (GValue *) data;
+
+	g_hash_table_insert (options, g_strdup (key), g_value_dup_string (value));
+}
+
+static gboolean
+demarshal_dhcp6_options (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field)
+{
+	NMDHCP6ConfigPrivate *priv = NM_DHCP6_CONFIG_GET_PRIVATE (object);
+	GHashTable *new_options;
+
+	g_hash_table_remove_all (priv->options);
+
+	new_options = g_value_get_boxed (value);
+	if (new_options)
+		g_hash_table_foreach (new_options, copy_options, priv->options);
+
+	_nm_object_queue_notify (object, NM_DHCP6_CONFIG_OPTIONS);
+	return TRUE;
+}
+
+static void
+register_for_property_changed (NMDHCP6Config *config)
+{
+	NMDHCP6ConfigPrivate *priv = NM_DHCP6_CONFIG_GET_PRIVATE (config);
+	const NMPropertiesChangedInfo property_changed_info[] = {
+		{ NM_DHCP6_CONFIG_OPTIONS,   demarshal_dhcp6_options,  &priv->options },
+		{ NULL },
+	};
+
+	_nm_object_handle_properties_changed (NM_OBJECT (config),
+	                                     priv->proxy,
+	                                     property_changed_info);
+}
+
+static GObject*
+constructor (GType type,
+		   guint n_construct_params,
+		   GObjectConstructParam *construct_params)
+{
+	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;
+
+	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);
+
+	priv->proxy = dbus_g_proxy_new_for_name (connection,
+										   NM_DBUS_SERVICE,
+										   nm_object_get_path (object),
+										   NM_DBUS_INTERFACE_DHCP6_CONFIG);
+
+	register_for_property_changed (NM_DHCP6_CONFIG (object));
+
+	return G_OBJECT (object);
+}
+
+static void
+finalize (GObject *object)
+{
+	NMDHCP6ConfigPrivate *priv = NM_DHCP6_CONFIG_GET_PRIVATE (object);
+
+	if (priv->options)
+		g_hash_table_destroy (priv->options);
+
+	g_object_unref (priv->proxy);
+
+	G_OBJECT_CLASS (nm_dhcp6_config_parent_class)->finalize (object);
+}
+
+static void
+get_property (GObject *object,
+              guint prop_id,
+              GValue *value,
+              GParamSpec *pspec)
+{
+	NMDHCP6Config *self = NM_DHCP6_CONFIG (object);
+
+	switch (prop_id) {
+	case PROP_OPTIONS:
+		g_value_set_boxed (value, nm_dhcp6_config_get_options (self));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+nm_dhcp6_config_class_init (NMDHCP6ConfigClass *config_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (config_class);
+
+	g_type_class_add_private (config_class, sizeof (NMDHCP6ConfigPrivate));
+
+	/* virtual methods */
+	object_class->constructor = constructor;
+	object_class->get_property = get_property;
+	object_class->finalize = finalize;
+
+	/* properties */
+
+	/**
+	 * NMDHCP6Config:options:
+	 *
+	 * The #GHashTable containing options of the configuration.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_OPTIONS,
+		 g_param_spec_boxed (NM_DHCP6_CONFIG_OPTIONS,
+						       "Options",
+						       "Options",
+						       G_TYPE_HASH_TABLE,
+						       G_PARAM_READABLE));
+}
+
+/**
+ * nm_dhcp6_config_new:
+ * @connection: the #DBusGConnection
+ * @object_path: the DBus object path of the device
+ *
+ * Creates a new #NMDHCP6Config.
+ *
+ * Returns: a new configuration
+ **/
+GObject *
+nm_dhcp6_config_new (DBusGConnection *connection, const char *object_path)
+{
+	return (GObject *) g_object_new (NM_TYPE_DHCP6_CONFIG,
+									 NM_OBJECT_DBUS_CONNECTION, connection,
+									 NM_OBJECT_DBUS_PATH, object_path,
+									 NULL);
+}
+
+/**
+ * nm_dhcp6_config_get_options:
+ * @config: a #NMDHCP6Config
+ *
+ * Gets all the options contained in the configuration.
+ *
+ * Returns: the #GHashTable containing strings for keys and values.
+ * This is the internal copy used by the configuration, and must not be modified.
+ **/
+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),
+	                             "org.freedesktop.DBus.Properties",
+	                             "Options",
+	                             &value))
+		goto out;
+
+	demarshal_dhcp6_options (NM_OBJECT (config), NULL, &value, &priv->options);	
+	g_value_unset (&value);
+
+out:
+	return priv->options;
+}
+
+/**
+ * nm_dhcp6_config_get_one_option:
+ * @config: a #NMDHCP6Config
+ * @option: the option to retrieve
+ *
+ * Gets one option by option name.
+ *
+ * Returns: the configuration option's value. This is the internal string used by the
+ * configuration, and must not be modified.
+ **/
+const char *
+nm_dhcp6_config_get_one_option (NMDHCP6Config *config, const char *option)
+{
+	g_return_val_if_fail (NM_IS_DHCP6_CONFIG (config), NULL);
+
+	return g_hash_table_lookup (nm_dhcp6_config_get_options (config), option);
+}
+
diff --git a/libnm-glib/nm-dhcp6-config.h b/libnm-glib/nm-dhcp6-config.h
new file mode 100644
index 00000000..91f32fa0
--- /dev/null
+++ b/libnm-glib/nm-dhcp6-config.h
@@ -0,0 +1,68 @@
+/* -*- 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) 2008 - 2010 Red Hat, Inc.
+ * Copyright (C) 2008 Novell, Inc.
+ */
+
+#ifndef NM_DHCP6_CONFIG_H
+#define NM_DHCP6_CONFIG_H
+
+#include <glib.h>
+#include <glib-object.h>
+#include <dbus/dbus-glib.h>
+#include "nm-object.h"
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_DHCP6_CONFIG            (nm_dhcp6_config_get_type ())
+#define NM_DHCP6_CONFIG(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DHCP6_CONFIG, NMDHCP6Config))
+#define NM_DHCP6_CONFIG_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DHCP6_CONFIG, NMDHCP6ConfigClass))
+#define NM_IS_DHCP6_CONFIG(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DHCP6_CONFIG))
+#define NM_IS_DHCP6_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_DHCP6_CONFIG))
+
+typedef struct {
+	NMObject parent;
+} NMDHCP6Config;
+
+typedef struct {
+	NMObjectClass parent;
+
+	/* Padding for future expansion */
+	void (*_reserved1) (void);
+	void (*_reserved2) (void);
+	void (*_reserved3) (void);
+	void (*_reserved4) (void);
+	void (*_reserved5) (void);
+	void (*_reserved6) (void);
+} NMDHCP6ConfigClass;
+
+#define NM_DHCP6_CONFIG_OPTIONS "options"
+
+GType nm_dhcp6_config_get_type (void);
+
+GObject *nm_dhcp6_config_new (DBusGConnection *connection, const char *object_path);
+
+GHashTable * nm_dhcp6_config_get_options (NMDHCP6Config *config);
+
+const char * nm_dhcp6_config_get_one_option (NMDHCP6Config *config, const char *option);
+
+G_END_DECLS
+
+#endif /* NM_DHCP6_CONFIG_H */
diff --git a/libnm-glib/nm-exported-connection.c b/libnm-glib/nm-exported-connection.c
new file mode 100644
index 00000000..3a8e51ce
--- /dev/null
+++ b/libnm-glib/nm-exported-connection.c
@@ -0,0 +1,281 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager system settings service
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2008 Novell, Inc.
+ * (C) Copyright 2008 - 2009 Red Hat, Inc.
+ */
+
+#include <NetworkManager.h>
+#include <dbus/dbus-glib-lowlevel.h>
+#include <nm-setting-connection.h>
+
+#include "nm-exported-connection.h"
+#include "nm-settings-interface.h"
+#include "nm-settings-connection-interface.h"
+
+static gboolean impl_exported_connection_get_settings (NMExportedConnection *connection,
+                                                       GHashTable **settings,
+                                                       GError **error);
+
+static void impl_exported_connection_update (NMExportedConnection *connection,
+                                             GHashTable *new_settings,
+                                             DBusGMethodInvocation *context);
+
+static void impl_exported_connection_delete (NMExportedConnection *connection,
+                                             DBusGMethodInvocation *context);
+
+static void impl_exported_connection_get_secrets (NMExportedConnection *connection,
+                                                  const gchar *setting_name,
+                                                  const gchar **hints,
+                                                  gboolean request_new,
+                                                  DBusGMethodInvocation *context);
+
+#include "nm-exported-connection-glue.h"
+
+static void settings_connection_interface_init (NMSettingsConnectionInterface *class);
+
+G_DEFINE_TYPE_EXTENDED (NMExportedConnection, nm_exported_connection, NM_TYPE_CONNECTION, 0,
+                        G_IMPLEMENT_INTERFACE (NM_TYPE_SETTINGS_CONNECTION_INTERFACE,
+                                               settings_connection_interface_init))
+
+#define NM_EXPORTED_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
+                                               NM_TYPE_EXPORTED_CONNECTION, \
+                                               NMExportedConnectionPrivate))
+
+typedef struct {
+	gboolean foo;
+} NMExportedConnectionPrivate;
+
+
+/**************************************************************/
+
+static GHashTable *
+real_get_settings (NMExportedConnection *self, GError **error)
+{
+	NMConnection *no_secrets;
+	GHashTable *settings;
+
+	/* Secrets should *never* be returned by the GetSettings method, they
+	 * get returned by the GetSecrets method which can be better
+	 * protected against leakage of secrets to unprivileged callers.
+	 */
+	no_secrets = nm_connection_duplicate (NM_CONNECTION (self));
+	g_assert (no_secrets);
+	nm_connection_clear_secrets (no_secrets);
+	settings = nm_connection_to_hash (no_secrets);
+	g_assert (settings);
+	g_object_unref (no_secrets);
+
+	return settings;
+}
+
+/**************************************************************/
+
+static gboolean
+check_writable (NMConnection *connection, GError **error)
+{
+	NMSettingConnection *s_con;
+
+	g_return_val_if_fail (connection != NULL, FALSE);
+	g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
+
+	s_con = (NMSettingConnection *) nm_connection_get_setting (connection,
+	                                                           NM_TYPE_SETTING_CONNECTION);
+	if (!s_con) {
+		g_set_error_literal (error,
+		                     NM_SETTINGS_INTERFACE_ERROR,
+		                     NM_SETTINGS_INTERFACE_ERROR_INVALID_CONNECTION,
+		                     "Connection did not have required 'connection' setting");
+		return FALSE;
+	}
+
+	/* If the connection is read-only, that has to be changed at the source of
+	 * the problem (ex a system settings plugin that can't write connections out)
+	 * instead of over D-Bus.
+	 */
+	if (nm_setting_connection_get_read_only (s_con)) {
+		g_set_error_literal (error,
+		                     NM_SETTINGS_INTERFACE_ERROR,
+		                     NM_SETTINGS_INTERFACE_ERROR_READ_ONLY_CONNECTION,
+		                     "Connection is read-only");
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+static gboolean
+impl_exported_connection_get_settings (NMExportedConnection *self,
+                                       GHashTable **settings,
+                                       GError **error)
+{
+	/* Must always be implemented */
+	g_assert (NM_EXPORTED_CONNECTION_GET_CLASS (self)->get_settings);
+	*settings = NM_EXPORTED_CONNECTION_GET_CLASS (self)->get_settings (self, error);
+	return *settings ? TRUE : FALSE;
+}
+
+static gboolean
+update (NMSettingsConnectionInterface *connection,
+	    NMSettingsConnectionInterfaceUpdateFunc callback,
+	    gpointer user_data)
+{
+	g_object_ref (connection);
+	nm_settings_connection_interface_emit_updated (connection);
+	callback (connection, NULL, user_data);
+	g_object_unref (connection);
+	return TRUE;
+}
+
+static void
+impl_exported_connection_update (NMExportedConnection *self,
+                                 GHashTable *new_settings,
+                                 DBusGMethodInvocation *context)
+{
+	NMConnection *tmp;
+	GError *error = NULL;
+
+	/* If the connection is read-only, that has to be changed at the source of
+	 * the problem (ex a system settings plugin that can't write connections out)
+	 * instead of over D-Bus.
+	 */
+	if (!check_writable (NM_CONNECTION (self), &error)) {
+		dbus_g_method_return_error (context, error);
+		g_error_free (error);
+		return;
+	}
+
+	/* Check if the settings are valid first */
+	tmp = nm_connection_new_from_hash (new_settings, &error);
+	if (!tmp) {
+		g_assert (error);
+		dbus_g_method_return_error (context, error);
+		g_error_free (error);
+		return;
+	}
+	g_object_unref (tmp);
+
+	if (NM_EXPORTED_CONNECTION_GET_CLASS (self)->update)
+		NM_EXPORTED_CONNECTION_GET_CLASS (self)->update (self, new_settings, context);
+	else {
+		error = g_error_new (NM_SETTINGS_INTERFACE_ERROR,
+		                     NM_SETTINGS_INTERFACE_ERROR_INTERNAL_ERROR,
+		                     "%s: %s:%d update() unimplemented", __func__, __FILE__, __LINE__);
+		dbus_g_method_return_error (context, error);
+		g_error_free (error);
+	}
+}
+
+static gboolean
+do_delete (NMSettingsConnectionInterface *connection,
+	       NMSettingsConnectionInterfaceDeleteFunc callback,
+	       gpointer user_data)
+{
+	g_object_ref (connection);
+	g_signal_emit_by_name (connection, "removed");
+	callback (connection, NULL, user_data);
+	g_object_unref (connection);
+	return TRUE;
+}
+
+static void
+impl_exported_connection_delete (NMExportedConnection *self,
+                                 DBusGMethodInvocation *context)
+{
+	GError *error = NULL;
+
+	if (!check_writable (NM_CONNECTION (self), &error)) {
+		dbus_g_method_return_error (context, error);
+		g_error_free (error);
+		return;
+	}
+
+	if (NM_EXPORTED_CONNECTION_GET_CLASS (self)->delete)
+		NM_EXPORTED_CONNECTION_GET_CLASS (self)->delete (self, context);
+	else {
+		error = g_error_new (NM_SETTINGS_INTERFACE_ERROR,
+		                     NM_SETTINGS_INTERFACE_ERROR_INTERNAL_ERROR,
+		                     "%s: %s:%d delete() unimplemented", __func__, __FILE__, __LINE__);
+		dbus_g_method_return_error (context, error);
+		g_error_free (error);
+	}
+}
+
+static void
+impl_exported_connection_get_secrets (NMExportedConnection *self,
+                                      const gchar *setting_name,
+                                      const gchar **hints,
+                                      gboolean request_new,
+                                      DBusGMethodInvocation *context)
+{
+	GError *error = NULL;
+
+	if (NM_EXPORTED_CONNECTION_GET_CLASS (self)->get_secrets)
+		NM_EXPORTED_CONNECTION_GET_CLASS (self)->get_secrets (self, setting_name, hints, request_new, context);
+	else {
+		error = g_error_new (NM_SETTINGS_INTERFACE_ERROR,
+		                     NM_SETTINGS_INTERFACE_ERROR_INTERNAL_ERROR,
+		                     "%s: %s:%d get_secrets() unimplemented", __func__, __FILE__, __LINE__);
+		dbus_g_method_return_error (context, error);
+		g_error_free (error);
+	}
+}
+
+/**************************************************************/
+
+static void
+settings_connection_interface_init (NMSettingsConnectionInterface *iface)
+{
+	iface->update = update;
+	iface->delete = do_delete;
+}
+
+/**
+ * nm_exported_connection_new:
+ * @scope: the Connection scope (either user or system)
+ *
+ * Creates a new object representing the remote connection.
+ *
+ * Returns: the new exported connection object on success, or %NULL on failure
+ **/
+NMExportedConnection *
+nm_exported_connection_new (NMConnectionScope scope)
+{
+	g_return_val_if_fail (scope != NM_CONNECTION_SCOPE_UNKNOWN, NULL);
+
+	return (NMExportedConnection *) g_object_new (NM_TYPE_EXPORTED_CONNECTION,
+	                                              NM_CONNECTION_SCOPE, scope,
+	                                              NULL);
+}
+
+static void
+nm_exported_connection_init (NMExportedConnection *self)
+{
+}
+
+static void
+nm_exported_connection_class_init (NMExportedConnectionClass *class)
+{
+	g_type_class_add_private (class, sizeof (NMExportedConnectionPrivate));
+
+	/* Virtual methods */
+	class->get_settings = real_get_settings;
+
+	dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (class),
+	                                 &dbus_glib_nm_exported_connection_object_info);
+}
diff --git a/libnm-glib/nm-exported-connection.h b/libnm-glib/nm-exported-connection.h
new file mode 100644
index 00000000..53dc3b02
--- /dev/null
+++ b/libnm-glib/nm-exported-connection.h
@@ -0,0 +1,75 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager system settings service
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2009 Red Hat, Inc.
+ */
+
+#ifndef NM_EXPORTED_CONNECTION_H
+#define NM_EXPORTED_CONNECTION_H
+
+#include <nm-connection.h>
+#include <dbus/dbus-glib.h>
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_EXPORTED_CONNECTION            (nm_exported_connection_get_type ())
+#define NM_EXPORTED_CONNECTION(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_EXPORTED_CONNECTION, NMExportedConnection))
+#define NM_EXPORTED_CONNECTION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_EXPORTED_CONNECTION, NMExportedConnectionClass))
+#define NM_IS_EXPORTED_CONNECTION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_EXPORTED_CONNECTION))
+#define NM_IS_EXPORTED_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_EXPORTED_CONNECTION))
+#define NM_EXPORTED_CONNECTION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_EXPORTED_CONNECTION, NMExportedConnectionClass))
+
+typedef struct {
+	NMConnection parent;
+} NMExportedConnection;
+
+typedef struct {
+	NMConnectionClass parent;
+
+	GHashTable * (*get_settings) (NMExportedConnection *self,
+	                              GError **error);
+
+	void (*update) (NMExportedConnection *self,
+	                GHashTable *new_settings,
+	                DBusGMethodInvocation *context);
+
+	void (*delete) (NMExportedConnection *self,
+	                DBusGMethodInvocation *context);
+
+	void (*get_secrets) (NMExportedConnection *self,
+	                     const gchar *setting_name,
+	                     const gchar **hints,
+	                     gboolean request_new,
+	                     DBusGMethodInvocation *context);
+
+	/* Padding for future expansion */
+	void (*_reserved1) (void);
+	void (*_reserved2) (void);
+	void (*_reserved3) (void);
+	void (*_reserved4) (void);
+	void (*_reserved5) (void);
+	void (*_reserved6) (void);
+} NMExportedConnectionClass;
+
+GType nm_exported_connection_get_type (void);
+
+NMExportedConnection *nm_exported_connection_new (NMConnectionScope scope);
+
+G_END_DECLS
+
+#endif /* NM_EXPORTED_CONNECTION_H */
diff --git a/libnm-glib/nm-gsm-device.c b/libnm-glib/nm-gsm-device.c
new file mode 100644
index 00000000..aacbbb82
--- /dev/null
+++ b/libnm-glib/nm-gsm-device.c
@@ -0,0 +1,130 @@
+/* -*- 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.
+ * Copyright (C) 2007 - 2008 Red Hat, Inc.
+ */
+
+#include "nm-gsm-device.h"
+#include "nm-device-private.h"
+#include "nm-object-private.h"
+
+G_DEFINE_TYPE (NMGsmDevice, nm_gsm_device, NM_TYPE_SERIAL_DEVICE)
+
+#define NM_GSM_DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_GSM_DEVICE, NMGsmDevicePrivate))
+
+typedef struct {
+	DBusGProxy *proxy;
+
+	gboolean disposed;
+} NMGsmDevicePrivate;
+
+static void
+nm_gsm_device_init (NMGsmDevice *device)
+{
+}
+
+static void
+register_for_property_changed (NMGsmDevice *device)
+{
+	NMGsmDevicePrivate *priv = NM_GSM_DEVICE_GET_PRIVATE (device);
+	const NMPropertiesChangedInfo property_changed_info[] = {
+		{ NULL },
+	};
+
+	_nm_object_handle_properties_changed (NM_OBJECT (device),
+	                                     priv->proxy,
+	                                     property_changed_info);
+}
+
+static GObject*
+constructor (GType type,
+             guint n_construct_params,
+             GObjectConstructParam *construct_params)
+{
+	GObject *object;
+	NMGsmDevicePrivate *priv;
+
+	object = G_OBJECT_CLASS (nm_gsm_device_parent_class)->constructor (type,
+														  n_construct_params,
+														  construct_params);
+	if (!object)
+		return NULL;
+
+	priv = NM_GSM_DEVICE_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_GSM_DEVICE);
+
+	register_for_property_changed (NM_GSM_DEVICE (object));
+
+	return object;
+}
+
+static void
+dispose (GObject *object)
+{
+	NMGsmDevicePrivate *priv = NM_GSM_DEVICE_GET_PRIVATE (object);
+
+	if (priv->disposed) {
+		G_OBJECT_CLASS (nm_gsm_device_parent_class)->dispose (object);
+		return;
+	}
+
+	priv->disposed = TRUE;
+
+	g_object_unref (priv->proxy);
+
+	G_OBJECT_CLASS (nm_gsm_device_parent_class)->dispose (object);
+}
+
+static void
+nm_gsm_device_class_init (NMGsmDeviceClass *device_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (device_class);
+
+	g_type_class_add_private (device_class, sizeof (NMGsmDevicePrivate));
+
+	/* virtual methods */
+	object_class->constructor = constructor;
+	object_class->dispose = dispose;
+}
+
+/**
+ * nm_gsm_device_new:
+ * @connection: the #DBusGConnection
+ * @path: the DBus object path of the device
+ *
+ * Creates a new #NMGsmDevice.
+ *
+ * Returns: a new device
+ **/
+NMGsmDevice *
+nm_gsm_device_new (DBusGConnection *connection, const char *path)
+{
+	g_return_val_if_fail (connection != NULL, NULL);
+	g_return_val_if_fail (path != NULL, NULL);
+
+	return (NMGsmDevice *) g_object_new (NM_TYPE_GSM_DEVICE,
+								  NM_OBJECT_DBUS_CONNECTION, connection,
+								  NM_OBJECT_DBUS_PATH, path,
+								  NULL);
+}
diff --git a/libnm-glib/nm-gsm-device.h b/libnm-glib/nm-gsm-device.h
new file mode 100644
index 00000000..d8440973
--- /dev/null
+++ b/libnm-glib/nm-gsm-device.h
@@ -0,0 +1,61 @@
+/* -*- 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.
+ * Copyright (C) 2007 - 2008 Red Hat, Inc.
+ */
+
+#ifndef NM_GSM_DEVICE_H
+#define NM_GSM_DEVICE_H
+
+#include "nm-serial-device.h"
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_GSM_DEVICE            (nm_gsm_device_get_type ())
+#define NM_GSM_DEVICE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_GSM_DEVICE, NMGsmDevice))
+#define NM_GSM_DEVICE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_GSM_DEVICE, NMGsmDeviceClass))
+#define NM_IS_GSM_DEVICE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_GSM_DEVICE))
+#define NM_IS_GSM_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_GSM_DEVICE))
+#define NM_GSM_DEVICE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_GSM_DEVICE, NMGsmDeviceClass))
+
+typedef struct {
+	NMSerialDevice parent;
+} NMGsmDevice;
+
+typedef struct {
+	NMSerialDeviceClass parent;
+
+	/* Padding for future expansion */
+	void (*_reserved1) (void);
+	void (*_reserved2) (void);
+	void (*_reserved3) (void);
+	void (*_reserved4) (void);
+	void (*_reserved5) (void);
+	void (*_reserved6) (void);
+} NMGsmDeviceClass;
+
+GType        nm_gsm_device_get_type (void);
+
+NMGsmDevice *nm_gsm_device_new (DBusGConnection *connection,
+						  const char *path);
+
+G_END_DECLS
+
+#endif /* NM_GSM_DEVICE_H */
diff --git a/libnm-glib/nm-ip4-config.c b/libnm-glib/nm-ip4-config.c
new file mode 100644
index 00000000..4bedc7a1
--- /dev/null
+++ b/libnm-glib/nm-ip4-config.c
@@ -0,0 +1,526 @@
+/* -*- 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.
+ * Copyright (C) 2008 Red Hat, Inc.
+ */
+
+#include <string.h>
+
+#include <nm-setting-ip4-config.h>
+#include "nm-ip4-config.h"
+#include "NetworkManager.h"
+#include "nm-types-private.h"
+#include "nm-object-private.h"
+#include "nm-utils.h"
+
+G_DEFINE_TYPE (NMIP4Config, nm_ip4_config, NM_TYPE_OBJECT)
+
+#define NM_IP4_CONFIG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_IP4_CONFIG, NMIP4ConfigPrivate))
+
+typedef struct {
+	DBusGProxy *proxy;
+
+	GSList *addresses;
+	GArray *nameservers;
+	GPtrArray *domains;
+	GSList *routes;
+	GArray *wins;
+} NMIP4ConfigPrivate;
+
+enum {
+	PROP_0,
+	PROP_ADDRESSES,
+	PROP_HOSTNAME,
+	PROP_NAMESERVERS,
+	PROP_DOMAINS,
+	PROP_ROUTES,
+	PROP_WINS_SERVERS,
+
+	LAST_PROP
+};
+
+static void
+nm_ip4_config_init (NMIP4Config *config)
+{
+}
+
+static gboolean
+demarshal_ip4_address_array (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field)
+{
+	NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (object);
+
+	g_slist_foreach (priv->addresses, (GFunc) nm_ip4_address_unref, NULL);
+	g_slist_free (priv->addresses);
+	priv->addresses = NULL;
+
+	priv->addresses = nm_utils_ip4_addresses_from_gvalue (value);
+	_nm_object_queue_notify (object, NM_IP4_CONFIG_ADDRESSES);
+
+	return TRUE;
+}
+
+static gboolean
+demarshal_ip4_array (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field)
+{
+	if (!_nm_uint_array_demarshal (value, (GArray **) field))
+		return FALSE;
+
+	if (!strcmp (pspec->name, NM_IP4_CONFIG_NAMESERVERS))
+		_nm_object_queue_notify (object, NM_IP4_CONFIG_NAMESERVERS);
+	else if (!strcmp (pspec->name, NM_IP4_CONFIG_WINS_SERVERS))
+		_nm_object_queue_notify (object, NM_IP4_CONFIG_WINS_SERVERS);
+
+	return TRUE;
+}
+
+static gboolean
+demarshal_domains (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field)
+{
+	if (!_nm_string_array_demarshal (value, (GPtrArray **) field))
+		return FALSE;
+
+	_nm_object_queue_notify (object, NM_IP4_CONFIG_DOMAINS);
+	return TRUE;
+}
+
+static gboolean
+demarshal_ip4_routes_array (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field)
+{
+	NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (object);
+
+	g_slist_foreach (priv->routes, (GFunc) g_free, NULL);
+	g_slist_free (priv->routes);
+	priv->routes = NULL;
+
+	priv->routes = nm_utils_ip4_routes_from_gvalue (value);
+	_nm_object_queue_notify (object, NM_IP4_CONFIG_ROUTES);
+
+	return TRUE;
+}
+
+static void
+register_for_property_changed (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 },
+		{ NULL },
+	};
+
+	_nm_object_handle_properties_changed (NM_OBJECT (config),
+	                                     priv->proxy,
+	                                     property_changed_info);
+}
+
+static GObject*
+constructor (GType type,
+		   guint n_construct_params,
+		   GObjectConstructParam *construct_params)
+{
+	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;
+
+	priv = NM_IP4_CONFIG_GET_PRIVATE (object);
+	connection = nm_object_get_connection (object);
+
+	priv->proxy = dbus_g_proxy_new_for_name (connection,
+										   NM_DBUS_SERVICE,
+										   nm_object_get_path (object),
+										   NM_DBUS_INTERFACE_IP4_CONFIG);
+
+	register_for_property_changed (NM_IP4_CONFIG (object));
+
+	return G_OBJECT (object);
+}
+
+static void
+finalize (GObject *object)
+{
+	NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (object);
+
+	g_slist_foreach (priv->addresses, (GFunc) g_free, NULL);
+	g_slist_free (priv->addresses);
+
+	g_slist_foreach (priv->routes, (GFunc) g_free, NULL);
+	g_slist_free (priv->routes);
+
+	if (priv->nameservers)
+		g_array_free (priv->nameservers, TRUE);
+
+	if (priv->wins)
+		g_array_free (priv->wins, TRUE);
+
+	if (priv->domains) {
+		g_ptr_array_foreach (priv->domains, (GFunc) g_free, NULL);
+		g_ptr_array_free (priv->domains, TRUE);
+	}
+
+	g_object_unref (priv->proxy);
+
+	G_OBJECT_CLASS (nm_ip4_config_parent_class)->finalize (object);
+}
+
+static void
+get_property (GObject *object,
+              guint prop_id,
+              GValue *value,
+              GParamSpec *pspec)
+{
+	NMIP4Config *self = NM_IP4_CONFIG (object);
+	NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+
+	switch (prop_id) {
+	case PROP_ADDRESSES:
+		nm_utils_ip4_addresses_to_gvalue (priv->addresses, value);
+		break;
+	case PROP_HOSTNAME:
+		g_value_set_string (value, NULL);
+		break;
+	case PROP_NAMESERVERS:
+		g_value_set_boxed (value, nm_ip4_config_get_nameservers (self));
+		break;
+	case PROP_DOMAINS:
+		g_value_set_boxed (value, nm_ip4_config_get_domains (self));
+		break;
+	case PROP_ROUTES:
+		nm_utils_ip4_routes_to_gvalue (priv->routes, value);
+		break;
+	case PROP_WINS_SERVERS:
+		g_value_set_boxed (value, nm_ip4_config_get_wins_servers (self));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+nm_ip4_config_class_init (NMIP4ConfigClass *config_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (config_class);
+
+	g_type_class_add_private (config_class, sizeof (NMIP4ConfigPrivate));
+
+	/* virtual methods */
+	object_class->constructor = constructor;
+	object_class->get_property = get_property;
+	object_class->finalize = finalize;
+
+	/* properties */
+
+	/**
+	 * NMIP4Config:addresses:
+	 *
+	 * The #GPtrArray containing #NMSettingIP4Address<!-- -->es of the configuration.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_ADDRESSES,
+		 g_param_spec_pointer (NM_IP4_CONFIG_ADDRESSES,
+						       "Addresses",
+						       "Addresses",
+						       G_PARAM_READABLE));
+
+	/**
+	 * NMIP4Config:hostname:
+	 *
+	 * DEPRECATED.  Don't use.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_HOSTNAME,
+		 g_param_spec_string (NM_IP4_CONFIG_HOSTNAME,
+						    "Hostname",
+						    "Hostname",
+						    NULL,
+						    G_PARAM_READABLE));
+
+	/**
+	 * NMIP4Config:nameservers:
+	 *
+	 * The #GArray containing name servers (%guint32<!-- -->es) of the configuration.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_NAMESERVERS,
+		 g_param_spec_boxed (NM_IP4_CONFIG_NAMESERVERS,
+						    "Nameservers",
+						    "Nameservers",
+						    NM_TYPE_UINT_ARRAY,
+						    G_PARAM_READABLE));
+
+	/**
+	 * NMIP4Config:domains:
+	 *
+	 * The #GPtrArray containing domain strings of the configuration.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_DOMAINS,
+		 g_param_spec_boxed (NM_IP4_CONFIG_DOMAINS,
+						    "Domains",
+						    "Domains",
+						    NM_TYPE_STRING_ARRAY,
+						    G_PARAM_READABLE));
+
+	/**
+	 * NMIP4Config:routes:
+	 *
+	 * The #GPtrArray containing #NMSettingIP4Route<!-- -->s of the configuration.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_ROUTES,
+		 g_param_spec_pointer (NM_IP4_CONFIG_ROUTES,
+						       "Routes",
+						       "Routes",
+						       G_PARAM_READABLE));
+
+	/**
+	 * NMIP4Config:wins-servers:
+	 *
+	 * The #GArray containing WINS servers (%guint32<!-- -->es) of the configuration.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_WINS_SERVERS,
+		 g_param_spec_boxed (NM_IP4_CONFIG_WINS_SERVERS,
+						    "WINS Servers",
+						    "WINS Servers",
+						    NM_TYPE_UINT_ARRAY,
+						    G_PARAM_READABLE));
+}
+
+/**
+ * nm_ip4_config_new:
+ * @connection: the #DBusGConnection
+ * @object_path: the DBus object path of the device
+ *
+ * Creates a new #NMIP4Config.
+ *
+ * Returns: a new IP4 configuration
+ **/
+GObject *
+nm_ip4_config_new (DBusGConnection *connection, const char *object_path)
+{
+	return (GObject *) g_object_new (NM_TYPE_IP4_CONFIG,
+									 NM_OBJECT_DBUS_CONNECTION, connection,
+									 NM_OBJECT_DBUS_PATH, object_path,
+									 NULL);
+}
+
+/**
+ * nm_ip4_config_get_addresses:
+ * @config: a #NMIP4Config
+ *
+ * Gets the IP4 addresses (containing the address, prefix, and gateway).
+ *
+ * Returns: the #GSList containing #NMSettingIP4Address<!-- -->es. This is the internal copy
+ * used by the configuration and must not be modified.
+ **/
+const GSList *
+nm_ip4_config_get_addresses (NMIP4Config *config)
+{
+	NMIP4ConfigPrivate *priv;
+	GValue value = { 0, };
+
+	g_return_val_if_fail (NM_IS_IP4_CONFIG (config), 0);
+
+	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)) {
+		return NULL;
+	}
+
+	demarshal_ip4_address_array (NM_OBJECT (config), NULL, &value, &priv->addresses);	
+	g_value_unset (&value);
+
+	return priv->addresses;
+}
+
+/**
+ * nm_ip4_config_get_hostname:
+ * @config: a #NMIP4Config
+ *
+ * DEPRECATED.  Don't use.
+ *
+ * Returns: NULL
+ **/
+const char *
+nm_ip4_config_get_hostname (NMIP4Config *config)
+{
+	return NULL;
+}
+
+/**
+ * nm_ip4_config_get_nameservers:
+ * @config: a #NMIP4Config
+ *
+ * Gets the domain name servers (DNS).
+ *
+ * Returns: the #GArray containing %guint32<!-- -->s. This is the internal copy used by the
+ * configuration and must not be modified.
+ **/
+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)) {
+			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_ip4_config_get_domains:
+ * @config: a #NMIP4Config
+ *
+ * Gets the domain names.
+ *
+ * Returns: the #GPtrArray containing domains as strings. This is the 
+ * internal copy used by the configuration, and must not be modified.
+ **/
+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)) {
+		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_ip4_config_get_wins_servers:
+ * @config: a #NMIP4Config
+ *
+ * Gets the Windows Internet Name Service servers (WINS).
+ *
+ * Returns: the #GArray containing %guint32<!-- -->s. This is the internal copy used by the
+ * configuration and must not be modified.
+ **/
+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->nameservers) {
+		if (_nm_object_get_property (NM_OBJECT (config),
+		                             NM_DBUS_INTERFACE_IP4_CONFIG,
+		                             "Nameservers",
+		                             &value)) {
+			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_ip4_config_get_routes:
+ * @config: a #NMIP4Config
+ *
+ * Gets the routes.
+ *
+ * Returns: the #GSList containing #NMSettingIP4Route<!-- -->s. This is the 
+ * internal copy used by the configuration, and must not be modified.
+ **/
+const GSList *
+nm_ip4_config_get_routes (NMIP4Config *config)
+{
+	NMIP4ConfigPrivate *priv;
+	GValue value = { 0, };
+
+	g_return_val_if_fail (NM_IS_IP4_CONFIG (config), 0);
+
+	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)) {
+		return NULL;
+	}
+
+	demarshal_ip4_routes_array (NM_OBJECT (config), NULL, &value, &priv->routes);
+	g_value_unset (&value);
+
+	return priv->routes;
+}
+
diff --git a/libnm-glib/nm-ip4-config.h b/libnm-glib/nm-ip4-config.h
new file mode 100644
index 00000000..373d12e1
--- /dev/null
+++ b/libnm-glib/nm-ip4-config.h
@@ -0,0 +1,77 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * libnm_glib -- Access network status & information from glib applications
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2007 - 2008 Novell, Inc.
+ * Copyright (C) 2008 Red Hat, Inc.
+ */
+
+#ifndef NM_IP4_CONFIG_H
+#define NM_IP4_CONFIG_H
+
+#include <glib.h>
+#include <glib-object.h>
+#include <dbus/dbus-glib.h>
+#include "nm-object.h"
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_IP4_CONFIG            (nm_ip4_config_get_type ())
+#define NM_IP4_CONFIG(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_IP4_CONFIG, NMIP4Config))
+#define NM_IP4_CONFIG_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_IP4_CONFIG, NMIP4ConfigClass))
+#define NM_IS_IP4_CONFIG(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_IP4_CONFIG))
+#define NM_IS_IP4_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_IP4_CONFIG))
+#define NM_IP4_CONFIG_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_IP4_CONFIG, NMIP4ConfigClass))
+
+typedef struct {
+	NMObject parent;
+} NMIP4Config;
+
+typedef struct {
+	NMObjectClass parent;
+
+	/* Padding for future expansion */
+	void (*_reserved1) (void);
+	void (*_reserved2) (void);
+	void (*_reserved3) (void);
+	void (*_reserved4) (void);
+	void (*_reserved5) (void);
+	void (*_reserved6) (void);
+} NMIP4ConfigClass;
+
+#define NM_IP4_CONFIG_ADDRESSES "addresses"
+#define NM_IP4_CONFIG_HOSTNAME "hostname" /* DEPRECATED */
+#define NM_IP4_CONFIG_NAMESERVERS "nameservers"
+#define NM_IP4_CONFIG_DOMAINS "domains"
+#define NM_IP4_CONFIG_ROUTES "routes"
+#define NM_IP4_CONFIG_WINS_SERVERS "wins-servers"
+
+GType nm_ip4_config_get_type (void);
+
+GObject *nm_ip4_config_new (DBusGConnection *connection, const char *object_path);
+
+const GSList *   nm_ip4_config_get_addresses    (NMIP4Config *config);
+const char *     nm_ip4_config_get_hostname     (NMIP4Config *config); /* DEPRECATED */
+const GArray *   nm_ip4_config_get_nameservers  (NMIP4Config *config);
+const GPtrArray *nm_ip4_config_get_domains      (NMIP4Config *config);
+const GSList *   nm_ip4_config_get_routes       (NMIP4Config *config);
+const GArray *   nm_ip4_config_get_wins_servers (NMIP4Config *config);
+
+G_END_DECLS
+
+#endif /* NM_IP4_CONFIG_H */
diff --git a/libnm-glib/nm-ip6-config.c b/libnm-glib/nm-ip6-config.c
new file mode 100644
index 00000000..1f2d13be
--- /dev/null
+++ b/libnm-glib/nm-ip6-config.c
@@ -0,0 +1,438 @@
+/* -*- 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.
+ * Copyright (C) 2008 Red Hat, Inc.
+ */
+
+#include <string.h>
+
+#include <nm-setting-ip6-config.h>
+#include "nm-ip6-config.h"
+#include "NetworkManager.h"
+#include "nm-types-private.h"
+#include "nm-object-private.h"
+#include "nm-utils.h"
+
+G_DEFINE_TYPE (NMIP6Config, nm_ip6_config, NM_TYPE_OBJECT)
+
+#define NM_IP6_CONFIG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_IP6_CONFIG, NMIP6ConfigPrivate))
+
+typedef struct {
+	DBusGProxy *proxy;
+
+	GSList *addresses;
+	GSList *nameservers;
+	GPtrArray *domains;
+	GSList *routes;
+} NMIP6ConfigPrivate;
+
+enum {
+	PROP_0,
+	PROP_ADDRESSES,
+	PROP_NAMESERVERS,
+	PROP_DOMAINS,
+	PROP_ROUTES,
+
+	LAST_PROP
+};
+
+/**
+ * nm_ip6_config_new:
+ * @connection: the #DBusGConnection
+ * @object_path: the DBus object path of the device
+ *
+ * Creates a new #NMIP6Config.
+ *
+ * Returns: a new IP6 configuration
+ **/
+GObject *
+nm_ip6_config_new (DBusGConnection *connection, const char *object_path)
+{
+	return (GObject *) g_object_new (NM_TYPE_IP6_CONFIG,
+									 NM_OBJECT_DBUS_CONNECTION, connection,
+									 NM_OBJECT_DBUS_PATH, object_path,
+									 NULL);
+}
+
+static gboolean
+demarshal_ip6_address_array (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field)
+{
+	NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (object);
+
+	g_slist_foreach (priv->addresses, (GFunc) nm_ip6_address_unref, NULL);
+	g_slist_free (priv->addresses);
+	priv->addresses = NULL;
+
+	priv->addresses = nm_utils_ip6_addresses_from_gvalue (value);
+	_nm_object_queue_notify (object, NM_IP6_CONFIG_ADDRESSES);
+
+	return TRUE;
+}
+
+static gboolean
+demarshal_ip6_nameserver_array (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field)
+{
+	if (!_nm_ip6_address_array_demarshal (value, (GSList **) field))
+		return FALSE;
+
+	if (pspec && !strcmp (pspec->name, NM_IP6_CONFIG_NAMESERVERS))
+		_nm_object_queue_notify (object, NM_IP6_CONFIG_NAMESERVERS);
+
+	return TRUE;
+}
+
+static gboolean
+demarshal_domains (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field)
+{
+	if (!_nm_string_array_demarshal (value, (GPtrArray **) field))
+		return FALSE;
+
+	_nm_object_queue_notify (object, NM_IP6_CONFIG_DOMAINS);
+	return TRUE;
+}
+
+static gboolean
+demarshal_ip6_routes_array (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field)
+{
+	NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (object);
+
+	g_slist_foreach (priv->routes, (GFunc) nm_ip6_route_unref, NULL);
+	g_slist_free (priv->routes);
+	priv->routes = NULL;
+
+	priv->routes = nm_utils_ip6_routes_from_gvalue (value);
+	_nm_object_queue_notify (object, NM_IP6_CONFIG_ROUTES);
+
+	return TRUE;
+}
+
+static void
+register_for_property_changed (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 },
+		{ NULL },
+	};
+
+	_nm_object_handle_properties_changed (NM_OBJECT (config),
+	                                      priv->proxy,
+	                                      property_changed_info);
+}
+
+/**
+ * nm_ip6_config_get_addresses:
+ * @config: a #NMIP6Config
+ *
+ * Gets the IP6 addresses (containing the address, prefix, and gateway).
+ *
+ * Returns: the #GSList containing #NMSettingIP6Address<!-- -->es. This is the internal copy
+ * used by the configuration and must not be modified.
+ **/
+const GSList *
+nm_ip6_config_get_addresses (NMIP6Config *config)
+{
+	NMIP6ConfigPrivate *priv;
+	GValue value = { 0, };
+
+	g_return_val_if_fail (NM_IS_IP6_CONFIG (config), 0);
+
+	priv = NM_IP6_CONFIG_GET_PRIVATE (config);
+	if (priv->addresses)
+		return priv->addresses;
+
+	if (!_nm_object_get_property (NM_OBJECT (config),
+	                             "org.freedesktop.DBus.Properties",
+	                             "Addresses",
+	                             &value)) {
+		return NULL;
+	}
+
+	demarshal_ip6_address_array (NM_OBJECT (config), NULL, &value, &priv->addresses);	
+	g_value_unset (&value);
+
+	return priv->addresses;
+}
+
+/**
+ * nm_ip6_config_get_nameservers:
+ * @config: a #NMIP6Config
+ *
+ * Gets the domain name servers (DNS).
+ *
+ * Returns: a #GSList containing elements of type 'struct in6_addr' which contain
+ * the addresses of nameservers of the configuration.  This is the internal copy
+ * used by the configuration and must not be modified.
+ **/
+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)) {
+		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_ip6_config_get_domains:
+ * @config: a #NMIP6Config
+ *
+ * Gets the domain names.
+ *
+ * Returns: the #GPtrArray containing domains as strings. This is the 
+ * internal copy used by the configuration, and must not be modified.
+ **/
+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)) {
+		return NULL;
+	}
+
+	demarshal_domains (NM_OBJECT (config), NULL, &value, &priv->domains);
+	g_value_unset (&value);
+
+	return handle_ptr_array_return (priv->domains);
+}
+
+/**
+ * nm_ip6_config_get_routes:
+ * @config: a #NMIP6Config
+ *
+ * Gets the routes.
+ *
+ * Returns: the #GSList containing #NMSettingIP6Route<!-- -->s. This is the 
+ * internal copy used by the configuration, and must not be modified.
+ **/
+const GSList *
+nm_ip6_config_get_routes (NMIP6Config *config)
+{
+	NMIP6ConfigPrivate *priv;
+	GValue value = { 0, };
+
+	g_return_val_if_fail (NM_IS_IP6_CONFIG (config), 0);
+
+	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)) {
+		return NULL;
+	}
+
+	demarshal_ip6_routes_array (NM_OBJECT (config), NULL, &value, &priv->routes);
+	g_value_unset (&value);
+
+	return priv->routes;
+}
+
+static GObject*
+constructor (GType type,
+             guint n_construct_params,
+             GObjectConstructParam *construct_params)
+{
+	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;
+
+	priv = NM_IP6_CONFIG_GET_PRIVATE (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 (NM_OBJECT (object)),
+	                                         NM_DBUS_INTERFACE_IP6_CONFIG);
+
+	register_for_property_changed (NM_IP6_CONFIG (object));
+
+	return object;
+}
+
+static void
+finalize (GObject *object)
+{
+	NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (object);
+
+	g_slist_foreach (priv->addresses, (GFunc) nm_ip6_address_unref, NULL);
+	g_slist_free (priv->addresses);
+
+	g_slist_foreach (priv->routes, (GFunc) nm_ip6_route_unref, NULL);
+	g_slist_free (priv->routes);
+
+	g_slist_foreach (priv->nameservers, (GFunc) g_free, NULL);
+	g_slist_free (priv->nameservers);
+
+	if (priv->domains) {
+		g_ptr_array_foreach (priv->domains, (GFunc) g_free, NULL);
+		g_ptr_array_free (priv->domains, TRUE);
+	}
+
+	g_object_unref (priv->proxy);
+
+	G_OBJECT_CLASS (nm_ip6_config_parent_class)->finalize (object);
+}
+
+static void
+get_property (GObject *object,
+              guint prop_id,
+              GValue *value,
+              GParamSpec *pspec)
+{
+	NMIP6Config *self = NM_IP6_CONFIG (object);
+	NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self);
+
+	switch (prop_id) {
+	case PROP_ADDRESSES:
+		nm_utils_ip6_addresses_to_gvalue (priv->addresses, value);
+		break;
+	case PROP_NAMESERVERS:
+		g_value_set_boxed (value, nm_ip6_config_get_nameservers (self));
+		break;
+	case PROP_DOMAINS:
+		g_value_set_boxed (value, nm_ip6_config_get_domains (self));
+		break;
+	case PROP_ROUTES:
+		nm_utils_ip6_routes_to_gvalue (priv->routes, value);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+nm_ip6_config_init (NMIP6Config *config)
+{
+}
+
+static void
+nm_ip6_config_class_init (NMIP6ConfigClass *config_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (config_class);
+
+	g_type_class_add_private (config_class, sizeof (NMIP6ConfigPrivate));
+
+	/* virtual methods */
+	object_class->constructor = constructor;
+	object_class->get_property = get_property;
+	object_class->finalize = finalize;
+
+	/* properties */
+
+	/**
+	 * NMIP6Config:addresses:
+	 *
+	 * The #GPtrArray containing the IPv6 addresses;  use
+	 * nm_utils_ip6_addresses_from_gvalue() to return a #GSList of
+	 * #NMSettingIP6Address objects that is more usable than the raw data.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_ADDRESSES,
+		 g_param_spec_boxed (NM_IP6_CONFIG_ADDRESSES,
+						     "Addresses",
+						     "Addresses",
+						     NM_TYPE_IP6_ADDRESS_OBJECT_ARRAY,
+						     G_PARAM_READABLE));
+
+	/**
+	 * NMIP6Config:nameservers:
+	 *
+	 * The #GPtrArray containing elements of type 'struct ip6_addr' which
+	 * contain the addresses of nameservers of the configuration.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_NAMESERVERS,
+		 g_param_spec_boxed (NM_IP6_CONFIG_NAMESERVERS,
+						    "Nameservers",
+						    "Nameservers",
+						    NM_TYPE_IP6_ADDRESS_ARRAY,
+						    G_PARAM_READABLE));
+
+	/**
+	 * NMIP6Config:domains:
+	 *
+	 * The #GPtrArray containing domain strings of the configuration.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_DOMAINS,
+		 g_param_spec_boxed (NM_IP6_CONFIG_DOMAINS,
+						    "Domains",
+						    "Domains",
+						    NM_TYPE_STRING_ARRAY,
+						    G_PARAM_READABLE));
+
+	/**
+	 * NMIP6Config:routes:
+	 *
+	 * The #GPtrArray containing the IPv6 routes;  use
+	 * nm_utils_ip6_routes_from_gvalue() to return a #GSList of
+	 * #NMSettingIP6Address objects that is more usable than the raw data.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_ROUTES,
+		 g_param_spec_boxed (NM_IP6_CONFIG_ROUTES,
+		                     "Routes",
+		                     "Routes",
+		                     NM_TYPE_IP6_ROUTE_OBJECT_ARRAY,
+		                     G_PARAM_READABLE));
+}
+
diff --git a/libnm-glib/nm-ip6-config.h b/libnm-glib/nm-ip6-config.h
new file mode 100644
index 00000000..7865dfdb
--- /dev/null
+++ b/libnm-glib/nm-ip6-config.h
@@ -0,0 +1,73 @@
+/* -*- 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.
+ * Copyright (C) 2008 Red Hat, Inc.
+ */
+
+#ifndef NM_IP6_CONFIG_H
+#define NM_IP6_CONFIG_H
+
+#include <glib.h>
+#include <glib-object.h>
+#include <dbus/dbus-glib.h>
+#include "nm-object.h"
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_IP6_CONFIG            (nm_ip6_config_get_type ())
+#define NM_IP6_CONFIG(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_IP6_CONFIG, NMIP6Config))
+#define NM_IP6_CONFIG_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_IP6_CONFIG, NMIP6ConfigClass))
+#define NM_IS_IP6_CONFIG(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_IP6_CONFIG))
+#define NM_IS_IP6_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_IP6_CONFIG))
+#define NM_IP6_CONFIG_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_IP6_CONFIG, NMIP6ConfigClass))
+
+typedef struct {
+	NMObject parent;
+} NMIP6Config;
+
+typedef struct {
+	NMObjectClass parent;
+
+	/* Padding for future expansion */
+	void (*_reserved1) (void);
+	void (*_reserved2) (void);
+	void (*_reserved3) (void);
+	void (*_reserved4) (void);
+	void (*_reserved5) (void);
+	void (*_reserved6) (void);
+} NMIP6ConfigClass;
+
+#define NM_IP6_CONFIG_ADDRESSES "addresses"
+#define NM_IP6_CONFIG_NAMESERVERS "nameservers"
+#define NM_IP6_CONFIG_DOMAINS "domains"
+#define NM_IP6_CONFIG_ROUTES "routes"
+
+GType nm_ip6_config_get_type (void);
+
+GObject *nm_ip6_config_new (DBusGConnection *connection, const char *object_path);
+
+const GSList *   nm_ip6_config_get_addresses    (NMIP6Config *config);
+const GSList *   nm_ip6_config_get_nameservers  (NMIP6Config *config);
+const GPtrArray *nm_ip6_config_get_domains      (NMIP6Config *config);
+const GSList *   nm_ip6_config_get_routes       (NMIP6Config *config);
+
+G_END_DECLS
+
+#endif /* NM_IP6_CONFIG_H */
diff --git a/libnm-glib/nm-object-cache.c b/libnm-glib/nm-object-cache.c
new file mode 100644
index 00000000..fdbca00f
--- /dev/null
+++ b/libnm-glib/nm-object-cache.c
@@ -0,0 +1,72 @@
+/* -*- 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) 2008 Red Hat, Inc.
+ */
+
+#include <string.h>
+#include <glib.h>
+#include "nm-object-cache.h"
+#include "nm-object.h"
+
+static GHashTable *cache = NULL;
+
+static void
+_init_cache (void)
+{
+	if (G_UNLIKELY (cache == NULL))
+		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)
+{
+	_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));
+}
+
+void
+_nm_object_cache_add (NMObject *object)
+{
+	char *path;
+
+	_init_cache ();
+	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);
+}
+
+NMObject *
+_nm_object_cache_get (const char *path)
+{
+	NMObject *object;
+
+	_init_cache ();
+	object = g_hash_table_lookup (cache, path);
+	return object;
+}
+
diff --git a/libnm-glib/nm-object-cache.h b/libnm-glib/nm-object-cache.h
new file mode 100644
index 00000000..b8cf2121
--- /dev/null
+++ b/libnm-glib/nm-object-cache.h
@@ -0,0 +1,39 @@
+/* -*- 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) 2008 Red Hat, Inc.
+ */
+
+#ifndef NM_OBJECT_CACHE_H
+#define NM_OBJECT_CACHE_H
+
+#include <glib.h>
+#include <glib-object.h>
+#include "nm-object.h"
+
+G_BEGIN_DECLS
+
+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
+
+#endif /* NM_OBJECT_CACHE_H */
diff --git a/libnm-glib/nm-object-private.h b/libnm-glib/nm-object-private.h
new file mode 100644
index 00000000..93514cbe
--- /dev/null
+++ b/libnm-glib/nm-object-private.h
@@ -0,0 +1,101 @@
+/* -*- 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) 2008 Red Hat, Inc.
+ */
+
+#ifndef NM_OBJECT_PRIVATE_H
+#define NM_OBJECT_PRIVATE_H
+
+#include <glib.h>
+#include <glib-object.h>
+#include "nm-object.h"
+
+typedef gboolean (*PropChangedMarshalFunc) (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);
+
+gboolean _nm_object_demarshal_generic (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field);
+
+void _nm_object_queue_notify (NMObject *object, const char *property);
+
+/* DBus property accessors */
+
+gboolean _nm_object_get_property (NMObject *object,
+								 const char *interface,
+								 const char *prop_name,
+								 GValue *value);
+
+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);
+
+char *_nm_object_get_object_path_property (NMObject *object,
+										  const char *interface,
+										  const char *prop_name);
+
+gint32 _nm_object_get_int_property (NMObject *object,
+								   const char *interface,
+								   const char *prop_name);
+
+guint32 _nm_object_get_uint_property (NMObject *object,
+									 const char *interface,
+									 const char *prop_name);
+
+gboolean _nm_object_get_boolean_property (NMObject *object,
+										const char *interface,
+										const char *prop_name);
+
+gint8 _nm_object_get_byte_property (NMObject *object,
+								   const char *interface,
+								   const char *prop_name);
+
+gdouble _nm_object_get_double_property (NMObject *object,
+									   const char *interface,
+									   const char *prop_name);
+
+GByteArray *_nm_object_get_byte_array_property (NMObject *object,
+											   const char *interface,
+											   const char *prop_name);
+
+static inline const GPtrArray *
+handle_ptr_array_return (GPtrArray *array)
+{
+	/* zero-length is special-case; return NULL */
+	if (!array || !array->len)
+		return NULL;
+	return array;
+}
+
+#endif /* NM_OBJECT_PRIVATE_H */
diff --git a/libnm-glib/nm-object.c b/libnm-glib/nm-object.c
new file mode 100644
index 00000000..72ea0500
--- /dev/null
+++ b/libnm-glib/nm-object.c
@@ -0,0 +1,675 @@
+/* -*- 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.
+ * Copyright (C) 2007 - 2008 Red Hat, Inc.
+ */
+
+#include <string.h>
+#include <nm-utils.h>
+#include "NetworkManager.h"
+#include "nm-object.h"
+#include "nm-object-cache.h"
+#include "nm-object-private.h"
+#include "nm-dbus-glib-types.h"
+
+
+G_DEFINE_ABSTRACT_TYPE (NMObject, nm_object, G_TYPE_OBJECT)
+
+#define NM_OBJECT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_OBJECT, NMObjectPrivate))
+
+typedef struct {
+	PropChangedMarshalFunc func;
+	gpointer field;
+} PropChangedInfo;
+
+typedef struct {
+	DBusGConnection *connection;
+	char *path;
+	DBusGProxy *properties_proxy;
+	GSList *pcs;
+	NMObject *parent;
+
+	GSList *notify_props;
+	guint32 notify_id;
+	gboolean disposed;
+} NMObjectPrivate;
+
+enum {
+	PROP_0,
+	PROP_CONNECTION,
+	PROP_PATH,
+
+	LAST_PROP
+};
+
+static void
+nm_object_init (NMObject *object)
+{
+}
+
+static GObject*
+constructor (GType type,
+			 guint n_construct_params,
+			 GObjectConstructParam *construct_params)
+{
+	GObject *object;
+	NMObjectPrivate *priv;
+
+	object = G_OBJECT_CLASS (nm_object_parent_class)->constructor (type,
+																   n_construct_params,
+																   construct_params);
+	if (!object)
+		return NULL;
+
+	_nm_object_cache_add (NM_OBJECT (object));
+
+	priv = NM_OBJECT_GET_PRIVATE (object);
+
+	if (priv->connection == NULL || priv->path == NULL) {
+		g_warning ("%s: bus connection and path required.", __func__);
+		g_object_unref (object);
+		return NULL;
+	}
+
+	priv->properties_proxy = dbus_g_proxy_new_for_name (priv->connection,
+														NM_DBUS_SERVICE,
+														priv->path,
+														"org.freedesktop.DBus.Properties");
+
+	return object;
+}
+
+static void
+dispose (GObject *object)
+{
+	NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
+
+	if (priv->disposed) {
+		G_OBJECT_CLASS (nm_object_parent_class)->dispose (object);
+		return;
+	}
+
+	priv->disposed = TRUE;
+
+	if (priv->notify_id) {
+		g_source_remove (priv->notify_id);
+		priv->notify_id = 0;
+	}
+
+	g_slist_foreach (priv->notify_props, (GFunc) g_free, NULL);
+	g_slist_free (priv->notify_props);
+
+	g_object_unref (priv->properties_proxy);
+	dbus_g_connection_unref (priv->connection);
+
+	G_OBJECT_CLASS (nm_object_parent_class)->dispose (object);
+}
+
+static void
+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_free (priv->path);
+
+	G_OBJECT_CLASS (nm_object_parent_class)->finalize (object);
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+			  const GValue *value, GParamSpec *pspec)
+{
+	NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
+
+	switch (prop_id) {
+	case PROP_CONNECTION:
+		/* Construct only */
+		priv->connection = dbus_g_connection_ref ((DBusGConnection *) g_value_get_boxed (value));
+		break;
+	case PROP_PATH:
+		/* Construct only */
+		priv->path = g_value_dup_string (value);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+			  GValue *value, GParamSpec *pspec)
+{
+	NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
+
+	switch (prop_id) {
+	case PROP_CONNECTION:
+		g_value_set_boxed (value, priv->connection);
+		break;
+	case PROP_PATH:
+		g_value_set_string (value, priv->path);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+nm_object_class_init (NMObjectClass *nm_object_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (nm_object_class);
+
+	g_type_class_add_private (nm_object_class, sizeof (NMObjectPrivate));
+
+	/* virtual methods */
+	object_class->constructor = constructor;
+	object_class->set_property = set_property;
+	object_class->get_property = get_property;
+	object_class->dispose = dispose;
+	object_class->finalize = finalize;
+
+	/* porperties */
+
+	/**
+	 * NMObject:connection:
+	 *
+	 * The #DBusGConnection of the object.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_CONNECTION,
+		 g_param_spec_boxed (NM_OBJECT_DBUS_CONNECTION,
+							 "Connection",
+							 "Connection",
+							 DBUS_TYPE_G_CONNECTION,
+							 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+	/**
+	 * NMObject:path:
+	 *
+	 * The DBus object path.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_PATH,
+		 g_param_spec_string (NM_OBJECT_DBUS_PATH,
+							  "Object Path",
+							  "DBus Object Path",
+							  NULL,
+							  G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+}
+
+/**
+ * nm_object_get_connection:
+ * @object: a #NMObject
+ *
+ * Gets the #NMObject's DBusGConnection.
+ *
+ * Returns: the connection
+ **/
+DBusGConnection *
+nm_object_get_connection (NMObject *object)
+{
+	g_return_val_if_fail (NM_IS_OBJECT (object), NULL);
+
+	return NM_OBJECT_GET_PRIVATE (object)->connection;
+}
+
+/**
+ * nm_object_get_path:
+ * @object: a #NMObject
+ *
+ * Gets the DBus path of the #NMObject.
+ *
+ * Returns: the object's path. This is the internal string used by the
+ * device, and must not be modified.
+ **/
+const char *
+nm_object_get_path (NMObject *object)
+{
+	g_return_val_if_fail (NM_IS_OBJECT (object), NULL);
+
+	return NM_OBJECT_GET_PRIVATE (object)->path;
+}
+
+static gboolean
+deferred_notify_cb (gpointer data)
+{
+	NMObject *object = NM_OBJECT (data);
+	NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
+	GSList *props, *iter;
+
+	priv->notify_id = 0;
+
+	/* Clear priv->notify_props early so that an NMObject subclass that
+	 * listens to property changes can queue up other property changes
+	 * during the g_object_notify() call separately from the property
+	 * list we're iterating.
+	 */
+	props = g_slist_reverse (priv->notify_props);
+	priv->notify_props = NULL;
+
+	for (iter = props; iter; iter = g_slist_next (iter)) {
+		g_object_notify (G_OBJECT (object), (const char *) iter->data);
+		g_free (iter->data);
+	}
+	g_slist_free (props);
+	return FALSE;
+}
+
+void
+_nm_object_queue_notify (NMObject *object, const char *property)
+{
+	NMObjectPrivate *priv;
+	gboolean found = FALSE;
+	GSList *iter;
+
+	g_return_if_fail (NM_IS_OBJECT (object));
+	g_return_if_fail (property != NULL);
+
+	priv = NM_OBJECT_GET_PRIVATE (object);
+	if (!priv->notify_id)
+		priv->notify_id = g_idle_add_full (G_PRIORITY_LOW, deferred_notify_cb, object, NULL);
+
+	for (iter = priv->notify_props; iter; iter = g_slist_next (iter)) {
+		if (!strcmp ((char *) iter->data, property)) {
+			found = TRUE;
+			break;
+		}
+	}
+
+	if (!found)
+		priv->notify_props = g_slist_prepend (priv->notify_props, g_strdup (property));
+}
+
+/* Stolen from dbus-glib */
+static char*
+wincaps_to_dash (const char *caps)
+{
+	const char *p;
+	GString *str;
+
+	str = g_string_new (NULL);
+	p = caps;
+	while (*p) {
+		if (g_ascii_isupper (*p)) {
+			if (str->len > 0 && (str->len < 2 || str->str[str->len-2] != '-'))
+				g_string_append_c (str, '-');
+			g_string_append_c (str, g_ascii_tolower (*p));
+		} else
+			g_string_append_c (str, *p);
+		++p;
+	}
+
+	return g_string_free (str, FALSE);
+}
+
+static void
+handle_property_changed (gpointer key, gpointer data, gpointer user_data)
+{
+	NMObject *self = NM_OBJECT (user_data);
+	NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self);
+	char *prop_name;
+	PropChangedInfo *pci;
+	GParamSpec *pspec;
+	gboolean success = FALSE, found = FALSE;
+	GSList *iter;
+
+	prop_name = wincaps_to_dash ((char *) key);
+	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.",
+		           __func__,
+		           prop_name,
+		           G_OBJECT_TYPE_NAME (self));
+		goto out;
+	}
+
+	/* Iterate through the object and it's 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;
+			success = (*(pci->func)) (self, pspec, (GValue *) data, pci->field);
+			if (success)
+				break;
+		}
+	}
+
+	if (!found) {
+#if DEBUG
+		g_warning ("Property '%s' unhandled.", prop_name);
+#endif
+	} else if (!success) {
+		g_warning ("%s: failed to update property '%s' of object type %s.",
+		           __func__,
+		           prop_name,
+		           G_OBJECT_TYPE_NAME (self));
+	}
+
+out:
+	g_free (prop_name);
+}
+
+static void
+properties_changed_proxy (DBusGProxy *proxy,
+                          GHashTable *properties,
+                          gpointer user_data)
+{
+	g_hash_table_foreach (properties, handle_property_changed, user_data);
+}
+
+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);
+	}
+}
+
+#define HANDLE_TYPE(ucase, lcase) \
+	} else if (pspec->value_type == G_TYPE_##ucase) { \
+		if (G_VALUE_HOLDS_##ucase (value)) { \
+			g##lcase *param = (g##lcase *) field; \
+			*param = g_value_get_##lcase (value); \
+		} else { \
+			success = FALSE; \
+			goto done; \
+		}
+
+gboolean
+_nm_object_demarshal_generic (NMObject *object,
+                             GParamSpec *pspec,
+                             GValue *value,
+                             gpointer field)
+{
+	gboolean success = TRUE;
+
+	if (pspec->value_type == G_TYPE_STRING) {
+		if (G_VALUE_HOLDS_STRING (value)) {
+			char **param = (char **) field;
+			g_free (*param);
+			*param = g_value_dup_string (value);
+		} else if (G_VALUE_HOLDS (value, DBUS_TYPE_G_OBJECT_PATH)) {
+			char **param = (char **) field;
+			g_free (*param);
+			*param = g_strdup (g_value_get_boxed (value));
+		} else {
+			success = FALSE;
+			goto done;
+		}
+	HANDLE_TYPE(BOOLEAN, boolean)
+	HANDLE_TYPE(CHAR, char)
+	HANDLE_TYPE(UCHAR, uchar)
+	HANDLE_TYPE(DOUBLE, double)
+	HANDLE_TYPE(INT, int)
+	HANDLE_TYPE(UINT, uint)
+	HANDLE_TYPE(INT64, int)
+	HANDLE_TYPE(UINT64, uint)
+	HANDLE_TYPE(LONG, long)
+	HANDLE_TYPE(ULONG, ulong)
+	} else {
+		g_warning ("%s: %s/%s unhandled type %s.",
+		           __func__, G_OBJECT_TYPE_NAME (object), pspec->name,
+		           g_type_name (pspec->value_type));
+		success = FALSE;
+	}
+
+done:
+	if (success) {
+		_nm_object_queue_notify (object, pspec->name);
+	} else {
+		g_warning ("%s: %s/%s (type %s) couldn't be set with type %s.",
+		           __func__, G_OBJECT_TYPE_NAME (object), pspec->name,
+		           g_type_name (pspec->value_type), G_VALUE_TYPE_NAME (value));
+	}
+	return success;
+}
+
+gboolean
+_nm_object_get_property (NMObject *object,
+						const char *interface,
+						const char *prop_name,
+						GValue *value)
+{
+	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);
+
+	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_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.
+		 */
+		if (!(err->domain == DBUS_GERROR && err->code == DBUS_GERROR_NO_REPLY)) {
+			g_warning ("%s: Error getting '%s' for %s: (%d) %s\n",
+			           __func__,
+			           prop_name,
+			           nm_object_get_path (object),
+			           err->code,
+			           err->message);
+		}
+		g_error_free (err);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+void
+_nm_object_set_property (NMObject *object,
+						const char *interface,
+						const char *prop_name,
+						GValue *value)
+{
+	g_return_if_fail (NM_IS_OBJECT (object));
+	g_return_if_fail (interface != NULL);
+	g_return_if_fail (prop_name != NULL);
+	g_return_if_fail (G_IS_VALUE (value));
+
+	dbus_g_proxy_call_no_reply (NM_OBJECT_GET_PRIVATE (object)->properties_proxy,
+								"Set",
+								G_TYPE_STRING, interface,
+								G_TYPE_STRING, prop_name,
+								G_TYPE_VALUE, value,
+								G_TYPE_INVALID);
+}
+
+char *
+_nm_object_get_string_property (NMObject *object,
+							   const char *interface,
+							   const char *prop_name)
+{
+	char *str = NULL;
+	GValue value = {0,};
+
+	if (_nm_object_get_property (object, interface, prop_name, &value)) {
+		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))
+			str = g_strdup (g_value_get_boxed (&value));
+		g_value_unset (&value);
+	}
+
+	return str;
+}
+
+char *
+_nm_object_get_object_path_property (NMObject *object,
+									const char *interface,
+									const char *prop_name)
+{
+	char *path = NULL;
+	GValue value = {0,};
+
+	if (_nm_object_get_property (object, interface, prop_name, &value)) {
+		path = g_strdup (g_value_get_boxed (&value));
+		g_value_unset (&value);
+	}
+
+	return path;
+}
+
+gint32
+_nm_object_get_int_property (NMObject *object,
+							const char *interface,
+							const char *prop_name)
+{
+	gint32 i = 0;
+	GValue value = {0,};
+
+	if (_nm_object_get_property (object, interface, prop_name, &value)) {
+		i = g_value_get_int (&value);
+		g_value_unset (&value);
+	}
+
+	return i;
+}
+
+guint32
+_nm_object_get_uint_property (NMObject *object,
+							 const char *interface,
+							 const char *prop_name)
+{
+	guint32 i = 0;
+	GValue value = {0,};
+
+	if (_nm_object_get_property (object, interface, prop_name, &value)) {
+		i = g_value_get_uint (&value);
+		g_value_unset (&value);
+	}
+
+	return i;
+}
+
+gboolean
+_nm_object_get_boolean_property (NMObject *object,
+								const char *interface,
+								const char *prop_name)
+{
+	gboolean b = FALSE;  // FIXME: somehow convey failure if needed
+	GValue value = {0,};
+
+	if (_nm_object_get_property (object, interface, prop_name, &value)) {
+		b = g_value_get_boolean (&value);
+		g_value_unset (&value);
+	}
+
+	return b;
+}
+
+gint8
+_nm_object_get_byte_property (NMObject *object,
+							 const char *interface,
+							 const char *prop_name)
+{
+	gint8 b = G_MAXINT8;
+	GValue value = {0,};
+
+	if (_nm_object_get_property (object, interface, prop_name, &value)) {
+		b = g_value_get_uchar (&value);
+		g_value_unset (&value);
+	}
+
+	return b;
+}
+
+gdouble
+_nm_object_get_double_property (NMObject *object,
+							   const char *interface,
+							   const char *prop_name)
+{
+	gdouble d = G_MAXDOUBLE;
+	GValue value = {0,};
+
+	if (_nm_object_get_property (object, interface, prop_name, &value)) {
+		d = g_value_get_double (&value);
+		g_value_unset (&value);
+	}
+
+	return d;
+}
+
+GByteArray *
+_nm_object_get_byte_array_property (NMObject *object,
+								   const char *interface,
+								   const char *prop_name)
+{
+	GByteArray * array = NULL;
+	GValue value = {0,};
+
+	if (_nm_object_get_property (object, interface, prop_name, &value)) {
+		GArray * tmp = g_value_get_boxed (&value);
+		int i;
+		unsigned char byte;
+
+		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);
+		}
+		g_value_unset (&value);
+	}
+
+	return array;
+}
diff --git a/libnm-glib/nm-object.h b/libnm-glib/nm-object.h
new file mode 100644
index 00000000..3f7b36cf
--- /dev/null
+++ b/libnm-glib/nm-object.h
@@ -0,0 +1,66 @@
+/* -*- 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.
+ * Copyright (C) 2007 - 2008 Red Hat, Inc.
+ */
+
+#ifndef NM_OBJECT_H
+#define NM_OBJECT_H
+
+#include <glib.h>
+#include <glib-object.h>
+#include <dbus/dbus-glib.h>
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_OBJECT            (nm_object_get_type ())
+#define NM_OBJECT(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_OBJECT, NMObject))
+#define NM_OBJECT_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_OBJECT, NMObjectClass))
+#define NM_IS_OBJECT(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_OBJECT))
+#define NM_IS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_OBJECT))
+#define NM_OBJECT_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_OBJECT, NMObjectClass))
+
+#define NM_OBJECT_DBUS_CONNECTION "dbus-connection"
+#define NM_OBJECT_DBUS_PATH "dbus-path"
+
+typedef struct {
+	GObject parent;
+} NMObject;
+
+typedef struct {
+	GObjectClass parent;
+
+	/* Padding for future expansion */
+	void (*_reserved1) (void);
+	void (*_reserved2) (void);
+	void (*_reserved3) (void);
+	void (*_reserved4) (void);
+	void (*_reserved5) (void);
+	void (*_reserved6) (void);
+} NMObjectClass;
+
+GType nm_object_get_type (void);
+
+DBusGConnection *nm_object_get_connection (NMObject *object);
+const char      *nm_object_get_path       (NMObject *object);
+
+G_END_DECLS
+
+#endif /* NM_OBJECT_H */
diff --git a/libnm-glib/nm-remote-connection-private.h b/libnm-glib/nm-remote-connection-private.h
new file mode 100644
index 00000000..22d84ae7
--- /dev/null
+++ b/libnm-glib/nm-remote-connection-private.h
@@ -0,0 +1,35 @@
+/* -*- 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) 2009 Red Hat, Inc.
+ */
+
+#ifndef __NM_REMOTE_CONNECTION_PRIVATE_H__
+#define __NM_REMOTE_CONNECTION_PRIVATE_H__
+
+#define NM_REMOTE_CONNECTION_INIT_RESULT "init-result"
+
+typedef enum {
+	NM_REMOTE_CONNECTION_INIT_RESULT_UNKNOWN = 0,
+	NM_REMOTE_CONNECTION_INIT_RESULT_SUCCESS,
+	NM_REMOTE_CONNECTION_INIT_RESULT_ERROR
+} NMRemoteConnectionInitResult;
+
+#endif  /* __NM_REMOTE_CONNECTION_PRIVATE__ */
+
diff --git a/libnm-glib/nm-remote-connection.c b/libnm-glib/nm-remote-connection.c
new file mode 100644
index 00000000..1039a7d1
--- /dev/null
+++ b/libnm-glib/nm-remote-connection.c
@@ -0,0 +1,439 @@
+/* -*- 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.
+ * Copyright (C) 2007 - 2010 Red Hat, Inc.
+ */
+
+#include <string.h>
+
+#include <NetworkManager.h>
+#include <nm-utils.h>
+#include <nm-setting-connection.h>
+#include "nm-remote-connection.h"
+#include "nm-remote-connection-private.h"
+#include "nm-dbus-glib-types.h"
+#include "nm-exported-connection-bindings.h"
+#include "nm-settings-connection-interface.h"
+
+#define NM_REMOTE_CONNECTION_BUS "bus"
+
+static void settings_connection_interface_init (NMSettingsConnectionInterface *klass);
+
+G_DEFINE_TYPE_EXTENDED (NMRemoteConnection, nm_remote_connection, NM_TYPE_CONNECTION, 0,
+                        G_IMPLEMENT_INTERFACE (NM_TYPE_SETTINGS_CONNECTION_INTERFACE, settings_connection_interface_init))
+
+enum {
+	PROP_0,
+	PROP_BUS,
+	PROP_INIT_RESULT,
+
+	LAST_PROP
+};
+
+
+typedef struct {
+	NMRemoteConnection *self;
+	DBusGProxy *proxy;
+	DBusGProxyCall *call;
+	GFunc callback;
+	gpointer user_data;
+} RemoteCall;
+
+typedef struct {
+	DBusGConnection *bus;
+	DBusGProxy *proxy;
+	DBusGProxy *secrets_proxy;
+	GSList *calls;
+
+	NMRemoteConnectionInitResult init_result;
+	gboolean disposed;
+} NMRemoteConnectionPrivate;
+
+#define NM_REMOTE_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_REMOTE_CONNECTION, NMRemoteConnectionPrivate))
+
+/****************************************************************/
+
+static void
+remote_call_complete (NMRemoteConnection *self, RemoteCall *call)
+{
+	NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (self);
+
+	priv->calls = g_slist_remove (priv->calls, call);
+	/* Don't need to cancel it since this function should only be called from
+	 * the dispose handler (where the proxy will be destroyed immediately after)
+	 * or from the call's completion callback.
+	 */
+	memset (call, 0, sizeof (RemoteCall));
+	g_free (call);
+}
+
+static void
+update_cb (DBusGProxy *proxy, GError *error, gpointer user_data)
+{
+	RemoteCall *call = user_data;
+	NMSettingsConnectionInterfaceUpdateFunc func = (NMSettingsConnectionInterfaceUpdateFunc) call->callback;
+
+	(*func)(NM_SETTINGS_CONNECTION_INTERFACE (call->self), error, call->user_data);
+	remote_call_complete (call->self, call);
+}
+
+static gboolean
+update (NMSettingsConnectionInterface *connection,
+        NMSettingsConnectionInterfaceUpdateFunc callback,
+        gpointer user_data)
+{
+	NMRemoteConnection *self = NM_REMOTE_CONNECTION (connection);
+	NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (self);
+	GHashTable *settings = NULL;
+	RemoteCall *call;
+
+	call = g_malloc0 (sizeof (RemoteCall));
+	call->self = self;
+	call->callback = (GFunc) callback;
+	call->user_data = user_data;
+	call->proxy = priv->proxy;
+
+	settings = nm_connection_to_hash (NM_CONNECTION (self));
+
+	call->call = org_freedesktop_NetworkManagerSettings_Connection_update_async (priv->proxy,
+	                                                                             settings,
+	                                                                             update_cb,
+	                                                                             call);
+	g_assert (call->call);
+	priv->calls = g_slist_append (priv->calls, call);
+
+	g_hash_table_destroy (settings);
+
+	return TRUE;
+}
+
+static void
+delete_cb (DBusGProxy *proxy, GError *error, gpointer user_data)
+{
+	RemoteCall *call = user_data;
+	NMSettingsConnectionInterfaceDeleteFunc func = (NMSettingsConnectionInterfaceDeleteFunc) call->callback;
+
+	(*func)(NM_SETTINGS_CONNECTION_INTERFACE (call->self), error, call->user_data);
+	remote_call_complete (call->self, call);
+}
+
+static gboolean
+do_delete (NMSettingsConnectionInterface *connection,
+           NMSettingsConnectionInterfaceDeleteFunc callback,
+           gpointer user_data)
+{
+	NMRemoteConnection *self = NM_REMOTE_CONNECTION (connection);
+	NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (self);
+	RemoteCall *call;
+
+	call = g_malloc0 (sizeof (RemoteCall));
+	call->self = self;
+	call->callback = (GFunc) callback;
+	call->user_data = user_data;
+	call->proxy = priv->proxy;
+
+	call->call = org_freedesktop_NetworkManagerSettings_Connection_delete_async (priv->proxy,
+	                                                                             delete_cb,
+	                                                                             call);
+	g_assert (call->call);
+	priv->calls = g_slist_append (priv->calls, call);
+
+	return TRUE;
+}
+
+static void
+get_secrets_cb (DBusGProxy *proxy, GHashTable *secrets, GError *error, gpointer user_data)
+{
+	RemoteCall *call = user_data;
+	NMSettingsConnectionInterfaceGetSecretsFunc func = (NMSettingsConnectionInterfaceGetSecretsFunc) call->callback;
+
+	(*func)(NM_SETTINGS_CONNECTION_INTERFACE (call->self), error ? NULL : secrets, error, call->user_data);
+	remote_call_complete (call->self, call);
+}
+
+static gboolean
+get_secrets (NMSettingsConnectionInterface *connection,
+             const char *setting_name,
+             const char **hints,
+             gboolean request_new,
+             NMSettingsConnectionInterfaceGetSecretsFunc callback,
+             gpointer user_data)
+{
+	NMRemoteConnection *self = NM_REMOTE_CONNECTION (connection);
+	NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (self);
+	RemoteCall *call;
+
+	call = g_malloc0 (sizeof (RemoteCall));
+	call->self = self;
+	call->callback = (GFunc) callback;
+	call->user_data = user_data;
+	call->proxy = priv->secrets_proxy;
+
+	call->call = org_freedesktop_NetworkManagerSettings_Connection_Secrets_get_secrets_async (priv->secrets_proxy,
+	                                                                                          setting_name,
+	                                                                                          hints,
+	                                                                                          request_new,
+	                                                                                          get_secrets_cb,
+	                                                                                          call);
+	g_assert (call->call);
+	priv->calls = g_slist_append (priv->calls, call);
+
+	return TRUE;
+}
+
+/****************************************************************/
+
+static gboolean
+replace_settings (NMRemoteConnection *self, GHashTable *new_settings)
+{
+	GError *error = NULL;
+
+	if (!nm_connection_replace_settings (NM_CONNECTION (self), new_settings, &error)) {
+		g_warning ("%s: error updating %s connection %s settings: (%d) %s",
+		           __func__,
+		           (nm_connection_get_scope (NM_CONNECTION (self)) == NM_CONNECTION_SCOPE_USER) ? "user" : "system",
+		           nm_connection_get_path (NM_CONNECTION (self)),
+		           error ? error->code : -1,
+		           (error && error->message) ? error->message : "(unknown)");
+		g_clear_error (&error);
+		return FALSE;
+	}
+
+	/* Emit update irregardless to let listeners figure out what to do with
+	 * the connection; whether to delete / ignore it or not.
+	 */
+	nm_settings_connection_interface_emit_updated (NM_SETTINGS_CONNECTION_INTERFACE (self));
+	return TRUE;
+}
+
+static void
+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) {
+		g_warning ("%s: error getting %s connection %s settings: (%d) %s",
+		           __func__,
+		           (nm_connection_get_scope (NM_CONNECTION (self)) == NM_CONNECTION_SCOPE_USER) ? "user" : "system",
+		           nm_connection_get_path (NM_CONNECTION (self)),
+		           error ? error->code : -1,
+		           (error && error->message) ? error->message : "(unknown)");
+		g_error_free (error);
+		priv->init_result = NM_REMOTE_CONNECTION_INIT_RESULT_ERROR;
+		g_object_notify (G_OBJECT (self), NM_REMOTE_CONNECTION_INIT_RESULT);
+	} else {
+		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_cb (DBusGProxy *proxy, GHashTable *settings, gpointer user_data)
+{
+	replace_settings (NM_REMOTE_CONNECTION (user_data), settings);
+}
+
+static void
+removed_cb (DBusGProxy *proxy, gpointer user_data)
+{
+	g_signal_emit_by_name (G_OBJECT (user_data), "removed");
+}
+
+/****************************************************************/
+
+static void
+settings_connection_interface_init (NMSettingsConnectionInterface *klass)
+{
+	/* interface implementation */
+	klass->update = update;
+	klass->delete = do_delete;
+	klass->get_secrets = get_secrets;
+}
+
+/**
+ * nm_remote_connection_new:
+ * @bus: a valid and connected D-Bus connection
+ * @scope: the Connection scope (either user or system)
+ * @path: the D-Bus path of the connection as exported by the settings service
+ *  indicated by @scope
+ *
+ * Creates a new object representing the remote connection.
+ *
+ * Returns: the new remote connection object on success, or %NULL on failure
+ **/
+NMRemoteConnection *
+nm_remote_connection_new (DBusGConnection *bus,
+                          NMConnectionScope scope,
+                          const char *path)
+{
+	g_return_val_if_fail (bus != NULL, NULL);
+	g_return_val_if_fail (path != NULL, NULL);
+
+	return (NMRemoteConnection *) g_object_new (NM_TYPE_REMOTE_CONNECTION,
+	                                            NM_REMOTE_CONNECTION_BUS, bus,
+	                                            NM_CONNECTION_SCOPE, scope,
+	                                            NM_CONNECTION_PATH, path,
+	                                            NULL);
+}
+
+static GObject *
+constructor (GType type,
+             guint n_construct_params,
+             GObjectConstructParam *construct_params)
+{
+	GObject *object;
+	NMRemoteConnectionPrivate *priv;
+	const char *service = NM_DBUS_SERVICE_USER_SETTINGS;
+
+	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)));
+
+	if (nm_connection_get_scope (NM_CONNECTION (object)) == NM_CONNECTION_SCOPE_SYSTEM)
+		service = NM_DBUS_SERVICE_SYSTEM_SETTINGS;
+
+	priv->proxy = dbus_g_proxy_new_for_name (priv->bus,
+	                                         service,
+	                                         nm_connection_get_path (NM_CONNECTION (object)),
+	                                         NM_DBUS_IFACE_SETTINGS_CONNECTION);
+	g_assert (priv->proxy);
+	dbus_g_proxy_set_default_timeout (priv->proxy, G_MAXINT);
+
+	priv->secrets_proxy = dbus_g_proxy_new_for_name (priv->bus,
+	                                                 service,
+	                                                 nm_connection_get_path (NM_CONNECTION (object)),
+	                                                 NM_DBUS_IFACE_SETTINGS_CONNECTION_SECRETS);
+	g_assert (priv->secrets_proxy);
+	dbus_g_proxy_set_default_timeout (priv->secrets_proxy, G_MAXINT);
+
+	dbus_g_proxy_add_signal (priv->proxy, "Updated", DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, G_TYPE_INVALID);
+	dbus_g_proxy_connect_signal (priv->proxy, "Updated", G_CALLBACK (updated_cb), object, NULL);
+
+	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);
+
+	org_freedesktop_NetworkManagerSettings_Connection_get_settings_async (priv->proxy,
+	                                                                      get_settings_cb,
+	                                                                      object);
+	return object;
+}
+
+static void
+nm_remote_connection_init (NMRemoteConnection *self)
+{
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+              const GValue *value, GParamSpec *pspec)
+{
+	NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (object);
+
+	switch (prop_id) {
+	case PROP_BUS:
+		/* Construct only */
+		priv->bus = dbus_g_connection_ref ((DBusGConnection *) g_value_get_boxed (value));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+              GValue *value, GParamSpec *pspec)
+{
+	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);
+	NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (object);
+
+	if (!priv->disposed) {
+		priv->disposed = TRUE;
+
+		while (g_slist_length (priv->calls))
+			remote_call_complete (self, priv->calls->data);
+
+		g_object_unref (priv->proxy);
+		g_object_unref (priv->secrets_proxy);
+		dbus_g_connection_unref (priv->bus);
+	}
+
+	G_OBJECT_CLASS (nm_remote_connection_parent_class)->dispose (object);
+}
+
+static void
+nm_remote_connection_class_init (NMRemoteConnectionClass *remote_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (remote_class);
+
+	g_type_class_add_private (object_class, sizeof (NMRemoteConnectionPrivate));
+
+	/* virtual methods */
+	object_class->set_property = set_property;
+	object_class->get_property = get_property;
+	object_class->dispose = dispose;
+	object_class->constructor = constructor;
+
+	/* Properties */
+	g_object_class_install_property
+		(object_class, PROP_BUS,
+		 g_param_spec_boxed (NM_REMOTE_CONNECTION_BUS,
+						 "DBusGConnection",
+						 "DBusGConnection",
+						 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));
+}
+
diff --git a/libnm-glib/nm-remote-connection.h b/libnm-glib/nm-remote-connection.h
new file mode 100644
index 00000000..ef5452f9
--- /dev/null
+++ b/libnm-glib/nm-remote-connection.h
@@ -0,0 +1,65 @@
+/* -*- 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.
+ * Copyright (C) 2007 - 2009 Red Hat, Inc.
+ */
+
+#ifndef __NM_REMOTE_CONNECTION_H__
+#define __NM_REMOTE_CONNECTION_H__
+
+#include <glib-object.h>
+#include <dbus/dbus-glib.h>
+
+#include <nm-connection.h>
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_REMOTE_CONNECTION            (nm_remote_connection_get_type ())
+#define NM_REMOTE_CONNECTION(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_REMOTE_CONNECTION, NMRemoteConnection))
+#define NM_REMOTE_CONNECTION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_REMOTE_CONNECTION, NMRemoteConnectionClass))
+#define NM_IS_REMOTE_CONNECTION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_REMOTE_CONNECTION))
+#define NM_IS_REMOTE_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_REMOTE_CONNECTION))
+#define NM_REMOTE_CONNECTION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_REMOTE_CONNECTION, NMRemoteConnectionClass))
+
+typedef struct {
+	NMConnection parent;
+} NMRemoteConnection;
+
+typedef struct {
+	NMConnectionClass parent_class;
+
+	/* Padding for future expansion */
+	void (*_reserved1) (void);
+	void (*_reserved2) (void);
+	void (*_reserved3) (void);
+	void (*_reserved4) (void);
+	void (*_reserved5) (void);
+	void (*_reserved6) (void);
+} NMRemoteConnectionClass;
+
+GType nm_remote_connection_get_type (void);
+
+NMRemoteConnection *nm_remote_connection_new (DBusGConnection *bus,
+                                              NMConnectionScope scope,
+                                              const char *path);
+G_END_DECLS
+
+#endif  /* __NM_REMOTE_CONNECTION__ */
+
diff --git a/libnm-glib/nm-remote-settings-system.c b/libnm-glib/nm-remote-settings-system.c
new file mode 100644
index 00000000..95098c7e
--- /dev/null
+++ b/libnm-glib/nm-remote-settings-system.c
@@ -0,0 +1,375 @@
+/* -*- 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) 2008 Novell, Inc.
+ * Copyright (C) 2009 - 2010 Red Hat, Inc.
+ */
+
+#include <string.h>
+#include <NetworkManager.h>
+#include <nm-connection.h>
+
+#include "nm-marshal.h"
+#include "nm-dbus-glib-types.h"
+#include "nm-remote-settings-system.h"
+#include "nm-settings-system-bindings.h"
+#include "nm-settings-system-interface.h"
+
+static void settings_system_interface_init (NMSettingsSystemInterface *klass);
+
+G_DEFINE_TYPE_EXTENDED (NMRemoteSettingsSystem, nm_remote_settings_system, NM_TYPE_REMOTE_SETTINGS, 0,
+                        G_IMPLEMENT_INTERFACE (NM_TYPE_SETTINGS_SYSTEM_INTERFACE, settings_system_interface_init))
+
+#define NM_REMOTE_SETTINGS_SYSTEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_REMOTE_SETTINGS_SYSTEM, NMRemoteSettingsSystemPrivate))
+
+typedef struct {
+	DBusGProxy *proxy;
+	DBusGProxy *props_proxy;
+
+	char *hostname;
+	gboolean can_modify;
+
+	NMSettingsSystemPermissions permissions;
+	gboolean have_permissions;
+
+	gboolean disposed;
+} NMRemoteSettingsSystemPrivate;
+
+static void
+properties_changed_cb (DBusGProxy *proxy,
+                       GHashTable *properties,
+                       gpointer user_data)
+{
+	NMRemoteSettingsSystem *self = NM_REMOTE_SETTINGS_SYSTEM (user_data);
+	NMRemoteSettingsSystemPrivate *priv = NM_REMOTE_SETTINGS_SYSTEM_GET_PRIVATE (self);
+	GHashTableIter iter;
+	gpointer key, tmp;
+
+	g_hash_table_iter_init (&iter, properties);
+	while (g_hash_table_iter_next (&iter, &key, &tmp)) {
+		GValue *value = tmp;
+
+		if (!strcmp ((const char *) key, "Hostname")) {
+			g_free (priv->hostname);
+			priv->hostname = g_value_dup_string (value);
+			g_object_notify (G_OBJECT (self), NM_SETTINGS_SYSTEM_INTERFACE_HOSTNAME);
+		}
+
+		if (!strcmp ((const char *) key, "CanModify")) {
+			priv->can_modify = g_value_get_boolean (value);
+			g_object_notify (G_OBJECT (self), NM_SETTINGS_SYSTEM_INTERFACE_CAN_MODIFY);
+		}
+	}
+}
+
+static void
+get_all_cb  (DBusGProxy *proxy,
+             DBusGProxyCall *call,
+             gpointer user_data)
+{
+	NMRemoteSettingsSystem *self = NM_REMOTE_SETTINGS_SYSTEM (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);
+}
+
+typedef struct {
+	NMSettingsSystemInterface *settings;
+	NMSettingsSystemSaveHostnameFunc callback;
+	gpointer callback_data;
+} SaveHostnameInfo;
+
+static void
+save_hostname_cb (DBusGProxy *proxy,
+                  DBusGProxyCall *call,
+                  gpointer user_data)
+{
+	SaveHostnameInfo *info = user_data;
+	GError *error = NULL;
+
+	dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INVALID);
+	info->callback (info->settings, error, info->callback_data);
+	g_clear_error (&error);
+}
+
+static gboolean
+save_hostname (NMSettingsSystemInterface *settings,
+	           const char *hostname,
+	           NMSettingsSystemSaveHostnameFunc callback,
+	           gpointer user_data)
+{
+	NMRemoteSettingsSystem *self = NM_REMOTE_SETTINGS_SYSTEM (settings);
+	NMRemoteSettingsSystemPrivate *priv = NM_REMOTE_SETTINGS_SYSTEM_GET_PRIVATE (self);
+	SaveHostnameInfo *info;
+
+	info = g_malloc0 (sizeof (SaveHostnameInfo));
+	info->settings = settings;
+	info->callback = callback;
+	info->callback_data = user_data;
+
+	dbus_g_proxy_begin_call (priv->proxy, "SaveHostname",
+	                         save_hostname_cb,
+	                         info,
+	                         g_free,
+	                         G_TYPE_STRING, hostname ? hostname : "",
+	                         G_TYPE_INVALID);
+	return TRUE;
+}
+
+typedef struct {
+	NMSettingsSystemInterface *settings;
+	NMSettingsSystemGetPermissionsFunc callback;
+	gpointer callback_data;
+} GetPermissionsInfo;
+
+static void
+get_permissions_cb  (DBusGProxy *proxy,
+                     DBusGProxyCall *call,
+                     gpointer user_data)
+{
+	GetPermissionsInfo *info = user_data;
+	NMRemoteSettingsSystem *self = NM_REMOTE_SETTINGS_SYSTEM (info->settings);
+	NMRemoteSettingsSystemPrivate *priv = NM_REMOTE_SETTINGS_SYSTEM_GET_PRIVATE (self);
+	NMSettingsSystemPermissions permissions = NM_SETTINGS_SYSTEM_PERMISSION_NONE;
+	GError *error = NULL;
+
+	dbus_g_proxy_end_call (proxy, call, &error,
+	                       G_TYPE_UINT, &permissions,
+	                       G_TYPE_INVALID);
+	priv->permissions = permissions;
+	priv->have_permissions = !error;
+	info->callback (info->settings, permissions, error, info->callback_data);
+	g_clear_error (&error);
+}
+
+static gboolean
+get_permissions (NMSettingsSystemInterface *settings,
+                 NMSettingsSystemGetPermissionsFunc callback,
+                 gpointer user_data)
+{
+	NMRemoteSettingsSystemPrivate *priv = NM_REMOTE_SETTINGS_SYSTEM_GET_PRIVATE (settings);
+	GetPermissionsInfo *info;
+
+	/* Skip D-Bus if we already have permissions */
+	if (priv->have_permissions) {
+		callback (settings, priv->permissions, NULL, user_data);
+		return TRUE;
+	}
+
+	/* Otherwise fetch them from NM */
+	info = g_malloc0 (sizeof (GetPermissionsInfo));
+	info->settings = settings;
+	info->callback = callback;
+	info->callback_data = user_data;
+
+	dbus_g_proxy_begin_call (priv->proxy, "GetPermissions",
+	                         get_permissions_cb,
+	                         info,
+	                         g_free,
+	                         G_TYPE_INVALID);
+	return TRUE;
+}
+
+static void
+check_permissions_cb (DBusGProxy *proxy, gpointer user_data)
+{
+	NMRemoteSettingsSystem *self = NM_REMOTE_SETTINGS_SYSTEM (user_data);
+	NMRemoteSettingsSystemPrivate *priv = NM_REMOTE_SETTINGS_SYSTEM_GET_PRIVATE (self);
+
+	/* Permissions need to be re-fetched */
+	priv->have_permissions = FALSE;
+	g_signal_emit_by_name (self, NM_SETTINGS_SYSTEM_INTERFACE_CHECK_PERMISSIONS);
+}
+
+/****************************************************************/
+
+static void
+settings_system_interface_init (NMSettingsSystemInterface *klass)
+{
+	/* interface implementation */
+	klass->save_hostname = save_hostname;
+	klass->get_permissions = get_permissions;
+}
+
+/**
+ * nm_remote_settings_system_new:
+ * @bus: a valid and connected D-Bus connection
+ *
+ * Creates a new object representing the remote system settings service.
+ *
+ * Returns: the new remote system settings object on success, or %NULL on failure
+ **/
+NMRemoteSettingsSystem *
+nm_remote_settings_system_new (DBusGConnection *bus)
+{
+	g_return_val_if_fail (bus != NULL, NULL);
+
+	return (NMRemoteSettingsSystem *) g_object_new (NM_TYPE_REMOTE_SETTINGS_SYSTEM,
+	                                                NM_REMOTE_SETTINGS_BUS, bus,
+	                                                NM_REMOTE_SETTINGS_SCOPE, NM_CONNECTION_SCOPE_SYSTEM,
+	                                                NULL);
+}
+
+static void
+nm_remote_settings_system_init (NMRemoteSettingsSystem *self)
+{
+}
+
+static GObject *
+constructor (GType type,
+             guint n_construct_params,
+             GObjectConstructParam *construct_params)
+{
+	GObject *object;
+	NMRemoteSettingsSystemPrivate *priv;
+	DBusGConnection *bus = NULL;
+
+	object = G_OBJECT_CLASS (nm_remote_settings_system_parent_class)->constructor (type, n_construct_params, construct_params);
+	if (!object)
+		return NULL;
+
+	priv = NM_REMOTE_SETTINGS_SYSTEM_GET_PRIVATE (object);
+
+	g_object_get (G_OBJECT (object), NM_REMOTE_SETTINGS_BUS, &bus, NULL);
+	g_assert (bus);
+
+	/* D-Bus properties proxy */
+	priv->props_proxy = dbus_g_proxy_new_for_name (bus,
+	                                               NM_DBUS_SERVICE_SYSTEM_SETTINGS,
+	                                               NM_DBUS_PATH_SETTINGS,
+	                                               "org.freedesktop.DBus.Properties");
+	g_assert (priv->props_proxy);
+
+	/* System settings proxy */
+	priv->proxy = dbus_g_proxy_new_for_name (bus,
+	                                         NM_DBUS_SERVICE_SYSTEM_SETTINGS,
+	                                         NM_DBUS_PATH_SETTINGS,
+	                                         NM_DBUS_IFACE_SETTINGS_SYSTEM);
+	g_assert (priv->proxy);
+	dbus_g_proxy_set_default_timeout (priv->proxy, G_MAXINT);
+
+	dbus_g_object_register_marshaller (g_cclosure_marshal_VOID__BOXED,
+	                                   G_TYPE_NONE,
+	                                   DBUS_TYPE_G_MAP_OF_VARIANT,
+	                                   G_TYPE_INVALID);
+	dbus_g_proxy_add_signal (priv->proxy, "PropertiesChanged",
+	                         DBUS_TYPE_G_MAP_OF_VARIANT,
+	                         G_TYPE_INVALID);
+	dbus_g_proxy_connect_signal (priv->proxy, "PropertiesChanged",
+	                             G_CALLBACK (properties_changed_cb),
+	                             object,
+	                             NULL);
+
+	/* Monitor for permissions changes */
+	dbus_g_proxy_add_signal (priv->proxy, "CheckPermissions", G_TYPE_INVALID);
+	dbus_g_proxy_connect_signal (priv->proxy, "CheckPermissions",
+	                             G_CALLBACK (check_permissions_cb),
+	                             object,
+	                             NULL);
+
+	/* Get properties */
+	dbus_g_proxy_begin_call (priv->props_proxy, "GetAll",
+	                         get_all_cb,
+	                         object,
+	                         NULL,
+	                         G_TYPE_STRING, NM_DBUS_IFACE_SETTINGS_SYSTEM,
+	                         G_TYPE_INVALID);
+
+	dbus_g_connection_unref (bus);
+
+	return object;
+}
+
+static void
+dispose (GObject *object)
+{
+	NMRemoteSettingsSystemPrivate *priv = NM_REMOTE_SETTINGS_SYSTEM_GET_PRIVATE (object);
+
+	if (priv->disposed)
+		return;
+
+	priv->disposed = TRUE;
+
+	g_free (priv->hostname);
+
+	g_object_unref (priv->props_proxy);
+	g_object_unref (priv->proxy);
+
+	G_OBJECT_CLASS (nm_remote_settings_system_parent_class)->dispose (object);
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+              GValue *value, GParamSpec *pspec)
+{
+	NMRemoteSettingsSystemPrivate *priv = NM_REMOTE_SETTINGS_SYSTEM_GET_PRIVATE (object);
+
+	switch (prop_id) {
+	case NM_SETTINGS_SYSTEM_INTERFACE_PROP_HOSTNAME:
+		g_value_set_string (value, priv->hostname);
+		break;
+	case NM_SETTINGS_SYSTEM_INTERFACE_PROP_CAN_MODIFY:
+		g_value_set_boolean (value, priv->can_modify);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+nm_remote_settings_system_class_init (NMRemoteSettingsSystemClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	g_type_class_add_private (klass, sizeof (NMRemoteSettingsSystemPrivate));
+
+	/* Virtual methods */
+	object_class->constructor = constructor;
+	object_class->get_property = get_property;
+	object_class->dispose = dispose;
+
+	/* Properties */
+	g_object_class_override_property (object_class,
+									  NM_SETTINGS_SYSTEM_INTERFACE_PROP_HOSTNAME,
+									  NM_SETTINGS_SYSTEM_INTERFACE_HOSTNAME);
+
+	g_object_class_override_property (object_class,
+									  NM_SETTINGS_SYSTEM_INTERFACE_PROP_CAN_MODIFY,
+									  NM_SETTINGS_SYSTEM_INTERFACE_CAN_MODIFY);
+}
+
diff --git a/libnm-glib/nm-remote-settings-system.h b/libnm-glib/nm-remote-settings-system.h
new file mode 100644
index 00000000..b5182273
--- /dev/null
+++ b/libnm-glib/nm-remote-settings-system.h
@@ -0,0 +1,64 @@
+/* -*- 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) 2008 Novell, Inc.
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
+
+#ifndef NM_REMOTE_SETTINGS_SYSTEM_H
+#define NM_REMOTE_SETTINGS_SYSTEM_H
+
+#include <glib.h>
+#include <dbus/dbus-glib.h>
+
+#include "nm-remote-settings.h"
+#include "nm-settings-system-interface.h"
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_REMOTE_SETTINGS_SYSTEM            (nm_remote_settings_system_get_type ())
+#define NM_REMOTE_SETTINGS_SYSTEM(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_REMOTE_SETTINGS_SYSTEM, NMRemoteSettingsSystem))
+#define NM_REMOTE_SETTINGS_SYSTEM_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_REMOTE_SETTINGS_SYSTEM, NMRemoteSettingsSystemClass))
+#define NM_IS_REMOTE_SETTINGS_SYSTEM(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_REMOTE_SETTINGS_SYSTEM))
+#define NM_IS_REMOTE_SETTINGS_SYSTEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_REMOTE_SETTINGS_SYSTEM))
+#define NM_REMOTE_SETTINGS_SYSTEM_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_REMOTE_SETTINGS_SYSTEM, NMRemoteSettingsSystemClass))
+
+typedef struct {
+	NMRemoteSettings parent;
+} NMRemoteSettingsSystem;
+
+typedef struct {
+	NMRemoteSettingsClass parent;
+
+	/* Padding for future expansion */
+	void (*_reserved1) (void);
+	void (*_reserved2) (void);
+	void (*_reserved3) (void);
+	void (*_reserved4) (void);
+	void (*_reserved5) (void);
+	void (*_reserved6) (void);
+} NMRemoteSettingsSystemClass;
+
+GType nm_remote_settings_system_get_type (void);
+
+NMRemoteSettingsSystem *nm_remote_settings_system_new (DBusGConnection *bus);
+
+G_END_DECLS
+
+#endif /* NM_REMOTE_SETTINGS_SYSTEM_H */
diff --git a/libnm-glib/nm-remote-settings.c b/libnm-glib/nm-remote-settings.c
new file mode 100644
index 00000000..92814a15
--- /dev/null
+++ b/libnm-glib/nm-remote-settings.c
@@ -0,0 +1,540 @@
+/* -*- 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) 2008 Novell, Inc.
+ * Copyright (C) 2009 - 2010 Red Hat, Inc.
+ */
+
+#include <string.h>
+#include <NetworkManager.h>
+#include <nm-connection.h>
+
+#include "nm-marshal.h"
+#include "nm-remote-settings.h"
+#include "nm-settings-bindings.h"
+#include "nm-settings-interface.h"
+#include "nm-remote-connection-private.h"
+
+static void settings_interface_init (NMSettingsInterface *class);
+
+G_DEFINE_TYPE_EXTENDED (NMRemoteSettings, nm_remote_settings, G_TYPE_OBJECT, 0,
+                        G_IMPLEMENT_INTERFACE (NM_TYPE_SETTINGS_INTERFACE, settings_interface_init))
+
+#define NM_REMOTE_SETTINGS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_REMOTE_SETTINGS, NMRemoteSettingsPrivate))
+
+typedef struct {
+	DBusGConnection *bus;
+	NMConnectionScope scope;
+
+	DBusGProxy *proxy;
+	GHashTable *connections;
+	GHashTable *pending;  /* Connections we don't have settings for yet */
+	gboolean service_running;
+
+	DBusGProxy *dbus_proxy;
+
+	guint fetch_id;
+
+	gboolean disposed;
+} NMRemoteSettingsPrivate;
+
+enum {
+	PROP_0,
+	PROP_BUS,
+	PROP_SCOPE,
+	PROP_SERVICE_RUNNING,
+
+	LAST_PROP
+};
+
+static NMSettingsConnectionInterface *
+get_connection_by_path (NMSettingsInterface *settings, const char *path)
+{
+	return g_hash_table_lookup (NM_REMOTE_SETTINGS_GET_PRIVATE (settings)->connections, path);
+}
+
+static void
+connection_removed_cb (NMRemoteConnection *remote, gpointer user_data)
+{
+	NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data);
+	NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
+	const char *path;
+
+	path = nm_connection_get_path (NM_CONNECTION (remote));
+	g_hash_table_remove (priv->connections, path);
+	g_hash_table_remove (priv->pending, path);
+}
+
+static void
+connection_init_result_cb (NMRemoteConnection *remote,
+                           GParamSpec *pspec,
+                           gpointer user_data)
+{
+	NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data);
+	NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
+	guint32 init_result = NM_REMOTE_CONNECTION_INIT_RESULT_UNKNOWN;
+	const char *path;
+
+	/* 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);
+
+	switch (init_result) {
+	case NM_REMOTE_CONNECTION_INIT_RESULT_SUCCESS:
+		/* ref it when adding to ->connections, since removing it from ->pending
+		 * will unref it.
+		 */
+		g_hash_table_insert (priv->connections, g_strdup (path), g_object_ref (remote));
+
+		/* Finally, let users know of the new connection now that it has all
+		 * its settings and is valid.
+		 */
+		g_signal_emit_by_name (self, "new-connection", remote);
+		break;
+	case NM_REMOTE_CONNECTION_INIT_RESULT_ERROR:
+	default:
+		break;
+	}
+
+	g_hash_table_remove (priv->pending, path);
+
+	/* Let listeners know that all connections have been found */
+	if (!g_hash_table_size (priv->pending))
+		g_signal_emit_by_name (self, NM_SETTINGS_INTERFACE_CONNECTIONS_READ);
+}
+
+static void
+new_connection_cb (DBusGProxy *proxy, const char *path, gpointer user_data)
+{
+	NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data);
+	NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
+	NMRemoteConnection *connection;
+
+	connection = nm_remote_connection_new (priv->bus, priv->scope, path);
+	if (connection) {
+		g_signal_connect (connection, "removed",
+		                  G_CALLBACK (connection_removed_cb),
+		                  self);
+
+		g_signal_connect (connection, "notify::" NM_REMOTE_CONNECTION_INIT_RESULT,
+		                  G_CALLBACK (connection_init_result_cb),
+		                  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
+		 * really valid until it has all its settings, so hide it until it does.
+		 */
+		g_hash_table_insert (priv->pending, g_strdup (path), connection);
+	}
+}
+
+static void
+fetch_connections_done (DBusGProxy *proxy,
+                        GPtrArray *connections,
+                        GError *error,
+                        gpointer user_data)
+{
+	NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data);
+	NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);	
+	int i;
+
+	if (error) {
+		g_warning ("%s: error fetching %s connections: (%d) %s.",
+		           __func__,
+		           priv->scope == NM_CONNECTION_SCOPE_USER ? "user" : "system",
+		           error->code,
+		           error->message ? error->message : "(unknown)");
+		g_clear_error (&error);
+		return;
+	}
+
+	/* Let listeners know we are done getting connections */
+	if (connections->len == 0) {
+		g_signal_emit_by_name (self, NM_SETTINGS_INTERFACE_CONNECTIONS_READ);
+		return;
+	}
+
+	for (i = 0; connections && (i < connections->len); i++) {
+		char *path = g_ptr_array_index (connections, i);
+
+		new_connection_cb (proxy, path, user_data);
+		g_free (path);
+	}
+	g_ptr_array_free (connections, TRUE);
+}
+
+static gboolean
+fetch_connections (gpointer user_data)
+{
+	NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data);
+	NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
+
+	priv->fetch_id = 0;
+
+	org_freedesktop_NetworkManagerSettings_list_connections_async (priv->proxy,
+	                                                               fetch_connections_done,
+	                                                               self);
+	return FALSE;
+}
+
+static GSList *
+list_connections (NMSettingsInterface *settings)
+{
+	NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings);
+	GSList *list = NULL;
+	GHashTableIter iter;
+	gpointer value;
+
+	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;
+}
+
+typedef struct {
+	NMSettingsInterface *self;
+	NMSettingsAddConnectionFunc callback;
+	gpointer callback_data;
+} AddConnectionInfo;
+
+static void
+add_connection_done (DBusGProxy *proxy,
+                     GError *error,
+                     gpointer user_data)
+{
+	AddConnectionInfo *info = user_data;
+
+	info->callback (info->self, error, info->callback_data);
+	g_free (info);
+}
+
+static gboolean
+add_connection (NMSettingsInterface *settings,
+	            NMConnection *connection,
+	            NMSettingsAddConnectionFunc callback,
+	            gpointer user_data)
+{
+	NMRemoteSettings *self = NM_REMOTE_SETTINGS (settings);
+	NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
+	AddConnectionInfo *info;
+	GHashTable *new_settings;
+
+	info = g_malloc0 (sizeof (AddConnectionInfo));
+	info->self = settings;
+	info->callback = callback;
+	info->callback_data = user_data;
+
+	new_settings = nm_connection_to_hash (connection);
+	org_freedesktop_NetworkManagerSettings_add_connection_async (priv->proxy,
+	                                                             new_settings,
+	                                                             add_connection_done,
+	                                                             info);
+	g_hash_table_destroy (new_settings);
+	return TRUE;
+}
+
+static gboolean
+remove_connections (gpointer user_data)
+{
+	NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data);
+	NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
+	GHashTableIter iter;
+	gpointer value;
+	GSList *list = NULL, *list_iter;
+
+	/* Build up the list of connections; we can't emit "removed" during hash
+	 * table iteration because emission of the "removed" signal may trigger code
+	 * that explicitly removes the the connection from the hash table somewhere
+	 * else.
+	 */
+	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));
+
+	for (list_iter = list; list_iter; list_iter = g_slist_next (list_iter))
+		g_signal_emit_by_name (NM_REMOTE_CONNECTION (list_iter->data), "removed");
+	g_slist_free (list);
+
+	g_hash_table_remove_all (priv->connections);
+	return FALSE;
+}
+
+static void
+name_owner_changed (DBusGProxy *proxy,
+                    const char *name,
+                    const char *old_owner,
+                    const char *new_owner,
+                    gpointer user_data)
+{
+	NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data);
+	NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
+	const char *sname = NM_DBUS_SERVICE_USER_SETTINGS;
+
+	if (priv->scope == NM_CONNECTION_SCOPE_SYSTEM)
+		sname = NM_DBUS_SERVICE_SYSTEM_SETTINGS;
+
+	if (!strcmp (name, sname)) {
+		if (priv->fetch_id)
+			g_source_remove (priv->fetch_id);
+
+		if (new_owner && strlen (new_owner) > 0) {
+			priv->fetch_id = g_idle_add (fetch_connections, self);
+			priv->service_running = TRUE;
+		} else {
+			priv->fetch_id = g_idle_add (remove_connections, self);
+			priv->service_running = FALSE;
+		}
+		g_object_notify (G_OBJECT (self), NM_REMOTE_SETTINGS_SERVICE_RUNNING);
+	}
+}
+
+/****************************************************************/
+
+static void
+settings_interface_init (NMSettingsInterface *iface)
+{
+	/* interface implementation */
+	iface->list_connections = list_connections;
+	iface->get_connection_by_path = get_connection_by_path;
+	iface->add_connection = add_connection;
+}
+
+/**
+ * nm_remote_settings_new:
+ * @bus: a valid and connected D-Bus connection
+ * @scope: the settings service scope (either user or system)
+ *
+ * Creates a new object representing the remote settings service.
+ *
+ * Returns: the new remote settings object on success, or %NULL on failure
+ **/
+NMRemoteSettings *
+nm_remote_settings_new (DBusGConnection *bus, NMConnectionScope scope)
+{
+	g_return_val_if_fail (bus != NULL, NULL);
+	g_return_val_if_fail (scope != NM_CONNECTION_SCOPE_UNKNOWN, NULL);
+
+	return (NMRemoteSettings *) g_object_new (NM_TYPE_REMOTE_SETTINGS,
+	                                          NM_REMOTE_SETTINGS_BUS, bus,
+	                                          NM_REMOTE_SETTINGS_SCOPE, scope,
+	                                          NULL);
+}
+
+static void
+nm_remote_settings_init (NMRemoteSettings *self)
+{
+	NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
+
+	priv->connections = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
+	priv->pending = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
+}
+
+static GObject *
+constructor (GType type,
+             guint n_construct_params,
+             GObjectConstructParam *construct_params)
+{
+	GObject *object;
+	NMRemoteSettingsPrivate *priv;
+	const char *service = NM_DBUS_SERVICE_USER_SETTINGS;
+	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);
+
+	/* D-Bus proxy for clearing connections on NameOwnerChanged */
+	priv->dbus_proxy = dbus_g_proxy_new_for_name (priv->bus,
+	                                              "org.freedesktop.DBus",
+	                                              "/org/freedesktop/DBus",
+	                                              "org.freedesktop.DBus");
+	g_assert (priv->dbus_proxy);
+
+	dbus_g_object_register_marshaller (_nm_marshal_VOID__STRING_STRING_STRING,
+	                                   G_TYPE_NONE,
+	                                   G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
+	                                   G_TYPE_INVALID);
+	dbus_g_proxy_add_signal (priv->dbus_proxy, "NameOwnerChanged",
+	                         G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
+	                         G_TYPE_INVALID);
+	dbus_g_proxy_connect_signal (priv->dbus_proxy,
+	                             "NameOwnerChanged",
+	                             G_CALLBACK (name_owner_changed),
+	                             object, NULL);
+
+	/* Settings service proxy */
+	if (priv->scope == NM_CONNECTION_SCOPE_SYSTEM)
+		service = NM_DBUS_SERVICE_SYSTEM_SETTINGS;
+
+	if (!dbus_g_proxy_call (priv->dbus_proxy, "NameHasOwner", &error,
+	                        G_TYPE_STRING, 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,
+	                                         service,
+	                                         NM_DBUS_PATH_SETTINGS,
+	                                         NM_DBUS_IFACE_SETTINGS);
+	g_assert (priv->proxy);
+	dbus_g_proxy_set_default_timeout (priv->proxy, G_MAXINT);
+
+	dbus_g_proxy_add_signal (priv->proxy, "NewConnection",
+	                         DBUS_TYPE_G_OBJECT_PATH,
+	                         G_TYPE_INVALID);
+	dbus_g_proxy_connect_signal (priv->proxy, "NewConnection",
+	                             G_CALLBACK (new_connection_cb),
+	                             object,
+	                             NULL);
+
+	priv->fetch_id = g_idle_add (fetch_connections, object);
+
+	return object;
+}
+
+static void
+dispose (GObject *object)
+{
+	NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (object);
+
+	if (priv->disposed)
+		return;
+
+	priv->disposed = TRUE;
+
+	if (priv->fetch_id)
+		g_source_remove (priv->fetch_id);
+
+	if (priv->connections)
+		g_hash_table_destroy (priv->connections);
+
+	if (priv->pending)
+		g_hash_table_destroy (priv->pending);
+
+	g_object_unref (priv->dbus_proxy);
+	g_object_unref (priv->proxy);
+	dbus_g_connection_unref (priv->bus);
+
+	G_OBJECT_CLASS (nm_remote_settings_parent_class)->dispose (object);
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+              const GValue *value, GParamSpec *pspec)
+{
+	NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (object);
+
+	switch (prop_id) {
+	case PROP_BUS:
+		/* Construct only */
+		priv->bus = dbus_g_connection_ref ((DBusGConnection *) g_value_get_boxed (value));
+		break;
+	case PROP_SCOPE:
+		priv->scope = (NMConnectionScope) g_value_get_uint (value);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+              GValue *value, GParamSpec *pspec)
+{
+	NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (object);
+
+	switch (prop_id) {
+	case PROP_BUS:
+		g_value_set_boxed (value, priv->bus);
+		break;
+	case PROP_SCOPE:
+		g_value_set_uint (value, priv->scope);
+		break;
+	case PROP_SERVICE_RUNNING:
+		g_value_set_boolean (value, priv->service_running);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+nm_remote_settings_class_init (NMRemoteSettingsClass *class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+	g_type_class_add_private (class, sizeof (NMRemoteSettingsPrivate));
+
+	/* Virtual methods */
+	object_class->constructor = constructor;
+	object_class->set_property = set_property;
+	object_class->get_property = get_property;
+	object_class->dispose = dispose;
+
+	/* Properties */
+	g_object_class_install_property
+		(object_class, PROP_BUS,
+		 g_param_spec_boxed (NM_REMOTE_SETTINGS_BUS,
+		                     "DBusGConnection",
+		                     "DBusGConnection",
+		                     DBUS_TYPE_G_CONNECTION,
+		                     G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+	g_object_class_install_property
+		(object_class, PROP_SCOPE,
+		 g_param_spec_uint (NM_REMOTE_SETTINGS_SCOPE,
+		                    "Scope",
+		                    "NMConnection scope",
+		                    NM_CONNECTION_SCOPE_UNKNOWN,
+		                    NM_CONNECTION_SCOPE_USER,
+		                    NM_CONNECTION_SCOPE_USER,
+		                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+	g_object_class_install_property
+		(object_class, PROP_SERVICE_RUNNING,
+		 g_param_spec_boolean (NM_REMOTE_SETTINGS_SERVICE_RUNNING,
+		                       "Service running",
+		                       "Is service running",
+		                       FALSE,
+		                       G_PARAM_READABLE));
+}
+
diff --git a/libnm-glib/nm-remote-settings.h b/libnm-glib/nm-remote-settings.h
new file mode 100644
index 00000000..d3085566
--- /dev/null
+++ b/libnm-glib/nm-remote-settings.h
@@ -0,0 +1,67 @@
+/* -*- 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) 2008 Novell, Inc.
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
+
+#ifndef NM_REMOTE_SETTINGS_H
+#define NM_REMOTE_SETTINGS_H
+
+#include <glib.h>
+#include <dbus/dbus-glib.h>
+#include <nm-connection.h>
+#include <nm-remote-connection.h>
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_REMOTE_SETTINGS            (nm_remote_settings_get_type ())
+#define NM_REMOTE_SETTINGS(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_REMOTE_SETTINGS, NMRemoteSettings))
+#define NM_REMOTE_SETTINGS_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_REMOTE_SETTINGS, NMRemoteSettingsClass))
+#define NM_IS_REMOTE_SETTINGS(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_REMOTE_SETTINGS))
+#define NM_IS_REMOTE_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_REMOTE_SETTINGS))
+#define NM_REMOTE_SETTINGS_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_REMOTE_SETTINGS, NMRemoteSettingsClass))
+
+#define NM_REMOTE_SETTINGS_BUS "bus"
+#define NM_REMOTE_SETTINGS_SCOPE "scope"
+#define NM_REMOTE_SETTINGS_SERVICE_RUNNING "service-running"
+
+typedef struct {
+	GObject parent;
+} NMRemoteSettings;
+
+typedef struct {
+	GObjectClass parent;
+
+	/* Padding for future expansion */
+	void (*_reserved1) (void);
+	void (*_reserved2) (void);
+	void (*_reserved3) (void);
+	void (*_reserved4) (void);
+	void (*_reserved5) (void);
+	void (*_reserved6) (void);
+} NMRemoteSettingsClass;
+
+GType nm_remote_settings_get_type (void);
+
+NMRemoteSettings *nm_remote_settings_new (DBusGConnection *bus, NMConnectionScope scope);
+
+G_END_DECLS
+
+#endif /* NM_REMOTE_SETTINGS_H */
diff --git a/libnm-glib/nm-serial-device.c b/libnm-glib/nm-serial-device.c
new file mode 100644
index 00000000..bb45d7c4
--- /dev/null
+++ b/libnm-glib/nm-serial-device.c
@@ -0,0 +1,207 @@
+/* -*- 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) 2008 Novell, Inc.
+ */
+
+#include "nm-serial-device.h"
+#include "nm-device-private.h"
+#include "nm-object-private.h"
+#include "nm-marshal.h"
+
+G_DEFINE_ABSTRACT_TYPE (NMSerialDevice, nm_serial_device, NM_TYPE_DEVICE)
+
+#define NM_SERIAL_DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SERIAL_DEVICE, NMSerialDevicePrivate))
+
+typedef struct {
+	DBusGProxy *proxy;
+
+	guint32 in_bytes;
+	guint32 out_bytes;
+
+	gboolean disposed;
+} NMSerialDevicePrivate;
+
+enum {
+	PPP_STATS,
+
+	LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+/**
+ * nm_serial_device_get_bytes_received:
+ * @self: a #NMSerialDevice
+ *
+ * Gets the amount of bytes received by the serial device.
+ * This counter is reset when the device is activated.
+ *
+ * Returns: bytes received
+ **/
+guint32
+nm_serial_device_get_bytes_received (NMSerialDevice *self)
+{
+	g_return_val_if_fail (NM_IS_SERIAL_DEVICE (self), 0);
+
+	return NM_SERIAL_DEVICE_GET_PRIVATE (self)->in_bytes;
+}
+
+/**
+ * nm_serial_device_get_bytes_sent:
+ * @self: a #NMSerialDevice
+ *
+ * Gets the amount of bytes sent by the serial device.
+ * This counter is reset when the device is activated.
+ *
+ * Returns: bytes sent
+ **/
+guint32
+nm_serial_device_get_bytes_sent (NMSerialDevice *self)
+{
+	g_return_val_if_fail (NM_IS_SERIAL_DEVICE (self), 0);
+
+	return NM_SERIAL_DEVICE_GET_PRIVATE (self)->out_bytes;
+}
+
+static void
+ppp_stats (DBusGProxy *proxy,
+		   guint32 in_bytes,
+		   guint32 out_bytes,
+		   gpointer user_data)
+{
+	NMSerialDevice *self = NM_SERIAL_DEVICE (user_data);
+	NMSerialDevicePrivate *priv = NM_SERIAL_DEVICE_GET_PRIVATE (self);
+
+	priv->in_bytes = in_bytes;
+	priv->out_bytes = out_bytes;
+
+	g_signal_emit (self, signals[PPP_STATS], 0, in_bytes, out_bytes);
+}
+
+static void
+device_state_changed (NMDevice *device, GParamSpec *pspec, gpointer user_data)
+{
+	NMSerialDevicePrivate *priv;
+
+	switch (nm_device_get_state (device)) {
+	case NM_DEVICE_STATE_UNMANAGED:
+	case NM_DEVICE_STATE_UNAVAILABLE:
+	case NM_DEVICE_STATE_DISCONNECTED:
+		priv = NM_SERIAL_DEVICE_GET_PRIVATE (device);
+		priv->in_bytes = priv->out_bytes = 0;
+		break;
+	default:
+		break;
+	}
+}
+
+static void
+nm_serial_device_init (NMSerialDevice *device)
+{
+}
+
+static GObject*
+constructor (GType type,
+			 guint n_construct_params,
+			 GObjectConstructParam *construct_params)
+{
+	GObject *object;
+	NMSerialDevicePrivate *priv;
+
+	object = G_OBJECT_CLASS (nm_serial_device_parent_class)->constructor (type,
+																		  n_construct_params,
+																		  construct_params);
+	if (!object)
+		return NULL;
+
+	priv = NM_SERIAL_DEVICE_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_SERIAL_DEVICE);
+
+	dbus_g_object_register_marshaller (_nm_marshal_VOID__UINT_UINT,
+	                                   G_TYPE_NONE,
+	                                   G_TYPE_UINT, G_TYPE_UINT,
+	                                   G_TYPE_INVALID);
+
+	dbus_g_proxy_add_signal (priv->proxy, "PppStats", G_TYPE_UINT, G_TYPE_UINT, G_TYPE_INVALID);
+	dbus_g_proxy_connect_signal (priv->proxy, "PppStats",
+								 G_CALLBACK (ppp_stats),
+								 object,
+								 NULL);
+
+	/* Catch NMDevice::state changes to reset the counters */
+	g_signal_connect (object, "notify::state",
+					  G_CALLBACK (device_state_changed),
+					  object);
+
+	return object;
+}
+
+static void
+dispose (GObject *object)
+{
+	NMSerialDevicePrivate *priv = NM_SERIAL_DEVICE_GET_PRIVATE (object);
+
+	if (priv->disposed) {
+		G_OBJECT_CLASS (nm_serial_device_parent_class)->dispose (object);
+		return;
+	}
+
+	priv->disposed = TRUE;
+
+	g_object_unref (priv->proxy);
+
+	G_OBJECT_CLASS (nm_serial_device_parent_class)->dispose (object);
+}
+
+static void
+nm_serial_device_class_init (NMSerialDeviceClass *device_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (device_class);
+
+	g_type_class_add_private (device_class, sizeof (NMSerialDevicePrivate));
+
+	/* virtual methods */
+	object_class->constructor = constructor;
+	object_class->dispose = dispose;
+
+	/* Signals */
+
+	/**
+	 * NMSerialDevice::ppp-stats:
+	 * @device: the serial device that received the signal
+	 * @in_bytes: the amount of bytes received
+	 * @out_bytes: the amount of bytes sent
+	 *
+	 * Notifies that a #NMAccessPoint is added to the wifi device.
+	 **/
+	signals[PPP_STATS] =
+		g_signal_new ("ppp-stats",
+					  G_OBJECT_CLASS_TYPE (object_class),
+					  G_SIGNAL_RUN_FIRST,
+					  G_STRUCT_OFFSET (NMSerialDeviceClass, ppp_stats),
+					  NULL, NULL,
+					  _nm_marshal_VOID__UINT_UINT,
+					  G_TYPE_NONE, 2,
+					  G_TYPE_UINT, G_TYPE_UINT);
+}
diff --git a/libnm-glib/nm-serial-device.h b/libnm-glib/nm-serial-device.h
new file mode 100644
index 00000000..51f08df3
--- /dev/null
+++ b/libnm-glib/nm-serial-device.h
@@ -0,0 +1,63 @@
+/* -*- 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) 2008 Novell, Inc.
+ */
+
+#ifndef NM_SERIAL_DEVICE_H
+#define NM_SERIAL_DEVICE_H
+
+#include "nm-device.h"
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_SERIAL_DEVICE            (nm_serial_device_get_type ())
+#define NM_SERIAL_DEVICE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SERIAL_DEVICE, NMSerialDevice))
+#define NM_SERIAL_DEVICE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SERIAL_DEVICE, NMSerialDeviceClass))
+#define NM_IS_SERIAL_DEVICE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SERIAL_DEVICE))
+#define NM_IS_SERIAL_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_SERIAL_DEVICE))
+#define NM_SERIAL_DEVICE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SERIAL_DEVICE, NMSerialDeviceClass))
+
+typedef struct {
+	NMDevice parent;
+} NMSerialDevice;
+
+typedef struct {
+	NMDeviceClass parent;
+
+	/* Signals */
+	void (*ppp_stats) (NMSerialDevice *self, guint32 in_bytes, guint32 out_bytes);
+
+	/* Padding for future expansion */
+	void (*_reserved1) (void);
+	void (*_reserved2) (void);
+	void (*_reserved3) (void);
+	void (*_reserved4) (void);
+	void (*_reserved5) (void);
+	void (*_reserved6) (void);
+} NMSerialDeviceClass;
+
+GType nm_serial_device_get_type (void);
+
+guint32 nm_serial_device_get_bytes_received (NMSerialDevice *self);
+guint32 nm_serial_device_get_bytes_sent     (NMSerialDevice *self);
+
+G_END_DECLS
+
+#endif /* NM_SERIAL_DEVICE_H */
diff --git a/libnm-glib/nm-settings-connection-interface.c b/libnm-glib/nm-settings-connection-interface.c
new file mode 100644
index 00000000..868ad047
--- /dev/null
+++ b/libnm-glib/nm-settings-connection-interface.c
@@ -0,0 +1,192 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager -- Network link manager
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2007 - 2008 Novell, Inc.
+ * Copyright (C) 2007 - 2009 Red Hat, Inc.
+ */
+
+#include "nm-settings-connection-interface.h"
+#include "nm-dbus-glib-types.h"
+
+/**
+ * nm_settings_connection_interface_update:
+ * @connection: an object implementing #NMSettingsConnectionInterface
+ * @callback: a function to be called when the update completes
+ * @user_data: caller-specific data to be passed to @callback
+ *
+ * Update the connection with current settings and properties.
+ *
+ * Returns: TRUE on success, FALSE on failure
+ **/
+gboolean
+nm_settings_connection_interface_update (NMSettingsConnectionInterface *connection,
+                                         NMSettingsConnectionInterfaceUpdateFunc callback,
+                                         gpointer user_data)
+{
+	g_return_val_if_fail (connection != NULL, FALSE);
+	g_return_val_if_fail (NM_IS_SETTINGS_CONNECTION_INTERFACE (connection), FALSE);
+	g_return_val_if_fail (callback != NULL, FALSE);
+
+	if (NM_SETTINGS_CONNECTION_INTERFACE_GET_INTERFACE (connection)->update) {
+		return NM_SETTINGS_CONNECTION_INTERFACE_GET_INTERFACE (connection)->update (connection,
+		                                                                            callback,
+		                                                                            user_data);
+	}
+	return FALSE;
+}
+
+/**
+ * nm_settings_connection_interface_delete:
+ * @connection: a objecting implementing #NMSettingsConnectionInterface
+ * @callback: a function to be called when the delete completes
+ * @user_data: caller-specific data to be passed to @callback
+ *
+ * Delete the connection.
+ *
+ * Returns: TRUE on success, FALSE on failure
+ **/
+gboolean
+nm_settings_connection_interface_delete (NMSettingsConnectionInterface *connection,
+                                         NMSettingsConnectionInterfaceDeleteFunc callback,
+                                         gpointer user_data)
+{
+	g_return_val_if_fail (connection != NULL, FALSE);
+	g_return_val_if_fail (NM_IS_SETTINGS_CONNECTION_INTERFACE (connection), FALSE);
+	g_return_val_if_fail (callback != NULL, FALSE);
+
+	if (NM_SETTINGS_CONNECTION_INTERFACE_GET_INTERFACE (connection)->delete) {
+		return NM_SETTINGS_CONNECTION_INTERFACE_GET_INTERFACE (connection)->delete (connection,
+		                                                                            callback,
+		                                                                            user_data);
+	}
+	return FALSE;
+}
+
+/**
+ * nm_settings_connection_interface_get_secrets:
+ * @connection: a object implementing #NMSettingsConnectionInterface
+ * @setting_name: the #NMSetting object name to get secrets for
+ * @hints: #NMSetting key names to get secrets for (optional)
+ * @request_new: hint that new secrets (instead of cached or stored secrets) 
+ *  should be returned
+ * @callback: a function to be called when the update completes
+ * @user_data: caller-specific data to be passed to @callback
+ *
+ * Request the connection's secrets.
+ *
+ * Returns: TRUE on success, FALSE on failure
+ **/
+gboolean
+nm_settings_connection_interface_get_secrets (NMSettingsConnectionInterface *connection,
+                                              const char *setting_name,
+                                              const char **hints,
+                                              gboolean request_new,
+                                              NMSettingsConnectionInterfaceGetSecretsFunc callback,
+                                              gpointer user_data)
+{
+	g_return_val_if_fail (connection != NULL, FALSE);
+	g_return_val_if_fail (NM_IS_SETTINGS_CONNECTION_INTERFACE (connection), FALSE);
+	g_return_val_if_fail (callback != NULL, FALSE);
+
+	if (NM_SETTINGS_CONNECTION_INTERFACE_GET_INTERFACE (connection)->get_secrets) {
+		return NM_SETTINGS_CONNECTION_INTERFACE_GET_INTERFACE (connection)->get_secrets (connection,
+		                                                                                 setting_name,
+		                                                                                 hints,
+		                                                                                 request_new,
+		                                                                                 callback,
+		                                                                                 user_data);
+	}
+	return FALSE;
+}
+
+void
+nm_settings_connection_interface_emit_updated (NMSettingsConnectionInterface *connection)
+{
+	if (NM_SETTINGS_CONNECTION_INTERFACE_GET_INTERFACE (connection)->emit_updated)
+		NM_SETTINGS_CONNECTION_INTERFACE_GET_INTERFACE (connection)->emit_updated (connection);
+	else {
+		NMConnection *tmp;
+		GHashTable *settings;
+
+		tmp = nm_connection_duplicate (NM_CONNECTION (connection));
+		nm_connection_clear_secrets (tmp);
+		settings = nm_connection_to_hash (tmp);
+		g_object_unref (tmp);
+
+		g_signal_emit_by_name (connection, NM_SETTINGS_CONNECTION_INTERFACE_UPDATED, settings);
+		g_hash_table_destroy (settings);
+	}
+}
+
+static void
+nm_settings_connection_interface_init (gpointer g_iface)
+{
+	GType iface_type = G_TYPE_FROM_INTERFACE (g_iface);
+	static gboolean initialized = FALSE;
+
+	if (initialized)
+		return;
+
+	/* Signals */
+	g_signal_new (NM_SETTINGS_CONNECTION_INTERFACE_UPDATED,
+				  iface_type,
+				  G_SIGNAL_RUN_FIRST,
+				  G_STRUCT_OFFSET (NMSettingsConnectionInterface, updated),
+				  NULL, NULL,
+				  g_cclosure_marshal_VOID__BOXED,
+				  G_TYPE_NONE, 1, DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT);
+
+	g_signal_new (NM_SETTINGS_CONNECTION_INTERFACE_REMOVED,
+				  iface_type,
+				  G_SIGNAL_RUN_FIRST,
+				  G_STRUCT_OFFSET (NMSettingsConnectionInterface, removed),
+				  NULL, NULL,
+				  g_cclosure_marshal_VOID__VOID,
+				  G_TYPE_NONE, 0);
+
+	initialized = TRUE;
+}
+
+GType
+nm_settings_connection_interface_get_type (void)
+{
+	static GType itype = 0;
+
+	if (!itype) {
+		const GTypeInfo iinfo = {
+			sizeof (NMSettingsConnectionInterface), /* class_size */
+			nm_settings_connection_interface_init,   /* base_init */
+			NULL,		/* base_finalize */
+			NULL,
+			NULL,		/* class_finalize */
+			NULL,		/* class_data */
+			0,
+			0,              /* n_preallocs */
+			NULL
+		};
+
+		itype = g_type_register_static (G_TYPE_INTERFACE,
+		                                "NMSettingsConnectionInterface",
+		                                &iinfo, 0);
+
+		g_type_interface_add_prerequisite (itype, NM_TYPE_CONNECTION);
+	}
+
+	return itype;
+}
+
diff --git a/libnm-glib/nm-settings-connection-interface.h b/libnm-glib/nm-settings-connection-interface.h
new file mode 100644
index 00000000..7c7a198c
--- /dev/null
+++ b/libnm-glib/nm-settings-connection-interface.h
@@ -0,0 +1,116 @@
+/* -*- 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.
+ * Copyright (C) 2007 - 2009 Red Hat, Inc.
+ */
+
+#ifndef __NM_SETTINGS_CONNECTION_INTERFACE_H__
+#define __NM_SETTINGS_CONNECTION_INTERFACE_H__
+
+#include <glib-object.h>
+#include <dbus/dbus-glib.h>
+
+#include <nm-connection.h>
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_SETTINGS_CONNECTION_INTERFACE               (nm_settings_connection_interface_get_type ())
+#define NM_SETTINGS_CONNECTION_INTERFACE(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTINGS_CONNECTION_INTERFACE, NMSettingsConnectionInterface))
+#define NM_IS_SETTINGS_CONNECTION_INTERFACE(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTINGS_CONNECTION_INTERFACE))
+#define NM_SETTINGS_CONNECTION_INTERFACE_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), NM_TYPE_SETTINGS_CONNECTION_INTERFACE, NMSettingsConnectionInterface))
+
+#define NM_SETTINGS_CONNECTION_INTERFACE_UPDATED               "updated"
+#define NM_SETTINGS_CONNECTION_INTERFACE_REMOVED               "removed"
+
+typedef struct _NMSettingsConnectionInterface NMSettingsConnectionInterface;
+
+typedef void (*NMSettingsConnectionInterfaceUpdateFunc) (NMSettingsConnectionInterface *connection,
+                                                         GError *error,
+                                                         gpointer user_data);
+
+typedef void (*NMSettingsConnectionInterfaceDeleteFunc) (NMSettingsConnectionInterface *connection,
+                                                         GError *error,
+                                                         gpointer user_data);
+
+typedef void (*NMSettingsConnectionInterfaceGetSecretsFunc) (NMSettingsConnectionInterface *connection,
+                                                             GHashTable *secrets,
+                                                             GError *error,
+                                                             gpointer user_data);
+
+struct _NMSettingsConnectionInterface {
+	GTypeInterface g_iface;
+
+	/* Methods */
+	gboolean (*update) (NMSettingsConnectionInterface *connection,
+	                    NMSettingsConnectionInterfaceUpdateFunc callback,
+	                    gpointer user_data);
+
+	gboolean (*delete) (NMSettingsConnectionInterface *connection,
+	                    NMSettingsConnectionInterfaceDeleteFunc callback,
+	                    gpointer user_data);
+
+	gboolean (*get_secrets) (NMSettingsConnectionInterface *connection,
+	                         const char *setting_name,
+                             const char **hints,
+                             gboolean request_new,
+                             NMSettingsConnectionInterfaceGetSecretsFunc callback,
+                             gpointer user_data);
+
+	void (*emit_updated) (NMSettingsConnectionInterface *connection);
+
+	/* Signals */
+	/* 'new_settings' hash should *not* contain secrets */
+	void (*updated) (NMSettingsConnectionInterface *connection,
+	                 GHashTable *new_settings);
+
+	void (*removed) (NMSettingsConnectionInterface *connection);
+
+	/* Padding for future expansion */
+	void (*_reserved1) (void);
+	void (*_reserved2) (void);
+	void (*_reserved3) (void);
+	void (*_reserved4) (void);
+	void (*_reserved5) (void);
+	void (*_reserved6) (void);
+};
+
+GType nm_settings_connection_interface_get_type (void);
+
+gboolean nm_settings_connection_interface_update (NMSettingsConnectionInterface *connection,
+                                                  NMSettingsConnectionInterfaceUpdateFunc callback,
+                                                  gpointer user_data);
+
+gboolean nm_settings_connection_interface_delete (NMSettingsConnectionInterface *connection,
+                                                  NMSettingsConnectionInterfaceDeleteFunc callback,
+                                                  gpointer user_data);
+
+gboolean nm_settings_connection_interface_get_secrets (NMSettingsConnectionInterface *connection,
+                                                       const char *setting_name,
+                                                       const char **hints,
+                                                       gboolean request_new,
+                                                       NMSettingsConnectionInterfaceGetSecretsFunc callback,
+                                                       gpointer user_data);
+
+void nm_settings_connection_interface_emit_updated (NMSettingsConnectionInterface *connection);
+
+G_END_DECLS
+
+#endif  /* __NM_SETTINGS_CONNECTION_INTERFACE_H__ */
+
diff --git a/libnm-glib/nm-settings-interface.c b/libnm-glib/nm-settings-interface.c
new file mode 100644
index 00000000..3bd4037a
--- /dev/null
+++ b/libnm-glib/nm-settings-interface.c
@@ -0,0 +1,206 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager -- Network link manager
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2007 - 2008 Novell, Inc.
+ * Copyright (C) 2007 - 2010 Red Hat, Inc.
+ */
+
+#include "nm-settings-interface.h"
+
+
+/**
+ * nm_settings_interface_error_quark:
+ *
+ * Setting error quark.
+ *
+ * Returns: the setting error quark
+ **/
+GQuark
+nm_settings_interface_error_quark (void)
+{
+	static GQuark quark;
+
+	if (G_UNLIKELY (!quark))
+		quark = g_quark_from_static_string ("nm-settings-interface-error-quark");
+	return quark;
+}
+
+/* This should really be standard. */
+#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
+
+GType
+nm_settings_interface_error_get_type (void)
+{
+	static GType etype = 0;
+
+	if (etype == 0) {
+		static const GEnumValue values[] = {
+			/* The connection was invalid. */
+			ENUM_ENTRY (NM_SETTINGS_INTERFACE_ERROR_INVALID_CONNECTION, "InvalidConnection"),
+			/* The connection is read-only; modifications are not allowed. */
+			ENUM_ENTRY (NM_SETTINGS_INTERFACE_ERROR_READ_ONLY_CONNECTION, "ReadOnlyConnection"),
+			/* A bug in the settings service caused the error. */
+			ENUM_ENTRY (NM_SETTINGS_INTERFACE_ERROR_INTERNAL_ERROR, "InternalError"),
+			/* Retrieval or request of secrets failed. */
+			ENUM_ENTRY (NM_SETTINGS_INTERFACE_ERROR_SECRETS_UNAVAILABLE, "SecretsUnavailable"),
+			/* The request for secrets was canceled. */
+			ENUM_ENTRY (NM_SETTINGS_INTERFACE_ERROR_SECRETS_REQUEST_CANCELED, "SecretsRequestCanceled"),
+			/* The request could not be completed because permission was denied. */
+			ENUM_ENTRY (NM_SETTINGS_INTERFACE_ERROR_PERMISSION_DENIED, "PermissionDenied"),
+			/* The requested setting does not existing in this connection. */
+			ENUM_ENTRY (NM_SETTINGS_INTERFACE_ERROR_INVALID_SETTING, "InvalidSetting"),
+			{ 0, 0, 0 },
+		};
+		etype = g_enum_register_static ("NMSettingsInterfaceError", values);
+	}
+	return etype;
+}
+
+
+/**
+ * nm_settings_list_connections:
+ * @settings: a object implementing %NMSettingsInterface
+ *
+ * Returns: all connections known to the object.
+ **/
+GSList *
+nm_settings_interface_list_connections (NMSettingsInterface *settings)
+{
+	g_return_val_if_fail (settings != NULL, NULL);
+	g_return_val_if_fail (NM_IS_SETTINGS_INTERFACE (settings), NULL);
+
+	if (NM_SETTINGS_INTERFACE_GET_INTERFACE (settings)->list_connections)
+		return NM_SETTINGS_INTERFACE_GET_INTERFACE (settings)->list_connections (settings);
+	return NULL;
+}
+
+/**
+ * nm_settings_get_connection_by_path:
+ * @settings: a object implementing %NMSettingsInterface
+ * @path: the D-Bus object path of the remote connection
+ *
+ * Returns the object implementing %NMSettingsConnectionInterface at @path.
+ *
+ * Returns: the remote connection object on success, or NULL if the object was
+ *  not known
+ **/
+NMSettingsConnectionInterface *
+nm_settings_interface_get_connection_by_path (NMSettingsInterface *settings,
+                                              const char *path)
+{
+	g_return_val_if_fail (settings != NULL, NULL);
+	g_return_val_if_fail (NM_IS_SETTINGS_INTERFACE (settings), NULL);
+	g_return_val_if_fail (path != NULL, NULL);
+
+	if (NM_SETTINGS_INTERFACE_GET_INTERFACE (settings)->get_connection_by_path)
+		return NM_SETTINGS_INTERFACE_GET_INTERFACE (settings)->get_connection_by_path (settings, path);
+	return NULL;
+}
+
+/**
+ * nm_settings_interface_add_connection:
+ * @settings: a object implementing %NMSettingsInterface
+ * @connection: the settings to add; note that this object's settings will be
+ *  added, not the object itself
+ * @callback: callback to be called when the add operation completes
+ * @user_data: caller-specific data passed to @callback
+ *
+ * Requests that the settings service add the given settings to a new connection.
+ *
+ * Returns: TRUE if the request was successful, FALSE if it failed
+ **/
+gboolean
+nm_settings_interface_add_connection (NMSettingsInterface *settings,
+                                      NMConnection *connection,
+                                      NMSettingsAddConnectionFunc callback,
+                                      gpointer user_data)
+{
+	g_return_val_if_fail (settings != NULL, FALSE);
+	g_return_val_if_fail (NM_IS_SETTINGS_INTERFACE (settings), FALSE);
+	g_return_val_if_fail (connection != NULL, FALSE);
+	g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
+	g_return_val_if_fail (callback != NULL, FALSE);
+
+	if (NM_SETTINGS_INTERFACE_GET_INTERFACE (settings)->add_connection) {
+		return NM_SETTINGS_INTERFACE_GET_INTERFACE (settings)->add_connection (settings,
+		                                                                       connection,
+		                                                                       callback,
+		                                                                       user_data);
+	}
+	return FALSE;
+}
+
+/*****************************************************************/
+
+static void
+nm_settings_interface_init (gpointer g_iface)
+{
+	GType iface_type = G_TYPE_FROM_INTERFACE (g_iface);
+	static gboolean initialized = FALSE;
+
+	if (initialized)
+		return;
+
+	/* Signals */
+	g_signal_new (NM_SETTINGS_INTERFACE_NEW_CONNECTION,
+				  iface_type,
+				  G_SIGNAL_RUN_FIRST,
+				  G_STRUCT_OFFSET (NMSettingsInterface, new_connection),
+				  NULL, NULL,
+				  g_cclosure_marshal_VOID__OBJECT,
+				  G_TYPE_NONE, 1, G_TYPE_OBJECT);
+
+	g_signal_new (NM_SETTINGS_INTERFACE_CONNECTIONS_READ,
+				  iface_type,
+				  G_SIGNAL_RUN_FIRST,
+				  G_STRUCT_OFFSET (NMSettingsInterface, connections_read),
+				  NULL, NULL,
+				  g_cclosure_marshal_VOID__VOID,
+				  G_TYPE_NONE, 0);
+
+	initialized = TRUE;
+}
+
+GType
+nm_settings_interface_get_type (void)
+{
+	static GType settings_interface_type = 0;
+
+	if (!settings_interface_type) {
+		const GTypeInfo settings_interface_info = {
+			sizeof (NMSettingsInterface), /* class_size */
+			nm_settings_interface_init,   /* base_init */
+			NULL,		/* base_finalize */
+			NULL,
+			NULL,		/* class_finalize */
+			NULL,		/* class_data */
+			0,
+			0,              /* n_preallocs */
+			NULL
+		};
+
+		settings_interface_type = g_type_register_static (G_TYPE_INTERFACE,
+		                                                  "NMSettingsInterface",
+		                                                  &settings_interface_info, 0);
+
+		g_type_interface_add_prerequisite (settings_interface_type, G_TYPE_OBJECT);
+	}
+
+	return settings_interface_type;
+}
+
diff --git a/libnm-glib/nm-settings-interface.h b/libnm-glib/nm-settings-interface.h
new file mode 100644
index 00000000..5920bd82
--- /dev/null
+++ b/libnm-glib/nm-settings-interface.h
@@ -0,0 +1,109 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager -- Network link manager
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2007 - 2008 Novell, Inc.
+ * Copyright (C) 2007 - 2010 Red Hat, Inc.
+ */
+
+#ifndef NM_SETTINGS_INTERFACE_H
+#define NM_SETTINGS_INTERFACE_H
+
+#include <glib-object.h>
+
+#include "NetworkManager.h"
+#include "nm-settings-connection-interface.h"
+
+G_BEGIN_DECLS
+
+typedef enum {
+	NM_SETTINGS_INTERFACE_ERROR_INVALID_CONNECTION = 0,
+	NM_SETTINGS_INTERFACE_ERROR_READ_ONLY_CONNECTION,
+	NM_SETTINGS_INTERFACE_ERROR_INTERNAL_ERROR,
+	NM_SETTINGS_INTERFACE_ERROR_SECRETS_UNAVAILABLE,
+	NM_SETTINGS_INTERFACE_ERROR_SECRETS_REQUEST_CANCELED,
+	NM_SETTINGS_INTERFACE_ERROR_PERMISSION_DENIED,
+	NM_SETTINGS_INTERFACE_ERROR_INVALID_SETTING,
+} NMSettingsInterfaceError;
+
+#define NM_SETTINGS_INTERFACE_ERROR (nm_settings_interface_error_quark ())
+GQuark nm_settings_interface_error_quark (void);
+
+#define NM_TYPE_SETTINGS_INTERFACE_ERROR (nm_settings_interface_error_get_type ()) 
+GType nm_settings_interface_error_get_type (void);
+
+
+#define NM_TYPE_SETTINGS_INTERFACE               (nm_settings_interface_get_type ())
+#define NM_SETTINGS_INTERFACE(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTINGS_INTERFACE, NMSettingsInterface))
+#define NM_IS_SETTINGS_INTERFACE(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTINGS_INTERFACE))
+#define NM_SETTINGS_INTERFACE_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), NM_TYPE_SETTINGS_INTERFACE, NMSettingsInterface))
+
+#define NM_SETTINGS_INTERFACE_NEW_CONNECTION   "new-connection"
+#define NM_SETTINGS_INTERFACE_CONNECTIONS_READ "connections-read"
+
+typedef struct _NMSettingsInterface NMSettingsInterface;
+
+typedef void (*NMSettingsAddConnectionFunc) (NMSettingsInterface *settings,
+                                             GError *error,
+                                             gpointer user_data);
+
+struct _NMSettingsInterface {
+	GTypeInterface g_iface;
+
+	/* Methods */
+	/* Returns a list of objects implementing NMSettingsConnectionInterface */
+	GSList * (*list_connections) (NMSettingsInterface *settings);
+
+	NMSettingsConnectionInterface * (*get_connection_by_path) (NMSettingsInterface *settings,
+	                                                           const char *path);
+
+	gboolean (*add_connection) (NMSettingsInterface *settings,
+	                            NMConnection *connection,
+	                            NMSettingsAddConnectionFunc callback,
+	                            gpointer user_data);
+
+	/* Signals */
+	void (*new_connection) (NMSettingsInterface *settings,
+	                        NMSettingsConnectionInterface *connection);
+
+	void (*connections_read) (NMSettingsInterface *settings);
+
+	/* Padding for future expansion */
+	void (*_reserved1) (void);
+	void (*_reserved2) (void);
+	void (*_reserved3) (void);
+	void (*_reserved4) (void);
+	void (*_reserved5) (void);
+	void (*_reserved6) (void);
+};
+
+GType nm_settings_interface_get_type (void);
+
+/* Returns a list of objects implementing NMSettingsConnectionInterface */
+GSList *nm_settings_interface_list_connections (NMSettingsInterface *settings);
+
+NMSettingsConnectionInterface *nm_settings_interface_get_connection_by_path (NMSettingsInterface *settings,
+                                                                             const char *path); 
+
+gboolean nm_settings_interface_add_connection (NMSettingsInterface *settings,
+                                               NMConnection *connection,
+                                               NMSettingsAddConnectionFunc callback,
+                                               gpointer user_data);
+
+G_END_DECLS
+
+#endif /* NM_SETTINGS_INTERFACE_H */
diff --git a/libnm-glib/nm-settings-service.c b/libnm-glib/nm-settings-service.c
new file mode 100644
index 00000000..6266d10d
--- /dev/null
+++ b/libnm-glib/nm-settings-service.c
@@ -0,0 +1,372 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager system settings service
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2008 Novell, Inc.
+ * (C) Copyright 2008 - 2009 Red Hat, Inc.
+ */
+
+#include <string.h>
+#include <NetworkManager.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include "nm-settings-service.h"
+#include "nm-settings-interface.h"
+#include "nm-exported-connection.h"
+
+static gboolean impl_settings_list_connections (NMSettingsService *self,
+                                                GPtrArray **connections,
+                                                GError **error);
+
+static void impl_settings_add_connection (NMSettingsService *self,
+                                          GHashTable *settings,
+                                          DBusGMethodInvocation *context);
+
+#include "nm-settings-glue.h"
+
+static void settings_interface_init (NMSettingsInterface *class);
+
+G_DEFINE_TYPE_EXTENDED (NMSettingsService, nm_settings_service, G_TYPE_OBJECT, G_TYPE_FLAG_ABSTRACT,
+                        G_IMPLEMENT_INTERFACE (NM_TYPE_SETTINGS_INTERFACE, settings_interface_init))
+
+#define NM_SETTINGS_SERVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
+                                            NM_TYPE_SETTINGS_SERVICE, \
+                                            NMSettingsServicePrivate))
+
+typedef struct {
+	DBusGConnection *bus;
+	NMConnectionScope scope;
+	gboolean exported;
+
+	gboolean disposed;
+} NMSettingsServicePrivate;
+
+enum {
+	PROP_0,
+	PROP_BUS,
+	PROP_SCOPE,
+
+	LAST_PROP
+};
+
+
+/**************************************************************/
+
+void
+nm_settings_service_export (NMSettingsService *self)
+{
+	NMSettingsServicePrivate *priv;
+
+	g_return_if_fail (self != NULL);
+	g_return_if_fail (NM_IS_SETTINGS_SERVICE (self));
+
+	priv = NM_SETTINGS_SERVICE_GET_PRIVATE (self);
+
+	g_return_if_fail (priv->bus != NULL);
+
+	/* Don't allow exporting twice */
+	g_return_if_fail (priv->exported == FALSE);
+
+	dbus_g_connection_register_g_object (priv->bus,
+	                                     NM_DBUS_PATH_SETTINGS,
+	                                     G_OBJECT (self));
+	priv->exported = TRUE;
+}
+
+/**************************************************************/
+
+static GSList *
+list_connections (NMSettingsInterface *settings)
+{
+	/* Must always be implemented */
+	g_assert (NM_SETTINGS_SERVICE_GET_CLASS (settings)->list_connections);
+	return NM_SETTINGS_SERVICE_GET_CLASS (settings)->list_connections (NM_SETTINGS_SERVICE (settings));
+}
+
+static gboolean
+impl_settings_list_connections (NMSettingsService *self,
+                                GPtrArray **connections,
+                                GError **error)
+{
+	GSList *list = NULL, *iter;
+
+	list = list_connections (NM_SETTINGS_INTERFACE (self));
+	*connections = g_ptr_array_sized_new (g_slist_length (list) + 1);
+	for (iter = list; iter; iter = g_slist_next (iter)) {
+		g_ptr_array_add (*connections,
+		                 g_strdup (nm_connection_get_path (NM_CONNECTION (iter->data))));
+	}
+	g_slist_free (list);
+	return TRUE;
+}
+
+static NMSettingsConnectionInterface *
+get_connection_by_path (NMSettingsInterface *settings, const char *path)
+{
+	NMExportedConnection *connection = NULL;
+	GSList *list = NULL, *iter;
+
+	list = list_connections (settings);
+	for (iter = list; iter; iter = g_slist_next (iter)) {
+		if (!strcmp (nm_connection_get_path (NM_CONNECTION (iter->data)), path)) {
+			connection = NM_EXPORTED_CONNECTION (iter->data);
+			break;
+		}
+	}
+	g_slist_free (list);
+
+	return (NMSettingsConnectionInterface *) connection;
+}
+
+NMExportedConnection *
+nm_settings_service_get_connection_by_path (NMSettingsService *self,
+                                            const char *path)
+{
+	g_return_val_if_fail (self != NULL, NULL);
+	g_return_val_if_fail (NM_IS_SETTINGS_SERVICE (self), NULL);
+
+	return (NMExportedConnection *) get_connection_by_path (NM_SETTINGS_INTERFACE (self), path);
+}
+
+static gboolean
+add_connection (NMSettingsInterface *settings,
+                NMConnection *connection,
+                NMSettingsAddConnectionFunc callback,
+                gpointer user_data)
+{
+	NMSettingsService *self = NM_SETTINGS_SERVICE (settings);
+	GError *error = NULL;
+	gboolean success = FALSE;
+
+	if (NM_SETTINGS_SERVICE_GET_CLASS (self)->add_connection) {
+		NM_SETTINGS_SERVICE_GET_CLASS (self)->add_connection (NM_SETTINGS_SERVICE (self),
+		                                                      connection,
+		                                                      NULL,
+		                                                      callback,
+		                                                      user_data);
+		success = TRUE;
+	} else {
+		error = g_error_new (NM_SETTINGS_INTERFACE_ERROR,
+		                     NM_SETTINGS_INTERFACE_ERROR_INTERNAL_ERROR,
+		                     "%s: %s:%d add_connection() not implemented",
+		                     __func__, __FILE__, __LINE__);
+		callback (settings, error, user_data);
+		g_error_free (error);
+	}
+
+	return success;
+}
+
+static void
+dbus_add_connection_cb (NMSettingsInterface *settings,
+                        GError *error,
+                        gpointer user_data)
+{
+	DBusGMethodInvocation *context = user_data;
+
+	if (error)
+		dbus_g_method_return_error (context, error);
+	else
+		dbus_g_method_return (context);
+}
+
+static void
+impl_settings_add_connection (NMSettingsService *self,
+                              GHashTable *settings,
+                              DBusGMethodInvocation *context)
+{
+	NMConnection *tmp;
+	GError *error = NULL;
+
+	/* Check if the settings are valid first */
+	tmp = nm_connection_new_from_hash (settings, &error);
+	if (!tmp) {
+		g_assert (error);
+		dbus_g_method_return_error (context, error);
+		g_error_free (error);
+		return;
+	}
+
+	if (NM_SETTINGS_SERVICE_GET_CLASS (self)->add_connection) {
+		NM_SETTINGS_SERVICE_GET_CLASS (self)->add_connection (NM_SETTINGS_SERVICE (self),
+		                                                      tmp,
+		                                                      context,
+		                                                      dbus_add_connection_cb,
+		                                                      context);
+	} else {
+		error = g_error_new (NM_SETTINGS_INTERFACE_ERROR,
+		                     NM_SETTINGS_INTERFACE_ERROR_INTERNAL_ERROR,
+		                     "%s: %s:%d add_connection() not implemented",
+		                     __func__, __FILE__, __LINE__);
+		dbus_g_method_return_error (context, error);
+		g_error_free (error);
+	}
+
+	g_object_unref (tmp);
+}
+
+void
+nm_settings_service_export_connection (NMSettingsService *self,
+                                       NMSettingsConnectionInterface *connection)
+{
+	NMSettingsServicePrivate *priv = NM_SETTINGS_SERVICE_GET_PRIVATE (self);
+	static guint32 ec_counter = 0;
+	char *path;
+
+	g_return_if_fail (connection != NULL);
+	g_return_if_fail (NM_IS_SETTINGS_CONNECTION_INTERFACE (connection));
+	g_return_if_fail (priv->bus != NULL);
+
+	/* Don't allow exporting twice */
+	g_return_if_fail (nm_connection_get_path (NM_CONNECTION (connection)) == NULL);
+
+	path = g_strdup_printf ("%s/%u", NM_DBUS_PATH_SETTINGS, ec_counter++);
+	nm_connection_set_path (NM_CONNECTION (connection), path);
+	nm_connection_set_scope (NM_CONNECTION (connection), priv->scope);
+
+	dbus_g_connection_register_g_object (priv->bus, path, G_OBJECT (connection));
+	g_free (path);
+}
+
+/**************************************************************/
+
+static void
+settings_interface_init (NMSettingsInterface *iface)
+{
+	/* interface implementation */
+	iface->list_connections = list_connections;
+	iface->get_connection_by_path = get_connection_by_path;
+	iface->add_connection = add_connection;
+
+	dbus_g_object_type_install_info (G_TYPE_FROM_INTERFACE (iface),
+	                                 &dbus_glib_nm_settings_object_info);
+}
+
+static GObject *
+constructor (GType type,
+             guint n_construct_params,
+             GObjectConstructParam *construct_params)
+{
+	GObject *object;
+
+	object = G_OBJECT_CLASS (nm_settings_service_parent_class)->constructor (type, n_construct_params, construct_params);
+	if (object) {
+		g_assert (NM_SETTINGS_SERVICE_GET_PRIVATE (object)->scope != NM_CONNECTION_SCOPE_UNKNOWN);
+	}
+	return object;
+}
+
+static void
+nm_settings_service_init (NMSettingsService *self)
+{
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+              const GValue *value, GParamSpec *pspec)
+{
+	NMSettingsServicePrivate *priv = NM_SETTINGS_SERVICE_GET_PRIVATE (object);
+	DBusGConnection *bus;
+
+	switch (prop_id) {
+	case PROP_BUS:
+		/* Construct only */
+		bus = g_value_get_boxed (value);
+		if (bus)
+			priv->bus = dbus_g_connection_ref (bus);
+		break;
+	case PROP_SCOPE:
+		/* Construct only */
+		priv->scope = g_value_get_uint (value);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+              GValue *value, GParamSpec *pspec)
+{
+	NMSettingsServicePrivate *priv = NM_SETTINGS_SERVICE_GET_PRIVATE (object);
+
+	switch (prop_id) {
+	case PROP_BUS:
+		g_value_set_boxed (value, priv->bus);
+		break;
+	case PROP_SCOPE:
+		g_value_set_uint (value, priv->scope);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+dispose (GObject *object)
+{
+	NMSettingsServicePrivate *priv = NM_SETTINGS_SERVICE_GET_PRIVATE (object);
+
+	if (!priv->disposed) {
+		priv->disposed = TRUE;
+		if (priv->bus)
+			dbus_g_connection_unref (priv->bus);
+	}
+
+	G_OBJECT_CLASS (nm_settings_service_parent_class)->dispose (object);
+}
+
+static void
+nm_settings_service_class_init (NMSettingsServiceClass *class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+	g_type_class_add_private (class, sizeof (NMSettingsServicePrivate));
+
+	/* Virtual methods */
+	object_class->dispose = dispose;
+	object_class->constructor = constructor;
+	object_class->get_property = get_property;
+	object_class->set_property = set_property;
+
+	/**
+	 * NMSettingsService:bus:
+	 *
+	 * The %DBusGConnection which this object is exported on
+	 **/
+	g_object_class_install_property (object_class, PROP_BUS,
+	                                 g_param_spec_boxed (NM_SETTINGS_SERVICE_BUS,
+	                                                     "Bus",
+	                                                     "Bus",
+	                                                     DBUS_TYPE_G_CONNECTION,
+	                                                     G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+	/**
+	 * NMSettingsService:scope:
+	 *
+	 * The capabilities of the device.
+	 **/
+	g_object_class_install_property (object_class, PROP_SCOPE,
+	                                 g_param_spec_uint (NM_SETTINGS_SERVICE_SCOPE,
+	                                                    "Scope",
+	                                                    "Scope",
+	                                                    NM_CONNECTION_SCOPE_SYSTEM,
+	                                                    NM_CONNECTION_SCOPE_USER,
+	                                                    NM_CONNECTION_SCOPE_USER,
+	                                                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+}
diff --git a/libnm-glib/nm-settings-service.h b/libnm-glib/nm-settings-service.h
new file mode 100644
index 00000000..9f4b95fc
--- /dev/null
+++ b/libnm-glib/nm-settings-service.h
@@ -0,0 +1,82 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager system settings service
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2009 Red Hat, Inc.
+ */
+
+#ifndef NM_SETTINGS_SERVICE_H
+#define NM_SETTINGS_SERVICE_H
+
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+#include <nm-exported-connection.h>
+#include <nm-settings-interface.h>
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_SETTINGS_SERVICE            (nm_settings_service_get_type ())
+#define NM_SETTINGS_SERVICE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTINGS_SERVICE, NMSettingsService))
+#define NM_SETTINGS_SERVICE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTINGS_SERVICE, NMSettingsServiceClass))
+#define NM_IS_SETTINGS_SERVICE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTINGS_SERVICE))
+#define NM_IS_SETTINGS_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_SETTINGS_SERVICE))
+#define NM_SETTINGS_SERVICE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTINGS_SERVICE, NMSettingsServiceClass))
+
+#define NM_SETTINGS_SERVICE_BUS "bus"
+#define NM_SETTINGS_SERVICE_SCOPE "scope"
+
+typedef struct {
+	GObject parent;
+} NMSettingsService;
+
+typedef struct {
+	GObjectClass parent;
+
+	/* Returned list must contain all NMExportedConnection objects exported
+	 * by the settings service.  The list (but not the NMExportedConnection
+	 * objects) will be freed by caller.
+	 */
+	GSList * (*list_connections) (NMSettingsService *self);
+
+	void (*add_connection) (NMSettingsService *self,
+	                        NMConnection *connection,
+	                        DBusGMethodInvocation *context, /* Only present for D-Bus calls */
+	                        NMSettingsAddConnectionFunc callback,
+	                        gpointer user_data);
+
+	/* Padding for future expansion */
+	void (*_reserved1) (void);
+	void (*_reserved2) (void);
+	void (*_reserved3) (void);
+	void (*_reserved4) (void);
+	void (*_reserved5) (void);
+	void (*_reserved6) (void);
+} NMSettingsServiceClass;
+
+GType nm_settings_service_get_type (void);
+
+NMExportedConnection *nm_settings_service_get_connection_by_path (NMSettingsService *self,
+                                                                  const char *path);
+
+void nm_settings_service_export (NMSettingsService *self);
+
+void nm_settings_service_export_connection (NMSettingsService *self,
+                                            NMSettingsConnectionInterface *exported);
+
+G_END_DECLS
+
+#endif /* NM_SETTINGS_SERVICE_H */
diff --git a/libnm-glib/nm-settings-system-interface.c b/libnm-glib/nm-settings-system-interface.c
new file mode 100644
index 00000000..0f59377a
--- /dev/null
+++ b/libnm-glib/nm-settings-system-interface.c
@@ -0,0 +1,150 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager -- Network link manager
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2007 - 2008 Novell, Inc.
+ * Copyright (C) 2007 - 2008 Red Hat, Inc.
+ */
+
+#include "nm-settings-interface.h"
+#include "nm-settings-system-interface.h"
+
+
+/**
+ * nm_settings_system_interface_save_hostname:
+ * @settings: a object implementing %NMSettingsSystemInterface
+ * @hostname: the new persistent hostname to set, or NULL to clear any existing
+ *  persistent hostname
+ * @callback: callback to be called when the hostname operation completes
+ * @user_data: caller-specific data passed to @callback
+ *
+ * Requests that the machine's persistent hostname be set to the specified value
+ * or cleared.
+ *
+ * Returns: TRUE if the request was successful, FALSE if it failed
+ **/
+gboolean
+nm_settings_system_interface_save_hostname (NMSettingsSystemInterface *settings,
+                                            const char *hostname,
+                                            NMSettingsSystemSaveHostnameFunc callback,
+                                            gpointer user_data)
+{
+	g_return_val_if_fail (settings != NULL, FALSE);
+	g_return_val_if_fail (NM_IS_SETTINGS_SYSTEM_INTERFACE (settings), FALSE);
+	g_return_val_if_fail (hostname != NULL, FALSE);
+	g_return_val_if_fail (callback != NULL, FALSE);
+
+	if (NM_SETTINGS_SYSTEM_INTERFACE_GET_INTERFACE (settings)->save_hostname) {
+		return NM_SETTINGS_SYSTEM_INTERFACE_GET_INTERFACE (settings)->save_hostname (settings,
+		                                                                             hostname,
+		                                                                             callback,
+		                                                                             user_data);
+	}
+	return FALSE;
+}
+
+/**
+ * nm_settings_system_interface_get_permissions:
+ * @settings: a object implementing %NMSettingsSystemInterface
+ * @callback: callback to be called when the permissions operation completes
+ * @user_data: caller-specific data passed to @callback
+ *
+ * Requests an indication of the operations the caller is permitted to perform
+ * including those that may require authorization.
+ *
+ * Returns: TRUE if the request was successful, FALSE if it failed
+ **/
+gboolean
+nm_settings_system_interface_get_permissions (NMSettingsSystemInterface *settings,
+                                              NMSettingsSystemGetPermissionsFunc callback,
+                                              gpointer user_data)
+{
+	g_return_val_if_fail (settings != NULL, FALSE);
+	g_return_val_if_fail (NM_IS_SETTINGS_SYSTEM_INTERFACE (settings), FALSE);
+	g_return_val_if_fail (callback != NULL, FALSE);
+
+	if (NM_SETTINGS_SYSTEM_INTERFACE_GET_INTERFACE (settings)->get_permissions)
+		return NM_SETTINGS_SYSTEM_INTERFACE_GET_INTERFACE (settings)->get_permissions (settings, callback, user_data);
+	return FALSE;
+}
+
+static void
+nm_settings_system_interface_init (gpointer g_iface)
+{
+	GType iface_type = G_TYPE_FROM_INTERFACE (g_iface);
+	static gboolean initialized = FALSE;
+
+	if (initialized)
+		return;
+
+	/* Properties */
+	g_object_interface_install_property
+		(g_iface,
+		 g_param_spec_string (NM_SETTINGS_SYSTEM_INTERFACE_HOSTNAME,
+							  "Hostname",
+							  "Persistent hostname",
+							  NULL,
+							  G_PARAM_READABLE));
+
+	g_object_interface_install_property
+		(g_iface,
+		 g_param_spec_boolean (NM_SETTINGS_SYSTEM_INTERFACE_CAN_MODIFY,
+		                       "CanModify",
+		                       "Can modify anything (hostname, connections, etc)",
+		                       FALSE,
+		                       G_PARAM_READABLE));
+
+	/* Signals */
+	g_signal_new (NM_SETTINGS_SYSTEM_INTERFACE_CHECK_PERMISSIONS,
+				  iface_type,
+				  G_SIGNAL_RUN_FIRST,
+				  G_STRUCT_OFFSET (NMSettingsSystemInterface, check_permissions),
+				  NULL, NULL,
+				  g_cclosure_marshal_VOID__VOID,
+				  G_TYPE_NONE, 0);
+
+	initialized = TRUE;
+}
+
+GType
+nm_settings_system_interface_get_type (void)
+{
+	static GType itype = 0;
+
+	if (!itype) {
+		const GTypeInfo iinfo = {
+			sizeof (NMSettingsSystemInterface), /* class_size */
+			nm_settings_system_interface_init,   /* base_init */
+			NULL,		/* base_finalize */
+			NULL,
+			NULL,		/* class_finalize */
+			NULL,		/* class_data */
+			0,
+			0,              /* n_preallocs */
+			NULL
+		};
+
+		itype = g_type_register_static (G_TYPE_INTERFACE,
+		                                "NMSettingsSystemInterface",
+		                                &iinfo, 0);
+
+		g_type_interface_add_prerequisite (itype, NM_TYPE_SETTINGS_INTERFACE);
+	}
+
+	return itype;
+}
+
diff --git a/libnm-glib/nm-settings-system-interface.h b/libnm-glib/nm-settings-system-interface.h
new file mode 100644
index 00000000..d0165561
--- /dev/null
+++ b/libnm-glib/nm-settings-system-interface.h
@@ -0,0 +1,108 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager -- Network link manager
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2007 - 2008 Novell, Inc.
+ * Copyright (C) 2007 - 2009 Red Hat, Inc.
+ */
+
+#ifndef NM_SETTINGS_SYSTEM_INTERFACE_H
+#define NM_SETTINGS_SYSTEM_INTERFACE_H
+
+#include <glib-object.h>
+
+#include "NetworkManager.h"
+
+G_BEGIN_DECLS
+
+typedef enum {
+	NM_SETTINGS_SYSTEM_PERMISSION_NONE = 0x0,
+	NM_SETTINGS_SYSTEM_PERMISSION_CONNECTION_MODIFY = 0x1,
+	NM_SETTINGS_SYSTEM_PERMISSION_WIFI_SHARE_PROTECTED = 0x2,
+	NM_SETTINGS_SYSTEM_PERMISSION_WIFI_SHARE_OPEN = 0x4,
+	NM_SETTINGS_SYSTEM_PERMISSION_HOSTNAME_MODIFY = 0x8
+} NMSettingsSystemPermissions;
+
+#define NM_TYPE_SETTINGS_SYSTEM_INTERFACE               (nm_settings_system_interface_get_type ())
+#define NM_SETTINGS_SYSTEM_INTERFACE(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTINGS_SYSTEM_INTERFACE, NMSettingsSystemInterface))
+#define NM_IS_SETTINGS_SYSTEM_INTERFACE(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTINGS_SYSTEM_INTERFACE))
+#define NM_SETTINGS_SYSTEM_INTERFACE_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), NM_TYPE_SETTINGS_SYSTEM_INTERFACE, NMSettingsSystemInterface))
+
+#define NM_SETTINGS_SYSTEM_INTERFACE_HOSTNAME          "hostname"
+#define NM_SETTINGS_SYSTEM_INTERFACE_CAN_MODIFY        "can-modify"
+
+#define NM_SETTINGS_SYSTEM_INTERFACE_CHECK_PERMISSIONS "check-permissions"
+
+typedef enum {
+	NM_SETTINGS_SYSTEM_INTERFACE_PROP_FIRST = 0x1000,
+
+	NM_SETTINGS_SYSTEM_INTERFACE_PROP_HOSTNAME = NM_SETTINGS_SYSTEM_INTERFACE_PROP_FIRST,
+	NM_SETTINGS_SYSTEM_INTERFACE_PROP_CAN_MODIFY
+} NMSettingsSystemInterfaceProp;
+
+
+typedef struct _NMSettingsSystemInterface NMSettingsSystemInterface;
+
+
+typedef void (*NMSettingsSystemSaveHostnameFunc) (NMSettingsSystemInterface *settings,
+                                                  GError *error,
+                                                  gpointer user_data);
+
+typedef void (*NMSettingsSystemGetPermissionsFunc) (NMSettingsSystemInterface *settings,
+                                                    NMSettingsSystemPermissions permissions,
+                                                    GError *error,
+                                                    gpointer user_data);
+
+struct _NMSettingsSystemInterface {
+	GTypeInterface g_iface;
+
+	/* Methods */
+	gboolean (*save_hostname) (NMSettingsSystemInterface *settings,
+	                           const char *hostname,
+	                           NMSettingsSystemSaveHostnameFunc callback,
+	                           gpointer user_data);
+
+	gboolean (*get_permissions) (NMSettingsSystemInterface *settings,
+	                             NMSettingsSystemGetPermissionsFunc callback,
+	                             gpointer user_data);
+
+	/* Signals */
+	void (*check_permissions) (NMSettingsSystemInterface *settings);
+
+	/* Padding for future expansion */
+	void (*_reserved1) (void);
+	void (*_reserved2) (void);
+	void (*_reserved3) (void);
+	void (*_reserved4) (void);
+	void (*_reserved5) (void);
+	void (*_reserved6) (void);
+};
+
+GType nm_settings_system_interface_get_type (void);
+
+gboolean nm_settings_system_interface_save_hostname (NMSettingsSystemInterface *settings,
+                                                     const char *hostname,
+                                                     NMSettingsSystemSaveHostnameFunc callback,
+                                                     gpointer user_data);
+
+gboolean nm_settings_system_interface_get_permissions (NMSettingsSystemInterface *settings,
+                                                       NMSettingsSystemGetPermissionsFunc callback,
+                                                       gpointer user_data);
+
+G_END_DECLS
+
+#endif /* NM_SETTINGS_SYSTEM_INTERFACE_H */
diff --git a/libnm-glib/nm-types-private.h b/libnm-glib/nm-types-private.h
new file mode 100644
index 00000000..178890da
--- /dev/null
+++ b/libnm-glib/nm-types-private.h
@@ -0,0 +1,39 @@
+/* -*- 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 Red Hat, Inc.
+ */
+
+#ifndef NM_TYPES_PRIVATE_H
+#define NM_TYPES_PRIVATE_H
+
+#include <dbus/dbus-glib.h>
+#include "nm-types.h"
+#include "nm-object-private.h"
+
+gboolean _nm_ssid_demarshal (GValue *value, GByteArray **dest);
+gboolean _nm_uint_array_demarshal (GValue *value, GArray **dest);
+gboolean _nm_string_array_demarshal (GValue *value, GPtrArray **dest);
+gboolean _nm_object_array_demarshal (GValue *value,
+                                    GPtrArray **dest,
+                                    DBusGConnection *connection,
+                                    NMObjectCreatorFunc func);
+gboolean _nm_ip6_address_array_demarshal (GValue *value, GSList **dest);
+
+#endif /* NM_TYPES_PRIVATE_H */
diff --git a/libnm-glib/nm-types.c b/libnm-glib/nm-types.c
new file mode 100644
index 00000000..cf9e084c
--- /dev/null
+++ b/libnm-glib/nm-types.c
@@ -0,0 +1,423 @@
+/* -*- 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) 2008 Red Hat, Inc.
+ */
+
+#include <glib.h>
+#include <dbus/dbus-glib.h>
+#include <string.h>
+#include "nm-types.h"
+#include "nm-types-private.h"
+#include "nm-object-private.h"
+#include "nm-object-cache.h"
+#include "nm-dbus-glib-types.h"
+#include "nm-setting-ip6-config.h"
+
+static gpointer
+nm_ssid_copy (GByteArray *src)
+{
+	GByteArray *dest;
+
+	dest = g_byte_array_sized_new (src->len);
+	g_byte_array_append (dest, src->data, src->len);
+	return dest;
+}
+
+static void
+nm_ssid_free (GByteArray *ssid)
+{
+	g_byte_array_free (ssid, TRUE);
+}
+
+GType
+nm_ssid_get_type (void)
+{
+	static GType our_type = 0;
+
+	if (our_type == 0)
+		our_type = g_boxed_type_register_static (g_intern_static_string ("nm-ssid"),
+		                                         (GBoxedCopyFunc) nm_ssid_copy,
+		                                         (GBoxedFreeFunc) nm_ssid_free);
+	return our_type;
+}
+
+gboolean
+_nm_ssid_demarshal (GValue *value, GByteArray **dest)
+{
+	GByteArray *array;
+
+	if (!G_VALUE_HOLDS (value, DBUS_TYPE_G_UCHAR_ARRAY))
+		return FALSE;
+
+	if (*dest) {
+		g_boxed_free (NM_TYPE_SSID, *dest);
+		*dest = NULL;
+	}
+
+	array = (GByteArray *) g_value_get_boxed (value);
+	if (array && (array->len > 0)) {
+		*dest = g_byte_array_sized_new (array->len);
+		(*dest)->len = array->len;
+		memcpy ((*dest)->data, array->data, array->len);
+	}
+
+	return TRUE;
+}
+
+/*****************************/
+
+static gpointer
+nm_uint_array_copy (GArray *src)
+{
+	GArray *dest;
+
+	dest = g_array_sized_new (FALSE, TRUE, sizeof (guint32), src->len);
+	g_array_append_vals (dest, src->data, src->len);
+	return dest;
+}
+
+static void
+nm_uint_array_free (GArray *array)
+{
+	g_array_free (array, TRUE);
+}
+
+GType
+nm_uint_array_get_type (void)
+{
+	static GType our_type = 0;
+
+	if (our_type == 0)
+		our_type = g_boxed_type_register_static (g_intern_static_string ("nm-uint-array"),
+		                                         (GBoxedCopyFunc) nm_uint_array_copy,
+		                                         (GBoxedFreeFunc) nm_uint_array_free);
+	return our_type;
+}
+
+gboolean
+_nm_uint_array_demarshal (GValue *value, GArray **dest)
+{
+	GArray *array;
+
+	if (!G_VALUE_HOLDS (value, DBUS_TYPE_G_UINT_ARRAY))
+		return FALSE;
+
+	if (*dest) {
+		g_boxed_free (NM_TYPE_UINT_ARRAY, *dest);
+		*dest = NULL;
+	}
+
+	array = (GArray *) g_value_get_boxed (value);
+	if (array && (array->len > 0)) {
+		*dest = g_array_sized_new (FALSE, TRUE, sizeof (guint32), array->len);
+		g_array_append_vals (*dest, array->data, array->len);
+	}
+
+	return TRUE;
+}
+
+/*****************************/
+
+static gpointer
+nm_string_array_copy (GPtrArray *src)
+{
+	GPtrArray *dest;
+	int i;
+
+	dest = g_ptr_array_sized_new (src->len);
+	for (i = 0; i < src->len; i++)
+		g_ptr_array_add (dest, g_strdup (g_ptr_array_index (src, i)));
+	return dest;
+}
+
+static void
+nm_string_array_free (GPtrArray *array)
+{
+	int i;
+
+	for (i = 0; i < array->len; i++)
+		g_free (g_ptr_array_index (array, i));
+	g_ptr_array_free (array, TRUE);
+}
+
+GType
+nm_string_array_get_type (void)
+{
+	static GType our_type = 0;
+
+	if (our_type == 0)
+		our_type = g_boxed_type_register_static (g_intern_static_string ("nm-string-array"),
+		                                         (GBoxedCopyFunc) nm_string_array_copy,
+		                                         (GBoxedFreeFunc) nm_string_array_free);
+	return our_type;
+}
+
+gboolean
+_nm_string_array_demarshal (GValue *value, GPtrArray **dest)
+{
+	GPtrArray *array;
+
+	if (!G_VALUE_HOLDS (value, DBUS_TYPE_G_ARRAY_OF_STRING))
+		return FALSE;
+
+	if (*dest) {
+		g_boxed_free (NM_TYPE_STRING_ARRAY, *dest);
+		*dest = NULL;
+	}
+
+	array = (GPtrArray *) g_value_get_boxed (value);
+	if (array && array->len) {
+		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)));
+	}
+
+	return TRUE;
+}
+
+/*****************************/
+
+static gpointer
+nm_object_array_copy (GPtrArray *src)
+{
+	GPtrArray *dest;
+	int i;
+
+	dest = g_ptr_array_sized_new (src->len);
+	for (i = 0; i < src->len; i++)
+		g_ptr_array_add (dest, g_object_ref (g_ptr_array_index (src, i)));
+	return dest;
+}
+
+static void
+nm_object_array_free (GPtrArray *array)
+{
+	int i;
+
+	for (i = 0; i < array->len; i++)
+		g_object_unref (g_ptr_array_index (array, i));
+	g_ptr_array_free (array, TRUE);
+}
+
+GType
+nm_object_array_get_type (void)
+{
+	static GType our_type = 0;
+
+	if (our_type == 0)
+		our_type = g_boxed_type_register_static (g_intern_static_string ("nm-object-array"),
+		                                         (GBoxedCopyFunc) nm_object_array_copy,
+		                                         (GBoxedFreeFunc) nm_object_array_free);
+	return our_type;
+}
+
+gboolean
+_nm_object_array_demarshal (GValue *value,
+                           GPtrArray **dest,
+                           DBusGConnection *connection,
+                           NMObjectCreatorFunc func)
+{
+	GPtrArray *temp = NULL;
+	GPtrArray *array;
+
+	if (!G_VALUE_HOLDS (value, DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH))
+		return FALSE;
+
+	array = (GPtrArray *) g_value_get_boxed (value);
+	if (array && array->len) {
+		int i;
+
+		temp = g_ptr_array_sized_new (array->len);
+		for (i = 0; i < array->len; i++) {
+			const char *path;
+			GObject *object;
+
+			path = g_ptr_array_index (array, i);
+			object = G_OBJECT (_nm_object_cache_get (path));
+			if (object) {
+				g_ptr_array_add (temp, g_object_ref (object));
+			} else {
+				object = (*func) (connection, path);
+				if (object)
+					g_ptr_array_add (temp, object);
+				else
+					g_warning ("%s: couldn't create object for %s", __func__, path);
+			}
+		}
+	} else
+		temp = g_ptr_array_new ();
+
+	/* Deallocate after to ensure that an object that might already
+	 * be in the array doesn't get destroyed due to refcounting.
+	 */
+	if (*dest)
+		g_boxed_free (NM_TYPE_OBJECT_ARRAY, *dest);
+	*dest = temp;
+
+	return TRUE;
+}
+
+/*****************************/
+
+static gpointer
+nm_ip6_address_object_array_copy (GPtrArray *src)
+{
+	GPtrArray *dest;
+	int i;
+
+	dest = g_ptr_array_sized_new (src->len);
+	for (i = 0; i < src->len; i++)
+		g_ptr_array_add (dest, nm_ip6_address_dup (g_ptr_array_index (src, i)));
+	return dest;
+}
+
+static void
+nm_ip6_address_object_array_free (GPtrArray *array)
+{
+	int i;
+
+	for (i = 0; i < array->len; i++)
+		nm_ip6_address_unref (g_ptr_array_index (array, i));
+	g_ptr_array_free (array, TRUE);
+}
+
+GType
+nm_ip6_address_object_array_get_type (void)
+{
+	static GType our_type = 0;
+
+	if (our_type == 0)
+		our_type = g_boxed_type_register_static (g_intern_static_string ("nm-ip6-address-object-array"),
+		                                         (GBoxedCopyFunc) nm_ip6_address_object_array_copy,
+		                                         (GBoxedFreeFunc) nm_ip6_address_object_array_free);
+	return our_type;
+}
+
+/*****************************/
+
+static gpointer
+nm_ip6_address_array_copy (GPtrArray *src)
+{
+	GPtrArray *dest;
+	int i;
+
+	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;
+
+		dup = g_malloc0 (sizeof (struct in6_addr));
+		memcpy (dup, addr, sizeof (struct in6_addr));
+		g_ptr_array_add (dest, dup);
+	}
+	return dest;
+}
+
+static void
+nm_ip6_address_array_free (GPtrArray *array)
+{
+	int i;
+
+	for (i = 0; i < array->len; i++)
+		g_free (g_ptr_array_index (array, i));
+	g_ptr_array_free (array, TRUE);
+}
+
+GType
+nm_ip6_address_array_get_type (void)
+{
+	static GType our_type = 0;
+
+	if (our_type == 0)
+		our_type = g_boxed_type_register_static (g_intern_static_string ("nm-ip6-address-array"),
+		                                         (GBoxedCopyFunc) nm_ip6_address_array_copy,
+		                                         (GBoxedFreeFunc) nm_ip6_address_array_free);
+	return our_type;
+}
+
+gboolean
+_nm_ip6_address_array_demarshal (GValue *value, GSList **dest)
+{
+	GPtrArray *array;
+
+	if (!G_VALUE_HOLDS (value, DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UCHAR))
+		return FALSE;
+
+	if (*dest) {
+		g_slist_foreach (*dest, (GFunc) g_free, NULL);
+		g_slist_free (*dest);
+		*dest = NULL;
+	}
+
+	array = (GPtrArray *) g_value_get_boxed (value);
+	if (array && array->len) {
+		int i;
+
+		for (i = 0; i < array->len; i++) {
+			GByteArray *bytearray = (GByteArray *) g_ptr_array_index (array, i);
+			struct in6_addr *addr;
+
+			addr = g_malloc0 (sizeof (struct in6_addr));
+			memcpy (addr->s6_addr, bytearray->data, bytearray->len);
+			*dest = g_slist_append (*dest, addr);
+		}
+	}
+
+	return TRUE;
+}
+
+/*****************************/
+
+static gpointer
+nm_ip6_route_object_array_copy (GPtrArray *src)
+{
+	GPtrArray *dest;
+	int i;
+
+	dest = g_ptr_array_sized_new (src->len);
+	for (i = 0; i < src->len; i++)
+		g_ptr_array_add (dest, nm_ip6_route_dup (g_ptr_array_index (src, i)));
+	return dest;
+}
+
+static void
+nm_ip6_route_object_array_free (GPtrArray *array)
+{
+	int i;
+
+	for (i = 0; i < array->len; i++)
+		nm_ip6_route_unref (g_ptr_array_index (array, i));
+	g_ptr_array_free (array, TRUE);
+}
+
+GType
+nm_ip6_route_object_array_get_type (void)
+{
+	static GType our_type = 0;
+
+	if (our_type == 0)
+		our_type = g_boxed_type_register_static (g_intern_static_string ("nm-ip6-route-object-array"),
+		                                         (GBoxedCopyFunc) nm_ip6_route_object_array_copy,
+		                                         (GBoxedFreeFunc) nm_ip6_route_object_array_free);
+	return our_type;
+}
+
diff --git a/libnm-glib/nm-types.h b/libnm-glib/nm-types.h
new file mode 100644
index 00000000..cb1bf872
--- /dev/null
+++ b/libnm-glib/nm-types.h
@@ -0,0 +1,54 @@
+/* -*- 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) 2008 Red Hat, Inc.
+ */
+
+#ifndef NM_TYPES_H
+#define NM_TYPES_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_SSID  (nm_ssid_get_type ())
+GType     nm_ssid_get_type (void) G_GNUC_CONST;
+
+#define NM_TYPE_UINT_ARRAY  (nm_uint_array_get_type ())
+GType     nm_uint_array_get_type (void) G_GNUC_CONST;
+
+#define NM_TYPE_STRING_ARRAY  (nm_string_array_get_type ())
+GType     nm_string_array_get_type (void) G_GNUC_CONST;
+
+#define NM_TYPE_OBJECT_ARRAY  (nm_object_array_get_type ())
+GType     nm_object_array_get_type (void) G_GNUC_CONST;
+
+#define NM_TYPE_IP6_ADDRESS_OBJECT_ARRAY  (nm_ip6_address_object_array_get_type ())
+GType     nm_ip6_address_object_array_get_type (void) G_GNUC_CONST;
+
+#define NM_TYPE_IP6_ADDRESS_ARRAY  (nm_ip6_address_array_get_type ())
+GType     nm_ip6_address_array_get_type (void) G_GNUC_CONST;
+
+#define NM_TYPE_IP6_ROUTE_OBJECT_ARRAY  (nm_ip6_route_object_array_get_type ())
+GType     nm_ip6_route_object_array_get_type (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* NM_TYPES_H */
diff --git a/libnm-glib/nm-vpn-connection.c b/libnm-glib/nm-vpn-connection.c
new file mode 100644
index 00000000..6910b6f6
--- /dev/null
+++ b/libnm-glib/nm-vpn-connection.c
@@ -0,0 +1,257 @@
+/* -*- 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.
+ * Copyright (C) 2007 - 2010 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-object-private.h"
+#include "nm-active-connection.h"
+
+G_DEFINE_TYPE (NMVPNConnection, nm_vpn_connection, NM_TYPE_ACTIVE_CONNECTION)
+
+#define NM_VPN_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_VPN_CONNECTION, NMVPNConnectionPrivate))
+
+typedef struct {
+	DBusGProxy *proxy;
+	char *banner;
+	NMVPNConnectionState vpn_state;
+} NMVPNConnectionPrivate;
+
+enum {
+	PROP_0,
+	PROP_VPN_STATE,
+	PROP_BANNER,
+
+	LAST_PROP
+};
+
+#define DBUS_PROP_VPN_STATE "VpnState"
+#define DBUS_PROP_BANNER "Banner"
+
+enum {
+	VPN_STATE_CHANGED,
+
+	LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+
+GObject *
+nm_vpn_connection_new (DBusGConnection *dbus_connection, const char *path)
+{
+	g_return_val_if_fail (dbus_connection != NULL, NULL);
+	g_return_val_if_fail (path != NULL, NULL);
+
+	return g_object_new (NM_TYPE_VPN_CONNECTION, 
+	                     NM_OBJECT_DBUS_CONNECTION, dbus_connection,
+	                     NM_OBJECT_DBUS_PATH, path,
+	                     NULL);
+}
+
+const char *
+nm_vpn_connection_get_banner (NMVPNConnection *vpn)
+{
+	NMVPNConnectionPrivate *priv;
+
+	g_return_val_if_fail (NM_IS_VPN_CONNECTION (vpn), NULL);
+
+	priv = NM_VPN_CONNECTION_GET_PRIVATE (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);
+		if (priv->banner && !strlen (priv->banner)) {
+			g_free (priv->banner);
+			priv->banner = NULL;
+		}
+	}
+	return priv->banner;
+}
+
+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);
+	}
+	return priv->vpn_state;
+}
+
+static void
+vpn_state_changed_proxy (DBusGProxy *proxy,
+                         NMVPNConnectionState vpn_state,
+                         NMVPNConnectionStateReason reason,
+                         gpointer user_data)
+{
+	NMVPNConnection *connection = NM_VPN_CONNECTION (user_data);
+	NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection);
+
+	if (priv->vpn_state != vpn_state) {
+		priv->vpn_state = vpn_state;
+		g_signal_emit (connection, signals[VPN_STATE_CHANGED], 0, vpn_state, reason);
+	}
+}
+
+/*****************************************************************************/
+
+static void
+nm_vpn_connection_init (NMVPNConnection *connection)
+{
+	NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection);
+
+	priv->vpn_state = NM_VPN_CONNECTION_STATE_UNKNOWN;
+}
+
+static GObject*
+constructor (GType type,
+		   guint n_construct_params,
+		   GObjectConstructParam *construct_params)
+{
+	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;
+
+	priv = NM_VPN_CONNECTION_GET_PRIVATE (object);
+
+	priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (object),
+									 NM_DBUS_SERVICE,
+									 nm_object_get_path (object),
+									 NM_DBUS_INTERFACE_VPN_CONNECTION);
+
+	dbus_g_object_register_marshaller (_nm_marshal_VOID__UINT_UINT,
+	                                   G_TYPE_NONE,
+	                                   G_TYPE_UINT, G_TYPE_UINT,
+	                                   G_TYPE_INVALID);
+	dbus_g_proxy_add_signal (priv->proxy, "VpnStateChanged", G_TYPE_UINT, G_TYPE_UINT, G_TYPE_INVALID);
+	dbus_g_proxy_connect_signal (priv->proxy,
+						    "VpnStateChanged",
+						    G_CALLBACK (vpn_state_changed_proxy),
+						    object,
+						    NULL);
+	return G_OBJECT (object);
+}
+
+static void
+finalize (GObject *object)
+{
+	NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (object);
+
+	if (priv->banner)
+		g_free (priv->banner);
+
+	g_object_unref (priv->proxy);
+
+	G_OBJECT_CLASS (nm_vpn_connection_parent_class)->finalize (object);
+}
+
+static void
+get_property (GObject *object,
+              guint prop_id,
+              GValue *value,
+              GParamSpec *pspec)
+{
+	NMVPNConnection *self = NM_VPN_CONNECTION (object);
+
+	switch (prop_id) {
+	case PROP_VPN_STATE:
+		g_value_set_uint (value, nm_vpn_connection_get_vpn_state (self));
+		break;
+	case PROP_BANNER:
+		g_value_set_string (value, nm_vpn_connection_get_banner (self));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+nm_vpn_connection_class_init (NMVPNConnectionClass *connection_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (connection_class);
+
+	g_type_class_add_private (connection_class, sizeof (NMVPNConnectionPrivate));
+
+	/* virtual methods */
+	object_class->constructor = constructor;
+	object_class->get_property = get_property;
+	object_class->finalize = finalize;
+
+	/* properties */
+
+	/**
+	 * NMVPNConnection:vpn-state:
+	 *
+	 * The VPN state of the active VPN connection.
+	 **/
+	g_object_class_install_property (object_class, PROP_VPN_STATE,
+	                                 g_param_spec_uint (NM_VPN_CONNECTION_VPN_STATE,
+	                                                    "VpnState",
+	                                                    "Current VPN state",
+	                                                    NM_VPN_CONNECTION_STATE_UNKNOWN,
+	                                                    NM_VPN_CONNECTION_STATE_DISCONNECTED,
+	                                                    NM_VPN_CONNECTION_STATE_UNKNOWN,
+	                                                    G_PARAM_READABLE));
+
+	/**
+	 * NMVPNConnection:banner:
+	 *
+	 * The VPN login banner of the active VPN connection.
+	 **/
+	g_object_class_install_property (object_class, PROP_BANNER,
+	                                 g_param_spec_string (NM_VPN_CONNECTION_BANNER,
+	                                                      "Banner",
+	                                                      "Login Banner",
+	                                                      NULL,
+	                                                      G_PARAM_READABLE));
+
+	/* signals */
+	signals[VPN_STATE_CHANGED] =
+		g_signal_new ("vpn-state-changed",
+				    G_OBJECT_CLASS_TYPE (object_class),
+				    G_SIGNAL_RUN_FIRST,
+				    G_STRUCT_OFFSET (NMVPNConnectionClass, vpn_state_changed),
+				    NULL, NULL,
+				    _nm_marshal_VOID__UINT_UINT,
+				    G_TYPE_NONE, 2,
+				    G_TYPE_UINT, G_TYPE_UINT);
+}
diff --git a/libnm-glib/nm-vpn-connection.h b/libnm-glib/nm-vpn-connection.h
new file mode 100644
index 00000000..e03a80c7
--- /dev/null
+++ b/libnm-glib/nm-vpn-connection.h
@@ -0,0 +1,75 @@
+/* -*- 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.
+ * Copyright (C) 2007 - 2010 Red Hat, Inc.
+ */
+
+#ifndef NM_VPN_CONNECTION_H
+#define NM_VPN_CONNECTION_H
+
+#include <glib.h>
+#include <glib-object.h>
+#include <dbus/dbus-glib.h>
+#include "nm-active-connection.h"
+#include "NetworkManagerVPN.h"
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_VPN_CONNECTION            (nm_vpn_connection_get_type ())
+#define NM_VPN_CONNECTION(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_VPN_CONNECTION, NMVPNConnection))
+#define NM_VPN_CONNECTION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_VPN_CONNECTION, NMVPNConnectionClass))
+#define NM_IS_VPN_CONNECTION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_VPN_CONNECTION))
+#define NM_IS_VPN_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_VPN_CONNECTION))
+#define NM_VPN_CONNECTION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_VPN_CONNECTION, NMVPNConnectionClass))
+
+#define NM_VPN_CONNECTION_VPN_STATE "vpn-state"
+#define NM_VPN_CONNECTION_BANNER "banner"
+
+typedef struct {
+	NMActiveConnection parent;
+} NMVPNConnection;
+
+typedef struct {
+	NMActiveConnectionClass parent;
+
+	/* Signals */
+	void (*vpn_state_changed) (NMVPNConnection *connection,
+	                           NMVPNConnectionState state,
+	                           NMVPNConnectionStateReason reason);
+
+	/* Padding for future expansion */
+	void (*_reserved1) (void);
+	void (*_reserved2) (void);
+	void (*_reserved3) (void);
+	void (*_reserved4) (void);
+	void (*_reserved5) (void);
+	void (*_reserved6) (void);
+} NMVPNConnectionClass;
+
+GType nm_vpn_connection_get_type (void);
+
+GObject * nm_vpn_connection_new (DBusGConnection *dbus_connection, const char *path);
+
+NMVPNConnectionState  nm_vpn_connection_get_vpn_state  (NMVPNConnection *vpn);
+const char *          nm_vpn_connection_get_banner (NMVPNConnection *vpn);
+
+G_END_DECLS
+
+#endif /* NM_VPN_CONNECTION_H */
diff --git a/libnm-glib/nm-vpn-plugin-ui-interface.c b/libnm-glib/nm-vpn-plugin-ui-interface.c
new file mode 100644
index 00000000..ca3b738a
--- /dev/null
+++ b/libnm-glib/nm-vpn-plugin-ui-interface.c
@@ -0,0 +1,245 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * libnm_glib -- Access network status & information from glib applications
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2008 Red Hat, Inc.
+ * Copyright (C) 2008 Novell, Inc.
+ */
+
+#include "nm-vpn-plugin-ui-interface.h"
+
+static void
+interface_init (gpointer g_iface)
+{
+	static gboolean initialized = FALSE;
+
+	if (initialized)
+		return;
+
+	/* Properties */
+	g_object_interface_install_property (g_iface,
+		 g_param_spec_string (NM_VPN_PLUGIN_UI_INTERFACE_NAME,
+							  "Name",
+							  "VPN Plugin name",
+							  NULL,
+							  G_PARAM_READABLE));
+
+	g_object_interface_install_property (g_iface,
+		 g_param_spec_string (NM_VPN_PLUGIN_UI_INTERFACE_DESC,
+							  "Desc",
+							  "VPN Plugin description",
+							  NULL,
+							  G_PARAM_READABLE));
+
+	g_object_interface_install_property (g_iface,
+		 g_param_spec_string (NM_VPN_PLUGIN_UI_INTERFACE_SERVICE,
+							  "Service",
+							  "VPN Plugin D-Bus service name",
+							  NULL,
+							  G_PARAM_READABLE));
+
+	initialized = TRUE;
+}
+
+
+GType
+nm_vpn_plugin_ui_interface_get_type (void)
+{
+	static GType vpn_plugin_ui_interface_type = 0;
+
+	if (!vpn_plugin_ui_interface_type) {
+		const GTypeInfo vpn_plugin_ui_interface_info = {
+			sizeof (NMVpnPluginUiInterface), /* class_size */
+			interface_init,   /* base_init */
+			NULL,		/* base_finalize */
+			NULL,
+			NULL,		/* class_finalize */
+			NULL,		/* class_data */
+			0,
+			0,              /* n_preallocs */
+			NULL
+		};
+
+		vpn_plugin_ui_interface_type = g_type_register_static (G_TYPE_INTERFACE,
+														       "NMVpnPluginUiInterface",
+														       &vpn_plugin_ui_interface_info,
+														       0);
+
+		g_type_interface_add_prerequisite (vpn_plugin_ui_interface_type, G_TYPE_OBJECT);
+	}
+
+	return vpn_plugin_ui_interface_type;
+}
+
+
+NMVpnPluginUiWidgetInterface *
+nm_vpn_plugin_ui_interface_ui_factory (NMVpnPluginUiInterface *iface,
+                                       NMConnection *connection,
+                                       GError **error)
+{
+	g_return_val_if_fail (NM_IS_VPN_PLUGIN_UI_INTERFACE (iface), NULL);
+
+	return NM_VPN_PLUGIN_UI_INTERFACE_GET_INTERFACE (iface)->ui_factory (iface, connection, error);
+}
+
+guint32
+nm_vpn_plugin_ui_interface_get_capabilities (NMVpnPluginUiInterface *iface)
+{
+	g_return_val_if_fail (NM_IS_VPN_PLUGIN_UI_INTERFACE (iface), 0);
+
+	return NM_VPN_PLUGIN_UI_INTERFACE_GET_INTERFACE (iface)->get_capabilities (iface);
+}
+
+NMConnection *
+nm_vpn_plugin_ui_interface_import (NMVpnPluginUiInterface *iface,
+                                   const char *path,
+                                   GError **error)
+{
+	g_return_val_if_fail (NM_IS_VPN_PLUGIN_UI_INTERFACE (iface), NULL);
+
+	if (nm_vpn_plugin_ui_interface_get_capabilities (iface) & NM_VPN_PLUGIN_UI_CAPABILITY_IMPORT) {
+		g_return_val_if_fail (NM_VPN_PLUGIN_UI_INTERFACE_GET_INTERFACE (iface)->import != NULL, NULL);
+		return NM_VPN_PLUGIN_UI_INTERFACE_GET_INTERFACE (iface)->import (iface, path, error);
+	}
+	return NULL;
+}
+
+gboolean
+nm_vpn_plugin_ui_interface_export (NMVpnPluginUiInterface *iface,
+                                   const char *path,
+                                   NMConnection *connection,
+                                   GError **error)
+{
+	g_return_val_if_fail (NM_IS_VPN_PLUGIN_UI_INTERFACE (iface), FALSE);
+
+	if (nm_vpn_plugin_ui_interface_get_capabilities (iface) & NM_VPN_PLUGIN_UI_CAPABILITY_EXPORT) {
+		g_return_val_if_fail (NM_VPN_PLUGIN_UI_INTERFACE_GET_INTERFACE (iface)->export != NULL, FALSE);
+		return NM_VPN_PLUGIN_UI_INTERFACE_GET_INTERFACE (iface)->export (iface, path, connection, error);
+	}
+	return FALSE;
+}
+
+char *
+nm_vpn_plugin_ui_interface_get_suggested_name (NMVpnPluginUiInterface *iface,
+                                               NMConnection *connection)
+{
+	g_return_val_if_fail (NM_IS_VPN_PLUGIN_UI_INTERFACE (iface), NULL);
+
+	if (NM_VPN_PLUGIN_UI_INTERFACE_GET_INTERFACE (iface)->get_suggested_name)
+		return NM_VPN_PLUGIN_UI_INTERFACE_GET_INTERFACE (iface)->get_suggested_name (iface, connection);
+	return NULL;
+}
+
+gboolean
+nm_vpn_plugin_ui_interface_delete_connection (NMVpnPluginUiInterface *iface,
+                                              NMConnection *connection,
+                                              GError **error)
+{
+	g_return_val_if_fail (NM_IS_VPN_PLUGIN_UI_INTERFACE (iface), FALSE);
+
+	if (error)
+		g_return_val_if_fail (*error == NULL, FALSE);
+
+	return NM_VPN_PLUGIN_UI_INTERFACE_GET_INTERFACE (iface)->delete_connection (iface, connection, error);
+}
+
+
+static void
+widget_interface_init (gpointer g_iface)
+{
+	GType iface_type = G_TYPE_FROM_INTERFACE (g_iface);
+	static gboolean initialized = FALSE;
+
+	if (initialized)
+		return;
+
+	/* Signals */
+	g_signal_new ("changed",
+				  iface_type,
+				  G_SIGNAL_RUN_FIRST,
+				  G_STRUCT_OFFSET (NMVpnPluginUiWidgetInterface, changed),
+				  NULL, NULL,
+				  g_cclosure_marshal_VOID__VOID,
+				  G_TYPE_NONE, 0);
+
+	initialized = TRUE;
+}
+
+GType
+nm_vpn_plugin_ui_widget_interface_get_type (void)
+{
+	static GType vpn_plugin_ui_widget_interface_type = 0;
+
+	if (!vpn_plugin_ui_widget_interface_type) {
+		const GTypeInfo vpn_plugin_ui_widget_interface_info = {
+			sizeof (NMVpnPluginUiWidgetInterface), /* class_size */
+			widget_interface_init,   /* base_init */
+			NULL,		/* base_finalize */
+			NULL,
+			NULL,		/* class_finalize */
+			NULL,		/* class_data */
+			0,
+			0,              /* n_preallocs */
+			NULL
+		};
+
+		vpn_plugin_ui_widget_interface_type = g_type_register_static (G_TYPE_INTERFACE,
+		                                                              "NMVpnPluginUiWidgetInterface",
+		                                                              &vpn_plugin_ui_widget_interface_info,
+		                                                              0);
+
+		g_type_interface_add_prerequisite (vpn_plugin_ui_widget_interface_type, G_TYPE_OBJECT);
+	}
+
+	return vpn_plugin_ui_widget_interface_type;
+}
+
+GObject *
+nm_vpn_plugin_ui_widget_interface_get_widget (NMVpnPluginUiWidgetInterface *iface)
+{
+	g_return_val_if_fail (NM_IS_VPN_PLUGIN_UI_WIDGET_INTERFACE (iface), NULL);
+
+	return NM_VPN_PLUGIN_UI_WIDGET_INTERFACE_GET_INTERFACE (iface)->get_widget (iface);
+}
+
+gboolean
+nm_vpn_plugin_ui_widget_interface_update_connection (NMVpnPluginUiWidgetInterface *iface,
+                                                     NMConnection *connection,
+                                                     GError **error)
+{
+	g_return_val_if_fail (NM_IS_VPN_PLUGIN_UI_WIDGET_INTERFACE (iface), FALSE);
+
+	if (error)
+		g_return_val_if_fail (*error == NULL, FALSE);
+
+	return NM_VPN_PLUGIN_UI_WIDGET_INTERFACE_GET_INTERFACE (iface)->update_connection (iface, connection, error);
+}
+
+gboolean
+nm_vpn_plugin_ui_widget_interface_save_secrets (NMVpnPluginUiWidgetInterface *iface,
+                                                NMConnection *connection,
+                                                GError **error)
+{
+	g_return_val_if_fail (NM_IS_VPN_PLUGIN_UI_WIDGET_INTERFACE (iface), FALSE);
+
+	if (error)
+		g_return_val_if_fail (*error == NULL, FALSE);
+
+	return NM_VPN_PLUGIN_UI_WIDGET_INTERFACE_GET_INTERFACE (iface)->save_secrets (iface, connection, error);
+}
+
diff --git a/libnm-glib/nm-vpn-plugin-ui-interface.h b/libnm-glib/nm-vpn-plugin-ui-interface.h
new file mode 100644
index 00000000..44348c12
--- /dev/null
+++ b/libnm-glib/nm-vpn-plugin-ui-interface.h
@@ -0,0 +1,204 @@
+/* -*- 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) 2008 Red Hat, Inc.
+ * Copyright (C) 2008 Novell, Inc.
+ */
+
+#ifndef NM_VPN_PLUGIN_UI_INTERFACE_H
+#define NM_VPN_PLUGIN_UI_INTERFACE_H
+
+#include <glib.h>
+#include <glib-object.h>
+#include <nm-connection.h>
+
+G_BEGIN_DECLS
+
+typedef struct _NMVpnPluginUiInterface NMVpnPluginUiInterface;
+typedef struct _NMVpnPluginUiWidgetInterface NMVpnPluginUiWidgetInterface;
+
+/* Plugin's factory function that returns a GObject that implements
+ * NMVpnPluginUiInterface.
+ */
+typedef NMVpnPluginUiInterface * (*NMVpnPluginUiFactory) (GError **error);
+NMVpnPluginUiInterface *nm_vpn_plugin_ui_factory (GError **error);
+
+
+/**************************************************/
+/* Plugin interface                               */
+/**************************************************/
+
+#define NM_TYPE_VPN_PLUGIN_UI_INTERFACE      (nm_vpn_plugin_ui_interface_get_type ())
+#define NM_VPN_PLUGIN_UI_INTERFACE(obj)      (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_VPN_PLUGIN_UI_INTERFACE, NMVpnPluginUiInterface))
+#define NM_IS_VPN_PLUGIN_UI_INTERFACE(obj)   (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_VPN_PLUGIN_UI_INTERFACE))
+#define NM_VPN_PLUGIN_UI_INTERFACE_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), NM_TYPE_VPN_PLUGIN_UI_INTERFACE, NMVpnPluginUiInterface))
+
+#define NM_VPN_PLUGIN_UI_CAPABILITY_NONE     0x00
+#define NM_VPN_PLUGIN_UI_CAPABILITY_IMPORT   0x01
+#define NM_VPN_PLUGIN_UI_CAPABILITY_EXPORT   0x02
+
+/* Short display name of the VPN plugin */
+#define NM_VPN_PLUGIN_UI_INTERFACE_NAME "name"
+
+/* Longer description of the the VPN plugin */
+#define NM_VPN_PLUGIN_UI_INTERFACE_DESC "desc"
+
+/* D-Bus service name of the plugin's VPN service */
+#define NM_VPN_PLUGIN_UI_INTERFACE_SERVICE "service"
+
+typedef enum {
+	NM_VPN_PLUGIN_UI_INTERFACE_PROP_FIRST = 0x1000,
+
+	NM_VPN_PLUGIN_UI_INTERFACE_PROP_NAME = NM_VPN_PLUGIN_UI_INTERFACE_PROP_FIRST,
+	NM_VPN_PLUGIN_UI_INTERFACE_PROP_DESC,
+	NM_VPN_PLUGIN_UI_INTERFACE_PROP_SERVICE
+} NMVpnPluginUiInterfaceProp;
+
+struct _NMVpnPluginUiInterface {
+	GTypeInterface g_iface;
+
+	/* Plugin's factory function that returns a GObject that implements
+	 * NMVpnPluginUiWidgetInterface, pre-filled with values from 'connection'
+	 * if non-NULL.
+	 */
+	NMVpnPluginUiWidgetInterface * (*ui_factory) (NMVpnPluginUiInterface *iface,
+	                                              NMConnection *connection,
+	                                              GError **error);
+
+	/* Plugin's capabiltity function that returns a bitmask of capabilities
+	 * described by NM_VPN_PLUGIN_UI_CAPABILITY_* defines.
+	 */
+	guint32 (*get_capabilities) (NMVpnPluginUiInterface *iface);
+
+	/* Try to import a connection from the specified path.  On success, return a
+	 * partial NMConnection object.  On error, return NULL and set 'error' with
+	 * additional information.  Note that 'error' can be NULL, in which case no
+	 * additional error information should be provided.
+	 */
+	NMConnection * (*import) (NMVpnPluginUiInterface *iface, const char *path, GError **error);
+
+	/* Export the given connection to the specified path.  Return TRUE on success.
+	 * On error, return FALSE and set 'error' with additional error information.
+	 * Note that 'error' can be NULL, in which case no additional error information
+	 * should be provided.
+	 */
+	gboolean (*export) (NMVpnPluginUiInterface *iface, const char *path, NMConnection *connection, GError **error);
+
+	/* For a given connection, return a suggested file name.  Returned value should
+	 * be NULL or a suggested file name allocated via g_malloc/g_new/etc to be freed
+	 * by the caller.
+	 */
+	char * (*get_suggested_name) (NMVpnPluginUiInterface *iface, NMConnection *connection);
+
+	/* Called when the user has chosen to remove the connection (for user
+	 * connections only; system connections are handled by the system
+	 * settings service).  Should clear out any VPN-specific secrets or data
+	 * related to the connection.
+	 */
+	gboolean (*delete_connection) (NMVpnPluginUiInterface *iface, NMConnection *connection, GError **error);
+
+	/* Padding for future expansion */
+	void (*_reserved1) (void);
+	void (*_reserved2) (void);
+	void (*_reserved3) (void);
+	void (*_reserved4) (void);
+	void (*_reserved5) (void);
+	void (*_reserved6) (void);
+};
+
+GType nm_vpn_plugin_ui_interface_get_type (void);
+
+NMVpnPluginUiWidgetInterface *nm_vpn_plugin_ui_interface_ui_factory (NMVpnPluginUiInterface *iface,
+                                                                     NMConnection *connection,
+                                                                     GError **error);
+
+guint32 nm_vpn_plugin_ui_interface_get_capabilities (NMVpnPluginUiInterface *iface);
+
+NMConnection *nm_vpn_plugin_ui_interface_import (NMVpnPluginUiInterface *iface,
+                                                 const char *path,
+                                                 GError **error);
+
+gboolean nm_vpn_plugin_ui_interface_export (NMVpnPluginUiInterface *iface,
+                                            const char *path,
+                                            NMConnection *connection,
+                                            GError **error);
+
+char *nm_vpn_plugin_ui_interface_get_suggested_name (NMVpnPluginUiInterface *iface,
+                                                     NMConnection *connection);
+
+gboolean nm_vpn_plugin_ui_interface_delete_connection (NMVpnPluginUiInterface *iface,
+                                                       NMConnection *connection,
+                                                       GError **error);
+
+
+/**************************************************/
+/* UI widget interface                            */
+/**************************************************/
+
+#define NM_TYPE_VPN_PLUGIN_UI_WIDGET_INTERFACE      (nm_vpn_plugin_ui_widget_interface_get_type ())
+#define NM_VPN_PLUGIN_UI_WIDGET_INTERFACE(obj)      (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_VPN_PLUGIN_UI_WIDGET_INTERFACE, NMVpnPluginUiWidgetInterface))
+#define NM_IS_VPN_PLUGIN_UI_WIDGET_INTERFACE(obj)   (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_VPN_PLUGIN_UI_WIDGET_INTERFACE))
+#define NM_VPN_PLUGIN_UI_WIDGET_INTERFACE_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), NM_TYPE_VPN_PLUGIN_UI_WIDGET_INTERFACE, NMVpnPluginUiWidgetInterface))
+
+struct _NMVpnPluginUiWidgetInterface {
+	GTypeInterface g_iface;
+
+	/* Return the GtkWidget for the VPN's UI */
+	GObject * (*get_widget) (NMVpnPluginUiWidgetInterface *iface);
+
+	/* Called to save the user-entered options to the connection object.  Should
+	 * return FALSE and set 'error' if the current options are invalid.  'error'
+	 * should contain enough information for the plugin to determine which UI
+	 * widget is invalid at a later point in time.  For example, creating unique
+	 * error codes for what error occurred and populating the message field
+	 * of 'error' with the name of the invalid property.
+	 */
+	gboolean (*update_connection) (NMVpnPluginUiWidgetInterface *iface,
+	                               NMConnection *connection,
+	                               GError **error);
+
+	/* Called when the user has chosen to save the connection (for user
+	 * connections only; system connections are handled by the system
+	 * settings service).  Should save VPN-specific connection secrets in
+	 * a way that the auth-dialog can read them.
+	 */
+	gboolean (*save_secrets) (NMVpnPluginUiWidgetInterface *iface,
+	                          NMConnection *connection,
+	                          GError **error);
+
+	/* Emitted when the value of a UI widget changes.  May trigger a validity
+	 * check via update_connection() to write values to the connection */
+	void (*changed) (NMVpnPluginUiWidgetInterface *iface);
+};
+
+GType nm_vpn_plugin_ui_widget_interface_get_type (void);
+
+GObject * nm_vpn_plugin_ui_widget_interface_get_widget (NMVpnPluginUiWidgetInterface *iface);
+
+gboolean nm_vpn_plugin_ui_widget_interface_update_connection (NMVpnPluginUiWidgetInterface *iface,
+                                                              NMConnection *connection,
+                                                              GError **error);
+
+gboolean nm_vpn_plugin_ui_widget_interface_save_secrets (NMVpnPluginUiWidgetInterface *iface,
+                                                         NMConnection *connection,
+                                                         GError **error);
+
+G_END_DECLS
+
+#endif	/* NM_VPN_PLUGIN_UI_INTERFACE_H */
diff --git a/libnm-glib/nm-vpn-plugin.c b/libnm-glib/nm-vpn-plugin.c
new file mode 100644
index 00000000..fe7a2b63
--- /dev/null
+++ b/libnm-glib/nm-vpn-plugin.c
@@ -0,0 +1,807 @@
+/* -*- 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.
+ * Copyright (C) 2007 - 2008 Red Hat, Inc.
+ */
+
+#include <signal.h>
+#include "nm-glib-compat.h"
+#include "nm-vpn-plugin.h"
+#include "nm-utils.h"
+#include "nm-connection.h"
+#include "nm-dbus-glib-types.h"
+
+static gboolean impl_vpn_plugin_connect    (NMVPNPlugin *plugin,
+								    GHashTable *connection,
+								    GError **err);
+
+static gboolean impl_vpn_plugin_need_secrets (NMVPNPlugin *plugin,
+								    GHashTable *connection,
+								    char **service_name,
+								    GError **err);
+
+static gboolean impl_vpn_plugin_disconnect (NMVPNPlugin *plugin,
+								    GError **err);
+
+static gboolean impl_vpn_plugin_set_ip4_config (NMVPNPlugin *plugin,
+									   GHashTable *config,
+									   GError **err);
+
+static gboolean impl_vpn_plugin_set_failure (NMVPNPlugin *plugin,
+									char *reason,
+									GError **err);
+
+#include "nm-vpn-plugin-glue.h"
+
+#define NM_VPN_PLUGIN_CONNECT_TIMER 60
+#define NM_VPN_PLUGIN_QUIT_TIMER    20
+
+G_DEFINE_ABSTRACT_TYPE (NMVPNPlugin, nm_vpn_plugin, G_TYPE_OBJECT)
+
+typedef struct {
+	NMVPNServiceState state;
+
+	/* DBUS-y stuff */
+	DBusGConnection *connection;
+	char *dbus_service_name;
+
+	/* GObject-y stuff */
+	gboolean disposed;
+
+	/* Temporary stuff */
+	guint connect_timer;
+	guint quit_timer;
+	guint fail_stop_id;
+} NMVPNPluginPrivate;
+
+#define NM_VPN_PLUGIN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_VPN_PLUGIN, NMVPNPluginPrivate))
+
+enum {
+	STATE_CHANGED,
+	IP4_CONFIG,
+	LOGIN_BANNER,
+	FAILURE,
+	QUIT,
+
+	LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+enum {
+	PROP_0,
+	PROP_DBUS_SERVICE_NAME,
+	PROP_STATE,
+
+	LAST_PROP
+};
+
+static GSList *active_plugins = NULL;
+
+
+GQuark
+nm_vpn_plugin_error_quark (void)
+{
+	static GQuark quark = 0;
+	
+	if (!quark)
+		quark = g_quark_from_static_string ("nm_vpn_plugin_error");
+
+	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,
+						DBusGConnection *connection)
+{
+	NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin);
+
+	if (priv->connection)
+		dbus_g_connection_unref (priv->connection);
+
+	priv->connection = connection;
+}
+
+DBusGConnection *
+nm_vpn_plugin_get_connection (NMVPNPlugin *plugin)
+{
+	DBusGConnection *connection;
+
+	g_return_val_if_fail (NM_IS_VPN_PLUGIN (plugin), NULL);
+
+	connection = NM_VPN_PLUGIN_GET_PRIVATE (plugin)->connection;
+
+	if (connection)
+		dbus_g_connection_ref (connection);
+
+	return connection;
+}
+
+NMVPNServiceState
+nm_vpn_plugin_get_state (NMVPNPlugin *plugin)
+{
+	g_return_val_if_fail (NM_IS_VPN_PLUGIN (plugin), NM_VPN_SERVICE_STATE_UNKNOWN);
+
+	return NM_VPN_PLUGIN_GET_PRIVATE (plugin)->state;
+}
+
+void
+nm_vpn_plugin_set_state (NMVPNPlugin *plugin,
+					NMVPNServiceState state)
+{
+	NMVPNPluginPrivate *priv;
+
+	g_return_if_fail (NM_IS_VPN_PLUGIN (plugin));
+
+	priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin);
+	if (priv->state != state) {
+		priv->state = state;
+		g_signal_emit (plugin, signals[STATE_CHANGED], 0, state);
+	}
+}
+
+void
+nm_vpn_plugin_set_login_banner (NMVPNPlugin *plugin,
+						  const char *banner)
+{
+	g_return_if_fail (NM_IS_VPN_PLUGIN (plugin));
+	g_return_if_fail (banner != NULL);
+
+	g_signal_emit (plugin, signals[LOGIN_BANNER], 0, banner);
+}
+
+void
+nm_vpn_plugin_failure (NMVPNPlugin *plugin,
+				   NMVPNPluginFailure reason)
+{
+	g_return_if_fail (NM_IS_VPN_PLUGIN (plugin));
+
+	g_signal_emit (plugin, signals[FAILURE], 0, reason);
+}
+
+gboolean
+nm_vpn_plugin_disconnect (NMVPNPlugin *plugin, GError **err)
+{
+	gboolean ret = FALSE;
+	NMVPNServiceState state;
+
+	g_return_val_if_fail (NM_IS_VPN_PLUGIN (plugin), FALSE);
+
+	state = nm_vpn_plugin_get_state (plugin);
+	switch (state) {
+	case NM_VPN_SERVICE_STATE_STOPPING:
+		g_set_error (err,
+				   NM_VPN_PLUGIN_ERROR,
+				   NM_VPN_PLUGIN_ERROR_STOPPING_IN_PROGRESS,
+				   "%s",
+				   "Could not process the request because the VPN connection is already being stopped.");
+		break;
+	case NM_VPN_SERVICE_STATE_STOPPED:
+		g_set_error (err,
+				   NM_VPN_PLUGIN_ERROR,
+				   NM_VPN_PLUGIN_ERROR_ALREADY_STOPPED,
+				   "%s",
+				   "Could not process the request because no VPN connection was active.");
+		break;
+	case NM_VPN_SERVICE_STATE_STARTING:
+	case NM_VPN_SERVICE_STATE_STARTED:
+		nm_vpn_plugin_set_state (plugin, NM_VPN_SERVICE_STATE_STOPPING);
+		ret = NM_VPN_PLUGIN_GET_CLASS (plugin)->disconnect (plugin, err);
+		nm_vpn_plugin_set_state (plugin, NM_VPN_SERVICE_STATE_STOPPED);
+		break;
+	case NM_VPN_SERVICE_STATE_INIT:
+		ret = TRUE;
+		break;
+
+	default:
+		g_warning ("Unhandled VPN service state %d", state);
+		g_assert_not_reached ();
+		break;
+	}
+
+	return ret;
+}
+
+static void
+nm_vpn_plugin_emit_quit (NMVPNPlugin *plugin)
+{
+	g_signal_emit (plugin, signals[QUIT], 0);
+}
+
+static gboolean
+connect_timer_expired (gpointer data)
+{
+	NMVPNPlugin *plugin = NM_VPN_PLUGIN (data);
+	GError *err = NULL;
+
+	nm_info ("Connect timer expired, disconnecting.");
+	nm_vpn_plugin_disconnect (plugin, &err);
+	if (err) {
+		nm_warning ("Disconnect failed: %s", err->message);
+		g_error_free (err);
+	}
+
+	return FALSE;
+}
+
+static gboolean
+quit_timer_expired (gpointer data)
+{
+	NMVPNPlugin *plugin = NM_VPN_PLUGIN (data);
+
+	nm_vpn_plugin_emit_quit (plugin);
+
+	return FALSE;
+}
+
+static gboolean
+fail_stop (gpointer data)
+{
+	NMVPNPlugin *plugin = NM_VPN_PLUGIN (data);
+
+	nm_vpn_plugin_set_state (plugin, NM_VPN_SERVICE_STATE_STOPPED);
+	return FALSE;
+}
+
+static gboolean
+nm_vpn_plugin_connect (NMVPNPlugin *plugin,
+				   NMConnection *connection,
+				   GError **err)
+{
+	NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin);
+	gboolean ret = FALSE;
+	NMVPNServiceState state;
+
+	g_return_val_if_fail (NM_IS_VPN_PLUGIN (plugin), FALSE);
+
+	state = nm_vpn_plugin_get_state (plugin);
+	switch (state) {
+	case NM_VPN_SERVICE_STATE_STARTING:
+		g_set_error (err,
+				   NM_VPN_PLUGIN_ERROR,
+				   NM_VPN_PLUGIN_ERROR_STARTING_IN_PROGRESS,
+				   "%s",
+				   "Could not process the request because the VPN connection is already being started.");
+		break;
+	case NM_VPN_SERVICE_STATE_STARTED:
+		g_set_error (err,
+				   NM_VPN_PLUGIN_ERROR,
+				   NM_VPN_PLUGIN_ERROR_ALREADY_STARTED,
+				   "%s",
+				   "Could not process the request because a VPN connection was already active.");
+		break;
+	case NM_VPN_SERVICE_STATE_STOPPING:
+		g_set_error (err,
+				   NM_VPN_PLUGIN_ERROR,
+				   NM_VPN_PLUGIN_ERROR_STOPPING_IN_PROGRESS,
+				   "%s",
+				   "Could not process the request because the VPN connection is being stopped.");
+		break;
+	case NM_VPN_SERVICE_STATE_STOPPED:
+	case NM_VPN_SERVICE_STATE_INIT:
+		nm_vpn_plugin_set_state (plugin, NM_VPN_SERVICE_STATE_STARTING);
+		ret = NM_VPN_PLUGIN_GET_CLASS (plugin)->connect (plugin, connection, err);
+		if (!ret) {
+			/* Stop the plugin from and idle handler so that the Connect
+			 * method return gets sent before the STOP StateChanged signal.
+			 */
+			if (priv->fail_stop_id)
+				g_source_remove (priv->fail_stop_id);
+			priv->fail_stop_id = g_idle_add (fail_stop, plugin);
+		}
+		break;
+
+	default:
+		g_assert_not_reached ();
+		break;
+	}
+
+	return ret;
+}
+
+void
+nm_vpn_plugin_set_ip4_config (NMVPNPlugin *plugin,
+						GHashTable *ip4_config)
+{
+	g_return_if_fail (NM_IS_VPN_PLUGIN (plugin));
+	g_return_if_fail (ip4_config != NULL);
+
+	g_signal_emit (plugin, signals[IP4_CONFIG], 0, ip4_config);
+
+	nm_vpn_plugin_set_state (plugin, NM_VPN_SERVICE_STATE_STARTED);
+}
+
+
+static gboolean
+impl_vpn_plugin_connect (NMVPNPlugin *plugin,
+					GHashTable *properties,
+					GError **error)
+{
+	NMConnection *connection;
+	gboolean success = FALSE;
+
+	connection = nm_connection_new_from_hash (properties, error);
+	if (!connection) {
+		nm_warning ("%s: Invalid connection: '%s' / '%s' invalid: %d",
+		            __func__,
+		            g_type_name (nm_connection_lookup_setting_type_by_quark ((*error)->domain)),
+		            (*error)->message,
+		            (*error)->code);
+	} else {
+		success = nm_vpn_plugin_connect (plugin, connection, error);
+		g_object_unref (connection);
+	}
+
+	return success;
+}
+
+static gboolean
+impl_vpn_plugin_need_secrets (NMVPNPlugin *plugin,
+                              GHashTable *properties,
+                              char **setting_name,
+                              GError **err)
+{
+	gboolean ret = FALSE;
+	NMConnection *connection;
+	char *sn = NULL;
+	GError *ns_err = NULL;
+	gboolean needed = FALSE;
+	GError *cnfh_err = NULL;
+
+	g_return_val_if_fail (NM_IS_VPN_PLUGIN (plugin), FALSE);
+	g_return_val_if_fail (properties != NULL, FALSE);
+
+	connection = nm_connection_new_from_hash (properties, &cnfh_err);
+	if (!connection) {
+		g_set_error (err,
+		             NM_VPN_PLUGIN_ERROR,
+		             NM_VPN_PLUGIN_ERROR_CONNECTION_INVALID,
+		             "The connection was invalid: '%s' / '%s' invalid: %d.",
+		             g_type_name (nm_connection_lookup_setting_type_by_quark (cnfh_err->domain)),
+		             cnfh_err->message, cnfh_err->code);
+		g_error_free (cnfh_err);
+		return FALSE;
+	}
+
+	if (!NM_VPN_PLUGIN_GET_CLASS (plugin)->need_secrets) {
+		*setting_name = "";
+		ret = TRUE;
+		goto out;
+	}
+
+	needed = NM_VPN_PLUGIN_GET_CLASS (plugin)->need_secrets (plugin, connection, &sn, &ns_err);
+	if (ns_err) {
+		*err = g_error_copy (ns_err);
+		g_error_free (ns_err);
+		goto out;
+	}
+
+	ret = TRUE;
+	if (needed) {
+		g_assert (sn);
+		*setting_name = g_strdup (sn);
+	} else {
+		/* No secrets required */
+		*setting_name = g_strdup ("");
+	}
+
+out:
+	return ret;
+}
+
+static gboolean
+impl_vpn_plugin_disconnect (NMVPNPlugin *plugin,
+					   GError **err)
+{
+	return nm_vpn_plugin_disconnect (plugin, err);
+}
+
+static gboolean
+impl_vpn_plugin_set_ip4_config (NMVPNPlugin *plugin,
+						  GHashTable *config,
+						  GError **err)
+{
+	nm_vpn_plugin_set_ip4_config (plugin, config);
+
+	return TRUE;
+}
+
+static gboolean
+impl_vpn_plugin_set_failure (NMVPNPlugin *plugin,
+					    char *reason,
+					    GError **err)
+{
+	nm_vpn_plugin_failure (plugin, NM_VPN_PLUGIN_FAILURE_BAD_IP_CONFIG);
+
+	return TRUE;
+}
+
+/*********************************************************************/
+
+static void
+sigterm_handler (int signum)
+{
+	g_slist_foreach (active_plugins, (GFunc) nm_vpn_plugin_emit_quit, NULL);
+}
+
+static void
+setup_unix_signal_handler (void)
+{
+	struct sigaction action;
+	sigset_t block_mask;
+
+	action.sa_handler = sigterm_handler;
+	sigemptyset (&block_mask);
+	action.sa_mask = block_mask;
+	action.sa_flags = 0;
+	sigaction (SIGINT, &action, NULL);
+	sigaction (SIGTERM, &action, NULL);
+}
+
+/*********************************************************************/
+
+static void
+one_plugin_destroyed (gpointer data,
+				  GObject *object)
+{
+	active_plugins = g_slist_remove (active_plugins, object);
+}
+
+static void
+nm_vpn_plugin_init (NMVPNPlugin *plugin)
+{
+	active_plugins = g_slist_append (active_plugins, plugin);
+	g_object_weak_ref (G_OBJECT (plugin),
+				    one_plugin_destroyed,
+				    NULL);
+}
+
+static GObject *
+constructor (GType type,
+		   guint n_construct_params,
+		   GObjectConstructParam *construct_params)
+{
+	GObject *object;
+	NMVPNPlugin *plugin;
+	NMVPNPluginPrivate *priv;
+	DBusGConnection *connection;
+	DBusGProxy *proxy;
+	guint request_name_result;
+	GError *err = NULL;
+
+	object = G_OBJECT_CLASS (nm_vpn_plugin_parent_class)->constructor (type,
+														  n_construct_params,
+														  construct_params);
+	if (!object)
+		return NULL;
+
+	priv = NM_VPN_PLUGIN_GET_PRIVATE (object);
+	if (!priv->dbus_service_name)
+		goto err;
+
+	connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &err);
+	if (!connection)
+		goto err;
+
+	proxy = dbus_g_proxy_new_for_name (connection,
+								"org.freedesktop.DBus",
+								"/org/freedesktop/DBus",
+								"org.freedesktop.DBus");
+
+	if (!dbus_g_proxy_call (proxy, "RequestName", &err,
+					    G_TYPE_STRING, priv->dbus_service_name,
+					    G_TYPE_UINT, 0,
+					    G_TYPE_INVALID,
+					    G_TYPE_UINT, &request_name_result,
+					    G_TYPE_INVALID)) {
+		g_object_unref (proxy);
+		goto err;
+	}
+
+	g_object_unref (proxy);
+
+	dbus_g_connection_register_g_object (connection,
+								  NM_VPN_DBUS_PLUGIN_PATH,
+								  object);
+
+	plugin = NM_VPN_PLUGIN (object);
+
+	nm_vpn_plugin_set_connection (plugin, connection);
+	nm_vpn_plugin_set_state (plugin, NM_VPN_SERVICE_STATE_INIT);
+
+	return object;
+
+ err:
+	if (err) {
+		nm_warning ("%s", err->message);
+		g_error_free (err);
+	}
+
+	if (object)
+		g_object_unref (object);
+
+	return NULL;
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+		    const GValue *value, GParamSpec *pspec)
+{
+	NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (object);
+
+	switch (prop_id) {
+	case PROP_DBUS_SERVICE_NAME:
+		/* Construct-only */
+		priv->dbus_service_name = g_strdup (g_value_get_string (value));
+		break;
+	case PROP_STATE:
+		nm_vpn_plugin_set_state (NM_VPN_PLUGIN (object),
+							(NMVPNServiceState) g_value_get_uint (value));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+			  GValue *value, GParamSpec *pspec)
+{
+	NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (object);
+
+	switch (prop_id) {
+	case PROP_DBUS_SERVICE_NAME:
+		g_value_set_string (value, priv->dbus_service_name);
+		break;
+	case PROP_STATE:
+		g_value_set_uint (value, nm_vpn_plugin_get_state (NM_VPN_PLUGIN (object)));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+dispose (GObject *object)
+{
+	NMVPNPlugin *plugin = NM_VPN_PLUGIN (object);
+	NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin);
+	NMVPNServiceState state;
+	GError *err = NULL;
+
+	if (priv->disposed) {
+		G_OBJECT_CLASS (nm_vpn_plugin_parent_class)->dispose (object);
+		return;
+	}
+
+	priv->disposed = TRUE;
+
+	if (priv->fail_stop_id)
+		g_source_remove (priv->fail_stop_id);
+
+	state = nm_vpn_plugin_get_state (plugin);
+
+	if (state == NM_VPN_SERVICE_STATE_STARTED ||
+	    state == NM_VPN_SERVICE_STATE_STARTING)
+		nm_vpn_plugin_disconnect (plugin, &err);
+
+	if (err) {
+		nm_warning ("%s", err->message);
+		g_error_free (err);
+	}
+
+	G_OBJECT_CLASS (nm_vpn_plugin_parent_class)->dispose (object);
+}
+
+static void
+finalize (GObject *object)
+{
+	NMVPNPlugin *plugin = NM_VPN_PLUGIN (object);
+	NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin);
+
+	nm_vpn_plugin_set_connection (plugin, NULL);
+	g_free (priv->dbus_service_name);
+
+	G_OBJECT_CLASS (nm_vpn_plugin_parent_class)->finalize (object);
+}
+
+static void
+connect_timer_removed (gpointer data)
+{
+	NM_VPN_PLUGIN_GET_PRIVATE (data)->connect_timer = 0;
+}
+
+static void
+quit_timer_removed (gpointer data)
+{
+	NM_VPN_PLUGIN_GET_PRIVATE (data)->quit_timer = 0;
+}
+
+static void
+state_changed (NMVPNPlugin *plugin, NMVPNServiceState state)
+{
+	NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin);
+
+	switch (state) {
+	case NM_VPN_SERVICE_STATE_STARTING:
+		/* Remove the quit timer. */
+		if (priv->quit_timer)
+			g_source_remove (priv->quit_timer);
+
+		if (priv->fail_stop_id) {
+			g_source_remove (priv->fail_stop_id);
+			priv->fail_stop_id = 0;
+		}
+
+		/* Add a timer to make sure we do not wait indefinitely for the successful connect. */
+		priv->connect_timer = g_timeout_add_seconds_full (G_PRIORITY_DEFAULT,
+		                                                  NM_VPN_PLUGIN_CONNECT_TIMER,
+		                                                  connect_timer_expired,
+		                                                  plugin,
+		                                                  connect_timer_removed);
+		break;
+	case NM_VPN_SERVICE_STATE_STOPPED:
+		priv->quit_timer = g_timeout_add_seconds_full (G_PRIORITY_DEFAULT,
+		                                               NM_VPN_PLUGIN_QUIT_TIMER,
+		                                               quit_timer_expired,
+		                                               plugin,
+		                                               quit_timer_removed);
+		break;
+	default:
+		/* Clean up all timers we might have set up. */
+		if (priv->connect_timer)
+			g_source_remove (priv->connect_timer);
+
+		if (priv->quit_timer)
+			g_source_remove (priv->quit_timer);
+
+		if (priv->fail_stop_id) {
+			g_source_remove (priv->fail_stop_id);
+			priv->fail_stop_id = 0;
+		}
+		break;
+	}
+}
+
+static void
+nm_vpn_plugin_class_init (NMVPNPluginClass *plugin_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (plugin_class);
+
+	g_type_class_add_private (object_class, sizeof (NMVPNPluginPrivate));
+
+	dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (plugin_class),
+							   &dbus_glib_nm_vpn_plugin_object_info);
+
+	/* virtual methods */
+	object_class->constructor  = constructor;
+	object_class->set_property = set_property;
+	object_class->get_property = get_property;
+	object_class->dispose      = dispose;
+	object_class->finalize     = finalize;
+
+	plugin_class->state_changed = state_changed;
+
+	/* properties */
+	g_object_class_install_property
+		(object_class, PROP_DBUS_SERVICE_NAME,
+		 g_param_spec_string (NM_VPN_PLUGIN_DBUS_SERVICE_NAME,
+						  "DBus service name",
+						  "DBus service name",
+						  NULL,
+						  G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+	g_object_class_install_property
+		(object_class, PROP_STATE,
+		 g_param_spec_uint (NM_VPN_PLUGIN_STATE,
+						"State",
+						"Current VPN service state",
+						NM_VPN_SERVICE_STATE_UNKNOWN,
+						NM_VPN_SERVICE_STATE_STOPPED,
+						NM_VPN_SERVICE_STATE_INIT,
+						G_PARAM_READWRITE));
+
+	/* signals */
+	signals[STATE_CHANGED] =
+		g_signal_new ("state-changed",
+				    G_OBJECT_CLASS_TYPE (object_class),
+				    G_SIGNAL_RUN_FIRST,
+				    G_STRUCT_OFFSET (NMVPNPluginClass, state_changed),
+				    NULL, NULL,
+				    g_cclosure_marshal_VOID__UINT,
+				    G_TYPE_NONE, 1,
+				    G_TYPE_UINT);
+
+	signals[IP4_CONFIG] =
+		g_signal_new ("ip4-config",
+				    G_OBJECT_CLASS_TYPE (object_class),
+				    G_SIGNAL_RUN_FIRST,
+				    G_STRUCT_OFFSET (NMVPNPluginClass, ip4_config),
+				    NULL, NULL,
+				    g_cclosure_marshal_VOID__BOXED,
+				    G_TYPE_NONE, 1,
+				    DBUS_TYPE_G_MAP_OF_VARIANT);
+
+	signals[LOGIN_BANNER] =
+		g_signal_new ("login-banner",
+				    G_OBJECT_CLASS_TYPE (object_class),
+				    G_SIGNAL_RUN_FIRST,
+				    G_STRUCT_OFFSET (NMVPNPluginClass, login_banner),
+				    NULL, NULL,
+				    g_cclosure_marshal_VOID__STRING,
+				    G_TYPE_NONE, 1,
+				    G_TYPE_STRING);
+
+	signals[FAILURE] =
+		g_signal_new ("failure",
+				    G_OBJECT_CLASS_TYPE (object_class),
+				    G_SIGNAL_RUN_FIRST,
+				    G_STRUCT_OFFSET (NMVPNPluginClass, failure),
+				    NULL, NULL,
+				    g_cclosure_marshal_VOID__UINT,
+				    G_TYPE_NONE, 1,
+				    G_TYPE_UINT);
+
+	signals[QUIT] =
+		g_signal_new ("quit",
+				    G_OBJECT_CLASS_TYPE (object_class),
+				    G_SIGNAL_RUN_FIRST,
+				    G_STRUCT_OFFSET (NMVPNPluginClass, quit),
+				    NULL, NULL,
+				    g_cclosure_marshal_VOID__VOID,
+				    G_TYPE_NONE, 0,
+				    G_TYPE_NONE);
+
+	dbus_g_error_domain_register (NM_VPN_PLUGIN_ERROR,
+							NULL,
+							NM_TYPE_VPN_PLUGIN_ERROR);
+
+	setup_unix_signal_handler ();
+}
diff --git a/libnm-glib/nm-vpn-plugin.h b/libnm-glib/nm-vpn-plugin.h
new file mode 100644
index 00000000..8a3c2f1d
--- /dev/null
+++ b/libnm-glib/nm-vpn-plugin.h
@@ -0,0 +1,127 @@
+/* -*- 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.
+ * Copyright (C) 2007 - 2008 Red Hat, Inc.
+ */
+
+#ifndef NM_VPN_PLUGIN_H
+#define NM_VPN_PLUGIN_H
+
+#include <glib.h>
+#include <glib-object.h>
+#include <dbus/dbus-glib.h>
+#include <NetworkManagerVPN.h>
+#include <nm-connection.h>
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_VPN_PLUGIN            (nm_vpn_plugin_get_type ())
+#define NM_VPN_PLUGIN(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_VPN_PLUGIN, NMVPNPlugin))
+#define NM_VPN_PLUGIN_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_VPN_PLUGIN, NMVPNPluginClass))
+#define NM_IS_VPN_PLUGIN(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_VPN_PLUGIN))
+#define NM_IS_VPN_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_VPN_PLUGIN))
+#define NM_VPN_PLUGIN_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_VPN_PLUGIN, NMVPNPluginClass))
+
+#define NM_VPN_PLUGIN_DBUS_SERVICE_NAME "service-name"
+#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,
+} 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;
+} NMVPNPlugin;
+
+typedef struct {
+	GObjectClass parent;
+
+	/* virtual methods */
+	gboolean (*connect)    (NMVPNPlugin   *plugin,
+					    NMConnection  *connection,
+					    GError       **err);
+
+	gboolean (*need_secrets) (NMVPNPlugin *plugin,
+	                              NMConnection *connection,
+	                              char **setting_name,
+	                              GError **error);
+
+	gboolean (*disconnect) (NMVPNPlugin   *plugin,
+					    GError       **err);
+
+	/* Signals */
+	void (*state_changed)  (NMVPNPlugin *plugin,
+					    NMVPNServiceState state);
+
+	void (*ip4_config)     (NMVPNPlugin *plugin,
+					    GHashTable  *ip4_config);
+
+	void (*login_banner)   (NMVPNPlugin *plugin,
+					    const char *banner);
+
+	void (*failure)        (NMVPNPlugin *plugin,
+					    NMVPNPluginFailure reason);
+
+	void (*quit)           (NMVPNPlugin *plugin);
+
+	/* Padding for future expansion */
+	void (*_reserved1) (void);
+	void (*_reserved2) (void);
+	void (*_reserved3) (void);
+	void (*_reserved4) (void);
+	void (*_reserved5) (void);
+	void (*_reserved6) (void);
+} NMVPNPluginClass;
+
+GType  nm_vpn_plugin_get_type       (void);
+GQuark nm_vpn_plugin_error_quark    (void);
+GType  nm_vpn_plugin_error_get_type (void);
+
+DBusGConnection   *nm_vpn_plugin_get_connection (NMVPNPlugin *plugin);
+NMVPNServiceState  nm_vpn_plugin_get_state      (NMVPNPlugin *plugin);
+void               nm_vpn_plugin_set_state      (NMVPNPlugin *plugin,
+									    NMVPNServiceState state);
+
+void               nm_vpn_plugin_set_login_banner (NMVPNPlugin *plugin,
+										 const char *banner);
+
+void               nm_vpn_plugin_failure        (NMVPNPlugin *plugin,
+									    NMVPNPluginFailure reason);
+
+void               nm_vpn_plugin_set_ip4_config (NMVPNPlugin *plugin,
+									    GHashTable *ip4_config);
+
+gboolean           nm_vpn_plugin_disconnect     (NMVPNPlugin *plugin,
+									    GError **err);
+
+G_END_DECLS
+
+#endif /* NM_VPN_PLUGIN_H */