dispatcher: port to GDBus
authorDan Winship <danw@gnome.org>
Wed, 3 Sep 2014 16:27:33 +0000 (12:27 -0400)
committerDan Winship <danw@gnome.org>
Thu, 18 Sep 2014 15:26:59 +0000 (11:26 -0400)
Port nm-dispatcher to GDBus, mostly, using dbus-glib's GVariant
utilities to translate the return value of nm_connection_to_dbus().

.gitignore
callouts/Makefile.am
callouts/nm-dispatcher-api.h
callouts/nm-dispatcher-utils.c
callouts/nm-dispatcher-utils.h
callouts/nm-dispatcher.c
callouts/nm-dispatcher.xml
callouts/tests/test-dispatcher-envp.c

index 57325cc..c4790ed 100644 (file)
@@ -43,6 +43,7 @@ valgrind-*.log
 
 /callouts/nm-avahi-autoipd.action
 /callouts/nm-dispatcher
+/callouts/nmdbus-dispatcher.*
 /callouts/org.freedesktop.nm_dispatcher.service
 /callouts/tests/test-dispatcher-envp
 
index 1d1eb3c..d305554 100644 (file)
@@ -46,11 +46,33 @@ nm_dispatcher_SOURCES = \
 
 nm_dispatcher_LDADD = \
        $(top_builddir)/libnm/libnm.la \
-       $(DBUS_LIBS) \
+       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=$@ $<
+# We have to build the gdbus generated code separately, without
+# -DGLIB_VERSION_MAX_ALLOWED, due to a bug in GLib 2.38
+
+noinst_LTLIBRARIES += libnmdbus-dispatcher.la
+
+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.c \
+       nmdbus-dispatcher.h
 
 ###########################################
 # dispatcher envp
@@ -65,8 +87,7 @@ libtest_dispatcher_envp_la_CPPFLAGS = \
 
 libtest_dispatcher_envp_la_LIBADD = \
        $(top_builddir)/libnm/libnm.la \
-       $(GLIB_LIBS) \
-       $(DBUS_LIBS)
+       $(GLIB_LIBS)
 
 
 if WITH_UDEV_DIR
@@ -93,8 +114,6 @@ 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)
 
 EXTRA_DIST = \
index bc156aa..df1bced 100644 (file)
  * 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))
 
index 567c477..9a16880 100644 (file)
@@ -24,7 +24,6 @@
 #include <glib-object.h>
 
 #include <nm-dbus-interface.h>
-#include <nm-dbus-glib-types.h>
 #include <nm-connection.h>
 #include <nm-setting-ip4-config.h>
 #include <nm-setting-ip6-config.h>
@@ -55,25 +54,26 @@ construct_basic_items (GSList *list,
 
 static GSList *
 add_domains (GSList *items,
-             GHashTable *hash,
+             GVariant *dict,
              const char *prefix,
              const char four_or_six)
 {
-       GValue *val;
+       GVariant *val;
        char **domains = NULL;
        GString *tmp;
        guint i;
 
        /* Search domains */
-       val = g_hash_table_lookup (hash, "domains");
+       val = g_variant_lookup_value (dict, "domains", G_VARIANT_TYPE_STRING_ARRAY);
        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])
+       domains = g_variant_dup_strv (val, NULL);
+       g_variant_unref (val);
+       if (!domains[0]) {
+               g_strfreev (domains);
                return items;
+       }
 
        tmp = g_string_new (NULL);
        g_string_append_printf (tmp, "%sIP%c_DOMAINS=", prefix, four_or_six);
@@ -82,22 +82,22 @@ add_domains (GSList *items,
                        g_string_append_c (tmp, ' ');
                g_string_append (tmp, domains[i]);
        }
-       items = g_slist_prepend (items, tmp->str);
-       g_string_free (tmp, FALSE);
+       items = g_slist_prepend (items, g_string_free (tmp, FALSE));
 
+       g_strfreev (domains);
        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, *routes, *iter;
-       GArray *dns, *wins;
-       guint32 num, i;
+       GPtrArray *addresses, *routes;
+       char **dns, **wins;
        GString *tmp;
-       GValue *val;
+       GVariant *val;
        char str_addr[INET_ADDRSTRLEN];
        char str_gw[INET_ADDRSTRLEN];
+       int i;
 
        if (ip4_config == NULL)
                return items;
@@ -106,84 +106,78 @@ construct_ip4_items (GSList *items, GHashTable *ip4_config, const char *prefix)
                prefix = "";
 
        /* IP addresses */
