summary refs log tree commit diff
path: root/callouts
diff options
context:
space:
mode:
Diffstat (limited to 'callouts')
-rw-r--r--callouts/Makefile.am46
-rw-r--r--callouts/Makefile.in84
-rw-r--r--callouts/nm-avahi-autoipd-action.c150
-rw-r--r--callouts/nm-dispatcher-api.h10
-rw-r--r--callouts/nm-dispatcher-utils.c448
-rw-r--r--callouts/nm-dispatcher-utils.h24
-rw-r--r--callouts/nm-dispatcher.c262
-rw-r--r--callouts/nm-dispatcher.xml4
-rw-r--r--callouts/tests/Makefile.am17
-rw-r--r--callouts/tests/Makefile.in154
-rw-r--r--callouts/tests/dispatcher-old-up1
-rw-r--r--callouts/tests/dispatcher-old-vpn-down1
-rw-r--r--callouts/tests/dispatcher-old-vpn-up1
-rw-r--r--callouts/tests/test-dispatcher-envp.c374
14 files changed, 798 insertions, 778 deletions
diff --git a/callouts/Makefile.am b/callouts/Makefile.am
index a8c9026f..f682579e 100644
--- a/callouts/Makefile.am
+++ b/callouts/Makefile.am
@@ -2,11 +2,11 @@ SUBDIRS = . tests
 
 AM_CPPFLAGS = \
 	-I${top_srcdir}/include \
-	-I${top_builddir}/include \
-	-I${top_srcdir}/libnm-util \
-	-I${top_builddir}/libnm-util \
+	-I${top_srcdir}/libnm-core \
+	-I${top_builddir}/libnm-core \
 	$(GLIB_CFLAGS) \
 	$(DBUS_CFLAGS) \
+	-DNETWORKMANAGER_COMPILATION \
 	-DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \
 	-DNMCONFDIR=\"$(nmconfdir)\" \
 	-DSYSCONFDIR=\"$(sysconfdir)\" \
@@ -45,12 +45,31 @@ nm_dispatcher_SOURCES = \
 	nm-dispatcher-utils.h
 
 nm_dispatcher_LDADD = \
-	$(top_builddir)/libnm-util/libnm-util.la \
-	$(DBUS_LIBS) \
+	$(top_builddir)/libnm/libnm.la \
+	libnmdbus-dispatcher.la \
 	$(GLIB_LIBS)
 
-nm-dispatcher-glue.h: nm-dispatcher.xml
-	$(AM_V_GEN) dbus-binding-tool --prefix=nm_dispatcher --mode=glib-server --output=$@ $<
+# See note about gdbus-codegen in introspection/Makefile.am
+
+noinst_LTLIBRARIES += libnmdbus-dispatcher.la
+
+nodist_libnmdbus_dispatcher_la_SOURCES = \
+	nmdbus-dispatcher.c \
+	nmdbus-dispatcher.h
+
+libnmdbus_dispatcher_la_CPPFLAGS = $(filter-out -DGLIB_VERSION_MAX_ALLOWED%,$(AM_CPPFLAGS))
+
+nmdbus-dispatcher.h: nm-dispatcher.xml
+	$(AM_V_GEN) gdbus-codegen \
+		--generate-c-code $(basename $@) \
+		--c-namespace NMDBus \
+		--interface-prefix org.freedesktop \
+		$<
+
+nmdbus-dispatcher.c: nmdbus-dispatcher.h
+	@true
+
+BUILT_SOURCES = nmdbus-dispatcher.h nmdbus-dispatcher.c
 
 ###########################################
 # dispatcher envp
@@ -64,13 +83,14 @@ libtest_dispatcher_envp_la_CPPFLAGS = \
 	$(AM_CPPFLAGS)
 
 libtest_dispatcher_envp_la_LIBADD = \
-	$(top_builddir)/libnm-util/libnm-util.la \
-	$(GLIB_LIBS) \
-	$(DBUS_LIBS)
+	$(top_builddir)/libnm/libnm.la \
+	$(GLIB_LIBS)
 
 
-udevrulesdir = $(UDEV_BASE_DIR)/rules.d
+if WITH_UDEV_DIR
+udevrulesdir = $(UDEV_DIR)/rules.d
 udevrules_DATA = 77-nm-olpc-mesh.rules
+endif
 
 dbusactivationdir = $(datadir)/dbus-1/system-services
 dbusactivation_in_files = org.freedesktop.nm_dispatcher.service.in
@@ -91,9 +111,7 @@ install-data-hook:
 	   $(mkinstalldirs) -m 0755 $(DESTDIR)$(dispatcherdir)/pre-down.d
 	   $(mkinstalldirs) -m 0755 $(DESTDIR)$(dispatcherdir)/pre-up.d
 
-BUILT_SOURCES = nm-dispatcher-glue.h
-
-CLEANFILES = $(BUILT_SOURCES) $(dbusactivation_DATA)
+CLEANFILES = $(nodist_libnmdbus_dispatcher_la_SOURCES) $(dbusactivation_DATA)
 
 EXTRA_DIST = \
 	$(dbusservice_DATA) \
diff --git a/callouts/Makefile.in b/callouts/Makefile.in
index 06abda44..83151fcc 100644
--- a/callouts/Makefile.in
+++ b/callouts/Makefile.in
@@ -106,18 +106,22 @@ CONFIG_HEADER = $(top_builddir)/config.h
 CONFIG_CLEAN_FILES =
 CONFIG_CLEAN_VPATH_FILES =
 LTLIBRARIES = $(noinst_LTLIBRARIES)
+libnmdbus_dispatcher_la_LIBADD =
+nodist_libnmdbus_dispatcher_la_OBJECTS =  \
+	libnmdbus_dispatcher_la-nmdbus-dispatcher.lo
+libnmdbus_dispatcher_la_OBJECTS =  \
+	$(nodist_libnmdbus_dispatcher_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 = 
 am__DEPENDENCIES_1 =
 libtest_dispatcher_envp_la_DEPENDENCIES =  \
-	$(top_builddir)/libnm-util/libnm-util.la $(am__DEPENDENCIES_1) \
-	$(am__DEPENDENCIES_1)
+	$(top_builddir)/libnm/libnm.la $(am__DEPENDENCIES_1)
 am_libtest_dispatcher_envp_la_OBJECTS =  \
 	libtest_dispatcher_envp_la-nm-dispatcher-utils.lo
 libtest_dispatcher_envp_la_OBJECTS =  \
 	$(am_libtest_dispatcher_envp_la_OBJECTS)
-AM_V_lt = $(am__v_lt_@AM_V@)
-am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
-am__v_lt_0 = --silent
-am__v_lt_1 = 
 am__installdirs = "$(DESTDIR)$(libexecdir)" \
 	"$(DESTDIR)$(dbusactivationdir)" "$(DESTDIR)$(dbusservicedir)" \
 	"$(DESTDIR)$(udevrulesdir)"
@@ -131,8 +135,8 @@ nm_avahi_autoipd_action_DEPENDENCIES = $(am__DEPENDENCIES_1) \
 am_nm_dispatcher_OBJECTS = nm-dispatcher.$(OBJEXT) \
 	nm-dispatcher-utils.$(OBJEXT)
 nm_dispatcher_OBJECTS = $(am_nm_dispatcher_OBJECTS)
-nm_dispatcher_DEPENDENCIES = $(top_builddir)/libnm-util/libnm-util.la \
-	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+nm_dispatcher_DEPENDENCIES = $(top_builddir)/libnm/libnm.la \
+	libnmdbus-dispatcher.la $(am__DEPENDENCIES_1)
 AM_V_P = $(am__v_P_@AM_V@)
 am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
 am__v_P_0 = false
@@ -167,7 +171,8 @@ AM_V_CCLD = $(am__v_CCLD_@AM_V@)
 am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
 am__v_CCLD_0 = @echo "  CCLD    " $@;
 am__v_CCLD_1 = 
-SOURCES = $(libtest_dispatcher_envp_la_SOURCES) \
+SOURCES = $(nodist_libnmdbus_dispatcher_la_SOURCES) \
+	$(libtest_dispatcher_envp_la_SOURCES) \
 	$(nm_avahi_autoipd_action_SOURCES) $(nm_dispatcher_SOURCES)
 DIST_SOURCES = $(libtest_dispatcher_envp_la_SOURCES) \
 	$(nm_avahi_autoipd_action_SOURCES) $(nm_dispatcher_SOURCES)
@@ -275,6 +280,8 @@ AUTOCONF = @AUTOCONF@
 AUTOHEADER = @AUTOHEADER@
 AUTOMAKE = @AUTOMAKE@
 AWK = @AWK@
+BLUEZ5_CFLAGS = @BLUEZ5_CFLAGS@
+BLUEZ5_LIBS = @BLUEZ5_LIBS@
 CC = @CC@
 CCDEPMODE = @CCDEPMODE@
 CFLAGS = @CFLAGS@
@@ -398,6 +405,7 @@ NEWT_CFLAGS = @NEWT_CFLAGS@
 NEWT_LIBS = @NEWT_LIBS@
 NM = @NM@
 NMEDIT = @NMEDIT@
+NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@
 NM_MAJOR_VERSION = @NM_MAJOR_VERSION@
 NM_MICRO_VERSION = @NM_MICRO_VERSION@
 NM_MINOR_VERSION = @NM_MINOR_VERSION@
@@ -417,6 +425,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
 PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
 PKG_CONFIG = @PKG_CONFIG@
 PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
 PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
@@ -443,7 +452,7 @@ SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@
 SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@
 SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@
 SYSTEM_CA_PATH = @SYSTEM_CA_PATH@
-UDEV_BASE_DIR = @UDEV_BASE_DIR@
+UDEV_DIR = @UDEV_DIR@
 USE_NLS = @USE_NLS@
 UUID_CFLAGS = @UUID_CFLAGS@
 UUID_LIBS = @UUID_LIBS@
@@ -525,11 +534,11 @@ with_valgrind = @with_valgrind@
 SUBDIRS = . tests
 AM_CPPFLAGS = \
 	-I${top_srcdir}/include \
-	-I${top_builddir}/include \
-	-I${top_srcdir}/libnm-util \
-	-I${top_builddir}/libnm-util \
+	-I${top_srcdir}/libnm-core \
+	-I${top_builddir}/libnm-core \
 	$(GLIB_CFLAGS) \
 	$(DBUS_CFLAGS) \
+	-DNETWORKMANAGER_COMPILATION \
 	-DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \
 	-DNMCONFDIR=\"$(nmconfdir)\" \
 	-DSYSCONFDIR=\"$(sysconfdir)\" \
@@ -539,9 +548,10 @@ AM_CPPFLAGS = \
 ###########################################
 # Test libraries
 ###########################################
-noinst_LTLIBRARIES = \
-	libtest-dispatcher-envp.la
 
+# See note about gdbus-codegen in introspection/Makefile.am
+noinst_LTLIBRARIES = libtest-dispatcher-envp.la \
+	libnmdbus-dispatcher.la
 dbusservicedir = $(DBUS_SYS_DIR)
 dbusservice_DATA = \
 	nm-dispatcher.conf \
@@ -561,10 +571,16 @@ nm_dispatcher_SOURCES = \
 	nm-dispatcher-utils.h
 
 nm_dispatcher_LDADD = \
-	$(top_builddir)/libnm-util/libnm-util.la \
-	$(DBUS_LIBS) \
+	$(top_builddir)/libnm/libnm.la \
+	libnmdbus-dispatcher.la \
 	$(GLIB_LIBS)
 
+nodist_libnmdbus_dispatcher_la_SOURCES = \
+	nmdbus-dispatcher.c \
+	nmdbus-dispatcher.h
+
+libnmdbus_dispatcher_la_CPPFLAGS = $(filter-out -DGLIB_VERSION_MAX_ALLOWED%,$(AM_CPPFLAGS))
+BUILT_SOURCES = nmdbus-dispatcher.h nmdbus-dispatcher.c
 
 ###########################################
 # dispatcher envp
@@ -577,12 +593,11 @@ libtest_dispatcher_envp_la_CPPFLAGS = \
 	$(AM_CPPFLAGS)
 
 libtest_dispatcher_envp_la_LIBADD = \
-	$(top_builddir)/libnm-util/libnm-util.la \
-	$(GLIB_LIBS) \
-	$(DBUS_LIBS)
+	$(top_builddir)/libnm/libnm.la \
+	$(GLIB_LIBS)
 
-udevrulesdir = $(UDEV_BASE_DIR)/rules.d
-udevrules_DATA = 77-nm-olpc-mesh.rules
+@WITH_UDEV_DIR_TRUE@udevrulesdir = $(UDEV_DIR)/rules.d
+@WITH_UDEV_DIR_TRUE@udevrules_DATA = 77-nm-olpc-mesh.rules
 dbusactivationdir = $(datadir)/dbus-1/system-services
 dbusactivation_in_files = org.freedesktop.nm_dispatcher.service.in
 dbusactivation_DATA = $(dbusactivation_in_files:.service.in=.service)
@@ -593,8 +608,7 @@ edit = @sed \
 	-e 's|@libexecdir[@]|$(libexecdir)|g'
 
 dispatcherdir = $(sysconfdir)/NetworkManager/dispatcher.d
-BUILT_SOURCES = nm-dispatcher-glue.h
-CLEANFILES = $(BUILT_SOURCES) $(dbusactivation_DATA)
+CLEANFILES = $(nodist_libnmdbus_dispatcher_la_SOURCES) $(dbusactivation_DATA)
 EXTRA_DIST = \
 	$(dbusservice_DATA) \
 	$(udevrules_DATA) \
@@ -648,6 +662,9 @@ clean-noinstLTLIBRARIES:
 	  rm -f $${locs}; \
 	}
 
