diff options
Diffstat (limited to 'src/nm-dispatcher.c')
| -rw-r--r-- | src/nm-dispatcher.c | 571 |
1 files changed, 320 insertions, 251 deletions
diff --git a/src/nm-dispatcher.c b/src/nm-dispatcher.c index 78aa204e..dad48520 100644 --- a/src/nm-dispatcher.c +++ b/src/nm-dispatcher.c @@ -21,26 +21,26 @@ #include "config.h" -#include <glib.h> -#include <gio/gio.h> #include <string.h> #include <errno.h> +#include "nm-default.h" #include "nm-dispatcher.h" #include "nm-dispatcher-api.h" #include "NetworkManagerUtils.h" #include "nm-utils.h" -#include "nm-logging.h" -#include "nm-dbus-manager.h" #include "nm-device.h" #include "nm-dhcp4-config.h" #include "nm-dhcp6-config.h" -#include "nm-dbus-glib-types.h" -#include "nm-glib-compat.h" +#include "nm-ip4-config.h" +#include "nm-ip6-config.h" #include "nm-settings-connection.h" +#include "nm-platform.h" +#include "nm-core-internal.h" #define CALL_TIMEOUT (1000 * 60 * 10) /* 10 minutes for all scripts */ +static GDBusProxy *dispatcher_proxy; static GHashTable *requests = NULL; typedef struct { @@ -80,61 +80,150 @@ _get_monitor_by_action (DispatcherAction action) } static void -dump_object_to_props (GObject *object, GHashTable *hash) +dump_ip4_to_props (NMIP4Config *ip4, GVariantBuilder *builder) { - GParamSpec **pspecs; - guint len = 0, i; - - pspecs = g_object_class_list_properties (G_OBJECT_GET_CLASS (object), &len); - for (i = 0; i < len; i++) { - value_hash_add_object_property (hash, - pspecs[i]->name, - object, - pspecs[i]->name, - pspecs[i]->value_type); + GVariantBuilder int_builder; + guint n, i; + const NMPlatformIP4Address *addr; + const NMPlatformIP4Route *route; + guint32 array[4]; + + /* Addresses */ + g_variant_builder_init (&int_builder, G_VARIANT_TYPE ("aau")); + n = nm_ip4_config_get_num_addresses (ip4); + for (i = 0; i < n; i++) { + addr = nm_ip4_config_get_address (ip4, i); + array[0] = addr->address; + array[1] = addr->plen; + array[2] = (i == 0) ? nm_ip4_config_get_gateway (ip4) : 0; + g_variant_builder_add (&int_builder, "@au", + g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32, + array, 3, sizeof (guint32))); } - g_free (pspecs); -} - -static void -dump_dhcp4_to_props (NMDhcp4Config *config, GHashTable *hash) -{ - GSList *options, *iter; - - options = nm_dhcp4_config_list_options (config); - for (iter = options; iter; iter = g_slist_next (iter)) { - const char *option = (const char *) iter->data; - const char *val; - - val = nm_dhcp4_config_get_option (config, option); - value_hash_add_str (hash, option, val); + g_variant_builder_add (builder, "{sv}", + "addresses", + g_variant_builder_end (&int_builder)); + + /* DNS servers */ + g_variant_builder_init (&int_builder, G_VARIANT_TYPE ("au")); + n = nm_ip4_config_get_num_nameservers (ip4); + for (i = 0; i < n; i++) + g_variant_builder_add (&int_builder, "u", nm_ip4_config_get_nameserver (ip4, i)); + g_variant_builder_add (builder, "{sv}", + "nameservers", + g_variant_builder_end (&int_builder)); + + /* Search domains */ + g_variant_builder_init (&int_builder, G_VARIANT_TYPE ("as")); + n = nm_ip4_config_get_num_domains (ip4); + for (i = 0; i < n; i++) + g_variant_builder_add (&int_builder, "s", nm_ip4_config_get_domain (ip4, i)); + g_variant_builder_add (builder, "{sv}", + "domains", + g_variant_builder_end (&int_builder)); + + /* WINS servers */ + g_variant_builder_init (&int_builder, G_VARIANT_TYPE ("au")); + n = nm_ip4_config_get_num_wins (ip4); + for (i = 0; i < n; i++) + g_variant_builder_add (&int_builder, "u", nm_ip4_config_get_wins (ip4, i)); + g_variant_builder_add (builder, "{sv}", + "wins-servers", + g_variant_builder_end (&int_builder)); + + /* Static routes */ + g_variant_builder_init (&int_builder, G_VARIANT_TYPE ("aau")); + n = nm_ip4_config_get_num_routes (ip4); + for (i = 0; i < n; i++) { + route = nm_ip4_config_get_route (ip4, i); + array[0] = route->network; + array[1] = route->plen; + array[2] = route->gateway; + array[3] = route->metric; + g_variant_builder_add (&int_builder, "@au", + g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32, + array, 4, sizeof (guint32))); } - g_slist_free (options); + g_variant_builder_add (builder, "{sv}", + "routes", + g_variant_builder_end (&int_builder)); } static void -dump_dhcp6_to_props (NMDhcp6Config *config, GHashTable *hash) +dump_ip6_to_props (NMIP6Config *ip6, GVariantBuilder *builder) { - GSList *options, *iter; - - options = nm_dhcp6_config_list_options (config); - for (iter = options; iter; iter = g_slist_next (iter)) { - const char *option = (const char *) iter->data; - const char *val; - - val = nm_dhcp6_config_get_option (config, option); - value_hash_add_str (hash, option, val); + GVariantBuilder int_builder; + guint n, i; + const NMPlatformIP6Address *addr; + const struct in6_addr *gw_bytes; + const NMPlatformIP6Route *route; + GVariant *ip, *gw; + + /* Addresses */ + g_variant_builder_init (&int_builder, G_VARIANT_TYPE ("a(ayuay)")); + n = nm_ip6_config_get_num_addresses (ip6); + for (i = 0; i < n; i++) { + addr = nm_ip6_config_get_address (ip6, i); + gw_bytes = nm_ip6_config_get_gateway (ip6); + ip = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, + &addr->address, + sizeof (struct in6_addr), 1); + gw = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, + (i == 0 && gw_bytes) ? gw_bytes : &in6addr_any, + sizeof (struct in6_addr), 1); + g_variant_builder_add (&int_builder, "(@ayu@ay)", ip, addr->plen, gw); + } + g_variant_builder_add (builder, "{sv}", + "addresses", + g_variant_builder_end (&int_builder)); + + /* DNS servers */ + g_variant_builder_init (&int_builder, G_VARIANT_TYPE ("aay")); + n = nm_ip6_config_get_num_nameservers (ip6); + for (i = 0; i < n; i++) { + ip = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, + nm_ip6_config_get_nameserver (ip6, i), + sizeof (struct in6_addr), 1); + g_variant_builder_add (&int_builder, "@ay", ip); } - g_slist_free (options); + g_variant_builder_add (builder, "{sv}", + "nameservers", + g_variant_builder_end (&int_builder)); + + /* Search domains */ + g_variant_builder_init (&int_builder, G_VARIANT_TYPE ("as")); + n = nm_ip6_config_get_num_domains (ip6); + for (i = 0; i < n; i++) + g_variant_builder_add (&int_builder, "s", nm_ip6_config_get_domain (ip6, i)); + g_variant_builder_add (builder, "{sv}", + "domains", + g_variant_builder_end (&int_builder)); + + /* Static routes */ + g_variant_builder_init (&int_builder, G_VARIANT_TYPE ("a(ayuayu)")); + n = nm_ip6_config_get_num_routes (ip6); + for (i = 0; i < n; i++) { + route = nm_ip6_config_get_route (ip6, i); + ip = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, + &route->network, + sizeof (struct in6_addr), 1); + gw = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, + &route->gateway, + sizeof (struct in6_addr), 1); + g_variant_builder_add (&int_builder, "(@ayu@ayu)", ip, route->plen, gw, route->metric); + } + g_variant_builder_add (builder, "{sv}", + "routes", + g_variant_builder_end (&int_builder)); } static void fill_device_props (NMDevice *device, - GHashTable *dev_hash, - GHashTable *ip4_hash, - GHashTable *ip6_hash, - GHashTable *dhcp4_hash, - GHashTable *dhcp6_hash) + GVariantBuilder *dev_builder, + GVariantBuilder *ip4_builder, + GVariantBuilder *ip6_builder, + GVariant **dhcp4_props, + GVariant **dhcp6_props) { NMIP4Config *ip4_config; NMIP6Config *ip6_config; @@ -142,39 +231,45 @@ fill_device_props (NMDevice *device, NMDhcp6Config *dhcp6_config; /* If the action is for a VPN, send the VPN's IP interface instead of the device's */ - value_hash_add_str (dev_hash, NMD_DEVICE_PROPS_IP_INTERFACE, nm_device_get_ip_iface (device)); - value_hash_add_str (dev_hash, NMD_DEVICE_PROPS_INTERFACE, nm_device_get_iface (device)); - value_hash_add_uint (dev_hash, NMD_DEVICE_PROPS_TYPE, nm_device_get_device_type (device)); - value_hash_add_uint (dev_hash, NMD_DEVICE_PROPS_STATE, nm_device_get_state (device)); - value_hash_add_object_path (dev_hash, NMD_DEVICE_PROPS_PATH, nm_device_get_path (device)); + g_variant_builder_add (dev_builder, "{sv}", NMD_DEVICE_PROPS_IP_INTERFACE, + g_variant_new_string (nm_device_get_ip_iface (device))); + g_variant_builder_add (dev_builder, "{sv}", NMD_DEVICE_PROPS_INTERFACE, + g_variant_new_string (nm_device_get_iface (device))); + g_variant_builder_add (dev_builder, "{sv}", NMD_DEVICE_PROPS_TYPE, + g_variant_new_uint32 (nm_device_get_device_type (device))); + g_variant_builder_add (dev_builder, "{sv}", NMD_DEVICE_PROPS_STATE, + g_variant_new_uint32 (nm_device_get_state (device))); + if (nm_exported_object_is_exported (NM_EXPORTED_OBJECT (device))) + g_variant_builder_add (dev_builder, "{sv}", NMD_DEVICE_PROPS_PATH, + g_variant_new_object_path (nm_exported_object_get_path (NM_EXPORTED_OBJECT (device)))); ip4_config = nm_device_get_ip4_config (device); if (ip4_config) - dump_object_to_props (G_OBJECT (ip4_config), ip4_hash); + dump_ip4_to_props (ip4_config, ip4_builder); ip6_config = nm_device_get_ip6_config (device); if (ip6_config) - dump_object_to_props (G_OBJECT (ip6_config), ip6_hash); + dump_ip6_to_props (ip6_config, ip6_builder); dhcp4_config = nm_device_get_dhcp4_config (device); if (dhcp4_config) - dump_dhcp4_to_props (dhcp4_config, dhcp4_hash); + *dhcp4_props = nm_dhcp4_config_get_options (dhcp4_config); dhcp6_config = nm_device_get_dhcp6_config (device); if (dhcp6_config) - dump_dhcp6_to_props (dhcp6_config, dhcp6_hash); + *dhcp6_props = nm_dhcp6_config_get_options (dhcp6_config); } static void fill_vpn_props (NMIP4Config *ip4_config, NMIP6Config *ip6_config, - GHashTable *ip4_hash, - GHashTable *ip6_hash) + GVariantBuilder *ip4_builder, + GVariantBuilder *ip6_builder) { if (ip4_config) - dump_object_to_props (G_OBJECT (ip4_config), ip4_hash); + dump_ip4_to_props (ip4_config, ip4_builder); if (ip6_config) - dump_object_to_props (G_OBJECT (ip6_config), ip6_hash); + dump_ip6_to_props (ip6_config, ip6_builder); } typedef struct { @@ -228,51 +323,25 @@ dispatch_result_to_string (DispatchResult result) g_assert_not_reached (); } -static gboolean -validate_element (guint request_id, GValue *val, GType expected_type, guint idx, guint eltnum) -{ - if (G_VALUE_TYPE (val) != expected_type) { - nm_log_dbg (LOGD_DISPATCH, "(%u) result %d element %d invalid type %s", - request_id, idx, eltnum, G_VALUE_TYPE_NAME (val)); - return FALSE; - } - return TRUE; -} - static void -dispatcher_results_process (guint request_id, DispatcherAction action, GPtrArray *results) +dispatcher_results_process (guint request_id, DispatcherAction action, GVariantIter *results) { - guint i; + const char *script, *err; + guint32 result; const Monitor *monitor = _get_monitor_by_action (action); g_return_if_fail (results != NULL); - if (results->len == 0) { + if (g_variant_iter_n_children (results) == 0) { nm_log_dbg (LOGD_DISPATCH, "(%u) succeeded but no scripts invoked", request_id); return; } - for (i = 0; i < results->len; i++) { - GValueArray *item = g_ptr_array_index (results, i); - GValue *tmp; - const char *script, *err; - DispatchResult result; + while (g_variant_iter_next (results, "(&su&s)", &script, &result, &err)) { const char *script_validation_msg = ""; - if (item->n_values != 3) { - nm_log_dbg (LOGD_DISPATCH, "(%u) unexpected number of items in " - "dispatcher result (got %d, expected 3)", - request_id, item->n_values); - continue; - } - - /* Script */ - tmp = g_value_array_get_nth (item, 0); - if (!validate_element (request_id, tmp, G_TYPE_STRING, i, 0)) - continue; - script = g_value_get_string (tmp); - if (!script) { + if (!*script) { script_validation_msg = " (path is NULL)"; script = "(unknown)"; } else if (!strncmp (script, monitor->dir, monitor->dir_len) /* check: prefixed by script directory */ @@ -284,20 +353,6 @@ dispatcher_results_process (guint request_id, DispatcherAction action, GPtrArray } else script_validation_msg = " (unexpected path)"; - - /* Result */ - tmp = g_value_array_get_nth (item, 1); - if (!validate_element (request_id, tmp, G_TYPE_UINT, i, 1)) - continue; - result = g_value_get_uint (tmp); - - /* Error */ - tmp = g_value_array_get_nth (item, 2); - if (!validate_element (request_id, tmp, G_TYPE_STRING, i, 2)) - continue; - err = g_value_get_string (tmp); - - if (result == DISPATCH_RESULT_SUCCESS) { nm_log_dbg (LOGD_DISPATCH, "(%u) %s succeeded%s", request_id, @@ -307,52 +362,43 @@ dispatcher_results_process (guint request_id, DispatcherAction action, GPtrArray request_id, script, dispatch_result_to_string (result), - err ? err : "", script_validation_msg); + err, script_validation_msg); } } } static void -free_results (GPtrArray *results) -{ - g_return_if_fail (results != NULL); - g_ptr_array_foreach (results, (GFunc) g_value_array_free, NULL); - g_ptr_array_free (results, TRUE); -} - -static void -dispatcher_done_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) +dispatcher_done_cb (GObject *proxy, GAsyncResult *result, gpointer user_data) { DispatchInfo *info = user_data; + GVariant *ret; + GVariantIter *results; GError *error = NULL; - GPtrArray *results = NULL; - if (dbus_g_proxy_end_call (proxy, call, &error, - DISPATCHER_TYPE_RESULT_ARRAY, &results, - G_TYPE_INVALID)) { + ret = _nm_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result, + G_VARIANT_TYPE ("(a(sus))"), + &error); + if (ret) { + g_variant_get (ret, "(a(sus))", &results); dispatcher_results_process (info->request_id, info->action, results); - free_results (results); + g_variant_iter_free (results); + g_variant_unref (ret); } else { - g_assert (error); - - if (!g_error_matches (error, DBUS_GERROR, DBUS_GERROR_REMOTE_EXCEPTION)) { - nm_log_warn (LOGD_DISPATCH, "(%u) failed to call dispatcher scripts: (%s:%d) %s", - info->request_id, g_quark_to_string (error->domain), - error->code, error->message); - } else if (!dbus_g_error_has_name (error, "org.freedesktop.systemd1.LoadFailed")) { - nm_log_warn (LOGD_DISPATCH, "(%u) failed to call dispatcher scripts: (%s) %s", - info->request_id, dbus_g_error_get_name (error), error->message); + if (_nm_dbus_error_has_name (error, "org.freedesktop.systemd1.LoadFailed")) { + g_dbus_error_strip_remote_error (error); + nm_log_warn (LOGD_DISPATCH, "(%u) failed to call dispatcher scripts: %s", + info->request_id, error->message); } else { - nm_log_dbg (LOGD_DISPATCH, "(%u) failed to call dispatcher scripts: (%s) %s", - info->request_id, dbus_g_error_get_name (error), error->message); + nm_log_dbg (LOGD_DISPATCH, "(%u) failed to call dispatcher scripts: %s", + info->request_id, error->message); } + g_clear_error (&error); } if (info->callback) info->callback (info->request_id, info->user_data); - g_clear_error (&error); - g_object_unref (proxy); + dispatcher_info_cleanup (info); } static const char *action_table[] = { @@ -391,7 +437,8 @@ dispatcher_idle_cb (gpointer user_data) static gboolean _dispatcher_call (DispatcherAction action, gboolean blocking, - NMConnection *connection, + NMSettingsConnection *settings_connection, + NMConnection *applied_connection, NMDevice *device, const char *vpn_iface, NMIP4Config *vpn_ip4_config, @@ -400,23 +447,24 @@ _dispatcher_call (DispatcherAction action, gpointer user_data, guint *out_call_id) { - DBusGProxy *proxy; - DBusGConnection *g_connection; - 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; - GHashTable *vpn_ip4_props; - GHashTable *vpn_ip6_props; + GVariant *connection_dict; + GVariantBuilder connection_props; + GVariantBuilder device_props; + GVariantBuilder device_ip4_props; + GVariantBuilder device_ip6_props; + GVariant *device_dhcp4_props = NULL; + GVariant *device_dhcp6_props = NULL; + GVariantBuilder vpn_ip4_props; + GVariantBuilder vpn_ip6_props; DispatchInfo *info = NULL; gboolean success = FALSE; GError *error = NULL; static guint request_counter = 0; guint reqid = ++request_counter; + if (!dispatcher_proxy) + return FALSE; + /* Wrapping protection */ if (G_UNLIKELY (!reqid)) reqid = ++request_counter; @@ -459,87 +507,95 @@ _dispatcher_call (DispatcherAction action, goto done; } - g_connection = nm_dbus_manager_get_connection (nm_dbus_manager_get ()); - proxy = dbus_g_proxy_new_for_name (g_connection, - NM_DISPATCHER_DBUS_SERVICE, - NM_DISPATCHER_DBUS_PATH, - NM_DISPATCHER_DBUS_INTERFACE); - if (!proxy) { - nm_log_err (LOGD_DISPATCH, "(%u) could not get dispatcher proxy!", reqid); - return FALSE; - } + if (applied_connection) + connection_dict = nm_connection_to_dbus (applied_connection, NM_CONNECTION_SERIALIZE_NO_SECRETS); + else + connection_dict = g_variant_new_array (G_VARIANT_TYPE ("{sa{sv}}"), NULL, 0); - if (connection) { - GVariant *connection_dict; + g_variant_builder_init (&connection_props, G_VARIANT_TYPE_VARDICT); + if (settings_connection) { + const char *connection_path; const char *filename; - connection_dict = nm_connection_to_dbus (connection, NM_CONNECTION_SERIALIZE_NO_SECRETS); - connection_hash = nm_utils_connection_dict_to_hash (connection_dict); - g_variant_unref (connection_dict); - - connection_props = value_hash_create (); - value_hash_add_object_path (connection_props, - NMD_CONNECTION_PROPS_PATH, - nm_connection_get_path (connection)); - filename = nm_settings_connection_get_filename (NM_SETTINGS_CONNECTION (connection)); + connection_path = nm_connection_get_path (NM_CONNECTION (settings_connection)); + if (connection_path) { + g_variant_builder_add (&connection_props, "{sv}", + NMD_CONNECTION_PROPS_PATH, + g_variant_new_object_path (connection_path)); + } + filename = nm_settings_connection_get_filename (settings_connection); if (filename) { - value_hash_add_str (connection_props, - NMD_CONNECTION_PROPS_FILENAME, - filename); + g_variant_builder_add (&connection_props, "{sv}", + NMD_CONNECTION_PROPS_FILENAME, + g_variant_new_string (filename)); + } + if (nm_settings_connection_get_nm_generated_assumed (settings_connection)) { + g_variant_builder_add (&connection_props, "{sv}", + NMD_CONNECTION_PROPS_EXTERNAL, + g_variant_new_boolean (TRUE)); } - } else { - connection_hash = value_hash_create (); - connection_props = value_hash_create (); } - device_props = value_hash_create (); - device_ip4_props = value_hash_create (); - device_ip6_props = value_hash_create (); - device_dhcp4_props = value_hash_create (); - device_dhcp6_props = value_hash_create (); - vpn_ip4_props = value_hash_create (); - vpn_ip6_props = value_hash_create (); + g_variant_builder_init (&device_props, G_VARIANT_TYPE_VARDICT); + g_variant_builder_init (&device_ip4_props, G_VARIANT_TYPE_VARDICT); + g_variant_builder_init (&device_ip6_props, G_VARIANT_TYPE_VARDICT); + g_variant_builder_init (&vpn_ip4_props, G_VARIANT_TYPE_VARDICT); + g_variant_builder_init (&vpn_ip6_props, G_VARIANT_TYPE_VARDICT); /* hostname actions only send the hostname */ if (action != DISPATCHER_ACTION_HOSTNAME) { fill_device_props (device, - device_props, - device_ip4_props, - device_ip6_props, - device_dhcp4_props, - device_dhcp6_props); - if (vpn_ip4_config || vpn_ip6_config) - fill_vpn_props (vpn_ip4_config, vpn_ip6_config, vpn_ip4_props, vpn_ip6_props); + &device_props, + &device_ip4_props, + &device_ip6_props, + &device_dhcp4_props, + &device_dhcp6_props); + if (vpn_ip4_config || vpn_ip6_config) { + fill_vpn_props (vpn_ip4_config, + vpn_ip6_config, + &vpn_ip4_props, + &vpn_ip6_props); + } } + if (!device_dhcp4_props) + device_dhcp4_props = g_variant_ref_sink (g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0)); + if (!device_dhcp6_props) + device_dhcp6_props = g_variant_ref_sink (g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0)); + /* Send the action to the dispatcher */ if (blocking) { - GPtrArray *results = NULL; - - success = dbus_g_proxy_call_with_timeout (proxy, "Action", - CALL_TIMEOUT, - &error, - G_TYPE_STRING, action_to_string (action), - DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, connection_hash, - DBUS_TYPE_G_MAP_OF_VARIANT, connection_props, - DBUS_TYPE_G_MAP_OF_VARIANT, device_props, - DBUS_TYPE_G_MAP_OF_VARIANT, device_ip4_props, - DBUS_TYPE_G_MAP_OF_VARIANT, device_ip6_props, - DBUS_TYPE_G_MAP_OF_VARIANT, device_dhcp4_props, - DBUS_TYPE_G_MAP_OF_VARIANT, device_dhcp6_props, - G_TYPE_STRING, vpn_iface ? vpn_iface : "", - DBUS_TYPE_G_MAP_OF_VARIANT, vpn_ip4_props, - DBUS_TYPE_G_MAP_OF_VARIANT, vpn_ip6_props, - G_TYPE_BOOLEAN, nm_logging_enabled (LOGL_DEBUG, LOGD_DISPATCH), - G_TYPE_INVALID, - DISPATCHER_TYPE_RESULT_ARRAY, &results, - G_TYPE_INVALID); - if (success) { + GVariant *ret; + GVariantIter *results; + + ret = _nm_dbus_proxy_call_sync (dispatcher_proxy, "Action", + g_variant_new ("(s@a{sa{sv}}a{sv}a{sv}a{sv}a{sv}@a{sv}@a{sv}sa{sv}a{sv}b)", + action_to_string (action), + connection_dict, + &connection_props, + &device_props, + &device_ip4_props, + &device_ip6_props, + device_dhcp4_props, + device_dhcp6_props, + vpn_iface ? vpn_iface : "", + &vpn_ip4_props, + &vpn_ip6_props, + nm_logging_enabled (LOGL_DEBUG, LOGD_DISPATCH)), + G_VARIANT_TYPE ("(a(sus))"), + G_DBUS_CALL_FLAGS_NONE, CALL_TIMEOUT, + NULL, &error); + if (ret) { + g_variant_get (ret, "(a(sus))", &results); dispatcher_results_process (reqid, action, results); - free_results (results); + g_variant_iter_free (results); + g_variant_unref (ret); + success = TRUE; } else { - nm_log_warn (LOGD_DISPATCH, "(%u) failed: (%d) %s", reqid, error->code, error->message); - g_error_free (error); + g_dbus_error_strip_remote_error (error); + nm_log_warn (LOGD_DISPATCH, "(%u) failed: %s", reqid, error->message); + g_clear_error (&error); + success = FALSE; } } else { info = g_malloc0 (sizeof (*info)); @@ -547,36 +603,27 @@ _dispatcher_call (DispatcherAction action, info->request_id = reqid; info->callback = callback; info->user_data = user_data; - dbus_g_proxy_begin_call_with_timeout (proxy, "Action", - dispatcher_done_cb, - info, - (GDestroyNotify) dispatcher_info_cleanup, - CALL_TIMEOUT, - G_TYPE_STRING, action_to_string (action), - DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, connection_hash, - DBUS_TYPE_G_MAP_OF_VARIANT, connection_props, - DBUS_TYPE_G_MAP_OF_VARIANT, device_props, - DBUS_TYPE_G_MAP_OF_VARIANT, device_ip4_props, - DBUS_TYPE_G_MAP_OF_VARIANT, device_ip6_props, - DBUS_TYPE_G_MAP_OF_VARIANT, device_dhcp4_props, - DBUS_TYPE_G_MAP_OF_VARIANT, device_dhcp6_props, - G_TYPE_STRING, vpn_iface ? vpn_iface : "", - DBUS_TYPE_G_MAP_OF_VARIANT, vpn_ip4_props, - DBUS_TYPE_G_MAP_OF_VARIANT, vpn_ip6_props, - G_TYPE_BOOLEAN, nm_logging_enabled (LOGL_DEBUG, LOGD_DISPATCH), - G_TYPE_INVALID); + g_dbus_proxy_call (dispatcher_proxy, "Action", + g_variant_new ("(s@a{sa{sv}}a{sv}a{sv}a{sv}a{sv}@a{sv}@a{sv}sa{sv}a{sv}b)", + action_to_string (action), + connection_dict, + &connection_props, + &device_props, + &device_ip4_props, + &device_ip6_props, + device_dhcp4_props, + device_dhcp6_props, + vpn_iface ? vpn_iface : "", + &vpn_ip4_props, + &vpn_ip6_props, + nm_logging_enabled (LOGL_DEBUG, LOGD_DISPATCH)), + G_DBUS_CALL_FLAGS_NONE, CALL_TIMEOUT, + NULL, dispatcher_done_cb, info); success = TRUE; } - g_hash_table_destroy (connection_hash); - g_hash_table_destroy (connection_props); - g_hash_table_destroy (device_props); - g_hash_table_destroy (device_ip4_props); - g_hash_table_destroy (device_ip6_props); - g_hash_table_destroy (device_dhcp4_props); - g_hash_table_destroy (device_dhcp6_props); - g_hash_table_destroy (vpn_ip4_props); - g_hash_table_destroy (vpn_ip6_props); + g_variant_unref (device_dhcp4_props); + g_variant_unref (device_dhcp6_props); done: if (success && info) { @@ -593,7 +640,8 @@ done: /** * nm_dispatcher_call: * @action: the %DispatcherAction - * @connection: the #NMConnection the action applies to + * @settings_connection: the #NMSettingsConnection the action applies to + * @applied_connection: the currently applied connection * @device: the #NMDevice the action applies to * @callback: a caller-supplied callback to execute when done * @user_data: caller-supplied pointer passed to @callback @@ -607,20 +655,22 @@ done: */ gboolean nm_dispatcher_call (DispatcherAction action, - NMConnection *connection, + NMSettingsConnection *settings_connection, + NMConnection *applied_connection, NMDevice *device, DispatcherFunc callback, gpointer user_data, guint *out_call_id) { - return _dispatcher_call (action, FALSE, connection, device, NULL, NULL, + return _dispatcher_call (action, FALSE, settings_connection, applied_connection, device, NULL, NULL, NULL, callback, user_data, out_call_id); } /** * nm_dispatcher_call_sync(): * @action: the %DispatcherAction - * @connection: the #NMConnection the action applies to + * @settings_connection: the #NMSettingsConnection the action applies to + * @applied_connection: the currently applied connection * @device: the #NMDevice the action applies to * * This method always invokes the dispatcher action synchronously and it may @@ -630,17 +680,19 @@ nm_dispatcher_call (DispatcherAction action, */ gboolean nm_dispatcher_call_sync (DispatcherAction action, - NMConnection *connection, + NMSettingsConnection *settings_connection, + NMConnection *applied_connection, NMDevice *device) { - return _dispatcher_call (action, TRUE, connection, device, NULL, NULL, + return _dispatcher_call (action, TRUE, settings_connection, applied_connection, device, NULL, NULL, NULL, NULL, NULL, NULL); } /** * nm_dispatcher_call_vpn(): * @action: the %DispatcherAction - * @connection: the #NMConnection the action applies to + * @settings_connection: the #NMSettingsConnection the action applies to + * @applied_connection: the currently applied connection * @parent_device: the parent #NMDevice of the VPN connection * @vpn_iface: the IP interface of the VPN tunnel, if any * @vpn_ip4_config: the #NMIP4Config of the VPN connection @@ -657,7 +709,8 @@ nm_dispatcher_call_sync (DispatcherAction action, */ gboolean nm_dispatcher_call_vpn (DispatcherAction action, - NMConnection *connection, + NMSettingsConnection *settings_connection, + NMConnection *applied_connection, NMDevice *parent_device, const char *vpn_iface, NMIP4Config *vpn_ip4_config, @@ -666,14 +719,15 @@ nm_dispatcher_call_vpn (DispatcherAction action, gpointer user_data, guint *out_call_id) { - return _dispatcher_call (action, FALSE, connection, parent_device, vpn_iface, + return _dispatcher_call (action, FALSE, settings_connection, applied_connection, parent_device, vpn_iface, vpn_ip4_config, vpn_ip6_config, callback, user_data, out_call_id); } /** * nm_dispatcher_call_vpn_sync(): * @action: the %DispatcherAction - * @connection: the #NMConnection the action applies to + * @settings_connection: the #NMSettingsConnection the action applies to + * @applied_connection: the currently applied connection * @parent_device: the parent #NMDevice of the VPN connection * @vpn_iface: the IP interface of the VPN tunnel, if any * @vpn_ip4_config: the #NMIP4Config of the VPN connection @@ -686,13 +740,14 @@ nm_dispatcher_call_vpn (DispatcherAction action, */ gboolean nm_dispatcher_call_vpn_sync (DispatcherAction action, - NMConnection *connection, + NMSettingsConnection *settings_connection, + NMConnection *applied_connection, NMDevice *parent_device, const char *vpn_iface, NMIP4Config *vpn_ip4_config, NMIP6Config *vpn_ip6_config) { - return _dispatcher_call (action, TRUE, connection, parent_device, vpn_iface, + return _dispatcher_call (action, TRUE, settings_connection, applied_connection, parent_device, vpn_iface, vpn_ip4_config, vpn_ip6_config, NULL, NULL, NULL); } @@ -768,6 +823,7 @@ nm_dispatcher_init (void) { GFile *file; guint i; + GError *error = NULL; for (i = 0; i < G_N_ELEMENTS (monitors); i++) { file = g_file_new_for_path (monitors[i].dir); @@ -778,5 +834,18 @@ nm_dispatcher_init (void) } g_object_unref (file); } + + dispatcher_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | + G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, + NULL, + NM_DISPATCHER_DBUS_SERVICE, + NM_DISPATCHER_DBUS_PATH, + NM_DISPATCHER_DBUS_INTERFACE, + NULL, &error); + if (!dispatcher_proxy) { + nm_log_err (LOGD_DISPATCH, "could not get dispatcher proxy! %s", error->message); + g_clear_error (&error); + } } |