-       val = g_hash_table_lookup (ip4_config, "addresses");
+       val = g_variant_lookup_value (ip4_config, "addresses", G_VARIANT_TYPE ("aau"));
        if (val) {
-               addresses = nm_utils_ip4_addresses_from_gvalue (val);
+               addresses = nm_utils_ip4_addresses_from_variant (val);
 
-               for (iter = addresses, num = 0; iter; iter = g_slist_next (iter)) {
-                       NMIP4Address *addr = (NMIP4Address *) iter->data;
+               for (i = 0; i < addresses->len; i++) {
+                       NMIP4Address *addr = addresses->pdata[i];
                        guint32 ip_prefix = nm_ip4_address_get_prefix (addr);
                        char *addrtmp;
 
                        nm_utils_inet4_ntop (nm_ip4_address_get_address (addr), str_addr);
                        nm_utils_inet4_ntop (nm_ip4_address_get_gateway (addr), str_gw);
 
-                       addrtmp = g_strdup_printf ("%sIP4_ADDRESS_%d=%s/%d %s", prefix, num++, str_addr, ip_prefix, str_gw);
+                       addrtmp = g_strdup_printf ("%sIP4_ADDRESS_%d=%s/%d %s", prefix, i, str_addr, ip_prefix, str_gw);
                        items = g_slist_prepend (items, addrtmp);
                }
-               if (num)
-                       items = g_slist_prepend (items, g_strdup_printf ("%sIP4_NUM_ADDRESSES=%d", prefix, num));
-               g_slist_free_full (addresses, (GDestroyNotify) nm_ip4_address_unref);
+               if (addresses->len)
+                       items = g_slist_prepend (items, g_strdup_printf ("%sIP4_NUM_ADDRESSES=%d", prefix, addresses->len));
+               g_ptr_array_unref (addresses);
+               g_variant_unref (val);
        }
 
        /* 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;
+       val = g_variant_lookup_value (ip4_config, "nameservers", G_VARIANT_TYPE ("au"));
+       if (val) {
+               dns = nm_utils_ip4_dns_from_variant (val);
 
+               if (dns[0]) {
                        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)
+                       for (i = 0; dns[i]; i++) {
+                               if (i != 0)
                                        g_string_append_c (tmp, ' ');
-                               g_string_append (tmp, nm_utils_inet4_ntop (addr, NULL));
-                               first = FALSE;
+                               g_string_append (tmp, dns[i]);
                        }
-                       items = g_slist_prepend (items, tmp->str);
-                       g_string_free (tmp, FALSE);
+
+                       items = g_slist_prepend (items, g_string_free (tmp, FALSE));
                }
+               g_strfreev (dns);
+               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;
+       val = g_variant_lookup_value (ip4_config, "wins-servers", G_VARIANT_TYPE ("au"));
+       if (val) {
+               wins = nm_utils_ip4_dns_from_variant (val);
 
+               if (wins[0]) {
                        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)
+                       for (i = 0; wins[i]; i++) {
+                               if (i != 0)
                                        g_string_append_c (tmp, ' ');
-                               g_string_append (tmp, nm_utils_inet4_ntop (addr, NULL));
-                               first = FALSE;
+                               g_string_append (tmp, wins[i]);
                        }
-                       items = g_slist_prepend (items, tmp->str);
-                       g_string_free (tmp, FALSE);
+
+                       items = g_slist_prepend (items, g_string_free (tmp, FALSE));
                }
+               g_strfreev (wins);
+               g_variant_unref (val);
        }
 
        /* Static routes */
-       val = g_hash_table_lookup (ip4_config, "routes");
+       val = g_variant_lookup_value (ip4_config, "routes", G_VARIANT_TYPE ("aau"));
        if (val) {
-               routes = nm_utils_ip4_routes_from_gvalue (val);
+               routes = nm_utils_ip4_routes_from_variant (val);
 
-               for (iter = routes, num = 0; iter; iter = g_slist_next (iter)) {
-                       NMIP4Route *route = (NMIP4Route *) iter->data;
+               for (i = 0; i < routes->len; i++) {
+                       NMIP4Route *route = routes->pdata[i];
                        guint32 ip_prefix = nm_ip4_route_get_prefix (route);
                        guint32 metric = nm_ip4_route_get_metric (route);
                        char *routetmp;
@@ -191,11 +185,12 @@ construct_ip4_items (GSList *items, GHashTable *ip4_config, const char *prefix)
                        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);
+                       routetmp = g_strdup_printf ("%sIP4_ROUTE_%d=%s/%d %s %d", prefix, i, 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));
-               g_slist_free_full (routes, (GDestroyNotify) nm_ip4_route_unref);
+               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));
 
@@ -203,20 +198,20 @@ construct_ip4_items (GSList *items, GHashTable *ip4_config, const char *prefix)
 }
 
 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);
        }
@@ -224,14 +219,15 @@ 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, *routes, *dns, *iter;
-       guint32 num;
+       GPtrArray *addresses, *routes;
+       char **dns;
        GString *tmp;