+libnmdbus-dispatcher.la: $(libnmdbus_dispatcher_la_OBJECTS) $(libnmdbus_dispatcher_la_DEPENDENCIES) $(EXTRA_libnmdbus_dispatcher_la_DEPENDENCIES) 
+	$(AM_V_CCLD)$(LINK)  $(libnmdbus_dispatcher_la_OBJECTS) $(libnmdbus_dispatcher_la_LIBADD) $(LIBS)
+
 libtest-dispatcher-envp.la: $(libtest_dispatcher_envp_la_OBJECTS) $(libtest_dispatcher_envp_la_DEPENDENCIES) $(EXTRA_libtest_dispatcher_envp_la_DEPENDENCIES) 
 	$(AM_V_CCLD)$(LINK)  $(libtest_dispatcher_envp_la_OBJECTS) $(libtest_dispatcher_envp_la_LIBADD) $(LIBS)
 install-libexecPROGRAMS: $(libexec_PROGRAMS)
@@ -714,6 +731,7 @@ mostlyclean-compile:
 distclean-compile:
 	-rm -f *.tab.c
 
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnmdbus_dispatcher_la-nmdbus-dispatcher.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtest_dispatcher_envp_la-nm-dispatcher-utils.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-avahi-autoipd-action.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-dispatcher-utils.Po@am__quote@
@@ -740,6 +758,13 @@ distclean-compile:
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
 
+libnmdbus_dispatcher_la-nmdbus-dispatcher.lo: nmdbus-dispatcher.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnmdbus_dispatcher_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnmdbus_dispatcher_la-nmdbus-dispatcher.lo -MD -MP -MF $(DEPDIR)/libnmdbus_dispatcher_la-nmdbus-dispatcher.Tpo -c -o libnmdbus_dispatcher_la-nmdbus-dispatcher.lo `test -f 'nmdbus-dispatcher.c' || echo '$(srcdir)/'`nmdbus-dispatcher.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnmdbus_dispatcher_la-nmdbus-dispatcher.Tpo $(DEPDIR)/libnmdbus_dispatcher_la-nmdbus-dispatcher.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='nmdbus-dispatcher.c' object='libnmdbus_dispatcher_la-nmdbus-dispatcher.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnmdbus_dispatcher_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnmdbus_dispatcher_la-nmdbus-dispatcher.lo `test -f 'nmdbus-dispatcher.c' || echo '$(srcdir)/'`nmdbus-dispatcher.c
+
 libtest_dispatcher_envp_la-nm-dispatcher-utils.lo: nm-dispatcher-utils.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtest_dispatcher_envp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libtest_dispatcher_envp_la-nm-dispatcher-utils.lo -MD -MP -MF $(DEPDIR)/libtest_dispatcher_envp_la-nm-dispatcher-utils.Tpo -c -o libtest_dispatcher_envp_la-nm-dispatcher-utils.lo `test -f 'nm-dispatcher-utils.c' || echo '$(srcdir)/'`nm-dispatcher-utils.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libtest_dispatcher_envp_la-nm-dispatcher-utils.Tpo $(DEPDIR)/libtest_dispatcher_envp_la-nm-dispatcher-utils.Plo
@@ -1109,8 +1134,15 @@ uninstall-am: uninstall-dbusactivationDATA uninstall-dbusserviceDATA \
 	uninstall-libexecPROGRAMS uninstall-udevrulesDATA
 
 
-nm-dispatcher-glue.h: nm-dispatcher.xml
-	$(AM_V_GEN) dbus-binding-tool --prefix=nm_dispatcher --mode=glib-server --output=$@ $<
+nmdbus-dispatcher.h: nm-dispatcher.xml
+	$(AM_V_GEN) gdbus-codegen \
+		--generate-c-code $(basename $@) \
+		--c-namespace NMDBus \
+		--interface-prefix org.freedesktop \
+		$<
+
+nmdbus-dispatcher.c: nmdbus-dispatcher.h
+	@true
 
 %.service: %.service.in
 	$(edit) $< >$@
diff --git a/callouts/nm-avahi-autoipd-action.c b/callouts/nm-avahi-autoipd-action.c
index f84eed71..b28dae5d 100644
--- a/callouts/nm-avahi-autoipd-action.c
+++ b/callouts/nm-avahi-autoipd-action.c
@@ -15,87 +15,50 @@
  * with this program; 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 2008, 2014 Red Hat, Inc.
  */
 
-#include <stdio.h>
-#include <unistd.h>
+#include "config.h"
+
 #include <stdlib.h>
 #include <string.h>
 
-#include <glib.h>
-#include <dbus/dbus.h>
-#include <dbus/dbus-glib-lowlevel.h>
-#include <dbus/dbus-glib.h>
+#include <gio/gio.h>
 
-#define NM_AVAHI_AUTOIPD_DBUS_SERVICE "org.freedesktop.nm_avahi_autoipd"
-#define NM_AVAHI_AUTOIPD_DBUS_IFACE   "org.freedesktop.nm_avahi_autoipd"
+#define NM_AVAHI_AUTOIPD_DBUS_SERVICE   "org.freedesktop.nm_avahi_autoipd"
+#define NM_AVAHI_AUTOIPD_DBUS_INTERFACE "org.freedesktop.nm_avahi_autoipd"
 
-static DBusConnection *
-dbus_init (void)
+static void
+on_name_acquired (GDBusConnection *connection,
+                  const gchar     *name,
+                  gpointer         loop)
 {
-	DBusConnection * connection;
-	DBusError error;
-	int ret;
-
-	dbus_connection_set_change_sigpipe (TRUE);
-
-	dbus_error_init (&error);
-	connection = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
-	if (dbus_error_is_set (&error)) {
-		fprintf (stderr, "Error: could not get the system bus.  Make sure "
-		            "the message bus daemon is running!  Message: (%s) %s\n",
-		            error.name,
-		            error.message);
-		goto error;
-	}
-
-	dbus_connection_set_exit_on_disconnect (connection, FALSE);
-
-	dbus_error_init (&error);
-	ret = dbus_bus_request_name (connection,
-	                             NM_AVAHI_AUTOIPD_DBUS_SERVICE,
-	                             DBUS_NAME_FLAG_DO_NOT_QUEUE,
-	                             &error);
-	if (dbus_error_is_set (&error)) {
-		fprintf (stderr, "Error: Could not acquire the NM DHCP client service. "
-		            "Message: (%s) %s\n",
-		            error.name,
-		            error.message);
-		goto error;
-	}
-
-	if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
-		fprintf (stderr, "Error: Could not acquire the NM DHCP client service "
-		         "as it is already taken.  Return: %d\n",
-		         ret);
-		goto error;
-	}
-
-	return connection;
+	g_main_loop_quit (loop);
+}
 
