diff options
author | Dan Winship <danw@gnome.org> | 2014-09-18 11:50:23 -0400 |
---|---|---|
committer | Dan Winship <danw@gnome.org> | 2014-09-18 11:50:23 -0400 |
commit | 5f5a89b98ada1e23b6357aedaa6baef25afb1e0a (patch) | |
tree | f3fc35954477550c994063d330543142201b9b48 | |
parent | b99b632b473cf9d1058c472347d2714684e4f53d (diff) | |
parent | 8d26c45184cef91e0fc4b21378c25beaba682797 (diff) | |
download | NetworkManager-5f5a89b98ada1e23b6357aedaa6baef25afb1e0a.tar.gz |
Port callouts to gdbus (bgo #622927)
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | callouts/Makefile.am | 33 | ||||
-rw-r--r-- | callouts/nm-avahi-autoipd-action.c | 144 | ||||
-rw-r--r-- | callouts/nm-dispatcher-api.h | 4 | ||||
-rw-r--r-- | callouts/nm-dispatcher-utils.c | 384 | ||||
-rw-r--r-- | callouts/nm-dispatcher-utils.h | 18 | ||||
-rw-r--r-- | callouts/nm-dispatcher.c | 258 | ||||
-rw-r--r-- | callouts/nm-dispatcher.xml | 4 | ||||
-rw-r--r-- | callouts/tests/Makefile.am | 4 | ||||
-rw-r--r-- | callouts/tests/test-dispatcher-envp.c | 291 | ||||
-rw-r--r-- | libnm-core/nm-utils.c | 508 | ||||
-rw-r--r-- | libnm-core/nm-utils.h | 14 | ||||
-rw-r--r-- | libnm/libnm.ver | 12 |
13 files changed, 1053 insertions, 622 deletions
diff --git a/.gitignore b/.gitignore index 57325ccf51..c4790edc87 100644 --- a/.gitignore +++ b/.gitignore @@ -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 diff --git a/callouts/Makefile.am b/callouts/Makefile.am index 1d1eb3c764..d305554cc0 100644 --- a/callouts/Makefile.am +++ b/callouts/Makefile.am @@ -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 = \ diff --git a/callouts/nm-avahi-autoipd-action.c b/callouts/nm-avahi-autoipd-action.c index 02d5207b30..48969df1b9 100644 --- a/callouts/nm-avahi-autoipd-action.c +++ b/callouts/nm-avahi-autoipd-action.c @@ -15,87 +15,48 @@ * 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 <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_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 +65,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_INTERFACE, "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 bc156aa0f7..df1bced456 100644 --- a/callouts/nm-dispatcher-api.h +++ b/callouts/nm-dispatcher-api.h @@ -18,13 +18,11 @@ * 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)) diff --git a/callouts/nm-dispatcher-utils.c b/callouts/nm-dispatcher-utils.c index d48244f5a2..9a16880a57 100644 --- a/callouts/nm-dispatcher-utils.c +++ b/callouts/nm-dispatcher-utils.c @@ -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 = NULL, *routes = NULL, *iter; - GArray *dns = NULL, *wins = NULL; - 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,114 +106,112 @@ 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); + val = g_variant_lookup_value (ip4_config, "addresses", G_VARIANT_TYPE ("aau")); + if (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; - guint32 ip_prefix = nm_ip4_address_get_prefix (addr); - char *addrtmp; + 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); + 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); - items = g_slist_prepend (items, addrtmp); + 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 (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); } - 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; + 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; dns[i]; i++) { + if (i != 0) + g_string_append_c (tmp, ' '); + g_string_append (tmp, dns[i]); + } + + items = g_slist_prepend (items, g_string_free (tmp, FALSE)); } - items = g_slist_prepend (items, tmp->str); - 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; - - 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; + 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; wins[i]; i++) { + if (i != 0) + g_string_append_c (tmp, ' '); + g_string_append (tmp, wins[i]); + } + + items = g_slist_prepend (items, g_string_free (tmp, FALSE)); } - items = g_slist_prepend (items, tmp->str); - g_string_free (tmp, FALSE); + g_strfreev (wins); + g_variant_unref (val); } /* Static routes */ - val = g_hash_table_lookup (ip4_config, "routes"); - if (val) - routes = nm_utils_ip4_routes_from_gvalue (val); + val = g_variant_lookup_value (ip4_config, "routes", G_VARIANT_TYPE ("aau")); + if (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; - guint32 ip_prefix = nm_ip4_route_get_prefix (route); - guint32 metric = nm_ip4_route_get_metric (route); - char *routetmp; + 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; - 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); + 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); + 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, 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 +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 = NULL, *routes = NULL, *dns = NULL, *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; @@ -237,93 +236,92 @@ 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); + val = g_variant_lookup_value (ip6_config, "addresses", G_VARIANT_TYPE ("a(ayuay)")); + if (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; - guint32 ip_prefix = nm_ip6_address_get_prefix (addr); - char *addrtmp; + 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); + 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); - items = g_slist_prepend (items, addrtmp); + 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 (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); } - 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); + val = g_variant_lookup_value (ip6_config, "nameservers", G_VARIANT_TYPE ("aay")); + if (val) { + dns = nm_utils_ip6_dns_from_variant (val); - if (g_slist_length (dns)) { - gboolean first = TRUE; + if (dns[0]) { + tmp = g_string_new (NULL); + g_string_append_printf (tmp, "%sIP6_NAMESERVERS=", prefix); - tmp = g_string_new (NULL); - g_string_append_printf (tmp, "%sIP6_NAMESERVERS=", prefix); + for (i = 0; dns[i]; i++) { + if (i != 0) + g_string_append_c (tmp, ' '); + g_string_append (tmp, dns[i]); + } - 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, g_string_free (tmp, FALSE)); } - - items = g_slist_prepend (items, tmp->str); - 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"); - if (val) - routes = nm_utils_ip6_routes_from_gvalue (val); + val = g_variant_lookup_value (ip6_config, "routes", G_VARIANT_TYPE ("a(ayuayu)")); + if (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; - guint32 ip_prefix = nm_ip6_route_get_prefix (route); - guint32 metric = nm_ip6_route_get_metric (route); - char *routetmp; + 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; - 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); + 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); + 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 (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 +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); @@ -367,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)) { diff --git a/callouts/nm-dispatcher-utils.h b/callouts/nm-dispatcher-utils.h index d64dfce190..665a0d4eaf 100644 --- a/callouts/nm-dispatcher-utils.h +++ b/callouts/nm-dispatcher-utils.h @@ -25,16 +25,16 @@ 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__ */ diff --git a/callouts/nm-dispatcher.c b/callouts/nm-dispatcher.c index 733af511fb..a7a83d5aa5 100644 --- a/callouts/nm-dispatcher.c +++ b/callouts/nm-dispatcher.c @@ -32,17 +32,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 +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 (); diff --git a/callouts/nm-dispatcher.xml b/callouts/nm-dispatcher.xml index 1ae138b35b..b2c4a21aec 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 c06178b225..db73ef9372 100644 --- a/callouts/tests/Makefile.am +++ b/callouts/tests/Makefile.am @@ -7,6 +7,7 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/callouts \ -DNETWORKMANAGER_COMPILATION \ -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ + -DSRCDIR=\"$(abs_srcdir)\" \ $(GLIB_CFLAGS) \ $(DBUS_CFLAGS) @@ -26,8 +27,7 @@ test_dispatcher_envp_LDADD = \ ########################################### -check-local: test-dispatcher-envp - $(abs_builddir)/test-dispatcher-envp $(abs_srcdir) +TESTS = test-dispatcher-envp EXTRA_DIST= \ dispatcher-old-down \ diff --git a/callouts/tests/test-dispatcher-envp.c b/callouts/tests/test-dispatcher-envp.c index 05c2e8ed9c..b51c1c16a5 100644 --- a/callouts/tests/test-dispatcher-envp.c +++ b/callouts/tests/test-dispatcher-envp.c @@ -28,107 +28,31 @@ #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) +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_STRING); - g_value_set_string (value, str); + 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_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); + 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, @@ -480,18 +429,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 +451,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 +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,57 +530,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 +588,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 (); } diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c index d386440606..2a0497c342 100644 --- a/libnm-core/nm-utils.c +++ b/libnm-core/nm-utils.c @@ -1432,6 +1432,232 @@ nm_utils_ip4_routes_to_gvalue (GSList *list, GValue *value) } /** + * nm_utils_ip4_dns_to_variant: + * @dns: (type utf8): an array of IP address strings + * + * Utility function to convert an array of IP address strings int a #GVariant of + * type 'au' representing an array of IPv4 addresses. + * + * Returns: (transfer none): a new floating #GVariant representing @dns. + **/ +GVariant * +nm_utils_ip4_dns_to_variant (char **dns) +{ + GVariantBuilder builder; + int i; + + g_variant_builder_init (&builder, G_VARIANT_TYPE ("au")); + + if (dns) { + for (i = 0; dns[i]; i++) { + guint32 ip = 0; + + inet_pton (AF_INET, dns[i], &ip); + g_variant_builder_add (&builder, "u", ip); + } + } + + return g_variant_builder_end (&builder); +} + +/** + * nm_utils_ip4_dns_from_variant: + * @value: a #GVariant of type 'au' + * + * Utility function to convert a #GVariant of type 'au' representing a list of + * IPv4 addresses into an array of IP address strings. + * + * Returns: (transfer full) (type utf8): a %NULL-terminated array of IP address strings. + **/ +char ** +nm_utils_ip4_dns_from_variant (GVariant *value) +{ + const guint32 *array; + gsize length; + char **dns; + int i; + + g_return_val_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE ("au")), NULL); + + array = g_variant_get_fixed_array (value, &length, sizeof (guint32)); + dns = g_new (char *, length + 1); + + for (i = 0; i < length; i++) + dns[i] = g_strdup (nm_utils_inet4_ntop (array[i], NULL)); + dns[i] = NULL; + + return dns; +} + +/** + * nm_utils_ip4_addresses_to_variant: + * @addresses: (element-type NMIP4Address): an array of #NMIP4Address objects + * + * Utility function to convert a #GPtrArray of #NMIP4Address objects into a + * #GVariant of type 'aau' representing an array of NetworkManager IPv4 + * addresses (which are tuples of address, prefix, and gateway). + * + * Returns: (transfer none): a new floating #GVariant representing @addresses. + **/ +GVariant * +nm_utils_ip4_addresses_to_variant (GPtrArray *addresses) +{ + GVariantBuilder builder; + int i; + + g_variant_builder_init (&builder, G_VARIANT_TYPE ("aau")); + + if (addresses) { + for (i = 0; i < addresses->len; i++) { + NMIP4Address *addr = addresses->pdata[i]; + guint32 array[3]; + + array[0] = nm_ip4_address_get_address (addr); + array[1] = nm_ip4_address_get_prefix (addr); + array[2] = nm_ip4_address_get_gateway (addr); + + g_variant_builder_add (&builder, "@au", + g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32, + array, 3, sizeof (guint32))); + } + } + + return g_variant_builder_end (&builder); +} + +/** + * nm_utils_ip4_addresses_from_variant: + * @value: a #GVariant of type 'aau' + * + * Utility function to convert a #GVariant of type 'aau' representing a list of + * NetworkManager IPv4 addresses (which are tuples of address, prefix, and + * gateway) into a #GPtrArray of #NMIP4Address objects. + * + * Returns: (transfer full) (element-type NMIP4Address): a newly allocated + * #GPtrArray of #NMIP4Address objects + **/ +GPtrArray * +nm_utils_ip4_addresses_from_variant (GVariant *value) +{ + GPtrArray *addresses; + GVariantIter iter; + GVariant *addr_var; + + g_return_val_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE ("aau")), NULL); + + g_variant_iter_init (&iter, value); + addresses = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip4_address_unref); + + while (g_variant_iter_next (&iter, "@au", &addr_var)) { + const guint32 *addr_array; + gsize length; + NMIP4Address *addr; + + addr_array = g_variant_get_fixed_array (addr_var, &length, sizeof (guint32)); + if (length < 3) { + g_warning ("Ignoring invalid IP4 address"); + g_variant_unref (addr_var); + continue; + } + + addr = nm_ip4_address_new (); + nm_ip4_address_set_address (addr, addr_array[0]); + nm_ip4_address_set_prefix (addr, addr_array[1]); + nm_ip4_address_set_gateway (addr, addr_array[2]); + + g_ptr_array_add (addresses, addr); + g_variant_unref (addr_var); + } + + return addresses; +} + +/** + * nm_utils_ip4_routes_to_variant: + * @routes: (element-type NMIP4Route): an array of #NMIP4Route objects + * + * Utility function to convert a #GPtrArray of #NMIP4Route objects into a + * #GVariant of type 'aau' representing an array of NetworkManager IPv4 routes + * (which are tuples of route, prefix, next hop, and metric). + * + * Returns: (transfer none): a new floating #GVariant representing @routes. + **/ +GVariant * +nm_utils_ip4_routes_to_variant (GPtrArray *routes) +{ + GVariantBuilder builder; + int i; + + g_variant_builder_init (&builder, G_VARIANT_TYPE ("aau")); + + if (routes) { + for (i = 0; i < routes->len; i++) { + NMIP4Route *route = routes->pdata[i]; + guint32 array[4]; + + array[0] = nm_ip4_route_get_dest (route); + array[1] = nm_ip4_route_get_prefix (route); + array[2] = nm_ip4_route_get_next_hop (route); + array[3] = nm_ip4_route_get_metric (route); + + g_variant_builder_add (&builder, "@au", + g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32, + array, 4, sizeof (guint32))); + } + } + + return g_variant_builder_end (&builder); +} + +/** + * nm_utils_ip4_routes_from_variant: + * @value: #GVariant of type 'aau' + * + * Utility function to convert a #GVariant of type 'aau' representing an array + * of NetworkManager IPv4 routes (which are tuples of route, prefix, next hop, + * and metric) into a #GPtrArray of #NMIP4Route objects. + * + * Returns: (transfer full) (element-type NMIP4Route): a newly allocated + * #GPtrArray of #NMIP4Route objects + **/ +GPtrArray * +nm_utils_ip4_routes_from_variant (GVariant *value) +{ + GVariantIter iter; + GVariant *route_var; + GPtrArray *routes; + + g_return_val_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE ("aau")), NULL); + + g_variant_iter_init (&iter, value); + routes = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip4_route_unref); + + while (g_variant_iter_next (&iter, "@au", &route_var)) { + const guint32 *route_array; + gsize length; + NMIP4Route *route; + + route_array = g_variant_get_fixed_array (route_var, &length, sizeof (guint32)); + if (length < 4) { + g_warning ("Ignoring invalid IP4 route"); + g_variant_unref (route_var); + continue; + } + + route = nm_ip4_route_new (); + nm_ip4_route_set_dest (route, route_array[0]); + nm_ip4_route_set_prefix (route, route_array[1]); + nm_ip4_route_set_next_hop (route, route_array[2]); + nm_ip4_route_set_metric (route, route_array[3]); + + g_ptr_array_add (routes, route); + g_variant_unref (route_var); + } + + return routes; +} + +/** * nm_utils_ip4_netmask_to_prefix: * @netmask: an IPv4 netmask in network byte order * @@ -2117,6 +2343,288 @@ nm_utils_ip6_dns_to_gvalue (GSList *list, GValue *value) } /** + * nm_utils_ip6_dns_to_variant: + * @dns: (type utf8): an array of IP address strings + * + * Utility function to convert an array of IP address strings int a #GVariant of + * type 'aay' representing an array of IPv6 addresses. + * + * Returns: (transfer none): a new floating #GVariant representing @dns. + **/ +GVariant * +nm_utils_ip6_dns_to_variant (char **dns) +{ + GVariantBuilder builder; + int i; + + g_variant_builder_init (&builder, G_VARIANT_TYPE ("aay")); + + if (dns) { + for (i = 0; dns[i]; i++) { + struct in6_addr ip; + + inet_pton (AF_INET6, dns[i], &ip); + g_variant_builder_add (&builder, "@ay", + g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, + &ip, sizeof (ip), 1)); + } + } + + return g_variant_builder_end (&builder); +} + +/** + * nm_utils_ip6_dns_from_variant: + * @value: a #GVariant of type 'aay' + * + * Utility function to convert a #GVariant of type 'aay' representing a list of + * IPv6 addresses into an array of IP address strings. + * + * Returns: (transfer full) (type utf8): a %NULL-terminated array of IP address strings. + **/ +char ** +nm_utils_ip6_dns_from_variant (GVariant *value) +{ + GVariantIter iter; + GVariant *ip_var; + char **dns; + int i; + + g_return_val_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE ("aay")), NULL); + + dns = g_new (char *, g_variant_n_children (value) + 1); + + g_variant_iter_init (&iter, value); + i = 0; + while (g_variant_iter_next (&iter, "@ay", &ip_var)) { + gsize length; + const struct in6_addr *ip = g_variant_get_fixed_array (ip_var, &length, 1); + + if (length != sizeof (struct in6_addr)) { + g_warning ("%s: ignoring invalid IP6 address of length %d", + __func__, (int) length); + g_variant_unref (ip_var); + continue; + } + + dns[i++] = g_strdup (nm_utils_inet6_ntop (ip, NULL)); + g_variant_unref (ip_var); + } + dns[i] = NULL; + + return dns; +} + +/** + * nm_utils_ip6_addresses_to_variant: + * @addresses: (element-type NMIP6Address): an array of #NMIP6Address objects + * + * Utility function to convert a #GPtrArray of #NMIP6Address objects into a + * #GVariant of type 'a(ayuay)' representing an array of NetworkManager IPv6 + * addresses (which are tuples of address, prefix, and gateway). + * + * Returns: (transfer none): a new floating #GVariant representing @addresses. + **/ +GVariant * +nm_utils_ip6_addresses_to_variant (GPtrArray *addresses) +{ + GVariantBuilder builder; + int i; + + g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(ayuay)")); + + if (addresses) { + for (i = 0; i < addresses->len; i++) { + NMIP6Address *addr = addresses->pdata[i]; + GVariant *ip, *gateway; + guint32 prefix; + + ip = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, + nm_ip6_address_get_address (addr), + 16, 1); + prefix = nm_ip6_address_get_prefix (addr); + gateway = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, + nm_ip6_address_get_gateway (addr), + 16, 1); + + g_variant_builder_add (&builder, "(@ayu@ay)", ip, prefix, gateway); + } + } + + return g_variant_builder_end (&builder); +} + +/** + * nm_utils_ip6_addresses_from_variant: + * @value: a #GVariant of type 'a(ayuay)' + * + * Utility function to convert a #GVariant of type 'a(ayuay)' representing a + * list of NetworkManager IPv6 addresses (which are tuples of address, prefix, + * and gateway) into a #GPtrArray of #NMIP6Address objects. + * + * Returns: (transfer full) (element-type NMIP6Address): a newly allocated + * #GPtrArray of #NMIP6Address objects + **/ +GPtrArray * +nm_utils_ip6_addresses_from_variant (GVariant *value) +{ + GVariantIter iter; + GVariant *addr_var, *gateway_var; + guint32 prefix; + GPtrArray *addresses; + + g_return_val_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE ("a(ayuay)")), NULL); + + g_variant_iter_init (&iter, value); + addresses = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip6_address_unref); + + while (g_variant_iter_next (&iter, "(@ayu@ay)", &addr_var, &prefix, &gateway_var)) { + NMIP6Address *addr; + const struct in6_addr *addr_bytes, *gateway_bytes; + gsize addr_len, gateway_len; + + if ( !g_variant_is_of_type (addr_var, G_VARIANT_TYPE_BYTESTRING) + || !g_variant_is_of_type (gateway_var, G_VARIANT_TYPE_BYTESTRING)) { + g_warning ("%s: ignoring invalid IP6 address structure", __func__); + goto next; + } + + addr_bytes = g_variant_get_fixed_array (addr_var, &addr_len, 1); + if (addr_len != 16) { + g_warning ("%s: ignoring invalid IP6 address of length %d", + __func__, (int) addr_len); + goto next; + } + if (prefix > 128) { + g_warning ("%s: ignoring invalid IP6 prefix %d", + __func__, prefix); + goto next; + } + gateway_bytes = g_variant_get_fixed_array (gateway_var, &gateway_len, 1); + if (gateway_len != 16) { + g_warning ("%s: ignoring invalid IP6 address of length %d", + __func__, (int) gateway_len); + goto next; + } + + addr = nm_ip6_address_new (); + nm_ip6_address_set_address (addr, addr_bytes); + nm_ip6_address_set_prefix (addr, prefix); + nm_ip6_address_set_gateway (addr, gateway_bytes); + g_ptr_array_add (addresses, addr); + + next: + g_variant_unref (addr_var); + g_variant_unref (gateway_var); + } + + return addresses; +} + +/** + * nm_utils_ip6_routes_to_variant: + * @routes: (element-type NMIP6Route): an array of #NMIP6Route objects + * + * Utility function to convert a #GPtrArray of #NMIP6Route objects into a + * #GVariant of type 'a(ayuayu)' representing an array of NetworkManager IPv6 + * routes (which are tuples of route, prefix, next hop, and metric). + * + * Returns: (transfer none): a new floating #GVariant representing @routes. + **/ +GVariant * +nm_utils_ip6_routes_to_variant (GPtrArray *routes) +{ + GVariantBuilder builder; + int i; + + g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(ayuayu)")); + + if (routes) { + for (i = 0; i < routes->len; i++) { + NMIP6Route *route = routes->pdata[i]; + GVariant *dest, *next_hop; + guint32 prefix, metric; + + dest = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, + nm_ip6_route_get_dest (route), + 16, 1); + prefix = nm_ip6_route_get_prefix (route); + next_hop = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, + nm_ip6_route_get_next_hop (route), + 16, 1); + metric = nm_ip6_route_get_metric (route); + + g_variant_builder_add (&builder, "(@ayu@ayu)", dest, prefix, next_hop, metric); + } + } + + return g_variant_builder_end (&builder); +} + +/** + * nm_utils_ip6_routes_from_variant: + * @value: #GVariant of type 'a(ayuayu)' + * + * Utility function to convert a #GVariant of type 'a(ayuayu)' representing an + * array of NetworkManager IPv6 routes (which are tuples of route, prefix, next + * hop, and metric) into a #GPtrArray of #NMIP6Route objects. + * + * Returns: (transfer full) (element-type NMIP6Route): a newly allocated + * #GPtrArray of #NMIP6Route objects + **/ +GPtrArray * +nm_utils_ip6_routes_from_variant (GVariant *value) +{ + GPtrArray *routes; + GVariantIter iter; + GVariant *dest_var, *next_hop_var; + const struct in6_addr *dest, *next_hop; + gsize dest_len, next_hop_len; + guint32 prefix, metric; + + g_return_val_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE ("a(ayuayu)")), NULL); + + routes = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip6_route_unref); + + g_variant_iter_init (&iter, value); + while (g_variant_iter_next (&iter, "(@ayu@ayu)", &dest_var, &prefix, &next_hop_var, &metric)) { + NMIP6Route *route; + + if ( !g_variant_is_of_type (dest_var, G_VARIANT_TYPE_BYTESTRING) + || !g_variant_is_of_type (next_hop_var, G_VARIANT_TYPE_BYTESTRING)) { + g_warning ("%s: ignoring invalid IP6 address structure", __func__); + goto next; + } + + dest = g_variant_get_fixed_array (dest_var, &dest_len, 1); + if (dest_len != 16) { + g_warning ("%s: ignoring invalid IP6 address of length %d", + __func__, (int) dest_len); + goto next; + } + next_hop = g_variant_get_fixed_array (next_hop_var, &next_hop_len, 1); + if (next_hop_len != 16) { + g_warning ("%s: ignoring invalid IP6 address of length %d", + __func__, (int) next_hop_len); + goto next; + } + + route = nm_ip6_route_new (); + nm_ip6_route_set_dest (route, dest); + nm_ip6_route_set_prefix (route, prefix); + nm_ip6_route_set_next_hop (route, next_hop); + nm_ip6_route_set_metric (route, metric); + g_ptr_array_add (routes, route); + + next: + g_variant_unref (dest_var); + g_variant_unref (next_hop_var); + } + + return routes; +} + +/** * nm_utils_uuid_generate: * * Returns: a newly allocated UUID suitable for use as the #NMSettingConnection diff --git a/libnm-core/nm-utils.h b/libnm-core/nm-utils.h index b6b9db583b..5c11112357 100644 --- a/libnm-core/nm-utils.h +++ b/libnm-core/nm-utils.h @@ -101,6 +101,13 @@ void nm_utils_ip4_addresses_to_gvalue (GSList *list, GValue *value); GSList *nm_utils_ip4_routes_from_gvalue (const GValue *value); void nm_utils_ip4_routes_to_gvalue (GSList *list, GValue *value); +GVariant *nm_utils_ip4_dns_to_variant (char **dns); +char **nm_utils_ip4_dns_from_variant (GVariant *value); +GVariant *nm_utils_ip4_addresses_to_variant (GPtrArray *addresses); +GPtrArray *nm_utils_ip4_addresses_from_variant (GVariant *value); +GVariant *nm_utils_ip4_routes_to_variant (GPtrArray *routes); +GPtrArray *nm_utils_ip4_routes_from_variant (GVariant *value); + guint32 nm_utils_ip4_netmask_to_prefix (guint32 netmask); guint32 nm_utils_ip4_prefix_to_netmask (guint32 prefix); guint32 nm_utils_ip4_get_default_prefix (guint32 ip); @@ -114,6 +121,13 @@ void nm_utils_ip6_routes_to_gvalue (GSList *list, GValue *value); GSList *nm_utils_ip6_dns_from_gvalue (const GValue *value); void nm_utils_ip6_dns_to_gvalue (GSList *list, GValue *value); +GVariant *nm_utils_ip6_dns_to_variant (char **dns); +char **nm_utils_ip6_dns_from_variant (GVariant *value); +GVariant *nm_utils_ip6_addresses_to_variant (GPtrArray *addresses); +GPtrArray *nm_utils_ip6_addresses_from_variant (GVariant *value); +GVariant *nm_utils_ip6_routes_to_variant (GPtrArray *routes); +GPtrArray *nm_utils_ip6_routes_from_variant (GVariant *value); + char *nm_utils_uuid_generate (void); char *nm_utils_uuid_generate_from_string (const char *s); diff --git a/libnm/libnm.ver b/libnm/libnm.ver index e0592f548f..d48731c474 100644 --- a/libnm/libnm.ver +++ b/libnm/libnm.ver @@ -880,18 +880,30 @@ global: nm_utils_inet6_ntop; nm_utils_init; nm_utils_ip4_addresses_from_gvalue; + nm_utils_ip4_addresses_from_variant; nm_utils_ip4_addresses_to_gvalue; + nm_utils_ip4_addresses_to_variant; + nm_utils_ip4_dns_from_variant; + nm_utils_ip4_dns_to_variant; nm_utils_ip4_get_default_prefix; nm_utils_ip4_netmask_to_prefix; nm_utils_ip4_prefix_to_netmask; nm_utils_ip4_routes_from_gvalue; + nm_utils_ip4_routes_from_variant; nm_utils_ip4_routes_to_gvalue; + nm_utils_ip4_routes_to_variant; nm_utils_ip6_addresses_from_gvalue; + nm_utils_ip6_addresses_from_variant; nm_utils_ip6_addresses_to_gvalue; + nm_utils_ip6_addresses_to_variant; nm_utils_ip6_dns_from_gvalue; + nm_utils_ip6_dns_from_variant; nm_utils_ip6_dns_to_gvalue; + nm_utils_ip6_dns_to_variant; nm_utils_ip6_routes_from_gvalue; + nm_utils_ip6_routes_from_variant; nm_utils_ip6_routes_to_gvalue; + nm_utils_ip6_routes_to_variant; nm_utils_is_empty_ssid; nm_utils_is_uuid; nm_utils_rsa_key_encrypt; |