-       GValue *val;
+       GVariant *val;
        char str_addr[INET6_ADDRSTRLEN];
        char str_gw[INET6_ADDRSTRLEN];
+       int i;
 
        if (ip6_config == NULL)
                return items;
@@ -240,61 +236,58 @@ construct_ip6_items (GSList *items, GHashTable *ip6_config, const char *prefix)
                prefix = "";
 
        /* IP addresses */
-       val = g_hash_table_lookup (ip6_config, "addresses");
+       val = g_variant_lookup_value (ip6_config, "addresses", G_VARIANT_TYPE ("a(ayuay)"));
        if (val) {
-               addresses = nm_utils_ip6_addresses_from_gvalue (val);
+               addresses = nm_utils_ip6_addresses_from_variant (val);
 
-               for (iter = addresses, num = 0; iter; iter = g_slist_next (iter)) {
-                       NMIP6Address *addr = (NMIP6Address *) iter->data;
+               for (i = 0; i < addresses->len; i++) {
+                       NMIP6Address *addr = addresses->pdata[i];
                        guint32 ip_prefix = nm_ip6_address_get_prefix (addr);
                        char *addrtmp;
 
                        nm_utils_inet6_ntop (nm_ip6_address_get_address (addr), str_addr);
                        nm_utils_inet6_ntop (nm_ip6_address_get_gateway (addr), str_gw);
 
-                       addrtmp = g_strdup_printf ("%sIP6_ADDRESS_%d=%s/%d %s", prefix, num++, str_addr, ip_prefix, str_gw);
+                       addrtmp = g_strdup_printf ("%sIP6_ADDRESS_%d=%s/%d %s", prefix, i, str_addr, ip_prefix, str_gw);
                        items = g_slist_prepend (items, addrtmp);
                }
-               if (num)
-                       items = g_slist_prepend (items, g_strdup_printf ("%sIP6_NUM_ADDRESSES=%d", prefix, num));
-               g_slist_free_full (addresses, (GDestroyNotify) nm_ip6_address_unref);
+               if (addresses->len)
+                       items = g_slist_prepend (items, g_strdup_printf ("%sIP6_NUM_ADDRESSES=%d", prefix, addresses->len));
+               g_ptr_array_unref (addresses);
+               g_variant_unref (val);
        }
 
        /* DNS servers */
-       val = g_hash_table_lookup (ip6_config, "nameservers");
+       val = g_variant_lookup_value (ip6_config, "nameservers", G_VARIANT_TYPE ("aay"));
        if (val) {
-               dns = nm_utils_ip6_dns_from_gvalue (val);
-
-               if (g_slist_length (dns)) {
-                       gboolean first = TRUE;
+               dns = nm_utils_ip6_dns_from_variant (val);
 
+               if (dns[0]) {
                        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)
+                       for (i = 0; dns[i]; i++) {
+                               if (i != 0)
                                        g_string_append_c (tmp, ' ');
-                               g_string_append (tmp, nm_utils_inet6_ntop (addr, NULL));
-                               first = FALSE;
+                               g_string_append (tmp, dns[i]);
                        }
 
-                       items = g_slist_prepend (items, tmp->str);
-                       g_string_free (tmp, FALSE);
+                       items = g_slist_prepend (items, g_string_free (tmp, FALSE));
                }
+               g_strfreev (dns);
+               g_variant_unref (val);
        }
 
        /* Search domains */
        items = add_domains (items, ip6_config, prefix, '6');
 
        /* Static routes */
-       val = g_hash_table_lookup (ip6_config, "routes");
+       val = g_variant_lookup_value (ip6_config, "routes", G_VARIANT_TYPE ("a(ayuayu)"));
        if (val) {
-               routes = nm_utils_ip6_routes_from_gvalue (val);
+               routes = nm_utils_ip6_routes_from_variant (val);
 
-               for (iter = routes, num = 0; iter; iter = g_slist_next (iter)) {
-                       NMIP6Route *route = (NMIP6Route *) iter->data;
+               for (i = 0; i < routes->len; i++) {
+                       NMIP6Route *route = routes->pdata[i];
                        guint32 ip_prefix = nm_ip6_route_get_prefix (route);
                        guint32 metric = nm_ip6_route_get_metric (route);
                        char *routetmp;
@@ -302,32 +295,33 @@ construct_ip6_items (GSList *items, GHashTable *ip6_config, const char *prefix)
                        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);
+                       routetmp = g_strdup_printf ("%sIP6_ROUTE_%d=%s/%d %s %d", prefix, i, str_addr, ip_prefix, str_gw, metric);
                        items = g_slist_prepend (items, routetmp);
                }
-               if (num)
-                       items = g_slist_prepend (items, g_strdup_printf ("%sIP6_NUM_ROUTES=%d", prefix, num));
-               g_slist_free_full (routes, (GDestroyNotify) nm_ip6_route_unref);
+               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);
        }
 
        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);
        }