-error:
-	if (dbus_error_is_set (&error))
-		dbus_error_free (&error);
-	if (connection)
-		dbus_connection_unref (connection);
-	return NULL;
+static void
+on_name_lost (GDBusConnection *connection,
+              const gchar     *name,
+              gpointer         user_data)
+{
+	g_printerr ("Error: Could not acquire the NM autoipd service.");
+	exit (1);
 }
 
 int
 main (int argc, char *argv[])
 {
-	DBusConnection *connection;
-	DBusMessage *message;
-	dbus_bool_t result;
+	GDBusConnection *connection;
 	char *event, *iface, *address;
+	GMainLoop *loop;
+	GError *error = NULL;
 
 #if !GLIB_CHECK_VERSION (2, 35, 0)
 	g_type_init ();
 #endif
 
 	if (argc != 4) {
-		fprintf (stderr, "Error: expected 3 arguments (event, interface, address).\n");
+		g_printerr ("Error: expected 3 arguments (event, interface, address).\n");
 		exit (1);
 	}
 
@@ -104,41 +67,60 @@ main (int argc, char *argv[])
 	address = argv[3] ? argv[3] : "";
 
 	if (!event || !iface || !strlen (event) || !strlen (iface)) {
-		fprintf (stderr, "Error: unexpected arguments received from avahi-autoipd.\n");
+		g_printerr ("Error: unexpected arguments received from avahi-autoipd.\n");
 		exit (1);
 	}
 
 	/* Get a connection to the system bus */
-	connection = dbus_init ();
-	if (connection == NULL)
-		exit (1);
+	connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
+	if (error) {
+		char *remote_error = g_dbus_error_get_remote_error (error);
 
-	message = dbus_message_new_signal ("/", NM_AVAHI_AUTOIPD_DBUS_IFACE, "Event");
-	if (message == NULL) {
-		fprintf (stderr, "Error: not enough memory to send autoip Event signal.\n");
-		exit (1);
+		g_dbus_error_strip_remote_error (error);
+		g_printerr ("Error: could not get the system bus.  Make sure "
+		            "the message bus daemon is running!  Message: (%s) %s\n",
+		            remote_error, error->message);
+		g_free (remote_error);
+		g_error_free (error);
+		return 1;
 	}
 
-	if (!dbus_message_append_args (message,
-	                               DBUS_TYPE_STRING, &event,
-	                               DBUS_TYPE_STRING, &iface,
-	                               DBUS_TYPE_STRING, &address,
-	                               DBUS_TYPE_INVALID)) {
-		fprintf (stderr, "Error: failed to construct autoip Event signal.\n");
-		exit (1);
+	/* Acquire the bus name */
+	loop = g_main_loop_new (NULL, FALSE);
+	g_bus_own_name_on_connection (connection,
+	                              NM_AVAHI_AUTOIPD_DBUS_SERVICE,
+	                              0,
+	                              on_name_acquired,
+	                              on_name_lost,
+	                              loop, NULL);
+	g_main_loop_run (loop);
+	g_main_loop_unref (loop);
+
+	/* Send the signal */
+	if (!g_dbus_connection_emit_signal (connection,
+	                                    NULL,
+	                                    "/",
+	                                    NM_AVAHI_AUTOIPD_DBUS_INTERFACE,
+	                                    "Event",
+	                                    g_variant_new ("(sss)",
+	                                                   event,
+	                                                   iface,
+	                                                   address),
+	                                    &error)) {
+		g_dbus_error_strip_remote_error (error);
+		g_printerr ("Error: Could not send autoipd Event signal: %s\n", error->message);
+		g_error_free (error);
+		return 1;
 	}
 
-	/* queue the message */
-	result = dbus_connection_send (connection, message, NULL);
-	if (!result) {
-		fprintf (stderr, "Error: could not send send autoip Event signal.\n");
-		exit (1);
+	if (!g_dbus_connection_flush_sync (connection, NULL, &error)) {
+		g_dbus_error_strip_remote_error (error);
+		g_printerr ("Error: Could not flush D-Bus connection: %s\n", error->message);
+		g_error_free (error);
+		return 1;
 	}
-	dbus_message_unref (message);
-
-	/* Send out the message */
-	dbus_connection_flush (connection);
 
+	g_object_unref (connection);
 	return 0;
 }
 
diff --git a/callouts/nm-dispatcher-api.h b/callouts/nm-dispatcher-api.h
index 03e40f77..df1bced4 100644
--- a/callouts/nm-dispatcher-api.h
+++ b/callouts/nm-dispatcher-api.h
@@ -18,19 +18,17 @@
  * Copyright (C) 2008 - 2012 Red Hat, Inc.
  */
 
-#include <dbus/dbus-glib.h>
-
 #define NMD_SCRIPT_DIR_DEFAULT  NMCONFDIR "/dispatcher.d"
 #define NMD_SCRIPT_DIR_PRE_UP   NMD_SCRIPT_DIR_DEFAULT "/pre-up.d"
 #define NMD_SCRIPT_DIR_PRE_DOWN NMD_SCRIPT_DIR_DEFAULT "/pre-down.d"
 
-/* dbus-glib types for dispatcher call return value */
+/* dbus-glib types for dispatcher call return value (used by src/nm-dispatcher.c) */
 #define DISPATCHER_TYPE_RESULT       (dbus_g_type_get_struct ("GValueArray", G_TYPE_STRING, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_INVALID))
 #define DISPATCHER_TYPE_RESULT_ARRAY (dbus_g_type_get_collection ("GPtrArray", DISPATCHER_TYPE_RESULT))
 
-#define NM_DISPATCHER_DBUS_SERVICE "org.freedesktop.nm_dispatcher"
-#define NM_DISPATCHER_DBUS_IFACE   "org.freedesktop.nm_dispatcher"
-#define NM_DISPATCHER_DBUS_PATH    "/org/freedesktop/nm_dispatcher"
+#define NM_DISPATCHER_DBUS_SERVICE   "org.freedesktop.nm_dispatcher"
+#define NM_DISPATCHER_DBUS_INTERFACE "org.freedesktop.nm_dispatcher"
+#define NM_DISPATCHER_DBUS_PATH      "/org/freedesktop/nm_dispatcher"
 
 #define NMD_CONNECTION_PROPS_PATH         "path"
 
diff --git a/callouts/nm-dispatcher-utils.c b/callouts/nm-dispatcher-utils.c
index b1d11daf..99616c1a 100644
--- a/callouts/nm-dispatcher-utils.c
+++ b/callouts/nm-dispatcher-utils.c
@@ -18,13 +18,13 @@
  * Copyright (C) 2008 - 2011 Red Hat, Inc.
  */
 
-#include <config.h>
+#include "config.h"
+
 #include <string.h>
 
 #include <glib-object.h>
 
-#include <NetworkManager.h>
-#include <nm-dbus-glib-types.h>
+#include <nm-dbus-interface.h>
 #include <nm-connection.h>
 #include <nm-setting-ip4-config.h>
 #include <nm-setting-ip6-config.h>
@@ -53,51 +53,62 @@ construct_basic_items (GSList *list,
 	return list;
 }
 
+static GSList *_list_append_val_strv (GSList *items, char **values, const char *format, ...) G_GNUC_PRINTF(3, 4);
+
+static GSList *
+_list_append_val_strv (GSList *items, char **values, const char *format, ...)
+{
+	if (!values)
+		g_return_val_if_reached (items);
+
+	/*  Only add an item if the list of @values is not empty */
+	if (values[0]) {
+		va_list args;
+		guint i;
+		GString *str = g_string_new (NULL);
+
+		va_start (args, format);
+		g_string_append_vprintf (str, format, args);
+		va_end (args);
+
+		g_string_append (str, values[0]);
+		for (i = 1; values[i]; i++) {
+			g_string_append_c (str, ' ');
+			g_string_append (str, values[i]);
+		}
+		items = g_slist_prepend (items, g_string_free (str, FALSE));
+	}
+
+	/* we take ownership of the values array and free it. */
+	g_strfreev (values);
+	return items;
+}
+
 static GSList *
 add_domains (GSList *items,
-             GHashTable *hash,
+             GVariant *dict,
              const char *prefix,
              const char four_or_six)
 {
-	GValue *val;
-	char **domains = NULL;
-	GString *tmp;
-	guint i;
+	GVariant *val;
 
 	/* Search domains */
-	val = g_hash_table_lookup (hash, "domains");
-	if (!val)
-		return items;
-
-	g_return_val_if_fail (G_VALUE_HOLDS (val, G_TYPE_STRV), items);
-
-	domains = (char **) g_value_get_boxed (val);
-	if (!domains || !domains[0])
-		return items;
-
-	tmp = g_string_new (NULL);
-	g_string_append_printf (tmp, "%sIP%c_DOMAINS=", prefix, four_or_six);
-	for (i = 0; domains[i]; i++) {
-		if (i > 0)
-			g_string_append_c (tmp, ' ');
-		g_string_append (tmp, domains[i]);
+	val = g_variant_lookup_value (dict, "domains", G_VARIANT_TYPE_STRING_ARRAY);
+	if (val) {
+		items = _list_append_val_strv (items, g_variant_dup_strv (val, NULL),
+		                               "%sIP%c_DOMAINS=", prefix, four_or_six);
+		g_variant_unref (val);
 	}
-	items = g_slist_prepend (items, tmp->str);
-	g_string_free (tmp, FALSE);
-
 	return items;
 }
 
 static GSList *
-construct_ip4_items (GSList *items, GHashTable *ip4_config, const char *prefix)
+construct_ip4_items (GSList *items, GVariant *ip4_config, const char *prefix)
 {
-	GSList *addresses = NULL, *routes = NULL, *iter;
-	GArray *dns = NULL, *wins = NULL;
-	guint32 num, i;
-	GString *tmp;
-	GValue *val;
-	char str_addr[INET_ADDRSTRLEN];
-	char str_gw[INET_ADDRSTRLEN];
+	GPtrArray *addresses, *routes;
+	char *gateway;
+	GVariant *val;
+	int i;
 
 	if (ip4_config == NULL)
 		return items;
@@ -106,114 +117,97 @@ construct_ip4_items (GSList *items, GHashTable *ip4_config, const char *prefix)
 		prefix = "";
 
 	/* IP addresses */
-	val = g_hash_table_lookup (ip4_config, "addresses");
-	if (val)
-		addresses = nm_utils_ip4_addresses_from_gvalue (val);
-
-	for (iter = addresses, num = 0; iter; iter = g_slist_next (iter)) {
-		NMIP4Address *addr = (NMIP4Address *) iter->data;
-		guint32 ip_prefix = nm_ip4_address_get_prefix (addr);
-		char *addrtmp;
+	val = g_variant_lookup_value (ip4_config, "addresses", G_VARIANT_TYPE ("aau"));
+	if (val) {
+		addresses = nm_utils_ip4_addresses_from_variant (val, &gateway);
+		if (!gateway)
+			gateway = g_strdup ("0.0.0.0");
+
+		for (i = 0; i < addresses->len; i++) {
+			NMIPAddress *addr = addresses->pdata[i];
+			char *addrtmp;
+
+			addrtmp = g_strdup_printf ("%sIP4_ADDRESS_%d=%s/%d %s", prefix, i,
+			                           nm_ip_address_get_address (addr),
+			                           nm_ip_address_get_prefix (addr),
+			                           gateway);
+			items = g_slist_prepend (items, addrtmp);
+		}
+		if (addresses->len)
+			items = g_slist_prepend (items, g_strdup_printf ("%sIP4_NUM_ADDRESSES=%d", prefix, addresses->len));
 
-		nm_utils_inet4_ntop (nm_ip4_address_get_address (addr), str_addr);
-		nm_utils_inet4_ntop (nm_ip4_address_get_gateway (addr), str_gw);
+		/* Write gateway to a separate variable, too. */
+		items = g_slist_prepend (items, g_strdup_printf ("%sIP4_GATEWAY=%s", prefix, gateway));
 
-		addrtmp = g_strdup_printf ("%sIP4_ADDRESS_%d=%s/%d %s", prefix, num++, str_addr, ip_prefix, str_gw);
-		items = g_slist_prepend (items, addrtmp);
+		g_ptr_array_unref (addresses);
+		g_free (gateway);
+		g_variant_unref (val);
 	}
-	if (num)
-		items = g_slist_prepend (items, g_strdup_printf ("%sIP4_NUM_ADDRESSES=%d", prefix, num));
-	if (addresses)
-		g_slist_free_full (addresses, (GDestroyNotify) nm_ip4_address_unref);
 
 	/* DNS servers */
-	val = g_hash_table_lookup (ip4_config, "nameservers");
-	if (val && G_VALUE_HOLDS (val, DBUS_TYPE_G_UINT_ARRAY))
-		dns = (GArray *) g_value_get_boxed (val);
-
-	if (dns && (dns->len > 0)) {
-		gboolean first = TRUE;
-
-		tmp = g_string_new (NULL);
-		g_string_append_printf (tmp, "%sIP4_NAMESERVERS=", prefix);
-		for (i = 0; i < dns->len; i++) {
-			guint32 addr;
-
-			addr = g_array_index (dns, guint32, i);
-			if (!first)
-				g_string_append_c (tmp, ' ');
-			g_string_append (tmp, nm_utils_inet4_ntop (addr, NULL));
-			first = FALSE;
-		}
-		items = g_slist_prepend (items, tmp->str);
-		g_string_free (tmp, FALSE);
+	val = g_variant_lookup_value (ip4_config, "nameservers", G_VARIANT_TYPE ("au"));
+	if (val) {
+		items = _list_append_val_strv (items, nm_utils_ip4_dns_from_variant (val),
+		                               "%sIP4_NAMESERVERS=", prefix);
+		g_variant_unref (val);
 	}
 
 	/* Search domains */
 	items = add_domains (items, ip4_config, prefix, '4');
 
 	/* WINS servers */
-	val = g_hash_table_lookup (ip4_config, "wins-servers");
-	if (val && G_VALUE_HOLDS (val, DBUS_TYPE_G_UINT_ARRAY))
-		wins = (GArray *) g_value_get_boxed (val);
-
-	if (wins && wins->len) {
-		gboolean first = TRUE;
-
-		tmp = g_string_new (NULL);
-		g_string_append_printf (tmp, "%sIP4_WINS_SERVERS=", prefix);
-		for (i = 0; i < wins->len; i++) {
-			guint32 addr;
-
-			addr = g_array_index (wins, guint32, i);
-			if (!first)
-				g_string_append_c (tmp, ' ');
-			g_string_append (tmp, nm_utils_inet4_ntop (addr, NULL));
-			first = FALSE;
-		}
-		items = g_slist_prepend (items, tmp->str);
-		g_string_free (tmp, FALSE);
+	val = g_variant_lookup_value (ip4_config, "wins-servers", G_VARIANT_TYPE ("au"));
+	if (val) {
+		items = _list_append_val_strv (items, nm_utils_ip4_dns_from_variant (val),
+		                               "%sIP4_WINS_SERVERS=", prefix);
+		g_variant_unref (val);
 	}
 
 	/* Static routes */
-	val = g_hash_table_lookup (ip4_config, "routes");
-	if (val)
-		routes = nm_utils_ip4_routes_from_gvalue (val);
-
-	for (iter = routes, num = 0; iter; iter = g_slist_next (iter)) {
-		NMIP4Route *route = (NMIP4Route *) iter->data;
-		guint32 ip_prefix = nm_ip4_route_get_prefix (route);
-		guint32 metric = nm_ip4_route_get_metric (route);
-		char *routetmp;
-
-		nm_utils_inet4_ntop (nm_ip4_route_get_dest (route), str_addr);
-		nm_utils_inet4_ntop (nm_ip4_route_get_next_hop (route), str_gw);
-
-		routetmp = g_strdup_printf ("%sIP4_ROUTE_%d=%s/%d %s %d", prefix, num++, str_addr, ip_prefix, str_gw, metric);
-		items = g_slist_prepend (items, routetmp);
-	}
-	items = g_slist_prepend (items, g_strdup_printf ("%sIP4_NUM_ROUTES=%d", prefix, num));
-	if (routes)
-		g_slist_free_full (routes, (GDestroyNotify) nm_ip4_route_unref);
+	val = g_variant_lookup_value (ip4_config, "routes", G_VARIANT_TYPE ("aau"));
+	if (val) {
+		routes = nm_utils_ip4_routes_from_variant (val);
+
+		for (i = 0; i < routes->len; i++) {
+			NMIPRoute *route = routes->pdata[i];
+			const char *next_hop;
+			char *routetmp;
+
+			next_hop = nm_ip_route_get_next_hop (route);
+			if (!next_hop)
+				next_hop = "0.0.0.0";
+
+			routetmp = g_strdup_printf ("%sIP4_ROUTE_%d=%s/%d %s %u", prefix, i,
+			                            nm_ip_route_get_dest (route),
+			                            nm_ip_route_get_prefix (route),
+			                            next_hop,
+			                            (guint32) MAX (0, nm_ip_route_get_metric (route)));
+			items = g_slist_prepend (items, routetmp);
+		}
+		items = g_slist_prepend (items, g_strdup_printf ("%sIP4_NUM_ROUTES=%d", prefix, routes->len));
+		g_ptr_array_unref (routes);
+		g_variant_unref (val);
+	} else
+		items = g_slist_prepend (items, g_strdup_printf ("%sIP4_NUM_ROUTES=0", prefix));
 
 	return items;
 }
 
 static GSList *
-construct_device_dhcp4_items (GSList *items, GHashTable *dhcp4_config)
+construct_device_dhcp4_items (GSList *items, GVariant *dhcp4_config)
 {
-	GHashTableIter iter;
+	GVariantIter iter;
 	const char *key, *tmp;
-	GValue *val;
+	GVariant *val;
 	char *ucased;
 
 	if (dhcp4_config == NULL)
 		return items;
 
-	g_hash_table_iter_init (&iter, dhcp4_config);
-	while (g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &val)) {
+	g_variant_iter_init (&iter, dhcp4_config);
+	while (g_variant_iter_next (&iter, "{&sv}", &key, &val)) {
 		ucased = g_ascii_strup (key, -1);
-		tmp = g_value_get_string (val);
+		tmp = g_variant_get_string (val, NULL);
 		items = g_slist_prepend (items, g_strdup_printf ("DHCP4_%s=%s", ucased, tmp));
 		g_free (ucased);
 	}
@@ -221,14 +215,12 @@ construct_device_dhcp4_items (GSList *items, GHashTable *dhcp4_config)
 }
 
 static GSList *
-construct_ip6_items (GSList *items, GHashTable *ip6_config, const char *prefix)
+construct_ip6_items (GSList *items, GVariant *ip6_config, const char *prefix)
 {
-	GSList *addresses = NULL, *routes = NULL, *dns = NULL, *iter;
-	guint32 num;
-	GString *tmp;
-	GValue *val;
-	char str_addr[INET6_ADDRSTRLEN];
-	char str_gw[INET6_ADDRSTRLEN];
+	GPtrArray *addresses, *routes;
+	char *gateway = NULL;
+	GVariant *val;
+	int i;
 
 	if (ip6_config == NULL)
 		return items;
@@ -237,93 +229,89 @@ construct_ip6_items (GSList *items, GHashTable *ip6_config, const char *prefix)
 		prefix = "";
 
 	/* IP addresses */
-	val = g_hash_table_lookup (ip6_config, "addresses");
-	if (val)
-		addresses = nm_utils_ip6_addresses_from_gvalue (val);
-
-	for (iter = addresses, num = 0; iter; iter = g_slist_next (iter)) {
-		NMIP6Address *addr = (NMIP6Address *) iter->data;
-		guint32 ip_prefix = nm_ip6_address_get_prefix (addr);
-		char *addrtmp;
+	val = g_variant_lookup_value (ip6_config, "addresses", G_VARIANT_TYPE ("a(ayuay)"));
+	if (val) {
+		addresses = nm_utils_ip6_addresses_from_variant (val, &gateway);
+		if (!gateway)
+			gateway = g_strdup ("::");
+
+		for (i = 0; i < addresses->len; i++) {
+			NMIPAddress *addr = addresses->pdata[i];
+			char *addrtmp;
+
+			addrtmp = g_strdup_printf ("%sIP6_ADDRESS_%d=%s/%d %s", prefix, i,
+			                           nm_ip_address_get_address (addr),
+			                           nm_ip_address_get_prefix (addr),
+			                           gateway);
+			items = g_slist_prepend (items, addrtmp);
+		}
+		if (addresses->len)
+			items = g_slist_prepend (items, g_strdup_printf ("%sIP6_NUM_ADDRESSES=%d", prefix, addresses->len));
 
-		nm_utils_inet6_ntop (nm_ip6_address_get_address (addr), str_addr);
-		nm_utils_inet6_ntop (nm_ip6_address_get_gateway (addr), str_gw);
+		/* Write gateway to a separate variable, too. */
+		items = g_slist_prepend (items, g_strdup_printf ("%sIP6_GATEWAY=%s", prefix, gateway));
 
-		addrtmp = g_strdup_printf ("%sIP6_ADDRESS_%d=%s/%d %s", prefix, num++, str_addr, ip_prefix, str_gw);
-		items = g_slist_prepend (items, addrtmp);
+		g_ptr_array_unref (addresses);
+		g_free (gateway);
+		g_variant_unref (val);
 	}
-	if (num)
-		items = g_slist_prepend (items, g_strdup_printf ("%sIP6_NUM_ADDRESSES=%d", prefix, num));
-	if (addresses)
-		g_slist_free_full (addresses, (GDestroyNotify) nm_ip6_address_unref);
 
 	/* DNS servers */
-	val = g_hash_table_lookup (ip6_config, "nameservers");
-	if (val)
-		dns = nm_utils_ip6_dns_from_gvalue (val);
-
-	if (g_slist_length (dns)) {
-		gboolean first = TRUE;
-
-		tmp = g_string_new (NULL);
-		g_string_append_printf (tmp, "%sIP6_NAMESERVERS=", prefix);
-
-		for (iter = dns; iter; iter = g_slist_next (iter)) {
-			const struct in6_addr *addr = iter->data;
-
-			if (!first)
-				g_string_append_c (tmp, ' ');
-			g_string_append (tmp, nm_utils_inet6_ntop (addr, NULL));
-			first = FALSE;
-		}
-
-		items = g_slist_prepend (items, tmp->str);
-		g_string_free (tmp, FALSE);
+	val = g_variant_lookup_value (ip6_config, "nameservers", G_VARIANT_TYPE ("aay"));
+	if (val) {
+		items = _list_append_val_strv (items, nm_utils_ip6_dns_from_variant (val),
+		                               "%sIP6_NAMESERVERS=", prefix);
+		g_variant_unref (val);
 	}
 
 	/* Search domains */
 	items = add_domains (items, ip6_config, prefix, '6');
 
 	/* Static routes */
-	val = g_hash_table_lookup (ip6_config, "routes");
-	if (val)
-		routes = nm_utils_ip6_routes_from_gvalue (val);
-
-	for (iter = routes, num = 0; iter; iter = g_slist_next (iter)) {
-		NMIP6Route *route = (NMIP6Route *) iter->data;
-		guint32 ip_prefix = nm_ip6_route_get_prefix (route);
-		guint32 metric = nm_ip6_route_get_metric (route);
-		char *routetmp;
-
-		nm_utils_inet6_ntop (nm_ip6_route_get_dest (route), str_addr);
-		nm_utils_inet6_ntop (nm_ip6_route_get_next_hop (route), str_gw);
-
-		routetmp = g_strdup_printf ("%sIP6_ROUTE_%d=%s/%d %s %d", prefix, num++, str_addr, ip_prefix, str_gw, metric);
-		items = g_slist_prepend (items, routetmp);
+	val = g_variant_lookup_value (ip6_config, "routes", G_VARIANT_TYPE ("a(ayuayu)"));
+	if (val) {
+		routes = nm_utils_ip6_routes_from_variant (val);
+
+		for (i = 0; i < routes->len; i++) {
+			NMIPRoute *route = routes->pdata[i];
+			const char *next_hop;
+			char *routetmp;
+
+			next_hop = nm_ip_route_get_next_hop (route);
+			if (!next_hop)
+				next_hop = "::";
+
+			routetmp = g_strdup_printf ("%sIP6_ROUTE_%d=%s/%d %s %u", prefix, i,
+			                            nm_ip_route_get_dest (route),
+			                            nm_ip_route_get_prefix (route),
+			                            next_hop,
+			                            (guint32) MAX (0, nm_ip_route_get_metric (route)));
+			items = g_slist_prepend (items, routetmp);
+		}
+		if (routes->len)
+			items = g_slist_prepend (items, g_strdup_printf ("%sIP6_NUM_ROUTES=%d", prefix, routes->len));
+		g_ptr_array_unref (routes);
+		g_variant_unref (val);
 	}
-	if (num)
-		items = g_slist_prepend (items, g_strdup_printf ("%sIP6_NUM_ROUTES=%d", prefix, num));
-	if (routes)
-		g_slist_free_full (routes, (GDestroyNotify) nm_ip6_route_unref);
 
 	return items;
 }
 
 static GSList *
-construct_device_dhcp6_items (GSList *items, GHashTable *dhcp6_config)
+construct_device_dhcp6_items (GSList *items, GVariant *dhcp6_config)
 {
-	GHashTableIter iter;
+	GVariantIter iter;
 	const char *key, *tmp;
-	GValue *val;
+	GVariant *val;
 	char *ucased;
 
 	if (dhcp6_config == NULL)
 		return items;
 
-	g_hash_table_iter_init (&iter, dhcp6_config);
-	while (g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &val)) {
+	g_variant_iter_init (&iter, dhcp6_config);
+	while (g_variant_iter_next (&iter, "{&sv}", &key, &val)) {
 		ucased = g_ascii_strup (key, -1);
-		tmp = g_value_get_string (val);
+		tmp = g_variant_get_string (val, NULL);
 		items = g_slist_prepend (items, g_strdup_printf ("DHCP6_%s=%s", ucased, tmp));
 		g_free (ucased);
 	}
@@ -332,26 +320,26 @@ construct_device_dhcp6_items (GSList *items, GHashTable *dhcp6_config)
 
 char **
 nm_dispatcher_utils_construct_envp (const char *action,
-                                    GHashTable *connection_hash,
-                                    GHashTable *connection_props,
-                                    GHashTable *device_props,
-                                    GHashTable *device_ip4_props,
-                                    GHashTable *device_ip6_props,
-                                    GHashTable *device_dhcp4_props,
-                                    GHashTable *device_dhcp6_props,
+                                    GVariant *connection_dict,
+                                    GVariant *connection_props,
+                                    GVariant *device_props,
+                                    GVariant *device_ip4_props,
+                                    GVariant *device_ip6_props,
+                                    GVariant *device_dhcp4_props,
+                                    GVariant *device_dhcp6_props,
                                     const char *vpn_ip_iface,
-                                    GHashTable *vpn_ip4_props,
-                                    GHashTable *vpn_ip6_props,
+                                    GVariant *vpn_ip4_props,
+                                    GVariant *vpn_ip6_props,
                                     char **out_iface)
 {
 	const char *iface = NULL, *ip_iface = NULL;
 	const char *uuid = NULL, *id = NULL, *path;
 	NMDeviceState dev_state = NM_DEVICE_STATE_UNKNOWN;
-	GValue *value;
+	GVariant *value;
 	char **envp = NULL, *path_item;
 	GSList *items = NULL, *iter;
 	guint i;
-	GHashTable *con_setting_hash;
+	GVariant *con_setting;
 
 	g_return_val_if_fail (action != NULL, NULL);
 	g_return_val_if_fail (out_iface != NULL, NULL);
@@ -367,69 +355,67 @@ nm_dispatcher_utils_construct_envp (const char *action,
 	if (vpn_ip_iface && !strlen (vpn_ip_iface))
 		vpn_ip_iface = NULL;
 
-	con_setting_hash = g_hash_table_lookup (connection_hash, NM_SETTING_CONNECTION_SETTING_NAME);
-	if (!con_setting_hash) {
-		g_warning ("Failed to read connection setting");
-		return NULL;
-	}
-
-	value = g_hash_table_lookup (con_setting_hash, NM_SETTING_CONNECTION_UUID);
-	if (!value || !G_VALUE_HOLDS (value, G_TYPE_STRING)) {
-		g_warning ("Connection hash did not contain the UUID");
-		return NULL;
-	}
-	uuid = g_value_get_string (value);
-
-	value = g_hash_table_lookup (con_setting_hash, NM_SETTING_CONNECTION_ID);
-	if (!value || !G_VALUE_HOLDS (value, G_TYPE_STRING)) {
-		g_warning ("Connection hash did not contain the ID");
-		return NULL;
-	}
-	id = g_value_get_string (value);
-
 	/* interface name */
-	value = g_hash_table_lookup (device_props, NMD_DEVICE_PROPS_INTERFACE);
-	if (!value || !G_VALUE_HOLDS_STRING (value)) {
+	if (!g_variant_lookup (device_props, NMD_DEVICE_PROPS_INTERFACE, "&s", &iface)) {
 		g_warning ("Missing or invalid required value " NMD_DEVICE_PROPS_INTERFACE "!");
 		return NULL;
 	}
-	iface = g_value_get_string (value);
-	if (iface && !strlen (iface))
+	if (!*iface)
 		iface = NULL;
 
 	/* IP interface name */
-	value = g_hash_table_lookup (device_props, NMD_DEVICE_PROPS_IP_INTERFACE);
+	value = g_variant_lookup_value (device_props, NMD_DEVICE_PROPS_IP_INTERFACE, NULL);
 	if (value) {
-		if (!G_VALUE_HOLDS_STRING (value)) {
-			g_warning ("Invalid required value " NMD_DEVICE_PROPS_IP_INTERFACE "!");
+		if (!g_variant_is_of_type (value, G_VARIANT_TYPE_STRING)) {
+			g_warning ("Invalid value " NMD_DEVICE_PROPS_IP_INTERFACE "!");
 			return NULL;
 		}
-		ip_iface = g_value_get_string (value);
+		g_variant_unref (value);
+		g_variant_lookup (device_props, NMD_DEVICE_PROPS_IP_INTERFACE, "&s", &ip_iface);
 	}
 
 	/* Device type */
-	value = g_hash_table_lookup (device_props, NMD_DEVICE_PROPS_TYPE);
-	if (!value || !G_VALUE_HOLDS_UINT (value)) {
+	if (!g_variant_lookup (device_props, NMD_DEVICE_PROPS_TYPE, "u", NULL)) {
 		g_warning ("Missing or invalid required value " NMD_DEVICE_PROPS_TYPE "!");
 		return NULL;
 	}
 
 	/* Device state */
-	value = g_hash_table_lookup (device_props, NMD_DEVICE_PROPS_STATE);
-	if (!value || !G_VALUE_HOLDS_UINT (value)) {
+	value = g_variant_lookup_value (device_props, NMD_DEVICE_PROPS_STATE, G_VARIANT_TYPE_UINT32);
+	if (!value) {
 		g_warning ("Missing or invalid required value " NMD_DEVICE_PROPS_STATE "!");
 		return NULL;
 	}
-	dev_state = g_value_get_uint (value);
+	dev_state = g_variant_get_uint32 (value);
+	g_variant_unref (value);
 
 	/* device itself */
-	value = g_hash_table_lookup (device_props, NMD_DEVICE_PROPS_PATH);
-	if (!value || (G_VALUE_TYPE (value) != DBUS_TYPE_G_OBJECT_PATH)) {
+	if (!g_variant_lookup (device_props, NMD_DEVICE_PROPS_PATH, "o", NULL)) {
 		g_warning ("Missing or invalid required value " NMD_DEVICE_PROPS_PATH "!");
 		return NULL;
 	}
 
+	/* UUID and ID */
+	con_setting = g_variant_lookup_value (connection_dict, NM_SETTING_CONNECTION_SETTING_NAME, NM_VARIANT_TYPE_SETTING);
+	if (!con_setting) {
+		g_warning ("Failed to read connection setting");
+		return NULL;
+	}
+
+	if (!g_variant_lookup (con_setting, NM_SETTING_CONNECTION_UUID, "&s", &uuid)) {
+		g_warning ("Connection hash did not contain the UUID");
+		g_variant_unref (con_setting);
+		return NULL;
+	}
+
+	if (!g_variant_lookup (con_setting, NM_SETTING_CONNECTION_ID, "&s", &id)) {
+		g_warning ("Connection hash did not contain the ID");
+		g_variant_unref (con_setting);
+		return NULL;
+	}
+
 	items = construct_basic_items (items, uuid, id, iface, ip_iface);
+	g_variant_unref (con_setting);
 
 	/* Device it's aren't valid if the device isn't activated */
 	if (iface && (dev_state == NM_DEVICE_STATE_ACTIVATED)) {
diff --git a/callouts/nm-dispatcher-utils.h b/callouts/nm-dispatcher-utils.h
index 33202e0e..665a0d4e 100644
--- a/callouts/nm-dispatcher-utils.h
+++ b/callouts/nm-dispatcher-utils.h
@@ -18,24 +18,24 @@
  * Copyright (C) 2008 - 2011 Red Hat, Inc.
  */
 
-#ifndef NM_DISPATCHER_UTILS_H
-#define NM_DISPATCHER_UTILS_H
+#ifndef __NETWORKMANAGER_DISPATCHER_UTILS_H__
+#define __NETWORKMANAGER_DISPATCHER_UTILS_H__
 
 #include <glib.h>
 
 char **
 nm_dispatcher_utils_construct_envp (const char *action,
-                                    GHashTable *connection_hash,
-                                    GHashTable *connection_props,
-                                    GHashTable *device_props,
-                                    GHashTable *device_ip4_props,
-                                    GHashTable *device_ip6_props,
-                                    GHashTable *device_dhcp4_props,
-                                    GHashTable *device_dhcp6_props,
+                                    GVariant *connection_dict,
+                                    GVariant *connection_props,
+                                    GVariant *device_props,
+                                    GVariant *device_ip4_props,
+                                    GVariant *device_ip6_props,
+                                    GVariant *device_dhcp4_props,
+                                    GVariant *device_dhcp6_props,
                                     const char *vpn_ip_iface,
-                                    GHashTable *vpn_ip4_props,
-                                    GHashTable *vpn_ip6_props,
+                                    GVariant *vpn_ip4_props,
+                                    GVariant *vpn_ip6_props,
                                     char **out_iface);
 
-#endif  /* NM_DISPATCHER_UTILS_H */
+#endif  /* __NETWORKMANAGER_DISPATCHER_UTILS_H__ */
 
diff --git a/callouts/nm-dispatcher.c b/callouts/nm-dispatcher.c
index 733af511..0cd2531d 100644
--- a/callouts/nm-dispatcher.c
+++ b/callouts/nm-dispatcher.c
@@ -18,6 +18,8 @@
  * Copyright (C) 2008 - 2012 Red Hat, Inc.
  */
 
+#include "config.h"
+
 #include <syslog.h>
 #include <stdio.h>
 #include <unistd.h>
@@ -32,17 +34,18 @@
 
 #include <glib.h>
 #include <glib-unix.h>
-#include <dbus/dbus.h>
-#include <dbus/dbus-glib-lowlevel.h>
-#include <dbus/dbus-glib.h>
 
 
 #include "nm-dispatcher-api.h"
 #include "nm-dispatcher-utils.h"
 #include "nm-glib-compat.h"
 
+#include "nmdbus-dispatcher.h"
+
 static GMainLoop *loop = NULL;
 static gboolean debug = FALSE;
+static gboolean persist = FALSE;
+static guint quit_id;
 
 typedef struct Request Request;
 
@@ -50,10 +53,10 @@ typedef struct {
 	GObject parent;
 
 	/* Private data */
+	NMDBusDispatcher *dbus_dispatcher;
+
 	Request *current_request;
 	GQueue *pending_requests;
-	guint quit_id;
-	gboolean persist;
 } Handler;
 
 typedef struct {
@@ -68,28 +71,30 @@ GType handler_get_type (void);
 
 G_DEFINE_TYPE(Handler, handler, G_TYPE_OBJECT)
 
-static void
-impl_dispatch (Handler *h,
-               const char *action,
-               GHashTable *connection_hash,
-               GHashTable *connection_props,
-               GHashTable *device_props,
-               GHashTable *device_ip4_props,
-               GHashTable *device_ip6_props,
-               GHashTable *device_dhcp4_props,
-               GHashTable *device_dhcp6_props,
+static gboolean
+handle_action (NMDBusDispatcher *dbus_dispatcher,
+               GDBusMethodInvocation *context,
+               const char *str_action,
+               GVariant *connection_dict,
+               GVariant *connection_props,
+               GVariant *device_props,
+               GVariant *device_ip4_props,
+               GVariant *device_ip6_props,
+               GVariant *device_dhcp4_props,
+               GVariant *device_dhcp6_props,
                const char *vpn_ip_iface,
-               GHashTable *vpn_ip4_props,
-               GHashTable *vpn_ip6_props,
+               GVariant *vpn_ip4_props,
+               GVariant *vpn_ip6_props,
                gboolean request_debug,
-               DBusGMethodInvocation *context);
-
-#include "nm-dispatcher-glue.h"
-
+               gpointer user_data);
 
 static void
 handler_init (Handler *h)
 {
+	h->pending_requests = g_queue_new ();
+	h->dbus_dispatcher = nmdbus_dispatcher_skeleton_new ();
+	g_signal_connect (h->dbus_dispatcher, "handle-action",
+	                  G_CALLBACK (handle_action), h);
 }
 
 static void
@@ -111,7 +116,7 @@ typedef struct {
 struct Request {
 	Handler *handler;
 
-	DBusGMethodInvocation *context;
+	GDBusMethodInvocation *context;
 	char *action;
 	char *iface;
 	char **envp;
@@ -152,20 +157,20 @@ quit_timeout_cb (gpointer user_data)
 }
 
 static void
-quit_timeout_cancel (Handler *h)
+quit_timeout_cancel (void)
 {
-	if (h->quit_id) {
-		g_source_remove (h->quit_id);
-		h->quit_id = 0;
+	if (quit_id) {
+		g_source_remove (quit_id);
+		quit_id = 0;
 	}
 }
 
 static void
-quit_timeout_reschedule (Handler *h)
+quit_timeout_reschedule (void)
 {
-	quit_timeout_cancel (h);
-	if (!h->persist)
-		h->quit_id = g_timeout_add_seconds (10, quit_timeout_cb, NULL);
+	quit_timeout_cancel ();
+	if (!persist)
+		quit_id = g_timeout_add_seconds (10, quit_timeout_cb, NULL);
 }
 
 static void
@@ -191,7 +196,7 @@ next_request (Handler *h)
 	}
 
 	h->current_request = NULL;
-	quit_timeout_reschedule (h);
+	quit_timeout_reschedule ();
 }
 
 static gboolean
@@ -199,8 +204,8 @@ next_script (gpointer user_data)
 {
 	Request *request = user_data;
 	Handler *h = request->handler;
-	GPtrArray *results;
-	GValueArray *item;
+	GVariantBuilder results;
+	GVariant *ret;
 	guint i;
 
 	request->idx++;
@@ -210,36 +215,18 @@ next_script (gpointer user_data)
 	}
 
 	/* All done */
-	results = g_ptr_array_new_full (request->scripts->len, (GDestroyNotify) g_value_array_free);
+	g_variant_builder_init (&results, G_VARIANT_TYPE ("a(sus)"));
 	for (i = 0; i < request->scripts->len; i++) {
 		ScriptInfo *script = g_ptr_array_index (request->scripts, i);
-		GValue elt = G_VALUE_INIT;
-
-		item = g_value_array_new (3);
-
-		/* Script path */
-		g_value_init (&elt, G_TYPE_STRING);
-		g_value_set_string (&elt, script->script);
-		g_value_array_append (item, &elt);
-		g_value_unset (&elt);
-
-		/* Result */
-		g_value_init (&elt, G_TYPE_UINT);
-		g_value_set_uint (&elt, script->result);
-		g_value_array_append (item, &elt);
-		g_value_unset (&elt);
 
-		/* Error */
-		g_value_init (&elt, G_TYPE_STRING);
-		g_value_set_string (&elt, script->error ? script->error : "");
-		g_value_array_append (item, &elt);
-		g_value_unset (&elt);
-
-		g_ptr_array_add (results, item);
+		g_variant_builder_add (&results, "(sus)",
+		                       script->script,
+		                       script->result,
+		                       script->error ? script->error : "");
 	}
 
-	dbus_g_method_return (request->context, results);
-	g_ptr_array_unref (results);
+	ret = g_variant_new ("(a(sus))", &results);
+	g_dbus_method_invocation_return_value (request->context, ret);
 
 	if (request->debug) {
 		if (request->iface)
@@ -309,7 +296,7 @@ script_timeout_cb (gpointer user_data)
 
 	if (kill (script->pid, 0) == 0)
 		kill (script->pid, SIGKILL);
-	waitpid (script->pid, NULL, 0);
+	(void) waitpid (script->pid, NULL, 0);
 
 	script->error = g_strdup_printf ("Script '%s' timed out.", script->script);
 	script->result = DISPATCH_RESULT_TIMEOUT;
@@ -470,22 +457,24 @@ find_scripts (const char *str_action)
 	return sorted;
 }
 
-static void
-impl_dispatch (Handler *h,
+static gboolean
+handle_action (NMDBusDispatcher *dbus_dispatcher,
+               GDBusMethodInvocation *context,
                const char *str_action,
-               GHashTable *connection_hash,
-               GHashTable *connection_props,
-               GHashTable *device_props,
-               GHashTable *device_ip4_props,
-               GHashTable *device_ip6_props,
-               GHashTable *device_dhcp4_props,
-               GHashTable *device_dhcp6_props,
+               GVariant *connection_dict,
+               GVariant *connection_props,
+               GVariant *device_props,
+               GVariant *device_ip4_props,
+               GVariant *device_ip6_props,
+               GVariant *device_dhcp4_props,
+               GVariant *device_dhcp6_props,
                const char *vpn_ip_iface,
-               GHashTable *vpn_ip4_props,
-               GHashTable *vpn_ip6_props,
+               GVariant *vpn_ip4_props,
+               GVariant *vpn_ip6_props,
                gboolean request_debug,
-               DBusGMethodInvocation *context)
+               gpointer user_data)
 {
+	Handler *h = user_data;
 	GSList *sorted_scripts = NULL;
 	GSList *iter;
 	Request *request;
@@ -495,11 +484,14 @@ impl_dispatch (Handler *h,
 	sorted_scripts = find_scripts (str_action);
 
 	if (!sorted_scripts) {
-		dbus_g_method_return (context, g_ptr_array_new ());
-		return;
+		GVariant *results;
+
+		results = g_variant_new_array (G_VARIANT_TYPE ("(sus)"), NULL, 0);
+		g_dbus_method_invocation_return_value (context, g_variant_new ("(@a(sus))", results));
+		return TRUE;
 	}
 
-	quit_timeout_cancel (h);
+	quit_timeout_cancel ();
 
 	request = g_malloc0 (sizeof (*request));
 	request->handler = h;
@@ -508,7 +500,7 @@ impl_dispatch (Handler *h,
 	request->action = g_strdup (str_action);
 
 	request->envp = nm_dispatcher_utils_construct_envp (str_action,
-	                                                    connection_hash,
+	                                                    connection_dict,
 	                                                    connection_props,
 	                                                    device_props,
 	                                                    device_ip4_props,
@@ -543,76 +535,35 @@ impl_dispatch (Handler *h,
 		g_queue_push_tail (h->pending_requests, request);
 	else
 		start_request (request);
+
+	return TRUE;
 }
 
+static gboolean ever_acquired_name = FALSE;
+
 static void
-destroy_cb (DBusGProxy *proxy, gpointer user_data)
+on_name_acquired (GDBusConnection *connection,
+                  const char      *name,
+                  gpointer         user_data)
 {
-	g_warning ("Disconnected from the system bus, exiting.");
-	g_main_loop_quit (loop);
+	ever_acquired_name = TRUE;
 }
 
-static DBusGConnection *
-dbus_init (void)
+static void
+on_name_lost (GDBusConnection *connection,
+              const char      *name,
+              gpointer         user_data)
 {
-	GError *error = NULL;
-	DBusGConnection *bus;
-	DBusConnection *connection;
-	DBusGProxy *proxy;
-	int result;
-
-	dbus_connection_set_change_sigpipe (TRUE);
-
-	bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
-	if (!bus) {
-		g_warning ("Could not get the system bus.  Make sure "
-		           "the message bus daemon is running!  Message: %s",
-		           error->message);
-		g_error_free (error);
-		return NULL;
-	}
-
-	/* Clean up nicely if we get kicked off the bus */
-	connection = dbus_g_connection_get_connection (bus);
-	dbus_connection_set_exit_on_disconnect (connection, FALSE);
-
-	proxy = dbus_g_proxy_new_for_name (bus,
-	                                   "org.freedesktop.DBus",
-	                                   "/org/freedesktop/DBus",
-	                                   "org.freedesktop.DBus");
-	if (!proxy) {
-		g_warning ("Could not create the DBus proxy!");
-		goto error;
-	}
-
-	g_signal_connect (proxy, "destroy", G_CALLBACK (destroy_cb), NULL);
-
-	if (!dbus_g_proxy_call (proxy, "RequestName", &error,
-	                        G_TYPE_STRING, NM_DISPATCHER_DBUS_SERVICE,
-	                        G_TYPE_UINT, DBUS_NAME_FLAG_DO_NOT_QUEUE,
-	                        G_TYPE_INVALID,
-	                        G_TYPE_UINT, &result,
-	                        G_TYPE_INVALID)) {
-		g_warning ("Could not acquire the " NM_DISPATCHER_DBUS_SERVICE " service.\n"
-		           "  Message: '%s'", error->message);
-		g_error_free (error);
-		goto error;
-	}
-
-	if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
-		g_warning ("Could not acquire the " NM_DISPATCHER_DBUS_SERVICE " service "
-		           "as it is already taken.  Result: %d",
-		           result);
-		goto error;
+	if (!connection) {
+		g_warning ("Could not get the system bus.  Make sure the message bus daemon is running!");
+		exit (1);
+	} else if (!ever_acquired_name) {
+		g_warning ("Could not acquire the " NM_DISPATCHER_DBUS_SERVICE " service.");
+		exit (1);
+	} else {
+		g_message ("Lost the " NM_DISPATCHER_DBUS_SERVICE " name. Exiting");
+		exit (0);
 	}
-
-	return bus;
-
-error:
-	if (proxy)
-		g_object_unref (proxy);
-	dbus_g_connection_unref (bus);
-	return NULL;
 }
 
 static void
@@ -681,8 +632,7 @@ main (int argc, char **argv)
 {
 	GOptionContext *opt_ctx;
 	GError *error = NULL;
-	gboolean persist = FALSE;
-	DBusGConnection *bus;
+	GDBusConnection *bus;
 	Handler *handler;
 
 	GOptionEntry entries[] = {
@@ -715,31 +665,41 @@ main (int argc, char **argv)
 
 	loop = g_main_loop_new (NULL, FALSE);
 
-	bus = dbus_init ();
-	if (!bus)
+	bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
+	if (!bus) {
+		g_warning ("Could not get the system bus (%s).  Make sure the message bus daemon is running!",
+		           error->message);
+		g_error_free (error);
 		return 1;
+	}
 
 	handler = g_object_new (HANDLER_TYPE, NULL);
-	if (!handler)
+	g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (handler->dbus_dispatcher),
+	                                  bus,
+	                                  NM_DISPATCHER_DBUS_PATH,
+	                                  &error);
+	if (error) {
+		g_warning ("Could not export Dispatcher D-Bus interface: %s", error->message);
+		g_error_free (error);
 		return 1;
-	handler->persist = persist;
-	handler->pending_requests = g_queue_new ();
+	}
 
-	dbus_g_object_type_install_info (HANDLER_TYPE, &dbus_glib_nm_dispatcher_object_info);
-	dbus_g_connection_register_g_object (bus,
-	                                     NM_DISPATCHER_DBUS_PATH,
-	                                     G_OBJECT (handler));
+	g_bus_own_name_on_connection (bus,
+	                              NM_DISPATCHER_DBUS_SERVICE,
+	                              G_BUS_NAME_OWNER_FLAGS_NONE,
+	                              on_name_acquired,
+	                              on_name_lost,
+	                              NULL, NULL);
+	g_object_unref (bus);
 
 	if (!persist)
-		handler->quit_id = g_timeout_add_seconds (10, quit_timeout_cb, NULL);
+		quit_id = g_timeout_add_seconds (10, quit_timeout_cb, NULL);
 
 	g_main_loop_run (loop);
 
 	g_queue_free (handler->pending_requests);
 	g_object_unref (handler);
 
-	dbus_g_connection_unref (bus);
-
 	if (!debug)
 		logging_shutdown ();
 
diff --git a/callouts/nm-dispatcher.xml b/callouts/nm-dispatcher.xml
index 1ae138b3..b2c4a21a 100644
--- a/callouts/nm-dispatcher.xml
+++ b/callouts/nm-dispatcher.xml
@@ -2,15 +2,13 @@
 
 <node name="/" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
   <interface name="org.freedesktop.nm_dispatcher">
+    <annotation name="org.gtk.GDBus.C.Name" value="Dispatcher"/>
 
     <method name="Action">
       <tp:docstring>
         INTERNAL; not public API.  Perform an action.
       </tp:docstring>
 
-      <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_dispatch"/>
-      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
-
       <arg name="action" type="s" direction="in">
         <tp:docstring>
           The action being performed.
diff --git a/callouts/tests/Makefile.am b/callouts/tests/Makefile.am
index de4b5f52..f8fd82b7 100644
--- a/callouts/tests/Makefile.am
+++ b/callouts/tests/Makefile.am
@@ -2,11 +2,13 @@ if ENABLE_TESTS
 
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/include \
-	-I${top_builddir}/include \
-	-I$(top_srcdir)/libnm-util \
-	-I$(top_builddir)/libnm-util \
+	-I$(top_srcdir)/libnm-core \
+	-I$(top_builddir)/libnm-core \
 	-I$(top_srcdir)/callouts \
+	-I$(top_builddir)/callouts \
+	-DNETWORKMANAGER_COMPILATION \
 	-DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \
+	-DSRCDIR=\"$(abs_srcdir)\" \
 	$(GLIB_CFLAGS) \
 	$(DBUS_CFLAGS)
 
@@ -19,20 +21,19 @@ test_dispatcher_envp_SOURCES = \
 	test-dispatcher-envp.c
 
 test_dispatcher_envp_LDADD = \
-	$(top_builddir)/libnm-util/libnm-util.la \
+	$(top_builddir)/libnm/libnm.la \
 	$(top_builddir)/callouts/libtest-dispatcher-envp.la \
 	$(GLIB_LIBS) \
 	$(DBUS_LIBS)
 
 ###########################################
 
-check-local: test-dispatcher-envp
-	$(abs_builddir)/test-dispatcher-envp $(abs_srcdir)
+TESTS = test-dispatcher-envp
+
+endif
 
 EXTRA_DIST= \
 	dispatcher-old-down \
 	dispatcher-old-up \
 	dispatcher-old-vpn-down \
 	dispatcher-old-vpn-up
-
-endif
diff --git a/callouts/tests/Makefile.in b/callouts/tests/Makefile.in
index 25255b59..5372e352 100644
--- a/callouts/tests/Makefile.in
+++ b/callouts/tests/Makefile.in
@@ -79,6 +79,7 @@ POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
 @ENABLE_TESTS_TRUE@noinst_PROGRAMS = test-dispatcher-envp$(EXEEXT)
+@ENABLE_TESTS_TRUE@TESTS = test-dispatcher-envp$(EXEEXT)
 subdir = callouts/tests
 DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
 	$(top_srcdir)/build-aux/depcomp
@@ -109,7 +110,7 @@ am__test_dispatcher_envp_SOURCES_DIST = test-dispatcher-envp.c
 test_dispatcher_envp_OBJECTS = $(am_test_dispatcher_envp_OBJECTS)
 am__DEPENDENCIES_1 =
 @ENABLE_TESTS_TRUE@test_dispatcher_envp_DEPENDENCIES =  \
-@ENABLE_TESTS_TRUE@	$(top_builddir)/libnm-util/libnm-util.la \
+@ENABLE_TESTS_TRUE@	$(top_builddir)/libnm/libnm.la \
 @ENABLE_TESTS_TRUE@	$(top_builddir)/callouts/libtest-dispatcher-envp.la \
 @ENABLE_TESTS_TRUE@	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
 AM_V_lt = $(am__v_lt_@AM_V@)
@@ -176,6 +177,28 @@ am__define_uniq_tagged_files = \
   done | $(am__uniquify_input)`
 ETAGS = etags
 CTAGS = ctags
+am__tty_colors_dummy = \
+  mgn= red= grn= lgn= blu= brg= std=; \
+  am__color_tests=no
+am__tty_colors = { \
+  $(am__tty_colors_dummy); \
+  if test "X$(AM_COLOR_TESTS)" = Xno; then \
+    am__color_tests=no; \
+  elif test "X$(AM_COLOR_TESTS)" = Xalways; then \
+    am__color_tests=yes; \
+  elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \
+    am__color_tests=yes; \
+  fi; \
+  if test $$am__color_tests = yes; then \
+    red=''; \
+    grn=''; \
+    lgn=''; \
+    blu=''; \
+    mgn=''; \
+    brg=''; \
+    std=''; \
+  fi; \
+}
 DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
 ACLOCAL = @ACLOCAL@
 ALL_LINGUAS = @ALL_LINGUAS@
@@ -186,6 +209,8 @@ AUTOCONF = @AUTOCONF@
 AUTOHEADER = @AUTOHEADER@
 AUTOMAKE = @AUTOMAKE@
 AWK = @AWK@
+BLUEZ5_CFLAGS = @BLUEZ5_CFLAGS@
+BLUEZ5_LIBS = @BLUEZ5_LIBS@
 CC = @CC@
 CCDEPMODE = @CCDEPMODE@
 CFLAGS = @CFLAGS@
@@ -309,6 +334,7 @@ NEWT_CFLAGS = @NEWT_CFLAGS@
 NEWT_LIBS = @NEWT_LIBS@
 NM = @NM@
 NMEDIT = @NMEDIT@
+NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@
 NM_MAJOR_VERSION = @NM_MAJOR_VERSION@
 NM_MICRO_VERSION = @NM_MICRO_VERSION@
 NM_MINOR_VERSION = @NM_MINOR_VERSION@
@@ -328,6 +354,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
 PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
 PKG_CONFIG = @PKG_CONFIG@
 PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
 PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
@@ -354,7 +381,7 @@ SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@
 SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@
 SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@
 SYSTEM_CA_PATH = @SYSTEM_CA_PATH@
-UDEV_BASE_DIR = @UDEV_BASE_DIR@
+UDEV_DIR = @UDEV_DIR@
 USE_NLS = @USE_NLS@
 UUID_CFLAGS = @UUID_CFLAGS@
 UUID_LIBS = @UUID_LIBS@
@@ -435,11 +462,13 @@ with_resolvconf = @with_resolvconf@
 with_valgrind = @with_valgrind@
 @ENABLE_TESTS_TRUE@AM_CPPFLAGS = \
 @ENABLE_TESTS_TRUE@	-I$(top_srcdir)/include \
-@ENABLE_TESTS_TRUE@	-I${top_builddir}/include \
-@ENABLE_TESTS_TRUE@	-I$(top_srcdir)/libnm-util \
-@ENABLE_TESTS_TRUE@	-I$(top_builddir)/libnm-util \
+@ENABLE_TESTS_TRUE@	-I$(top_srcdir)/libnm-core \
+@ENABLE_TESTS_TRUE@	-I$(top_builddir)/libnm-core \
 @ENABLE_TESTS_TRUE@	-I$(top_srcdir)/callouts \
+@ENABLE_TESTS_TRUE@	-I$(top_builddir)/callouts \
+@ENABLE_TESTS_TRUE@	-DNETWORKMANAGER_COMPILATION \
 @ENABLE_TESTS_TRUE@	-DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \
+@ENABLE_TESTS_TRUE@	-DSRCDIR=\"$(abs_srcdir)\" \
 @ENABLE_TESTS_TRUE@	$(GLIB_CFLAGS) \
 @ENABLE_TESTS_TRUE@	$(DBUS_CFLAGS)
 
@@ -449,16 +478,16 @@ with_valgrind = @with_valgrind@
 @ENABLE_TESTS_TRUE@	test-dispatcher-envp.c
 
 @ENABLE_TESTS_TRUE@test_dispatcher_envp_LDADD = \
-@ENABLE_TESTS_TRUE@	$(top_builddir)/libnm-util/libnm-util.la \
+@ENABLE_TESTS_TRUE@	$(top_builddir)/libnm/libnm.la \
 @ENABLE_TESTS_TRUE@	$(top_builddir)/callouts/libtest-dispatcher-envp.la \
 @ENABLE_TESTS_TRUE@	$(GLIB_LIBS) \
 @ENABLE_TESTS_TRUE@	$(DBUS_LIBS)
 
-@ENABLE_TESTS_TRUE@EXTRA_DIST = \
-@ENABLE_TESTS_TRUE@	dispatcher-old-down \
-@ENABLE_TESTS_TRUE@	dispatcher-old-up \
-@ENABLE_TESTS_TRUE@	dispatcher-old-vpn-down \
-@ENABLE_TESTS_TRUE@	dispatcher-old-vpn-up
+EXTRA_DIST = \
+	dispatcher-old-down \
+	dispatcher-old-up \
+	dispatcher-old-vpn-down \
+	dispatcher-old-vpn-up
 
 all: all-am
 
@@ -595,6 +624,99 @@ cscopelist-am: $(am__tagged_files)
 distclean-tags:
 	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
 
+check-TESTS: $(TESTS)
+	@failed=0; all=0; xfail=0; xpass=0; skip=0; \
+	srcdir=$(srcdir); export srcdir; \
+	list=' $(TESTS) '; \
+	$(am__tty_colors); \
+	if test -n "$$list"; then \
+	  for tst in $$list; do \
+	    if test -f ./$$tst; then dir=./; \
+	    elif test -f $$tst; then dir=; \
+	    else dir="$(srcdir)/"; fi; \
+	    if $(TESTS_ENVIRONMENT) $${dir}$$tst $(AM_TESTS_FD_REDIRECT); then \
+	      all=`expr $$all + 1`; \
+	      case " $(XFAIL_TESTS) " in \
+	      *[\ \	]$$tst[\ \	]*) \
+		xpass=`expr $$xpass + 1`; \
+		failed=`expr $$failed + 1`; \
+		col=$$red; res=XPASS; \
+	      ;; \
+	      *) \
+		col=$$grn; res=PASS; \
+	      ;; \
+	      esac; \
+	    elif test $$? -ne 77; then \
+	      all=`expr $$all + 1`; \
+	      case " $(XFAIL_TESTS) " in \
+	      *[\ \	]$$tst[\ \	]*) \
+		xfail=`expr $$xfail + 1`; \
+		col=$$lgn; res=XFAIL; \
+	      ;; \
+	      *) \
+		failed=`expr $$failed + 1`; \
+		col=$$red; res=FAIL; \
+	      ;; \
+	      esac; \
+	    else \
+	      skip=`expr $$skip + 1`; \
+	      col=$$blu; res=SKIP; \
+	    fi; \
+	    echo "$${col}$$res$${std}: $$tst"; \
+	  done; \
+	  if test "$$all" -eq 1; then \
+	    tests="test"; \
+	    All=""; \
+	  else \
+	    tests="tests"; \
+	    All="All "; \
+	  fi; \
+	  if test "$$failed" -eq 0; then \
+	    if test "$$xfail" -eq 0; then \
+	      banner="$$All$$all $$tests passed"; \
+	    else \
+	      if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \
+	      banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \
+	    fi; \
+	  else \
+	    if test "$$xpass" -eq 0; then \
+	      banner="$$failed of $$all $$tests failed"; \
+	    else \
+	      if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \
+	      banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \
+	    fi; \
+	  fi; \
+	  dashes="$$banner"; \
+	  skipped=""; \
+	  if test "$$skip" -ne 0; then \
+	    if test "$$skip" -eq 1; then \
+	      skipped="($$skip test was not run)"; \
+	    else \
+	      skipped="($$skip tests were not run)"; \
+	    fi; \
+	    test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
+	      dashes="$$skipped"; \
+	  fi; \
+	  report=""; \
+	  if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
+	    report="Please report to $(PACKAGE_BUGREPORT)"; \
+	    test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
+	      dashes="$$report"; \
+	  fi; \
+	  dashes=`echo "$$dashes" | sed s/./=/g`; \
+	  if test "$$failed" -eq 0; then \
+	    col="$$grn"; \
+	  else \
+	    col="$$red"; \
+	  fi; \
+	  echo "$${col}$$dashes$${std}"; \
+	  echo "$${col}$$banner$${std}"; \
+	  test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \
+	  test -z "$$report" || echo "$${col}$$report$${std}"; \
+	  echo "$${col}$$dashes$${std}"; \
+	  test "$$failed" -eq 0; \
+	else :; fi
+
 distdir: $(DISTFILES)
 	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
 	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
@@ -625,9 +747,8 @@ distdir: $(DISTFILES)
 	    || exit 1; \
 	  fi; \
 	done
-@ENABLE_TESTS_FALSE@check-local:
 check-am: all-am
-	$(MAKE) $(AM_MAKEFLAGS) check-local
+	$(MAKE) $(AM_MAKEFLAGS) check-TESTS
 check: check-am
 all-am: Makefile $(PROGRAMS)
 installdirs:
@@ -734,7 +855,7 @@ uninstall-am:
 
 .MAKE: check-am install-am install-strip
 
-.PHONY: CTAGS GTAGS TAGS all all-am check check-am check-local clean \
+.PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \
 	clean-generic clean-libtool clean-noinstPROGRAMS cscopelist-am \
 	ctags ctags-am distclean distclean-compile distclean-generic \
 	distclean-libtool distclean-tags distdir dvi dvi-am html \
@@ -749,11 +870,6 @@ uninstall-am:
 	tags tags-am uninstall uninstall-am
 
 
-###########################################
-
-@ENABLE_TESTS_TRUE@check-local: test-dispatcher-envp
-@ENABLE_TESTS_TRUE@	$(abs_builddir)/test-dispatcher-envp $(abs_srcdir)
-
 # 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/callouts/tests/dispatcher-old-up b/callouts/tests/dispatcher-old-up
index a35812ee..53f35ace 100644
--- a/callouts/tests/dispatcher-old-up
+++ b/callouts/tests/dispatcher-old-up
@@ -39,6 +39,7 @@ DEVICE_IP_IFACE=wlan0
 IP4_ADDRESS_0=192.168.1.119/24 192.168.1.1
 IP4_NUM_ADDRESSES=1
 IP4_NAMESERVERS=68.87.77.134 68.87.72.134 192.168.1.1
+IP4_GATEWAY=192.168.1.1
 IP4_DOMAINS=hsd1.mn.comcast.net.
 IP4_NUM_ROUTES=0
 DHCP4_NETBIOS_NAME_SERVERS=0.0.0.0
diff --git a/callouts/tests/dispatcher-old-vpn-down b/callouts/tests/dispatcher-old-vpn-down
index 4fab5e95..1f1cf2b6 100644
--- a/callouts/tests/dispatcher-old-vpn-down
+++ b/callouts/tests/dispatcher-old-vpn-down
@@ -39,6 +39,7 @@ DEVICE_IP_IFACE=tun0
 IP4_ADDRESS_0=192.168.1.119/24 192.168.1.1
 IP4_NUM_ADDRESSES=1
 IP4_NAMESERVERS=68.87.77.134 68.87.72.134 192.168.1.1
+IP4_GATEWAY=192.168.1.1
 IP4_DOMAINS=hsd1.mn.comcast.net.
 IP4_NUM_ROUTES=0
 DHCP4_NETBIOS_NAME_SERVERS=0.0.0.0
diff --git a/callouts/tests/dispatcher-old-vpn-up b/callouts/tests/dispatcher-old-vpn-up
index 3c350dbf..7cda8a69 100644
--- a/callouts/tests/dispatcher-old-vpn-up
+++ b/callouts/tests/dispatcher-old-vpn-up
@@ -39,6 +39,7 @@ DEVICE_IP_IFACE=tun0
 IP4_ADDRESS_0=192.168.1.119/24 192.168.1.1
 IP4_NUM_ADDRESSES=1
 IP4_NAMESERVERS=68.87.77.134 68.87.72.134 192.168.1.1
+IP4_GATEWAY=192.168.1.1
 IP4_DOMAINS=hsd1.mn.comcast.net.
 IP4_NUM_ROUTES=0
 DHCP4_NETBIOS_NAME_SERVERS=0.0.0.0
diff --git a/callouts/tests/test-dispatcher-envp.c b/callouts/tests/test-dispatcher-envp.c
index a91ae2b2..460174b2 100644
--- a/callouts/tests/test-dispatcher-envp.c
+++ b/callouts/tests/test-dispatcher-envp.c
@@ -18,117 +18,24 @@
  *
  */
 
-#include <config.h>
+#include "config.h"
+
 #include <arpa/inet.h>
 #include <stdlib.h>
 #include <string.h>
 #include <glib.h>
 #include <glib-object.h>
 
-#include "nm-connection.h"
-#include "nm-setting-connection.h"
+#include "nm-core-internal.h"
 #include "nm-dispatcher-utils.h"
-#include "nm-dbus-glib-types.h"
 #include "nm-dispatcher-api.h"
-#include "nm-utils.h"
 
 /*******************************************/
 
-static void
-value_destroy (gpointer data)
-{
-	GValue *value = (GValue *) data;
-
-	g_value_unset (value);
-	g_slice_free (GValue, value);
-}
-
-static GHashTable *
-value_hash_create (void)
-{
-	return g_hash_table_new_full (g_str_hash, g_str_equal, g_free, value_destroy);
-}
-
-static void
-value_hash_add (GHashTable *hash,
-				const char *key,
-				GValue *value)
-{
-	g_hash_table_insert (hash, g_strdup (key), value);
-}
-
-static void
-value_hash_add_string (GHashTable *hash,
-					   const char *key,
-					   const char *str)
-{
-	GValue *value;
-
-	value = g_slice_new0 (GValue);
-	g_value_init (value, G_TYPE_STRING);
-	g_value_set_string (value, str);
-
-	value_hash_add (hash, key, value);
-}
-
-static void
-value_hash_add_object_path (GHashTable *hash,
-							const char *key,
-							const char *op)
-{
-	GValue *value;
-
-	value = g_slice_new0 (GValue);
-	g_value_init (value, DBUS_TYPE_G_OBJECT_PATH);
-	g_value_set_boxed (value, op);
-
-	value_hash_add (hash, key, value);
-}
-
-static void
-value_hash_add_uint (GHashTable *hash,
-					 const char *key,
-					 guint32 val)
-{
-	GValue *value;
-
-	value = g_slice_new0 (GValue);
-	g_value_init (value, G_TYPE_UINT);
-	g_value_set_uint (value, val);
-
-	value_hash_add (hash, key, value);
-}
-
-static void
-value_hash_add_strv (GHashTable *hash,
-                     const char *key,
-                     char **strv)
-{
-	GValue *value;
-
-	value = g_slice_new0 (GValue);
-	g_value_init (value, G_TYPE_STRV);
-	g_value_take_boxed (value, strv);
-	value_hash_add (hash, key, value);
-}
-
-static void
-value_hash_add_uint_array (GHashTable *hash,
-					       const char *key,
-					       GArray *array)
-{
-	GValue *value;
-
-	value = g_slice_new0 (GValue);
-	g_value_init (value, DBUS_TYPE_G_UINT_ARRAY);
-	g_value_take_boxed (value, array);
-	value_hash_add (hash, key, value);
-}
-
 static gboolean
 parse_main (GKeyFile *kf,
-            GHashTable **out_con_hash,
-            GHashTable **out_con_props,
+            GVariant **out_con_dict,
+            GVariant **out_con_props,
             char **out_expected_iface,
             char **out_action,
             char **out_vpn_ip_iface,
@@ -137,6 +44,7 @@ parse_main (GKeyFile *kf,
 	char *uuid, *id;
 	NMConnection *connection;
 	NMSettingConnection *s_con;
+	GVariantBuilder props;
 
 	*out_expected_iface = g_key_file_get_string (kf, "main", "expected-iface", error);
 	if (*out_expected_iface == NULL)
@@ -155,7 +63,7 @@ parse_main (GKeyFile *kf,
 	if (id == NULL)
 		return FALSE;
 
-	connection = nm_connection_new ();
+	connection = nm_simple_connection_new ();
 	g_assert (connection);
 	s_con = (NMSettingConnection *) nm_setting_connection_new ();
 	g_assert (s_con);
@@ -167,57 +75,72 @@ parse_main (GKeyFile *kf,
 	g_free (id);
 	nm_connection_add_setting (connection, NM_SETTING (s_con));
 
-	*out_con_hash = nm_connection_to_hash (connection, NM_SETTING_HASH_FLAG_ALL);
+	*out_con_dict = nm_connection_to_dbus (connection, NM_CONNECTION_SERIALIZE_ALL);
 	g_object_unref (connection);
 
-	*out_con_props = value_hash_create ();
-	value_hash_add_object_path (*out_con_props, "connection-path", "/org/freedesktop/NetworkManager/Connections/5");
+	g_variant_builder_init (&props, G_VARIANT_TYPE ("a{sv}"));
+	g_variant_builder_add (&props, "{sv}",
+	                       "connection-path",
+	                       g_variant_new_object_path ("/org/freedesktop/NetworkManager/Connections/5"));
+	*out_con_props = g_variant_builder_end (&props);
 
 	return TRUE;
 }
 
 static gboolean
-parse_device (GKeyFile *kf, GHashTable **out_device_props, GError **error)
+parse_device (GKeyFile *kf, GVariant **out_device_props, GError **error)
 {
+	GVariantBuilder props;
 	char *tmp;
 	gint i;
 
-	*out_device_props = value_hash_create ();
+	g_variant_builder_init (&props, G_VARIANT_TYPE ("a{sv}"));
 
 	i = g_key_file_get_integer (kf, "device", "state", error);
 	if (i == 0)
 		return FALSE;
-	value_hash_add_uint (*out_device_props, NMD_DEVICE_PROPS_STATE, (guint) i);
+	g_variant_builder_add (&props, "{sv}",
+	                       NMD_DEVICE_PROPS_STATE,
+	                       g_variant_new_uint32 (i));
 
 	i = g_key_file_get_integer (kf, "device", "type", error);
 	if (i == 0)
 		return FALSE;
-	value_hash_add_uint (*out_device_props, NMD_DEVICE_PROPS_TYPE, (guint) i);
+	g_variant_builder_add (&props, "{sv}",
+	                       NMD_DEVICE_PROPS_TYPE,
+	                       g_variant_new_uint32 (i));
 
 	tmp = g_key_file_get_string (kf, "device", "interface", error);
 	if (tmp == NULL)
 		return FALSE;
-	value_hash_add_string (*out_device_props, NMD_DEVICE_PROPS_INTERFACE, tmp);
+	g_variant_builder_add (&props, "{sv}",
+	                       NMD_DEVICE_PROPS_INTERFACE,
+	                       g_variant_new_string (tmp));
 	g_free (tmp);
 
 	tmp = g_key_file_get_string (kf, "device", "ip-interface", error);
 	if (tmp == NULL)
 		return FALSE;
-	value_hash_add_string (*out_device_props, NMD_DEVICE_PROPS_IP_INTERFACE, tmp);
+	g_variant_builder_add (&props, "{sv}",
+	                       NMD_DEVICE_PROPS_IP_INTERFACE,
+	                       g_variant_new_string (tmp));
 	g_free (tmp);
 
 	tmp = g_key_file_get_string (kf, "device", "path", error);
 	if (tmp == NULL)
 		return FALSE;
-	value_hash_add_object_path (*out_device_props, NMD_DEVICE_PROPS_PATH, tmp);
+	g_variant_builder_add (&props, "{sv}",
+	                       NMD_DEVICE_PROPS_PATH,
+	                       g_variant_new_object_path (tmp));
 	g_free (tmp);
 
+	*out_device_props = g_variant_builder_end (&props);
 	return TRUE;
 }
 
 static gboolean
 add_uint_array (GKeyFile *kf,
-                GHashTable *props,
+                GVariantBuilder *props,
                 const char *section,
                 const char *key,
                 GError **error)
@@ -244,21 +167,26 @@ add_uint_array (GKeyFile *kf,
 				g_array_append_val (items, addr);
 			}
 		}
-		value_hash_add_uint_array (props, key, items);
+		g_variant_builder_add (props, "{sv}", key,
+		                       g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32,
+		                                                  items->data, items->len,
+		                                                  sizeof (guint32)));
+		g_array_unref (items);
 	}
 	g_strfreev (split);
 	return TRUE;
 }
 
 static gboolean
-parse_ip4 (GKeyFile *kf, GHashTable **out_props, const char *section, GError **error)
+parse_ip4 (GKeyFile *kf, GVariant **out_props, const char *section, GError **error)
 {
+	GVariantBuilder props;
 	char *tmp;
 	char **split, **iter;
-	GSList *list;
-	GValue *val;
+	GPtrArray *addresses, *routes;
+	const char *gateway = NULL;
 
-	*out_props = value_hash_create ();
+	g_variant_builder_init (&props, G_VARIANT_TYPE ("a{sv}"));
 
 	/* search domains */
 	/* Use char** for domains. (DBUS_TYPE_G_ARRAY_OF_STRING of NMIP4Config
@@ -273,14 +201,15 @@ parse_ip4 (GKeyFile *kf, GHashTable **out_props, const char *section, GError **e
 	if (g_strv_length (split) > 0) {
 		for (iter = split; iter && *iter; iter++)
 			g_strstrip (*iter);
-		value_hash_add_strv (*out_props, "domains", split);
+		g_variant_builder_add (&props, "{sv}", "domains", g_variant_new_strv ((gpointer) split, -1));
+		g_strfreev (split);
 	}
 
 	/* nameservers */
-	if (!add_uint_array (kf, *out_props, "ip4", "nameservers", error))
+	if (!add_uint_array (kf, &props, "ip4", "nameservers", error))
 		return FALSE;
 	/* wins-servers */
-	if (!add_uint_array (kf, *out_props, "ip4", "wins-servers", error))
+	if (!add_uint_array (kf, &props, "ip4", "wins-servers", error))
 		return FALSE;
 
 	/* Addresses */
@@ -291,39 +220,37 @@ parse_ip4 (GKeyFile *kf, GHashTable **out_props, const char *section, GError **e
 	g_free (tmp);
 
 	if (g_strv_length (split) > 0) {
-		list = NULL;
+		addresses = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip_address_unref);
 		for (iter = split; iter && *iter; iter++) {
-			NMIP4Address *addr;
-			guint32 a;
-			char *p;
+			NMIPAddress *addr;
+			char *ip, *prefix;
 
 			if (strlen (g_strstrip (*iter)) == 0)
 				continue;
 
-			addr = nm_ip4_address_new ();
-
-			p = strchr (*iter, '/');
-			g_assert (p);
-			*p++ = '\0';
-
-			g_assert_cmpint (inet_pton (AF_INET, *iter, &a), ==, 1);
-			nm_ip4_address_set_address (addr, a);
-			nm_ip4_address_set_prefix (addr, (guint) atoi (p));
+			ip = *iter;
 
-			p = strchr (p, ' ');
-			g_assert (p);
-			p++;
+			prefix = strchr (ip, '/');
+			g_assert (prefix);
+			*prefix++ = '\0';
 
-			g_assert_cmpint (inet_pton (AF_INET, p, &a), ==, 1);
-			nm_ip4_address_set_gateway (addr, a);
+			if (addresses->len == 0) {
+				gateway = strchr (prefix, ' ');
+				g_assert (gateway);
+				gateway++;
+			}
 
-			list = g_slist_append (list, addr);
+			addr = nm_ip_address_new (AF_INET, ip, (guint) atoi (prefix), error);
+			if (!addr) {
+				g_ptr_array_unref (addresses);
+				return FALSE;
+			}
+			g_ptr_array_add (addresses, addr);
 		}
 
-		val = g_slice_new0 (GValue);
-		g_value_init (val, DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT);
-		nm_utils_ip4_addresses_to_gvalue (list, val);
-		value_hash_add (*out_props, "addresses", val);
+		g_variant_builder_add (&props, "{sv}", "addresses",
+		                       nm_utils_ip4_addresses_to_variant (addresses, gateway));
+		g_ptr_array_unref (addresses);
 	}
 	g_strfreev (split);
 
@@ -335,87 +262,88 @@ parse_ip4 (GKeyFile *kf, GHashTable **out_props, const char *section, GError **e
 		g_free (tmp);
 
 		if (g_strv_length (split) > 0) {
-			list = NULL;
+			routes = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip_route_unref);
 			for (iter = split; iter && *iter; iter++) {
-				NMIP4Route *route;
-				guint32 a;
-				char *p;
+				NMIPRoute *route;
+				char *dest, *prefix, *next_hop, *metric;
 
 				if (strlen (g_strstrip (*iter)) == 0)
 					continue;
 
-				route = nm_ip4_route_new ();
-
-				p = strchr (*iter, '/');
-				g_assert (p);
-				*p++ = '\0';
-
-				g_assert_cmpint (inet_pton (AF_INET, *iter, &a), ==, 1);
-				nm_ip4_route_set_dest (route, a);
-				nm_ip4_route_set_prefix (route, (guint) atoi (p));
-
-				p = strchr (p, ' ');
-				g_assert (p);
-				p++;
-
-				g_assert_cmpint (inet_pton (AF_INET, p, &a), ==, 1);
-				nm_ip4_route_set_next_hop (route, a);
-
-				p = strchr (p, ' ');
-				g_assert (p);
-				p++;
-				nm_ip4_route_set_metric (route, (guint) atoi (p));
-
-				list = g_slist_append (list, route);
+				dest = *iter;
+
+				prefix = strchr (dest, '/');
+				g_assert (prefix);
+				*prefix++ = '\0';
+
+				next_hop = strchr (prefix, ' ');
+				g_assert (next_hop);
+				next_hop++;
+
+				metric = strchr (next_hop, ' ');
+				g_assert (metric);
+				metric++;
+
+				route = nm_ip_route_new (AF_INET,
+				                         dest, (guint) atoi (prefix),
+				                         next_hop, (guint) atoi (metric),
+				                         error);
+				if (!route) {
+					g_ptr_array_unref (routes);
+					return FALSE;
+				}
+				g_ptr_array_add (routes, route);
 			}
 
-			val = g_slice_new0 (GValue);
-			g_value_init (val, DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT);
-			nm_utils_ip4_routes_to_gvalue (list, val);
-			value_hash_add (*out_props, "routes", val);
+			g_variant_builder_add (&props, "{sv}", "routes",
+			                       nm_utils_ip4_routes_to_variant (routes));
+			g_ptr_array_unref (routes);
 		}
 		g_strfreev (split);
 	}
 
+	*out_props = g_variant_builder_end (&props);
 	return TRUE;
 }
 
 static gboolean
 parse_dhcp (GKeyFile *kf,
             const char *group_name,
-            GHashTable **out_props,
+            GVariant **out_props,
             GError **error)
 {
 	char **keys, **iter, *val;
+	GVariantBuilder props;
 
 	keys = g_key_file_get_keys (kf, group_name, NULL, error);
 	if (!keys)
 		return FALSE;
 
-	*out_props = value_hash_create ();
+	g_variant_builder_init (&props, G_VARIANT_TYPE ("a{sv}"));
 	for (iter = keys; iter && *iter; iter++) {
 		val = g_key_file_get_string (kf, group_name, *iter, error);
 		if (!val)
 			return FALSE;
-		value_hash_add_string (*out_props, *iter, val);
+		g_variant_builder_add (&props, "{sv}", *iter, g_variant_new_string (val));
 		g_free (val);
 	}
 
+	*out_props = g_variant_builder_end (&props);
 	return TRUE;
 }
 
 static gboolean
 get_dispatcher_file (const char *file,
-                     GHashTable **out_con_hash,
-                     GHashTable **out_con_props,
-                     GHashTable **out_device_props,
-                     GHashTable **out_device_ip4_props,
-                     GHashTable **out_device_ip6_props,
-                     GHashTable **out_device_dhcp4_props,
-                     GHashTable **out_device_dhcp6_props,
+                     GVariant **out_con_dict,
+                     GVariant **out_con_props,
+                     GVariant **out_device_props,
+                     GVariant **out_device_ip4_props,
+                     GVariant **out_device_ip6_props,
+                     GVariant **out_device_dhcp4_props,
+                     GVariant **out_device_dhcp6_props,
                      char **out_vpn_ip_iface,
-                     GHashTable **out_vpn_ip4_props,
-                     GHashTable **out_vpn_ip6_props,
+                     GVariant **out_vpn_ip4_props,
+                     GVariant **out_vpn_ip6_props,
                      char **out_expected_iface,
                      char **out_action,
                      GHashTable **out_env,
@@ -430,7 +358,7 @@ get_dispatcher_file (const char *file,
 		return FALSE;
 
 	if (!parse_main (kf,
-	                 out_con_hash,
+	                 out_con_dict,
 	                 out_con_props,
 	                 out_expected_iface,
 	                 out_action,
@@ -480,18 +408,18 @@ out:
 /*******************************************/
 
 static void
-test_generic (const char *path, const char *file, const char *override_vpn_ip_iface)
+test_generic (const char *file, const char *override_vpn_ip_iface)
 {
-	GHashTable *con_hash = NULL;
-	GHashTable *con_props = NULL;
-	GHashTable *device_props = NULL;
-	GHashTable *device_ip4_props = NULL;
-	GHashTable *device_ip6_props = NULL;
-	GHashTable *device_dhcp4_props = NULL;
-	GHashTable *device_dhcp6_props = NULL;
+	GVariant *con_dict = NULL;
+	GVariant *con_props = NULL;
+	GVariant *device_props = NULL;
+	GVariant *device_ip4_props = NULL;
+	GVariant *device_ip6_props = NULL;
+	GVariant *device_dhcp4_props = NULL;
+	GVariant *device_dhcp6_props = NULL;
 	char *vpn_ip_iface = NULL;
-	GHashTable *vpn_ip4_props = NULL;
-	GHashTable *vpn_ip6_props = NULL;
+	GVariant *vpn_ip4_props = NULL;
+	GVariant *vpn_ip6_props = NULL;
 	char *expected_iface = NULL;
 	char *action = NULL;
 	char *out_iface = NULL;
@@ -502,9 +430,9 @@ test_generic (const char *path, const char *file, const char *override_vpn_ip_if
 	char **denv, **iter;
 
 	/* Read in the test file */
-	p = g_strdup_printf ("%s/%s", path, file);
+	p = g_build_filename (SRCDIR, file, NULL);
 	success = get_dispatcher_file (p,
-	                               &con_hash,
+	                               &con_dict,
 	                               &con_props,
 	                               &device_props,
 	                               &device_ip4_props,
@@ -524,7 +452,7 @@ test_generic (const char *path, const char *file, const char *override_vpn_ip_if
 
 	/* Get the environment from the dispatcher code */
 	denv = nm_dispatcher_utils_construct_envp (action,
-	                                           con_hash,
+	                                           con_dict,
 	                                           con_props,
 	                                           device_props,
 	                                           device_ip4_props,
@@ -581,57 +509,57 @@ test_generic (const char *path, const char *file, const char *override_vpn_ip_if
 	g_free (vpn_ip_iface);
 	g_free (expected_iface);
 	g_free (action);
-	g_hash_table_destroy (con_hash);
-	g_hash_table_destroy (con_props);
-	g_hash_table_destroy (device_props);
+	g_variant_unref (con_dict);
+	g_variant_unref (con_props);
+	g_variant_unref (device_props);
 	if (device_ip4_props)
-		g_hash_table_destroy (device_ip4_props);
+		g_variant_unref (device_ip4_props);
 	if (device_ip6_props)
-		g_hash_table_destroy (device_ip6_props);
+		g_variant_unref (device_ip6_props);
 	if (device_dhcp4_props)
-		g_hash_table_destroy (device_dhcp4_props);
+		g_variant_unref (device_dhcp4_props);
 	if (device_dhcp6_props)
-		g_hash_table_destroy (device_dhcp6_props);
+		g_variant_unref (device_dhcp6_props);
 	if (vpn_ip4_props)
-		g_hash_table_destroy (vpn_ip4_props);
+		g_variant_unref (vpn_ip4_props);
 	if (vpn_ip6_props)
-		g_hash_table_destroy (vpn_ip6_props);
+		g_variant_unref (vpn_ip6_props);
 	g_hash_table_destroy (expected_env);
 }
 
 /*******************************************/
 
 static void
-test_old_up (const char *path)
+test_old_up (void)
 {
-	test_generic (path, "dispatcher-old-up", NULL);
+	test_generic ("dispatcher-old-up", NULL);
 }
 
 static void
-test_old_down (const char *path)
+test_old_down (void)
 {
-	test_generic (path, "dispatcher-old-down", NULL);
+	test_generic ("dispatcher-old-down", NULL);
 }
 
 static void
-test_old_vpn_up (const char *path)
+test_old_vpn_up (void)
 {
-	test_generic (path, "dispatcher-old-vpn-up", NULL);
+	test_generic ("dispatcher-old-vpn-up", NULL);
 }
 
 static void
-test_old_vpn_down (const char *path)
+test_old_vpn_down (void)
 {
-	test_generic (path, "dispatcher-old-vpn-down", NULL);
+	test_generic ("dispatcher-old-vpn-down", NULL);
 }
 
 static void
-test_up_empty_vpn_iface (const char *path)
+test_up_empty_vpn_iface (void)
 {
 	/* Test that an empty VPN iface variable, like is passed through D-Bus
 	 * from NM, is ignored by the dispatcher environment construction code.
 	 */
-	test_generic (path, "dispatcher-old-up", "");
+	test_generic ("dispatcher-old-up", "");
 }
 
 /*******************************************/
@@ -639,20 +567,18 @@ test_up_empty_vpn_iface (const char *path)
 int
 main (int argc, char **argv)
 {
-	g_assert (argc > 1);
-
 	g_test_init (&argc, &argv, NULL);
 
 #if !GLIB_CHECK_VERSION (2, 35, 0)
 	g_type_init ();
 #endif
 
-	g_test_add_data_func ("/dispatcher/old_up", argv[1], (GTestDataFunc) test_old_up);
-	g_test_add_data_func ("/dispatcher/old_down", argv[1], (GTestDataFunc) test_old_down);
-	g_test_add_data_func ("/dispatcher/old_vpn_up", argv[1], (GTestDataFunc) test_old_vpn_up);
-	g_test_add_data_func ("/dispatcher/old_vpn_down", argv[1], (GTestDataFunc) test_old_vpn_down);
+	g_test_add_func ("/dispatcher/old_up", test_old_up);
+	g_test_add_func ("/dispatcher/old_down", test_old_down);
+	g_test_add_func ("/dispatcher/old_vpn_up", test_old_vpn_up);
+	g_test_add_func ("/dispatcher/old_vpn_down", test_old_vpn_down);
 
-	g_test_add_data_func ("/dispatcher/up_empty_vpn_iface", argv[1], (GTestDataFunc) test_up_empty_vpn_iface);
+	g_test_add_func ("/dispatcher/up_empty_vpn_iface", test_up_empty_vpn_iface);
 
 	return g_test_run ();
 }