@@ -336,26 +330,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);
@@ -371,69 +365,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, G_VARIANT_TYPE ("a{sv}"));
+       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)) {
index d64dfce..665a0d4 100644 (file)
 
 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  /* __NETWORKMANAGER_DISPATCHER_UTILS_H__ */
index 733af51..a7a83d5 100644 (file)
 
 #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 +51,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 +69,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 +114,7 @@ typedef struct {
 struct Request {
        Handler *handler;
 
-       DBusGMethodInvocation *context;
+       GDBusMethodInvocation *context;
        char *action;
        char *iface;
        char **envp;
@@ -152,20 +155,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 +194,7 @@ next_request (Handler *h)
        }
 
        h->current_request = NULL;
-       quit_timeout_reschedule (h);
+       quit_timeout_reschedule ();
 }
 
 static gboolean
@@ -199,8 +202,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 +213,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)
@@ -470,22 +455,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 +482,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 +498,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 +533,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 +630,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 +663,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 ();
 
index 1ae138b..b2c4a21 100644 (file)
@@ -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.
index 05c2e8e..f3a80c6 100644 (file)
 #include "nm-connection.h"
 #include "nm-setting-connection.h"
 #include "nm-dispatcher-utils.h"
-#include "nm-dbus-glib-types.h"
 #include "nm-dispatcher-api.h"
 #include "nm-utils.h"
+#include "nm-dbus-glib-types.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)
+static GVariant *
+connection_hash_to_dict (GHashTable *hash)
 {
-       GValue *value;
+       GValue val = { 0, };
+       GVariant *dict;
 
-       value = g_slice_new0 (GValue);
-       g_value_init (value, G_TYPE_UINT);
-       g_value_set_uint (value, val);
+       g_value_init (&val, DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT);
+       g_value_set_boxed (&val, hash);
+       dict = dbus_g_value_build_g_variant (&val);
+       g_value_unset (&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);
+       g_variant_ref_sink (dict);
+       return dict;
 }
 
 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 +61,8 @@ parse_main (GKeyFile *kf,
        char *uuid, *id;
        NMConnection *connection;
        NMSettingConnection *s_con;
+       GVariantBuilder props;
+       GHashTable *con_hash;
 
        *out_expected_iface = g_key_file_get_string (kf, "main", "expected-iface", error);
        if (*out_expected_iface == NULL)
@@ -167,57 +93,74 @@ parse_main (GKeyFile *kf,
        g_free (id);
        nm_connection_add_setting (connection, NM_SETTING (s_con));
 
-       *out_con_hash = nm_connection_to_dbus (connection, NM_CONNECTION_SERIALIZE_ALL);
+       con_hash = nm_connection_to_dbus (connection, NM_CONNECTION_SERIALIZE_ALL);
        g_object_unref (connection);
+       *out_con_dict = connection_hash_to_dict (con_hash);
+       g_hash_table_unref (con_hash);
 
-       *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 +187,25 @@ 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;
 
-       *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 +220,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,7 +239,7 @@ 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_ip4_address_unref);
                for (iter = split; iter && *iter; iter++) {
                        NMIP4Address *addr;
                        guint32 a;
@@ -317,13 +265,12 @@ parse_ip4 (GKeyFile *kf, GHashTable **out_props, const char *section, GError **e
                        g_assert_cmpint (inet_pton (AF_INET, p, &a), ==, 1);
                        nm_ip4_address_set_gateway (addr, a);
 
-                       list = g_slist_append (list, addr);
+                       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));
+               g_ptr_array_unref (addresses);
        }
        g_strfreev (split);
 
@@ -335,7 +282,7 @@ 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_ip4_route_unref);
                        for (iter = split; iter && *iter; iter++) {
                                NMIP4Route *route;
                                guint32 a;
@@ -366,56 +313,58 @@ parse_ip4 (GKeyFile *kf, GHashTable **out_props, const char *section, GError **e
                                p++;
                                nm_ip4_route_set_metric (route, (guint) atoi (p));
 
-                               list = g_slist_append (list, route);
+                               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 +379,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,
@@ -482,16 +431,16 @@ out:
 static void
 test_generic (const char *path, 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;
@@ -504,7 +453,7 @@ test_generic (const char *path, const char *file, const char *override_vpn_ip_if
        /* Read in the test file */
        p = g_strdup_printf ("%s/%s", path, file);
        success = get_dispatcher_file (p,
-                                      &con_hash,
+                                      &con_dict,
                                       &con_props,
                                       &device_props,
                                       &device_ip4_props,
@@ -524,7 +473,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,21 +530,21 @@ 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);
 }