core: merge branch 'more-gdbus-bgo746901'

https://bugzilla.gnome.org/show_bug.cgi?id=746901
This commit is contained in:
Dan Winship
2015-04-03 17:01:47 -04:00
19 changed files with 1089 additions and 979 deletions

View File

@@ -58,6 +58,7 @@ libnm_core_sources = \
$(core_build)/nm-core-enum-types.c \
$(core)/crypto.c \
$(core)/nm-connection.c \
$(core)/nm-dbus-utils.c \
$(core)/nm-errors.c \
$(core)/nm-keyfile-reader.c \
$(core)/nm-keyfile-utils.c \

View File

@@ -33,6 +33,8 @@
* and some test programs.
**/
#include <gio/gio.h>
#include "nm-connection.h"
#include "nm-core-enum-types.h"
#include "nm-dbus-interface.h"
@@ -139,4 +141,30 @@ GByteArray *nm_utils_rsa_key_encrypt (const guint8 *data,
gint64 _nm_utils_ascii_str_to_int64 (const char *str, guint base, gint64 min, gint64 max, gint64 fallback);
gulong _nm_dbus_signal_connect_data (GDBusProxy *proxy,
const char *signal_name,
const GVariantType *signature,
GCallback c_handler,
gpointer data,
GClosureNotify destroy_data,
GConnectFlags connect_flags);
#define _nm_dbus_signal_connect(proxy, name, signature, handler, data) \
_nm_dbus_signal_connect_data (proxy, name, signature, handler, data, NULL, (GConnectFlags) 0)
GVariant *_nm_dbus_proxy_call_finish (GDBusProxy *proxy,
GAsyncResult *res,
const GVariantType *reply_type,
GError **error);
GVariant *_nm_dbus_proxy_call_sync (GDBusProxy *proxy,
const gchar *method_name,
GVariant *parameters,
const GVariantType *reply_type,
GDBusCallFlags flags,
gint timeout_msec,
GCancellable *cancellable,
GError **error);
gboolean _nm_dbus_error_has_name (GError *error,
const char *dbus_error_name);
#endif

290
libnm-core/nm-dbus-utils.c Normal file
View File

@@ -0,0 +1,290 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* Copyright 2015 Red Hat, Inc.
*/
#include "config.h"
#include <string.h>
#include <gio/gio.h>
#include <glib/gi18n-lib.h>
#include "nm-core-internal.h"
typedef struct {
char *signal_name;
const GVariantType *signature;
} NMDBusSignalData;
static void
dbus_signal_data_free (gpointer data, GClosure *closure)
{
NMDBusSignalData *sd = data;
g_free (sd->signal_name);
g_slice_free (NMDBusSignalData, sd);
}
static void
dbus_signal_meta_marshal (GClosure *closure,
GValue *return_value,
guint n_param_values,
const GValue *param_values,
gpointer invocation_hint,
gpointer marshal_data)
{
NMDBusSignalData *sd = marshal_data;
const char *signal_name;
GVariant *parameters, *param;
GValue *closure_params;
gsize n_params, i;
g_return_if_fail (n_param_values == 4);
signal_name = g_value_get_string (&param_values[2]);
parameters = g_value_get_variant (&param_values[3]);
if (strcmp (signal_name, sd->signal_name) != 0)
return;
if (sd->signature) {
if (!g_variant_is_of_type (parameters, sd->signature)) {
g_warning ("%p: got signal '%s' but parameters were of type '%s', not '%s'",
g_value_get_object (&param_values[0]),
signal_name, g_variant_get_type_string (parameters),
g_variant_type_peek_string (sd->signature));
return;
}
n_params = g_variant_n_children (parameters) + 1;
} else
n_params = 1;
closure_params = g_new0 (GValue, n_params);
g_value_init (&closure_params[0], G_TYPE_OBJECT);
g_value_copy (&param_values[0], &closure_params[0]);
for (i = 1; i < n_params; i++) {
param = g_variant_get_child_value (parameters, i - 1);
if ( g_variant_is_of_type (param, G_VARIANT_TYPE ("ay"))
|| g_variant_is_of_type (param, G_VARIANT_TYPE ("aay"))) {
/* g_dbus_gvariant_to_gvalue() thinks 'ay' means "non-UTF-8 NUL-terminated string" */
g_value_init (&closure_params[i], G_TYPE_VARIANT);
g_value_set_variant (&closure_params[i], param);
} else
g_dbus_gvariant_to_gvalue (param, &closure_params[i]);
g_variant_unref (param);
}
g_cclosure_marshal_generic (closure,
NULL,
n_params,
closure_params,
invocation_hint,
NULL);
for (i = 0; i < n_params; i++)
g_value_unset (&closure_params[i]);
g_free (closure_params);
}
/**
* _nm_dbus_signal_connect_data:
* @proxy: a #GDBusProxy
* @signal_name: the D-Bus signal to connect to
* @signature: (allow-none): the signal's type signature (must be a tuple)
* @c_handler: the signal handler function
* @data: (allow-none): data to pass to @c_handler
* @destroy_data: (allow-none): closure destroy notify for @data
* @connect_flags: connection flags
*
* Connects to the D-Bus signal @signal_name on @proxy. @c_handler must be a
* void function whose first argument is a #GDBusProxy, followed by arguments
* for each element of @signature, ending with a #gpointer argument for @data.
*
* The argument types in @c_handler correspond to the types output by
* g_dbus_gvariant_to_gvalue(), except for 'ay' and 'aay'. In particular:
* - both 16-bit and 32-bit integers are passed as #gint/#guint
* - 'as' values are passed as #GStrv (char **)
* - all other array, tuple, and dict types are passed as #GVariant
*
* If @signature is %NULL, then the signal's parameters will be ignored, and
* @c_handler should take only the #GDBusProxy and #gpointer arguments.
*
* Returns: the signal handler ID, which can be used with
* g_signal_handler_remove(). Beware that because of the way the signal is
* connected, you will not be able to remove it with
* g_signal_handlers_disconnect_by_func(), although
* g_signal_handlers_disconnect_by_data() will work correctly.
*/
gulong
_nm_dbus_signal_connect_data (GDBusProxy *proxy,
const char *signal_name,
const GVariantType *signature,
GCallback c_handler,
gpointer data,
GClosureNotify destroy_data,
GConnectFlags connect_flags)
{
NMDBusSignalData *sd;
GClosure *closure;
gboolean swapped = !!(connect_flags & G_CONNECT_SWAPPED);
gboolean after = !!(connect_flags & G_CONNECT_AFTER);
g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), 0);
g_return_val_if_fail (signal_name != NULL, 0);
g_return_val_if_fail (signature == NULL || g_variant_type_is_tuple (signature), 0);
g_return_val_if_fail (c_handler != NULL, 0);
sd = g_slice_new (NMDBusSignalData);
sd->signal_name = g_strdup (signal_name);
sd->signature = signature;
closure = (swapped ? g_cclosure_new_swap : g_cclosure_new) (c_handler, data, destroy_data);
g_closure_set_marshal (closure, g_cclosure_marshal_generic);
g_closure_set_meta_marshal (closure, sd, dbus_signal_meta_marshal);
g_closure_add_finalize_notifier (closure, sd, dbus_signal_data_free);
return g_signal_connect_closure (proxy, "g-signal", closure, after);
}
/**
* _nm_dbus_signal_connect:
* @proxy: a #GDBusProxy
* @signal_name: the D-Bus signal to connect to
* @signature: the signal's type signature (must be a tuple)
* @c_handler: the signal handler function
* @data: (allow-none): data to pass to @c_handler
*
* Simplified version of _nm_dbus_signal_connect_data() with fewer arguments.
*
* Returns: the signal handler ID, as with _nm_signal_connect_data().
*/
static void
typecheck_response (GVariant **response,
const GVariantType *reply_type,
GError **error)
{
if (*response && reply_type && !g_variant_is_of_type (*response, reply_type)) {
/* This is the same error code that g_dbus_connection_call() returns if
* @reply_type doesn't match.
*/
g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
_("Method returned type '%s', but expected '%s'"),
g_variant_get_type_string (*response),
g_variant_type_peek_string (reply_type));
g_clear_pointer (response, g_variant_unref);
}
}
/**
* _nm_dbus_proxy_call_finish:
* @proxy: A #GDBusProxy.
* @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to
* g_dbus_proxy_call().
* @reply_type: (allow-none): the expected type of the reply, or %NULL
* @error: Return location for error or %NULL.
*
* Finishes an operation started with g_dbus_proxy_call(), as with
* g_dbus_proxy_call_finish(), except thatif @reply_type is non-%NULL, then it
* will also check that the response matches that type signature, and return
* an error if not.
*
* Returns: %NULL if @error is set. Otherwise a #GVariant tuple with
* return values. Free with g_variant_unref().
*/
GVariant *
_nm_dbus_proxy_call_finish (GDBusProxy *proxy,
GAsyncResult *res,
const GVariantType *reply_type,
GError **error)
{
GVariant *ret;
ret = g_dbus_proxy_call_finish (proxy, res, error);
typecheck_response (&ret, reply_type, error);
return ret;
}
/**
* _nm_dbus_proxy_call_sync:
* @proxy: A #GDBusProxy.
* @method_name: Name of method to invoke.
* @parameters: (allow-none): A #GVariant tuple with parameters for the signal
* or %NULL if not passing parameters.
* @reply_type: (allow-none): the expected type of the reply, or %NULL
* @flags: Flags from the #GDBusCallFlags enumeration.
* @timeout_msec: The timeout in milliseconds (with %G_MAXINT meaning
* "infinite") or -1 to use the proxy default timeout.
* @cancellable: (allow-none): A #GCancellable or %NULL.
* @error: Return location for error or %NULL.
*
* Synchronously invokes the @method_name method on @proxy, as with
* g_dbus_proxy_call_sync(), except that if @reply_type is non-%NULL, then the
* reply to the call will be checked against it, and an error returned if it
* does not match.
*
* Returns: %NULL if @error is set. Otherwise a #GVariant tuple with
* return values. Free with g_variant_unref().
*/
GVariant *
_nm_dbus_proxy_call_sync (GDBusProxy *proxy,
const gchar *method_name,
GVariant *parameters,
const GVariantType *reply_type,
GDBusCallFlags flags,
gint timeout_msec,
GCancellable *cancellable,
GError **error)
{
GVariant *ret;
ret = g_dbus_proxy_call_sync (proxy, method_name, parameters,
flags, timeout_msec,
cancellable, error);
typecheck_response (&ret, reply_type, error);
return ret;
}
/**
* _nm_dbus_error_has_name:
* @error: (allow-none): a #GError, or %NULL
* @dbus_error_name: a D-Bus error name
*
* Checks if @error is set and corresponds to the D-Bus error @dbus_error_name.
*
* Returns: %TRUE or %FALSE
*/
gboolean
_nm_dbus_error_has_name (GError *error,
const char *dbus_error_name)
{
gboolean has_name = FALSE;
if (error && g_dbus_error_is_remote_error (error)) {
char *error_name;
error_name = g_dbus_error_get_remote_error (error);
has_name = !g_strcmp0 (error_name, dbus_error_name);
g_free (error_name);
}
return has_name;
}

View File

@@ -34,6 +34,7 @@
#include "nm-glib-compat.h"
#include "nm-dbus-helpers.h"
#include "nm-client.h"
#include "nm-core-internal.h"
static gboolean debug = FALSE;
#define dbgmsg(f,...) if (G_UNLIKELY (debug)) { g_message (f, ## __VA_ARGS__ ); }
@@ -511,7 +512,8 @@ create_async_got_property (GObject *proxy, GAsyncResult *result, gpointer user_d
GError *error = NULL;
GType type;
ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result, &error);
ret = _nm_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result,
G_VARIANT_TYPE ("(v)"), &error);
if (ret) {
g_variant_get (ret, "(v)", &value);
type = type_data->type_func (value);
@@ -519,8 +521,8 @@ create_async_got_property (GObject *proxy, GAsyncResult *result, gpointer user_d
g_variant_unref (ret);
} else {
dbgmsg ("Could not fetch property '%s' of interface '%s' on %s: %s\n",
type_data->property, type_data->interface, async_data->path,
error->message);
type_data->property, type_data->interface, async_data->path,
error->message);
g_clear_error (&error);
type = G_TYPE_INVALID;
}
@@ -961,20 +963,11 @@ process_properties_changed (NMObject *self, GVariant *properties, gboolean synch
}
static void
property_proxy_signal (GDBusProxy *proxy,
const char *sender_name,
const char *signal_name,
GVariant *parameters,
gpointer user_data)
properties_changed (GDBusProxy *proxy,
GVariant *properties,
gpointer user_data)
{
GVariant *properties;
if (strcmp (signal_name, "PropertiesChanged") != 0)
return;
g_variant_get (parameters, "(@a{sv})", &properties);
process_properties_changed (NM_OBJECT (user_data), properties, FALSE);
g_variant_unref (properties);
}
#define HANDLE_TYPE(vtype, ctype, getter) \
@@ -1117,8 +1110,8 @@ _nm_object_register_properties (NMObject *object,
proxy = _nm_object_get_proxy (object, interface);
g_return_if_fail (proxy != NULL);
g_signal_connect (proxy, "g-signal",
G_CALLBACK (property_proxy_signal), object);
_nm_dbus_signal_connect (proxy, "PropertiesChanged", G_VARIANT_TYPE ("(a{sv})"),
G_CALLBACK (properties_changed), object);
instance = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
priv->property_tables = g_slist_prepend (priv->property_tables, instance);
@@ -1156,11 +1149,12 @@ _nm_object_reload_properties (NMObject *object, GError **error)
g_hash_table_iter_init (&iter, priv->proxies);
while (g_hash_table_iter_next (&iter, (gpointer *) &interface, (gpointer *) &proxy)) {
ret = g_dbus_proxy_call_sync (priv->properties_proxy,
"GetAll",
g_variant_new ("(s)", interface),
G_DBUS_CALL_FLAGS_NONE, -1,
NULL, error);
ret = _nm_dbus_proxy_call_sync (priv->properties_proxy,
"GetAll",
g_variant_new ("(s)", interface),
G_VARIANT_TYPE ("(a{sv})"),
G_DBUS_CALL_FLAGS_NONE, -1,
NULL, error);
if (!ret) {
if (error && *error)
g_dbus_error_strip_remote_error (*error);
@@ -1203,11 +1197,12 @@ _nm_object_reload_property (NMObject *object,
if (!NM_OBJECT_GET_PRIVATE (object)->nm_running)
return;
ret = g_dbus_proxy_call_sync (NM_OBJECT_GET_PRIVATE (object)->properties_proxy,
"Get",
g_variant_new ("(ss)", interface, prop_name),
G_DBUS_CALL_FLAGS_NONE, 15000,
NULL, &err);
ret = _nm_dbus_proxy_call_sync (NM_OBJECT_GET_PRIVATE (object)->properties_proxy,
"Get",
g_variant_new ("(ss)", interface, prop_name),
G_VARIANT_TYPE ("(v)"),
G_DBUS_CALL_FLAGS_NONE, 15000,
NULL, &err);
if (!ret) {
dbgmsg ("%s: Error getting '%s' for %s: (%d) %s\n",
__func__,
@@ -1305,7 +1300,9 @@ reload_got_properties (GObject *proxy,
GVariant *ret, *props;
GError *error = NULL;
ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result, &error);
ret = _nm_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result,
G_VARIANT_TYPE ("(a{sv})"),
&error);
if (ret) {
g_variant_get (ret, "(@a{sv})", &props);
process_properties_changed (object, props, FALSE);

View File

@@ -1153,101 +1153,6 @@ nm_utils_get_shared_wifi_permission (NMConnection *connection)
/*********************************/
static void
nm_gvalue_destroy (gpointer data)
{
GValue *value = (GValue *) data;
g_value_unset (value);
g_slice_free (GValue, value);
}
GHashTable *
value_hash_create (void)
{
return g_hash_table_new_full (g_str_hash, g_str_equal, g_free, nm_gvalue_destroy);
}
void
value_hash_add (GHashTable *hash,
const char *key,
GValue *value)
{
g_hash_table_insert (hash, g_strdup (key), value);
}
void
value_hash_add_str (GHashTable *hash,
const char *key,
const char *str)
{
GValue *value;
value = g_slice_new0 (GValue);
g_value_init (value, G_TYPE_STRING);
g_value_set_string (value, str);
value_hash_add (hash, key, value);
}
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);
}
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);
}
void
value_hash_add_bool (GHashTable *hash,
const char *key,
gboolean val)
{
GValue *value;
value = g_slice_new0 (GValue);
g_value_init (value, G_TYPE_BOOLEAN);
g_value_set_boolean (value, val);
value_hash_add (hash, key, value);
}
void
value_hash_add_object_property (GHashTable *hash,
const char *key,
GObject *object,
const char *prop,
GType val_type)
{
GValue *value;
value = g_slice_new0 (GValue);
g_value_init (value, val_type);
g_object_get_property (object, prop, value);
value_hash_add (hash, key, value);
}
static char *
get_new_connection_name (const GSList *existing,
const char *preferred,

View File

@@ -109,33 +109,6 @@ GSList *nm_match_spec_split (const char *value);
const char *nm_utils_get_shared_wifi_permission (NMConnection *connection);
GHashTable *value_hash_create (void);
void value_hash_add (GHashTable *hash,
const char *key,
GValue *value);
void value_hash_add_str (GHashTable *hash,
const char *key,
const char *str);
void value_hash_add_object_path (GHashTable *hash,
const char *key,
const char *op);
void value_hash_add_uint (GHashTable *hash,
const char *key,
guint32 val);
void value_hash_add_bool (GHashTable *hash,
const char *key,
gboolean val);
void value_hash_add_object_property (GHashTable *hash,
const char *key,
GObject *object,
const char *prop,
GType val_type);
const char *nm_utils_get_ip_config_method (NMConnection *connection,
GType ip_setting_type);

View File

@@ -864,21 +864,14 @@ properties_changed (GDBusProxy *proxy,
static void
bluez4_property_changed (GDBusProxy *proxy,
const char *sender,
const char *signal_name,
GVariant *parameters,
gpointer user_data)
const char *property,
GVariant *v,
gpointer user_data)
{
NMBluezDevice *self = NM_BLUEZ_DEVICE (user_data);
if (g_strcmp0 (signal_name, "PropertyChanged") == 0) {
const char *property = NULL;
GVariant *v = NULL;
g_variant_get (parameters, "(&sv)", &property, &v);
_take_one_variant_property (self, property, v);
check_emit_usable (self);
}
_take_one_variant_property (self, property, v);
check_emit_usable (self);
}
static void
@@ -888,27 +881,21 @@ get_properties_cb_4 (GObject *source_object, GAsyncResult *res, gpointer user_da
NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self);
GError *err = NULL;
GVariant *v_properties, *v_dict;
GVariantType *v_type;
v_properties = g_dbus_proxy_call_finish (priv->proxy, res, &err);
v_properties = _nm_dbus_proxy_call_finish (priv->proxy, res,
G_VARIANT_TYPE ("(a{sv})"),
&err);
if (!v_properties) {
nm_log_warn (LOGD_BT, "bluez[%s] error getting device properties: %s",
priv->path, err && err->message ? err->message : "(unknown)");
priv->path, err->message);
g_error_free (err);
g_signal_emit (self, signals[INITIALIZED], 0, FALSE);
goto END;
}
v_type = g_variant_type_new ("(a{sv})");
if (g_variant_is_of_type (v_properties, v_type)) {
v_dict = g_variant_get_child_value (v_properties, 0);
_set_properties (self, v_dict);
g_variant_unref (v_dict);
} else {
nm_log_warn (LOGD_BT, "bluez[%s] GetProperties returns unexpected result of type %s", priv->path, g_variant_get_type_string (v_properties));
}
g_variant_type_free (v_type);
v_dict = g_variant_get_child_value (v_properties, 0);
_set_properties (self, v_dict);
g_variant_unref (v_dict);
g_variant_unref (v_properties);
/* Check if any connections match this device */
@@ -917,7 +904,6 @@ get_properties_cb_4 (GObject *source_object, GAsyncResult *res, gpointer user_da
priv->initialized = TRUE;
g_signal_emit (self, signals[INITIALIZED], 0, TRUE);
check_emit_usable (self);
END:
@@ -985,8 +971,8 @@ on_proxy_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self)
G_CALLBACK (properties_changed), self);
if (priv->bluez_version == 4) {
/* Watch for custom Bluez4 PropertyChanged signals */
g_signal_connect (priv->proxy, "g-signal",
G_CALLBACK (bluez4_property_changed), self);
_nm_dbus_signal_connect (priv->proxy, "PropertyChanged", G_VARIANT_TYPE ("(sv)"),
G_CALLBACK (bluez4_property_changed), self);
}
query_properties (self);

View File

@@ -35,8 +35,7 @@
#include "nm-bluez-common.h"
#include "nm-connection-provider.h"
#include "nm-device-bt.h"
#include "nm-dbus-manager.h"
#include "nm-core-internal.h"
typedef struct {
int bluez_version;
@@ -276,8 +275,8 @@ check_bluez_and_try_setup_do_introspect (GObject *source_object,
g_clear_object (&priv->async_cancellable);
result = g_dbus_proxy_call_finish (priv->introspect_proxy, res, &error);
result = _nm_dbus_proxy_call_finish (priv->introspect_proxy, res,
G_VARIANT_TYPE ("(s)"), &error);
if (!result) {
char *reason2 = g_strdup_printf ("introspect failed with %s", error->message);
check_bluez_and_try_setup_final_step (self, 0, reason2);

View File

@@ -24,13 +24,11 @@
#include <string.h>
#include "nm-dbus-interface.h"
#include "nm-dbus-manager.h"
#include "nm-bluez4-adapter.h"
#include "nm-bluez-device.h"
#include "nm-bluez-common.h"
#include "nm-dbus-glib-types.h"
#include "nm-logging.h"
#include "nm-core-internal.h"
G_DEFINE_TYPE (NMBluez4Adapter, nm_bluez4_adapter, G_TYPE_OBJECT)
@@ -38,7 +36,7 @@ G_DEFINE_TYPE (NMBluez4Adapter, nm_bluez4_adapter, G_TYPE_OBJECT)
typedef struct {
char *path;
DBusGProxy *proxy;
GDBusProxy *proxy;
gboolean initialized;
char *address;
@@ -158,7 +156,7 @@ device_do_remove (NMBluez4Adapter *self, NMBluezDevice *device)
}
static void
device_created (DBusGProxy *proxy, const char *path, gpointer user_data)
device_created (GDBusProxy *proxy, const char *path, gpointer user_data)
{
NMBluez4Adapter *self = NM_BLUEZ4_ADAPTER (user_data);
NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self);
@@ -173,7 +171,7 @@ device_created (DBusGProxy *proxy, const char *path, gpointer user_data)
}
static void
device_removed (DBusGProxy *proxy, const char *path, gpointer user_data)
device_removed (GDBusProxy *proxy, const char *path, gpointer user_data)
{
NMBluez4Adapter *self = NM_BLUEZ4_ADAPTER (user_data);
NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self);
@@ -186,37 +184,35 @@ device_removed (DBusGProxy *proxy, const char *path, gpointer user_data)
device_do_remove (self, device);
}
static void
get_properties_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data)
get_properties_cb (GObject *proxy, GAsyncResult *result, gpointer user_data)
{
NMBluez4Adapter *self = NM_BLUEZ4_ADAPTER (user_data);
NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self);
GHashTable *properties = NULL;
GError *err = NULL;
GValue *value;
GPtrArray *devices;
GVariant *ret, *properties;
char **devices;
int i;
if (!dbus_g_proxy_end_call (proxy, call, &err,
DBUS_TYPE_G_MAP_OF_VARIANT, &properties,
G_TYPE_INVALID)) {
nm_log_warn (LOGD_BT, "bluez error getting adapter properties: %s",
err && err->message ? err->message : "(unknown)");
ret = _nm_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result,
G_VARIANT_TYPE ("(a{sv})"), &err);
if (!ret) {
nm_log_warn (LOGD_BT, "bluez error getting adapter properties: %s", err->message);
g_error_free (err);
goto done;
}
value = g_hash_table_lookup (properties, "Address");
priv->address = value ? g_value_dup_string (value) : NULL;
properties = g_variant_get_child_value (ret, 0);
value = g_hash_table_lookup (properties, "Devices");
devices = value ? g_value_get_boxed (value) : NULL;
g_variant_lookup (properties, "Address", "s", &priv->address);
if (g_variant_lookup (properties, "Devices", "^ao", &devices)) {
for (i = 0; devices[i]; i++)
device_created (priv->proxy, devices[i], self);
g_strfreev (devices);
}
for (i = 0; devices && i < devices->len; i++)
device_created (priv->proxy, g_ptr_array_index (devices, i), self);
g_hash_table_unref (properties);
g_variant_unref (properties);
g_variant_unref (ret);
priv->initialized = TRUE;
@@ -228,16 +224,12 @@ static void
query_properties (NMBluez4Adapter *self)
{
NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self);
DBusGProxyCall *call;
call = dbus_g_proxy_begin_call (priv->proxy, "GetProperties",
get_properties_cb,
self,
NULL, G_TYPE_INVALID);
if (!call) {
nm_log_warn (LOGD_BT, "failed to request Bluetooth adapter properties for %s.",
priv->path);
}
g_dbus_proxy_call (priv->proxy, "GetProperties",
NULL,
G_DBUS_CALL_FLAGS_NONE, -1,
NULL,
get_properties_cb, self);
}
/***********************************************************/
@@ -247,34 +239,25 @@ nm_bluez4_adapter_new (const char *path, NMConnectionProvider *provider)
{
NMBluez4Adapter *self;
NMBluez4AdapterPrivate *priv;
DBusGConnection *connection;
self = (NMBluez4Adapter *) g_object_new (NM_TYPE_BLUEZ4_ADAPTER,
NM_BLUEZ4_ADAPTER_PATH, path,
NULL);
if (!self)
return NULL;
priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self);
priv->provider = provider;
connection = nm_dbus_manager_get_connection (nm_dbus_manager_get ());
priv->proxy = dbus_g_proxy_new_for_name (connection,
BLUEZ_SERVICE,
priv->path,
BLUEZ4_ADAPTER_INTERFACE);
dbus_g_proxy_add_signal (priv->proxy, "DeviceCreated",
DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID);
dbus_g_proxy_connect_signal (priv->proxy, "DeviceCreated",
G_CALLBACK (device_created), self, NULL);
dbus_g_proxy_add_signal (priv->proxy, "DeviceRemoved",
DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID);
dbus_g_proxy_connect_signal (priv->proxy, "DeviceRemoved",
G_CALLBACK (device_removed), self, NULL);
priv->proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
NULL,
BLUEZ_SERVICE,
priv->path,
BLUEZ4_ADAPTER_INTERFACE,
NULL, NULL);
_nm_dbus_signal_connect (priv->proxy, "DeviceCreated", G_VARIANT_TYPE ("(o)"),
G_CALLBACK (device_created), self);
_nm_dbus_signal_connect (priv->proxy, "DeviceRemoved", G_VARIANT_TYPE ("(o)"),
G_CALLBACK (device_removed), self);
query_properties (self);
return self;

View File

@@ -24,24 +24,20 @@
#include <signal.h>
#include <string.h>
#include <stdlib.h>
#include <dbus/dbus-glib.h>
#include "nm-logging.h"
#include "nm-dbus-glib-types.h"
#include "nm-bluez-manager.h"
#include "nm-bluez4-manager.h"
#include "nm-bluez4-adapter.h"
#include "nm-dbus-manager.h"
#include "nm-bluez-common.h"
#include "nm-core-internal.h"
typedef struct {
NMDBusManager *dbus_mgr;
gulong name_owner_changed_id;
NMConnectionProvider *provider;
DBusGProxy *proxy;
GDBusProxy *proxy;
NMBluez4Adapter *adapter;
} NMBluez4ManagerPrivate;
@@ -120,7 +116,7 @@ adapter_initialized (NMBluez4Adapter *adapter, gboolean success, gpointer user_d
}
static void
adapter_removed (DBusGProxy *proxy, const char *path, NMBluez4Manager *self)
adapter_removed (GDBusProxy *proxy, const char *path, NMBluez4Manager *self)
{
NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self);
@@ -140,7 +136,7 @@ adapter_removed (DBusGProxy *proxy, const char *path, NMBluez4Manager *self)
}
static void
default_adapter_changed (DBusGProxy *proxy, const char *path, NMBluez4Manager *self)
default_adapter_changed (GDBusProxy *proxy, const char *path, NMBluez4Manager *self)
{
NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self);
const char *cur_path = NULL;
@@ -166,130 +162,65 @@ default_adapter_changed (DBusGProxy *proxy, const char *path, NMBluez4Manager *s
}
static void
default_adapter_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data)
default_adapter_cb (GObject *proxy, GAsyncResult *result, gpointer user_data)
{
NMBluez4Manager *self = NM_BLUEZ4_MANAGER (user_data);
NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self);
const char *default_adapter = NULL;
GVariant *ret;
GError *err = NULL;
if (!dbus_g_proxy_end_call (proxy, call, &err,
DBUS_TYPE_G_OBJECT_PATH, &default_adapter,
G_TYPE_INVALID)) {
ret = _nm_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result,
G_VARIANT_TYPE ("(o)"), &err);
if (ret) {
const char *default_adapter;
g_variant_get (ret, "(&o)", &default_adapter);
default_adapter_changed (priv->proxy, default_adapter, self);
g_variant_unref (ret);
} else {
/* Ignore "No such adapter" errors; just means bluetooth isn't active */
if ( !dbus_g_error_has_name (err, "org.bluez.Error.NoSuchAdapter")
&& !dbus_g_error_has_name (err, "org.freedesktop.systemd1.LoadFailed")
&& !g_error_matches (err, DBUS_GERROR, DBUS_GERROR_SERVICE_UNKNOWN)) {
if ( !_nm_dbus_error_has_name (err, "org.bluez.Error.NoSuchAdapter")
&& !_nm_dbus_error_has_name (err, "org.freedesktop.systemd1.LoadFailed")
&& !g_error_matches (err, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN)) {
g_dbus_error_strip_remote_error (err);
nm_log_warn (LOGD_BT, "bluez error getting default adapter: %s",
err && err->message ? err->message : "(unknown)");
err->message);
}
g_error_free (err);
return;
}
default_adapter_changed (priv->proxy, default_adapter, self);
}
static void
query_default_adapter (NMBluez4Manager *self)
{
NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self);
DBusGProxyCall *call;
call = dbus_g_proxy_begin_call (priv->proxy, "DefaultAdapter",
default_adapter_cb,
self,
NULL, G_TYPE_INVALID);
if (!call)
nm_log_warn (LOGD_BT, "failed to request default Bluetooth adapter.");
g_dbus_proxy_call (priv->proxy, "DefaultAdapter",
NULL,
G_DBUS_CALL_FLAGS_NONE, -1,
NULL,
default_adapter_cb, self);
}
static void
bluez_connect (NMBluez4Manager *self)
{
NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self);
DBusGConnection *connection;
g_return_if_fail (priv->proxy == NULL);
connection = nm_dbus_manager_get_connection (priv->dbus_mgr);
if (!connection)
return;
priv->proxy = dbus_g_proxy_new_for_name (connection,
BLUEZ_SERVICE,
BLUEZ_MANAGER_PATH,
BLUEZ4_MANAGER_INTERFACE);
dbus_g_proxy_add_signal (priv->proxy, "AdapterRemoved",
DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID);
dbus_g_proxy_connect_signal (priv->proxy, "AdapterRemoved",
G_CALLBACK (adapter_removed), self, NULL);
dbus_g_proxy_add_signal (priv->proxy, "DefaultAdapterChanged",
DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID);
dbus_g_proxy_connect_signal (priv->proxy, "DefaultAdapterChanged",
G_CALLBACK (default_adapter_changed), self, NULL);
query_default_adapter (self);
}
static void
name_owner_changed_cb (NMDBusManager *dbus_mgr,
const char *name,
const char *old_owner,
const char *new_owner,
name_owner_changed_cb (GObject *object,
GParamSpec *pspec,
gpointer user_data)
{
NMBluez4Manager *self = NM_BLUEZ4_MANAGER (user_data);
NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self);
gboolean old_owner_good = (old_owner && strlen (old_owner));
gboolean new_owner_good = (new_owner && strlen (new_owner));
char *owner;
/* Can't handle the signal if its not from the Bluez */
if (strcmp (BLUEZ_SERVICE, name))
return;
if (!old_owner_good && new_owner_good)
owner = g_dbus_proxy_get_name_owner (priv->proxy);
if (owner) {
query_default_adapter (self);
else if (old_owner_good && !new_owner_good) {
g_free (owner);
} else {
/* Throwing away the adapter removes all devices too */
if (priv->adapter) {
g_object_unref (priv->adapter);
priv->adapter = NULL;
}
g_clear_object (&priv->adapter);
}
}
static void
bluez_cleanup (NMBluez4Manager *self, gboolean do_signal)
{
NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self);
if (priv->proxy) {
g_object_unref (priv->proxy);
priv->proxy = NULL;
}
if (priv->adapter) {
g_object_unref (priv->adapter);
priv->adapter = NULL;
}
}
static void
dbus_connection_changed_cb (NMDBusManager *dbus_mgr,
DBusGConnection *connection,
gpointer user_data)
{
NMBluez4Manager *self = NM_BLUEZ4_MANAGER (user_data);
if (!connection)
bluez_cleanup (self, TRUE);
else
bluez_connect (self);
}
/****************************************************************/
NMBluez4Manager *
@@ -307,20 +238,21 @@ nm_bluez4_manager_init (NMBluez4Manager *self)
{
NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self);
priv->dbus_mgr = nm_dbus_manager_get ();
g_assert (priv->dbus_mgr);
priv->proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
NULL,
BLUEZ_SERVICE,
BLUEZ_MANAGER_PATH,
BLUEZ4_MANAGER_INTERFACE,
NULL, NULL);
_nm_dbus_signal_connect (priv->proxy, "AdapterRemoved", G_VARIANT_TYPE ("(o)"),
G_CALLBACK (adapter_removed), self);
_nm_dbus_signal_connect (priv->proxy, "DefaultAdapterChanged", G_VARIANT_TYPE ("(o)"),
G_CALLBACK (default_adapter_changed), self);
g_signal_connect (priv->proxy, "notify::g-name-owner",
G_CALLBACK (name_owner_changed_cb), self);
g_signal_connect (priv->dbus_mgr,
NM_DBUS_MANAGER_NAME_OWNER_CHANGED,
G_CALLBACK (name_owner_changed_cb),
self);
g_signal_connect (priv->dbus_mgr,
NM_DBUS_MANAGER_DBUS_CONNECTION_CHANGED,
G_CALLBACK (dbus_connection_changed_cb),
self);
bluez_connect (self);
query_default_adapter (self);
}
static void
@@ -329,13 +261,8 @@ dispose (GObject *object)
NMBluez4Manager *self = NM_BLUEZ4_MANAGER (object);
NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self);
bluez_cleanup (self, FALSE);
if (priv->dbus_mgr) {
g_signal_handlers_disconnect_by_func (priv->dbus_mgr, name_owner_changed_cb, self);
g_signal_handlers_disconnect_by_func (priv->dbus_mgr, dbus_connection_changed_cb, self);
priv->dbus_mgr = NULL;
}
g_clear_object (&priv->proxy);
g_clear_object (&priv->adapter);
G_OBJECT_CLASS (nm_bluez4_manager_parent_class)->dispose (object);
}

View File

@@ -34,6 +34,7 @@
#include "nm-bluez-common.h"
#include "nm-dbus-manager.h"
#include "nm-core-internal.h"
typedef struct {
NMDBusManager *dbus_mgr;
@@ -170,39 +171,23 @@ device_removed (GDBusProxy *proxy, const gchar *path, NMBluez5Manager *self)
}
static void
object_manager_g_signal (GDBusProxy *proxy,
gchar *sender_name,
gchar *signal_name,
GVariant *parameters,
NMBluez5Manager *self)
object_manager_interfaces_added (GDBusProxy *proxy,
const char *path,
GVariant *dict,
NMBluez5Manager *self)
{
GVariant *variant;
const gchar *path;
if (g_variant_lookup (dict, BLUEZ5_DEVICE_INTERFACE, "a{sv}", NULL))
device_added (proxy, path, self);
}
if (!strcmp (signal_name, "InterfacesRemoved")) {
const gchar **ifaces;
gsize i, length;
g_variant_get (parameters, "(&o*)", &path, &variant);
ifaces = g_variant_get_strv (variant, &length);
for (i = 0; i < length; i++) {
if (!strcmp (ifaces[i], BLUEZ5_DEVICE_INTERFACE)) {
device_removed (proxy, path, self);
break;
}
}
g_free (ifaces);
} else if (!strcmp (signal_name, "InterfacesAdded")) {
g_variant_get (parameters, "(&o*)", &path, &variant);
if (g_variant_lookup_value (variant, BLUEZ5_DEVICE_INTERFACE,
G_VARIANT_TYPE_DICTIONARY))
device_added (proxy, path, self);
}
static void
object_manager_interfaces_removed (GDBusProxy *proxy,
const char *path,
const char **ifaces,
NMBluez5Manager *self)
{
if (_nm_utils_string_in_list (BLUEZ5_DEVICE_INTERFACE, ifaces))
device_removed (proxy, path, self);
}
static void
@@ -215,8 +200,9 @@ get_managed_objects_cb (GDBusProxy *proxy,
GError *error = NULL;
const char *path;
variant = g_dbus_proxy_call_finish (proxy, res, &error);
variant = _nm_dbus_proxy_call_finish (proxy, res,
G_VARIANT_TYPE ("(a{oa{sa{sv}}})"),
&error);
if (!variant) {
if (g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD))
nm_log_warn (LOGD_BT, "Couldn't get managed objects: not running Bluez5?");
@@ -264,8 +250,10 @@ on_proxy_acquired (GObject *object,
(GAsyncReadyCallback) get_managed_objects_cb,
self);
g_signal_connect (priv->proxy, "g-signal",
G_CALLBACK (object_manager_g_signal), self);
_nm_dbus_signal_connect (priv->proxy, "InterfacesAdded", G_VARIANT_TYPE ("(oa{sa{sv}})"),
G_CALLBACK (object_manager_interfaces_added), self);
_nm_dbus_signal_connect (priv->proxy, "InterfacesRemoved", G_VARIANT_TYPE ("(oas)"),
G_CALLBACK (object_manager_interfaces_removed), self);
}
static void

View File

@@ -24,6 +24,7 @@
#include "nm-logging.h"
#include "nm-errors.h"
#include "nm-core-internal.h"
#define POLKIT_SERVICE "org.freedesktop.PolicyKit1"
#define POLKIT_OBJECT_PATH "/org/freedesktop/PolicyKit1/Authority"
@@ -176,7 +177,7 @@ check_authorization_cb (GDBusProxy *proxy,
GVariant *value;
GError *error = NULL;
value = g_dbus_proxy_call_finish (proxy, res, &error);
value = _nm_dbus_proxy_call_finish (proxy, res, G_VARIANT_TYPE ("((bba{ss}))"), &error);
if (value == NULL) {
if (data->cancellation_id != NULL &&
(!g_dbus_error_is_remote_error (error) &&
@@ -200,18 +201,15 @@ check_authorization_cb (GDBusProxy *proxy,
error->message);
g_error_free (error);
} else {
GVariant *result_value;
CheckAuthorizationResult *result;
result = g_new0 (CheckAuthorizationResult, 1);
result_value = g_variant_get_child_value (value, 0);
g_variant_get (result_value,
"(bb@a{ss})",
g_variant_get (value,
"((bb@a{ss}))",
&result->is_authorized,
&result->is_challenge,
NULL);
g_variant_unref (result_value);
g_variant_unref (value);
_LOGD ("call[%u]: CheckAuthorization succeeded: (is_authorized=%d, is_challenge=%d)", data->call_id, result->is_authorized, result->is_challenge);
@@ -394,21 +392,16 @@ _dbus_on_name_owner_notify_cb (GObject *object,
}
static void
_dbus_on_g_signal_cb (GDBusProxy *proxy,
const gchar *sender_name,
const gchar *signal_name,
GVariant *parameters,
gpointer user_data)
_dbus_on_changed_signal_cb (GDBusProxy *proxy,
gpointer user_data)
{
NMAuthManager *self = user_data;
NMAuthManagerPrivate *priv = NM_AUTH_MANAGER_GET_PRIVATE (self);
g_return_if_fail (priv->proxy == proxy);
_LOGD ("dbus signal: \"%s\"", signal_name ? signal_name : "(null)");
if (g_strcmp0 (signal_name, "Changed") == 0)
_emit_changed_signal (self);
_LOGD ("dbus signal: \"Changed\"");
_emit_changed_signal (self);
}
static void
@@ -463,10 +456,9 @@ _dbus_new_proxy_cb (GObject *source_object,
"notify::g-name-owner",
G_CALLBACK (_dbus_on_name_owner_notify_cb),
self);
g_signal_connect (priv->proxy,
"g-signal",
G_CALLBACK (_dbus_on_g_signal_cb),
self);
_nm_dbus_signal_connect (priv->proxy, "Changed", NULL,
G_CALLBACK (_dbus_on_changed_signal_cb),
self);
_log_name_owner (self, NULL);
@@ -604,8 +596,7 @@ dispose (GObject *object)
}
if (priv->proxy) {
g_signal_handlers_disconnect_by_func (priv->proxy, _dbus_on_name_owner_notify_cb, self);
g_signal_handlers_disconnect_by_func (priv->proxy, _dbus_on_g_signal_cb, self);
g_signal_handlers_disconnect_by_data (priv->proxy, self);
g_clear_object (&priv->proxy);
}
#endif

View File

@@ -35,12 +35,17 @@
#include "nm-device.h"
#include "nm-dhcp4-config.h"
#include "nm-dhcp6-config.h"
#include "nm-ip4-config.h"
#include "nm-ip6-config.h"
#include "nm-dbus-glib-types.h"
#include "nm-glib-compat.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,24 +85,145 @@ _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;
GVariantBuilder int_builder;
guint n, i;
const NMPlatformIP4Address *addr;
const NMPlatformIP4Route *route;
guint32 array[4];
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);
/* 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);
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_variant_builder_add (builder, "{sv}",
"routes",
g_variant_builder_end (&int_builder));
}
static void
dump_dhcp4_to_props (NMDhcp4Config *config, GHashTable *hash)
dump_ip6_to_props (NMIP6Config *ip6, GVariantBuilder *builder)
{
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_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
dump_dhcp4_to_props (NMDhcp4Config *config, GVariantBuilder *builder)
{
GSList *options, *iter;
@@ -107,13 +233,13 @@ dump_dhcp4_to_props (NMDhcp4Config *config, GHashTable *hash)
const char *val;
val = nm_dhcp4_config_get_option (config, option);
value_hash_add_str (hash, option, val);
g_variant_builder_add (builder, "{sv}", option, g_variant_new_string (val));
}
g_slist_free (options);
}
static void
dump_dhcp6_to_props (NMDhcp6Config *config, GHashTable *hash)
dump_dhcp6_to_props (NMDhcp6Config *config, GVariantBuilder *builder)
{
GSList *options, *iter;
@@ -123,18 +249,18 @@ dump_dhcp6_to_props (NMDhcp6Config *config, GHashTable *hash)
const char *val;
val = nm_dhcp6_config_get_option (config, option);
value_hash_add_str (hash, option, val);
g_variant_builder_add (builder, "{sv}", option, g_variant_new_string (val));
}
g_slist_free (options);
}
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,
GVariantBuilder *dhcp4_builder,
GVariantBuilder *dhcp6_builder)
{
NMIP4Config *ip4_config;
NMIP6Config *ip6_config;
@@ -142,39 +268,44 @@ 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)));
g_variant_builder_add (dev_builder, "{sv}", NMD_DEVICE_PROPS_PATH,
g_variant_new_object_path (nm_device_get_path (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);
dump_dhcp4_to_props (dhcp4_config, dhcp4_builder);
dhcp6_config = nm_device_get_dhcp6_config (device);
if (dhcp6_config)
dump_dhcp6_to_props (dhcp6_config, dhcp6_hash);
dump_dhcp6_to_props (dhcp6_config, dhcp6_builder);
}
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 +359,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 +389,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 +398,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[] = {
@@ -400,23 +482,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;
GVariantBuilder device_dhcp4_props;
GVariantBuilder device_dhcp6_props;
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;
@@ -463,92 +546,87 @@ _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 (connection) {
GVariant *connection_dict;
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));
g_variant_builder_init (&connection_props, G_VARIANT_TYPE_VARDICT);
g_variant_builder_add (&connection_props, "{sv}",
NMD_CONNECTION_PROPS_PATH,
g_variant_new_object_path (nm_connection_get_path (connection)));
filename = nm_settings_connection_get_filename (NM_SETTINGS_CONNECTION (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 (NM_SETTINGS_CONNECTION (connection))) {
value_hash_add_bool (connection_props,
NMD_CONNECTION_PROPS_EXTERNAL,
TRUE);
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 ();
connection_dict = g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0);
g_variant_builder_init (&connection_props, G_VARIANT_TYPE_VARDICT);
}
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 (&device_dhcp4_props, G_VARIANT_TYPE_VARDICT);
g_variant_builder_init (&device_dhcp6_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);
}
}
/* Send the action to the dispatcher */
if (blocking) {
GPtrArray *results = NULL;
GVariant *ret;
GVariantIter *results;
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) {
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);
nm_log_warn (LOGD_DISPATCH, "(%u) failed: %s", reqid, error->message);
g_clear_error (&error);
success = FALSE;
}
} else {
info = g_malloc0 (sizeof (*info));
@@ -556,37 +634,25 @@ _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);
done:
if (success && info) {
/* Track the request in case of cancelation */
@@ -777,6 +843,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);
@@ -787,5 +854,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);
}
}

View File

@@ -23,11 +23,10 @@
#include <string.h>
#include <glib.h>
#include <gio/gio.h>
#include <dbus/dbus.h>
#include "nm-firewall-manager.h"
#include "nm-dbus-manager.h"
#include "nm-logging.h"
#include "gsystem-local-alloc.h"
#define NM_FIREWALL_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
NM_TYPE_FIREWALL_MANAGER, \
@@ -43,9 +42,7 @@ enum {
};
typedef struct {
NMDBusManager * dbus_mgr;
guint name_owner_id;
DBusGProxy * proxy;
GDBusProxy * proxy;
gboolean running;
GSList *pending_calls;
@@ -70,36 +67,50 @@ typedef struct {
FwAddToZoneFunc callback;
gpointer user_data;
guint id;
gboolean completed;
guint idle_id;
DBusGProxyCall *dbus_call;
GCancellable *cancellable;
} CBInfo;
static void
_cb_info_free (CBInfo *info)
_cb_info_complete_and_free (CBInfo *info,
const char *tag,
const char *debug_error_match,
GError *error)
{
NMFirewallManagerPrivate *priv;
gs_free_error GError *local = NULL;
g_return_if_fail (info != NULL);
g_return_if_fail (tag != NULL);
if (!info->completed) {
nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone call cancelled [%u]", info->iface, info->id);
if (info->callback) {
GError *error;
error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_CANCELLED,
"Operation was cancelled");
info->callback (error, info->user_data);
g_error_free (error);
}
/* A cancelled idle call won't set the error; catch that here */
if (!error && g_cancellable_is_cancelled (info->cancellable)) {
error = local = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_CANCELLED,
"Operation was cancelled");
}
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone %s call cancelled [%u]",
info->iface, tag, info->id);
} else if (error) {
g_dbus_error_strip_remote_error (error);
if (!g_strcmp0 (error->message, debug_error_match)) {
nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone %s failed [%u]: %s",
info->iface, tag, info->id, error->message);
} else {
nm_log_warn (LOGD_FIREWALL, "(%s) firewall zone %s failed [%u]: %s",
info->iface, tag, info->id, error->message);
}
} else {
nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone %s succeeded [%u]",
info->iface, tag, info->id);
}
if (info->callback)
info->callback (error, info->user_data);
g_free (info->iface);
priv = NM_FIREWALL_MANAGER_GET_PRIVATE (info->self);
priv->pending_calls = g_slist_remove (priv->pending_calls, info);
g_object_unref (info->self);
g_object_unref (info->cancellable);
g_slice_free (CBInfo, info);
}
@@ -107,16 +118,14 @@ static CBInfo *
_cb_info_create (NMFirewallManager *self, const char *iface, FwAddToZoneFunc callback, gpointer user_data)
{
NMFirewallManagerPrivate *priv = NM_FIREWALL_MANAGER_GET_PRIVATE (self);
static guint id;
static guint id = 1;
CBInfo *info;
info = g_slice_new0 (CBInfo);
if (++id == 0)
++id;
info->self = g_object_ref (self);
info->id = id;
info->id = id++;
info->iface = g_strdup (iface);
info->completed = FALSE;
info->cancellable = g_cancellable_new ();
info->callback = callback;
info->user_data = user_data;
@@ -129,50 +138,20 @@ add_or_change_idle_cb (gpointer user_data)
{
CBInfo *info = user_data;
if (info->idle_id == 0) {
/* operation was cancelled. _cb_info_free will invoke callback. */
} else {
nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone call pretends success [%u]",
info->iface, info->id);
if (info->callback)
info->callback (NULL, info->user_data);
info->completed = TRUE;
info->idle_id = 0;
}
_cb_info_free (info);
info->idle_id = 0;
_cb_info_complete_and_free (info, "idle call", NULL, NULL);
return G_SOURCE_REMOVE;
}
static void
add_or_change_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
add_or_change_cb (GObject *proxy, GAsyncResult *result, gpointer user_data)
{
CBInfo *info = user_data;
GError *error = NULL;
char *zone = NULL;
gs_free_error GError *error = NULL;
gs_unref_variant GVariant *ret = NULL;
if (!dbus_g_proxy_end_call (proxy, call_id, &error,
G_TYPE_STRING, &zone,
G_TYPE_INVALID)) {
g_assert (error);
if (g_strcmp0 (error->message, "ZONE_ALREADY_SET") != 0) {
nm_log_warn (LOGD_FIREWALL, "(%s) firewall zone add/change failed [%u]: (%d) %s",
info->iface, info->id, error->code, error->message);
} else {
nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone add/change failed [%u]: (%d) %s",
info->iface, info->id, error->code, error->message);
}
} else {
nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone add/change succeeded [%u]",
info->iface, info->id);
}
if (info->callback)
info->callback (error, info->user_data);
info->completed = TRUE;
g_free (zone);
g_clear_error (&error);
ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result, &error);
_cb_info_complete_and_free (info, "add/change", "ZONE_ALREADY_SET", error);
}
NMFirewallPendingCall
@@ -203,45 +182,24 @@ nm_firewall_manager_add_or_change_zone (NMFirewallManager *self,
nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone %s -> %s%s%s [%u]", iface, add ? "add" : "change",
zone?"\"":"", zone ? zone : "default", zone?"\"":"", info->id);
info->dbus_call = dbus_g_proxy_begin_call_with_timeout (priv->proxy,
add ? "addInterface" : "changeZone",
add_or_change_cb,
info,
(GDestroyNotify) _cb_info_free,
10000, /* timeout */
G_TYPE_STRING, zone ? zone : "",
G_TYPE_STRING, iface,
G_TYPE_INVALID);
return PENDING_CALL_FROM_INFO (info);
g_dbus_proxy_call (priv->proxy,
add ? "addInterface" : "changeZone",
g_variant_new ("(ss)", zone ? zone : "", iface),
G_DBUS_CALL_FLAGS_NONE, 10000,
info->cancellable,
add_or_change_cb, info);
return (NMFirewallPendingCall) info;
}
static void
remove_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
remove_cb (GObject *proxy, GAsyncResult *result, gpointer user_data)
{
CBInfo *info = user_data;
GError *error = NULL;
char * zone = NULL;
gs_free_error GError *error = NULL;
gs_unref_variant GVariant *ret = NULL;
if (!dbus_g_proxy_end_call (proxy, call_id, &error,
G_TYPE_STRING, &zone,
G_TYPE_INVALID)) {
g_assert (error);
/* ignore UNKNOWN_INTERFACE errors */
if (error->message && !strstr (error->message, "UNKNOWN_INTERFACE")) {
nm_log_warn (LOGD_FIREWALL, "(%s) firewall zone remove failed [%u]: (%d) %s",
info->iface, info->id, error->code, error->message);
} else {
nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone remove failed [%u]: (%d) %s",
info->iface, info->id, error->code, error->message);
}
} else {
nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone remove succeeded [%u]",
info->iface, info->id);
}
info->completed = TRUE;
g_free (zone);
g_clear_error (&error);
ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result, &error);
_cb_info_complete_and_free (info, "remove", "UNKNOWN_INTERFACE", error);
}
NMFirewallPendingCall
@@ -261,42 +219,25 @@ nm_firewall_manager_remove_from_zone (NMFirewallManager *self,
nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone remove -> %s%s%s [%u]", iface,
zone?"\"":"", zone ? zone : "*", zone?"\"":"", info->id);
info->dbus_call = dbus_g_proxy_begin_call_with_timeout (priv->proxy,
"removeInterface",
remove_cb,
info,
(GDestroyNotify) _cb_info_free,
10000, /* timeout */
G_TYPE_STRING, zone ? zone : "",
G_TYPE_STRING, iface,
G_TYPE_INVALID);
return PENDING_CALL_FROM_INFO (info);
g_dbus_proxy_call (priv->proxy,
"removeInterface",
g_variant_new ("(ss)", zone ? zone : "", iface),
G_DBUS_CALL_FLAGS_NONE, 10000,
info->cancellable,
remove_cb, info);
return (NMFirewallPendingCall) info;
}
void nm_firewall_manager_cancel_call (NMFirewallManager *self, NMFirewallPendingCall call)
void
nm_firewall_manager_cancel_call (NMFirewallManager *self, NMFirewallPendingCall call)
{
NMFirewallManagerPrivate *priv = NM_FIREWALL_MANAGER_GET_PRIVATE (self);
GSList *pending;
CBInfo *info;
CBInfo *info = (CBInfo *) call;
g_return_if_fail (NM_IS_FIREWALL_MANAGER (self));
if (call == PENDING_CALL_DUMMY)
return;
pending = g_slist_find (priv->pending_calls, call);
if (!pending)
return;
priv->pending_calls = g_slist_remove_link (priv->pending_calls, pending);
info = (CBInfo *) call;
if (info->idle_id)
info->idle_id = 0;
else {
dbus_g_proxy_cancel_call (NM_FIREWALL_MANAGER_GET_PRIVATE (self)->proxy,
info->dbus_call);
}
info->callback = NULL;
info->idle_id = 0;
g_cancellable_cancel (info->cancellable);
}
static void
@@ -311,25 +252,19 @@ set_running (NMFirewallManager *self, gboolean now_running)
}
static void
name_owner_changed (NMDBusManager *dbus_mgr,
const char *name,
const char *old_owner,
const char *new_owner,
gpointer user_data)
name_owner_changed (GObject *object,
GParamSpec *pspec,
gpointer user_data)
{
NMFirewallManager *self = NM_FIREWALL_MANAGER (user_data);
gboolean old_owner_good = (old_owner && strlen (old_owner));
gboolean new_owner_good = (new_owner && strlen (new_owner));
gs_free char *owner = NULL;
/* We only care about the firewall here */
if (strcmp (FIREWALL_DBUS_SERVICE, name) != 0)
return;
if (!old_owner_good && new_owner_good) {
owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (object));
if (owner) {
nm_log_dbg (LOGD_FIREWALL, "firewall started");
set_running (self, TRUE);
g_signal_emit (self, signals[STARTED], 0);
} else if (old_owner_good && !new_owner_good) {
} else {
nm_log_dbg (LOGD_FIREWALL, "firewall stopped");
set_running (self, FALSE);
}
@@ -343,21 +278,23 @@ static void
nm_firewall_manager_init (NMFirewallManager * self)
{
NMFirewallManagerPrivate *priv = NM_FIREWALL_MANAGER_GET_PRIVATE (self);
DBusGConnection *bus;
gs_free char *owner = NULL;
priv->dbus_mgr = g_object_ref (nm_dbus_manager_get ());
priv->name_owner_id = g_signal_connect (priv->dbus_mgr,
NM_DBUS_MANAGER_NAME_OWNER_CHANGED,
G_CALLBACK (name_owner_changed),
self);
priv->running = nm_dbus_manager_name_has_owner (priv->dbus_mgr, FIREWALL_DBUS_SERVICE);
priv->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,
FIREWALL_DBUS_SERVICE,
FIREWALL_DBUS_PATH,
FIREWALL_DBUS_INTERFACE_ZONE,
NULL, NULL);
g_signal_connect (priv->proxy, "notify::g-name-owner",
G_CALLBACK (name_owner_changed), self);
owner = g_dbus_proxy_get_name_owner (priv->proxy);
priv->running = (owner != NULL);
nm_log_dbg (LOGD_FIREWALL, "firewall %s running", priv->running ? "is" : "is not" );
bus = nm_dbus_manager_get_connection (priv->dbus_mgr);
priv->proxy = dbus_g_proxy_new_for_name (bus,
FIREWALL_DBUS_SERVICE,
FIREWALL_DBUS_PATH,
FIREWALL_DBUS_INTERFACE_ZONE);
}
static void
@@ -386,12 +323,6 @@ dispose (GObject *object)
g_assert (priv->pending_calls == NULL);
if (priv->dbus_mgr) {
g_signal_handler_disconnect (priv->dbus_mgr, priv->name_owner_id);
priv->name_owner_id = 0;
g_clear_object (&priv->dbus_mgr);
}
g_clear_object (&priv->proxy);
/* Chain up to the parent class */

View File

@@ -190,7 +190,7 @@ typedef struct {
NMVpnManager *vpn_manager;
DBusGProxy *aipd_proxy;
GDBusProxy *aipd_proxy;
NMSleepMonitor *sleep_monitor;
GSList *auth_chains;
@@ -801,7 +801,7 @@ device_removed_cb (NMDevice *device, gpointer user_data)
}
static void
aipd_handle_event (DBusGProxy *proxy,
aipd_handle_event (GDBusProxy *proxy,
const char *event,
const char *iface,
const char *address,
@@ -812,11 +812,6 @@ aipd_handle_event (DBusGProxy *proxy,
GSList *iter;
gboolean handled = FALSE;
if (!event || !iface) {
nm_log_warn (LOGD_AUTOIP4, "incomplete message received from avahi-autoipd");
return;
}
if ( (strcmp (event, "BIND") != 0)
&& (strcmp (event, "CONFLICT") != 0)
&& (strcmp (event, "UNBIND") != 0)
@@ -3865,14 +3860,14 @@ impl_manager_sleep (NMManager *self,
}
static void
sleeping_cb (DBusGProxy *proxy, gpointer user_data)
sleeping_cb (NMSleepMonitor *monitor, gpointer user_data)
{
nm_log_dbg (LOGD_SUSPEND, "Received sleeping signal");
_internal_sleep (NM_MANAGER (user_data), TRUE);
}
static void
resuming_cb (DBusGProxy *proxy, gpointer user_data)
resuming_cb (NMSleepMonitor *monitor, gpointer user_data)
{
nm_log_dbg (LOGD_SUSPEND, "Received resuming signal");
_internal_sleep (NM_MANAGER (user_data), FALSE);
@@ -4870,9 +4865,9 @@ static void
nm_manager_init (NMManager *manager)
{
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
DBusGConnection *g_connection;
guint i;
GFile *file;
GError *error = NULL;
/* Initialize rfkill structures and states */
memset (priv->radio_states, 0, sizeof (priv->radio_states));
@@ -4913,30 +4908,22 @@ nm_manager_init (NMManager *manager)
priv->vpn_manager = g_object_ref (nm_vpn_manager_get ());
g_connection = nm_dbus_manager_get_connection (priv->dbus_mgr);
/* avahi-autoipd stuff */
priv->aipd_proxy = dbus_g_proxy_new_for_name (g_connection,
NM_AUTOIP_DBUS_SERVICE,
"/",
NM_AUTOIP_DBUS_IFACE);
priv->aipd_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
NULL,
NM_AUTOIP_DBUS_SERVICE,
"/",
NM_AUTOIP_DBUS_IFACE,
NULL, &error);
if (priv->aipd_proxy) {
dbus_g_object_register_marshaller (g_cclosure_marshal_generic,
G_TYPE_NONE,
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
G_TYPE_INVALID);
dbus_g_proxy_add_signal (priv->aipd_proxy,
"Event",
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
G_TYPE_INVALID);
dbus_g_proxy_connect_signal (priv->aipd_proxy, "Event",
G_CALLBACK (aipd_handle_event),
manager,
NULL);
} else
nm_log_warn (LOGD_AUTOIP4, "could not initialize avahi-autoipd D-Bus proxy");
_nm_dbus_signal_connect (priv->aipd_proxy, "Event", G_VARIANT_TYPE ("(sss)"),
G_CALLBACK (aipd_handle_event), manager);
} else {
nm_log_warn (LOGD_AUTOIP4, "could not initialize avahi-autoipd D-Bus proxy: %s",
error->message);
g_clear_error (&error);
}
/* sleep/wake handling */
priv->sleep_monitor = g_object_ref (nm_sleep_monitor_get ());

View File

@@ -28,6 +28,7 @@
#include "nm-logging.h"
#include "nm-dbus-manager.h"
#include "nm-core-internal.h"
#include "nm-sleep-monitor.h"
@@ -123,19 +124,12 @@ take_inhibitor (NMSleepMonitor *self)
}
static void
signal_cb (GDBusProxy *proxy,
const gchar *sendername,
const gchar *signalname,
GVariant *args,
gpointer data)
prepare_for_sleep_cb (GDBusProxy *proxy,
gboolean is_about_to_suspend,
gpointer data)
{
NMSleepMonitor *self = data;
gboolean is_about_to_suspend;
if (strcmp (signalname, "PrepareForSleep") != 0)
return;
g_variant_get (args, "(b)", &is_about_to_suspend);
nm_log_dbg (LOGD_SUSPEND, "Received PrepareForSleep signal: %d", is_about_to_suspend);
if (is_about_to_suspend) {
@@ -182,7 +176,8 @@ on_proxy_acquired (GObject *object,
}
g_signal_connect (self->sd_proxy, "notify::g-name-owner", G_CALLBACK (name_owner_cb), self);
g_signal_connect (self->sd_proxy, "g-signal", G_CALLBACK (signal_cb), self);
_nm_dbus_signal_connect (self->sd_proxy, "PrepareForSleep", G_VARIANT_TYPE ("(b)"),
G_CALLBACK (prepare_for_sleep_cb), self);
owner = g_dbus_proxy_get_name_owner (self->sd_proxy);
if (owner)

View File

@@ -22,33 +22,32 @@
#include <errno.h>
#include <string.h>
#include <sys/stat.h>
#include <dbus/dbus-glib.h>
#include <gio/gio.h>
#include "nm-logging.h"
#include "nm-dbus-manager.h"
#include "nm-core-internal.h"
#include "nm-sleep-monitor.h"
#define UPOWER_DBUS_SERVICE "org.freedesktop.UPower"
struct _NMSleepMonitor {
GObject parent_instance;
GObject parent_instance;
DBusGProxy *upower_proxy;
GDBusProxy *upower_proxy;
};
struct _NMSleepMonitorClass {
GObjectClass parent_class;
GObjectClass parent_class;
void (*sleeping) (NMSleepMonitor *monitor);
void (*resuming) (NMSleepMonitor *monitor);
void (*sleeping) (NMSleepMonitor *monitor);
void (*resuming) (NMSleepMonitor *monitor);
};
enum {
SLEEPING,
RESUMING,
LAST_SIGNAL,
SLEEPING,
RESUMING,
LAST_SIGNAL,
};
static guint signals[LAST_SIGNAL] = {0};
@@ -57,80 +56,78 @@ G_DEFINE_TYPE (NMSleepMonitor, nm_sleep_monitor, G_TYPE_OBJECT);
/********************************************************************/
static void
upower_sleeping_cb (DBusGProxy *proxy, gpointer user_data)
upower_sleeping_cb (GDBusProxy *proxy, gpointer user_data)
{
nm_log_dbg (LOGD_SUSPEND, "Received UPower sleeping signal");
g_signal_emit (user_data, signals[SLEEPING], 0);
nm_log_dbg (LOGD_SUSPEND, "Received UPower sleeping signal");
g_signal_emit (user_data, signals[SLEEPING], 0);
}
static void
upower_resuming_cb (DBusGProxy *proxy, gpointer user_data)
upower_resuming_cb (GDBusProxy *proxy, gpointer user_data)
{
nm_log_dbg (LOGD_SUSPEND, "Received UPower resuming signal");
g_signal_emit (user_data, signals[RESUMING], 0);
nm_log_dbg (LOGD_SUSPEND, "Received UPower resuming signal");
g_signal_emit (user_data, signals[RESUMING], 0);
}
static void
nm_sleep_monitor_init (NMSleepMonitor *self)
{
DBusGConnection *bus;
GError *error = NULL;
bus = nm_dbus_manager_get_connection (nm_dbus_manager_get ());
self->upower_proxy = dbus_g_proxy_new_for_name (bus,
UPOWER_DBUS_SERVICE,
"/org/freedesktop/UPower",
"org.freedesktop.UPower");
if (self->upower_proxy) {
dbus_g_proxy_add_signal (self->upower_proxy, "Sleeping", G_TYPE_INVALID);
dbus_g_proxy_connect_signal (self->upower_proxy, "Sleeping",
G_CALLBACK (upower_sleeping_cb),
self, NULL);
dbus_g_proxy_add_signal (self->upower_proxy, "Resuming", G_TYPE_INVALID);
dbus_g_proxy_connect_signal (self->upower_proxy, "Resuming",
G_CALLBACK (upower_resuming_cb),
self, NULL);
} else
nm_log_warn (LOGD_SUSPEND, "could not initialize UPower D-Bus proxy");
self->upower_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START |
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
NULL,
UPOWER_DBUS_SERVICE,
"/org/freedesktop/UPower",
"org.freedesktop.UPower",
NULL, &error);
if (self->upower_proxy) {
_nm_dbus_signal_connect (self->upower_proxy, "Sleeping", NULL,
G_CALLBACK (upower_sleeping_cb), self);
_nm_dbus_signal_connect (self->upower_proxy, "Resuming", NULL,
G_CALLBACK (upower_resuming_cb), self);
} else {
nm_log_warn (LOGD_SUSPEND, "could not initialize UPower D-Bus proxy: %s", error->message);
g_error_free (error);
}
}
static void
finalize (GObject *object)
{
NMSleepMonitor *self = NM_SLEEP_MONITOR (object);
NMSleepMonitor *self = NM_SLEEP_MONITOR (object);
if (self->upower_proxy)
g_object_unref (self->upower_proxy);
g_clear_object (&self->upower_proxy);
if (G_OBJECT_CLASS (nm_sleep_monitor_parent_class)->finalize != NULL)
G_OBJECT_CLASS (nm_sleep_monitor_parent_class)->finalize (object);
G_OBJECT_CLASS (nm_sleep_monitor_parent_class)->finalize (object);
}
static void
nm_sleep_monitor_class_init (NMSleepMonitorClass *klass)
{
GObjectClass *gobject_class;
GObjectClass *gobject_class;
gobject_class = G_OBJECT_CLASS (klass);
gobject_class = G_OBJECT_CLASS (klass);
gobject_class->finalize = finalize;
gobject_class->finalize = finalize;
signals[SLEEPING] = g_signal_new (NM_SLEEP_MONITOR_SLEEPING,
NM_TYPE_SLEEP_MONITOR,
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (NMSleepMonitorClass, sleeping),
NULL, /* accumulator */
NULL, /* accumulator data */
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
signals[RESUMING] = g_signal_new (NM_SLEEP_MONITOR_RESUMING,
NM_TYPE_SLEEP_MONITOR,
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (NMSleepMonitorClass, resuming),
NULL, /* accumulator */
NULL, /* accumulator data */
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
signals[SLEEPING] = g_signal_new (NM_SLEEP_MONITOR_SLEEPING,
NM_TYPE_SLEEP_MONITOR,
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (NMSleepMonitorClass, sleeping),
NULL, /* accumulator */
NULL, /* accumulator data */
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
signals[RESUMING] = g_signal_new (NM_SLEEP_MONITOR_RESUMING,
NM_TYPE_SLEEP_MONITOR,
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (NMSleepMonitorClass, resuming),
NULL, /* accumulator */
NULL, /* accumulator data */
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
}
NM_DEFINE_SINGLETON_GETTER (NMSleepMonitor, nm_sleep_monitor_get, NM_TYPE_SLEEP_MONITOR);

View File

@@ -404,19 +404,6 @@ nm_supplicant_interface_credentials_reply (NMSupplicantInterface *self,
return !!reply;
}
static gboolean
_dbus_error_has_name (GError *error, const char *dbus_error_name)
{
gs_free char *error_name = NULL;
gboolean is_error = FALSE;
if (error && g_dbus_error_is_remote_error (error)) {
error_name = g_dbus_error_get_remote_error (error);
is_error = !g_strcmp0 (error_name, dbus_error_name);
}
return is_error;
}
static void
iface_check_netreply_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
{
@@ -439,7 +426,7 @@ iface_check_netreply_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_
self = NM_SUPPLICANT_INTERFACE (user_data);
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
if (variant || _dbus_error_has_name (error, "fi.w1.wpa_supplicant1.InvalidArgs"))
if (variant || _nm_dbus_error_has_name (error, "fi.w1.wpa_supplicant1.InvalidArgs"))
priv->has_credreq = TRUE;
nm_log_dbg (LOGD_SUPPLICANT, "Supplicant %s network credentials requests",
@@ -477,14 +464,16 @@ iface_check_ap_mode_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_d
const char *data;
/* The ProbeRequest method only exists if AP mode has been enabled */
variant = g_dbus_proxy_call_finish (proxy, result, &error);
variant = _nm_dbus_proxy_call_finish (proxy, result,
G_VARIANT_TYPE ("(s)"),
&error);
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return;
self = NM_SUPPLICANT_INTERFACE (user_data);
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
if (variant && g_variant_is_of_type (variant, G_VARIANT_TYPE ("(s)"))) {
if (variant) {
g_variant_get (variant, "(&s)", &data);
if (strstr (data, "ProbeRequest"))
priv->ap_support = AP_SUPPORT_YES;
@@ -493,41 +482,59 @@ iface_check_ap_mode_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_d
iface_check_ready (self);
}
#define MATCH_SIGNAL(s, n, v, t) (!strcmp (s, n) && g_variant_is_of_type (v, t))
static void
signal_cb (GDBusProxy *proxy,
const gchar *sender,
const gchar *signal,
GVariant *args,
gpointer user_data)
wpas_iface_scan_done (GDBusProxy *proxy,
gboolean success,
gpointer user_data)
{
NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
const char *path, *field, *message;
gboolean success;
if (MATCH_SIGNAL (signal, "ScanDone", args, G_VARIANT_TYPE ("(b)"))) {
/* Cache last scan completed time */
/* Cache last scan completed time */
priv->last_scan = nm_utils_get_monotonic_timestamp_s ();
g_signal_emit (self, signals[SCAN_DONE], 0, success);
}
static void
wpas_iface_bss_added (GDBusProxy *proxy,
const char *path,
GVariant *props,
gpointer user_data)
{
NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
if (priv->scanning)
priv->last_scan = nm_utils_get_monotonic_timestamp_s ();
g_variant_get (args, "(b)", &success);
g_signal_emit (self, signals[SCAN_DONE], 0, success);
} else if (MATCH_SIGNAL (signal, "BSSAdded", args, G_VARIANT_TYPE ("(oa{sv})"))) {
if (priv->scanning)
priv->last_scan = nm_utils_get_monotonic_timestamp_s ();
handle_new_bss (self, path);
}
g_variant_get (args, "(&oa{sv})", &path, NULL);
handle_new_bss (self, path);
} else if (MATCH_SIGNAL (signal, "BSSRemoved", args, G_VARIANT_TYPE ("(o)"))) {
g_variant_get (args, "(&o)", &path);
g_signal_emit (self, signals[BSS_REMOVED], 0, path);
g_hash_table_remove (priv->bss_proxies, path);
} else if (MATCH_SIGNAL (signal, "NetworkRequest", args, G_VARIANT_TYPE ("(oss)"))) {
g_variant_get (args, "(&o&s&s)", &path, &field, &message);
if (priv->has_credreq && priv->net_path && !g_strcmp0 (path, priv->net_path))
g_signal_emit (self, signals[CREDENTIALS_REQUEST], 0, field, message);
}
static void
wpas_iface_bss_removed (GDBusProxy *proxy,
const char *path,
gpointer user_data)
{
NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
g_signal_emit (self, signals[BSS_REMOVED], 0, path);
g_hash_table_remove (priv->bss_proxies, path);
}
static void
wpas_iface_network_request (GDBusProxy *proxy,
const char *path,
const char *field,
const char *message,
gpointer user_data)
{
NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
if (priv->has_credreq && priv->net_path && !g_strcmp0 (path, priv->net_path))
g_signal_emit (self, signals[CREDENTIALS_REQUEST], 0, field, message);
}
static void
@@ -602,7 +609,14 @@ on_iface_proxy_acquired (GDBusProxy *proxy, GAsyncResult *result, gpointer user_
self = NM_SUPPLICANT_INTERFACE (user_data);
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
g_signal_connect (priv->iface_proxy, "g-signal", G_CALLBACK (signal_cb), self);
_nm_dbus_signal_connect (priv->iface_proxy, "ScanDone", G_VARIANT_TYPE ("(b)"),
G_CALLBACK (wpas_iface_scan_done), self);
_nm_dbus_signal_connect (priv->iface_proxy, "BSSAdded", G_VARIANT_TYPE ("(oa{sv})"),
G_CALLBACK (wpas_iface_bss_added), self);
_nm_dbus_signal_connect (priv->iface_proxy, "BSSRemoved", G_VARIANT_TYPE ("(o)"),
G_CALLBACK (wpas_iface_bss_removed), self);
_nm_dbus_signal_connect (priv->iface_proxy, "NetworkRequest", G_VARIANT_TYPE ("(oss)"),
G_CALLBACK (wpas_iface_network_request), self);
/* Check whether NetworkReply and AP mode are supported */
priv->ready_count = 1;
@@ -666,19 +680,20 @@ interface_get_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
NMSupplicantInterfacePrivate *priv;
gs_unref_variant GVariant *variant = NULL;
gs_free_error GError *error = NULL;
char *path;
const char *path;
variant = g_dbus_proxy_call_finish (proxy, result, &error);
variant = _nm_dbus_proxy_call_finish (proxy, result,
G_VARIANT_TYPE ("(o)"),
&error);
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return;
self = NM_SUPPLICANT_INTERFACE (user_data);
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
if (variant && g_variant_is_of_type (variant, G_VARIANT_TYPE ("(o)"))) {
g_variant_get (variant, "(o)", &path);
if (variant) {
g_variant_get (variant, "(&o)", &path);
interface_add_done (self, path);
g_free (path);
} else {
nm_log_err (LOGD_SUPPLICANT, "(%s): error getting interface: %s", priv->dev, error->message);
set_state (self, NM_SUPPLICANT_INTERFACE_STATE_DOWN);
@@ -692,20 +707,21 @@ interface_add_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
NMSupplicantInterfacePrivate *priv;
gs_free_error GError *error = NULL;
gs_unref_variant GVariant *variant = NULL;
char *path;
const char *path;
variant = g_dbus_proxy_call_finish (proxy, result, &error);
variant = _nm_dbus_proxy_call_finish (proxy, result,
G_VARIANT_TYPE ("(o)"),
&error);
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return;
self = NM_SUPPLICANT_INTERFACE (user_data);
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
if (variant && g_variant_is_of_type (variant, G_VARIANT_TYPE ("(o)"))) {
g_variant_get (variant, "(o)", &path);
if (variant) {
g_variant_get (variant, "(&o)", &path);
interface_add_done (self, path);
g_free (path);
} else if (_dbus_error_has_name (error, WPAS_ERROR_EXISTS_ERROR)) {
} else if (_nm_dbus_error_has_name (error, WPAS_ERROR_EXISTS_ERROR)) {
/* Interface already added, just get its object path */
g_dbus_proxy_call (priv->wpas_proxy,
"GetInterface",
@@ -963,19 +979,15 @@ add_network_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
const char *blob_name;
GByteArray *blob_data;
reply = g_dbus_proxy_call_finish (proxy, result, &error);
reply = _nm_dbus_proxy_call_finish (proxy, result,
G_VARIANT_TYPE ("(o)"),
&error);
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return;
self = NM_SUPPLICANT_INTERFACE (user_data);
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
if (reply && !g_variant_is_of_type (reply, G_VARIANT_TYPE ("(o)"))) {
error = g_error_new (NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED,
"Unexpected AddNetwork reply type %s",
g_variant_get_type_string (reply));
}
g_free (priv->net_path);
priv->net_path = NULL;
@@ -986,7 +998,6 @@ add_network_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
}
g_variant_get (reply, "(o)", &priv->net_path);
g_assert (priv->net_path);
/* Send blobs first; otherwise jump to selecting the network */
blobs = nm_supplicant_config_get_blobs (priv->cfg);

View File

@@ -1580,44 +1580,74 @@ really_activate (NMVpnConnection *self, const char *username)
_set_vpn_state (self, STATE_CONNECT, NM_VPN_CONNECTION_STATE_REASON_NONE, FALSE);
}
#define MATCH_SIGNAL(s, n, v, t) (!strcmp (s, n) && g_variant_is_of_type (v, t))
static void
failure_cb (GDBusProxy *proxy,
guint32 reason,
gpointer user_data)
{
NMVpnConnection *self = NM_VPN_CONNECTION (user_data);
plugin_failed (self, reason);
}
static void
signal_cb (GDBusProxy *proxy,
const gchar *sender,
const gchar *signal,
GVariant *args,
gpointer user_data)
state_changed_cb (GDBusProxy *proxy,
guint32 new_service_state,
gpointer user_data)
{
NMVpnConnection *self = NM_VPN_CONNECTION (user_data);
plugin_state_changed (self, new_service_state);
}
static void
secrets_required_cb (GDBusProxy *proxy,
const char *message,
const char **secrets,
gpointer user_data)
{
NMVpnConnection *self = NM_VPN_CONNECTION (user_data);
plugin_interactive_secrets_required (self, message, secrets);
}
static void
config_cb (GDBusProxy *proxy,
GVariant *dict,
gpointer user_data)
{
NMVpnConnection *self = NM_VPN_CONNECTION (user_data);
NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (self);
const char *message, **secrets;
gs_unref_variant GVariant *dict = NULL;
guint u32;
if (MATCH_SIGNAL (signal, "Failure", args, G_VARIANT_TYPE ("(u)"))) {
g_variant_get (args, "(u)", &u32);
plugin_failed (self, u32);
} else if (MATCH_SIGNAL (signal, "StateChanged", args, G_VARIANT_TYPE ("(u)"))) {
g_variant_get (args, "(u)", &u32);
plugin_state_changed (self, u32);
} else if (MATCH_SIGNAL (signal, "SecretsRequired", args, G_VARIANT_TYPE ("(sas)"))) {
g_variant_get (args, "(&s^a&s)", &message, &secrets);
plugin_interactive_secrets_required (self, message, secrets);
g_free (secrets);
} else if (priv->vpn_state >= STATE_NEED_AUTH) {
/* Only list to these signals during and after connection */
if (MATCH_SIGNAL (signal, "Config", args, G_VARIANT_TYPE ("(a{sv})"))) {
g_variant_get (args, "(@a{sv})", &dict);
nm_vpn_connection_config_get (self, dict);
} else if (MATCH_SIGNAL (signal, "Ip4Config", args, G_VARIANT_TYPE ("(a{sv})"))) {
g_variant_get (args, "(@a{sv})", &dict);
nm_vpn_connection_ip4_config_get (self, dict);
} else if (MATCH_SIGNAL (signal, "Ip6Config", args, G_VARIANT_TYPE ("(a{sv})"))) {
g_variant_get (args, "(@a{sv})", &dict);
nm_vpn_connection_ip6_config_get (self, dict);
}
}
/* Only list to this signals during and after connection */
if (priv->vpn_state >= STATE_NEED_AUTH)
nm_vpn_connection_config_get (self, dict);
}
static void
ip4_config_cb (GDBusProxy *proxy,
GVariant *dict,
gpointer user_data)
{
NMVpnConnection *self = NM_VPN_CONNECTION (user_data);
NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (self);
/* Only list to this signals during and after connection */
if (priv->vpn_state >= STATE_NEED_AUTH)
nm_vpn_connection_ip4_config_get (self, dict);
}
static void
ip6_config_cb (GDBusProxy *proxy,
GVariant *dict,
gpointer user_data)
{
NMVpnConnection *self = NM_VPN_CONNECTION (user_data);
NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (self);
/* Only list to this signals during and after connection */
if (priv->vpn_state >= STATE_NEED_AUTH)
nm_vpn_connection_ip6_config_get (self, dict);
}
static void
@@ -1648,7 +1678,18 @@ on_proxy_acquired (GObject *object, GAsyncResult *result, gpointer user_data)
}
priv->proxy = proxy;
g_signal_connect (priv->proxy, "g-signal", G_CALLBACK (signal_cb), self);
_nm_dbus_signal_connect (priv->proxy, "Failure", G_VARIANT_TYPE ("(u)"),
G_CALLBACK (failure_cb), self);
_nm_dbus_signal_connect (priv->proxy, "StateChanged", G_VARIANT_TYPE ("(u)"),
G_CALLBACK (state_changed_cb), self);
_nm_dbus_signal_connect (priv->proxy, "SecretsRequired", G_VARIANT_TYPE ("(sas)"),
G_CALLBACK (secrets_required_cb), self);
_nm_dbus_signal_connect (priv->proxy, "Config", G_VARIANT_TYPE ("(a{sv})"),
G_CALLBACK (config_cb), self);
_nm_dbus_signal_connect (priv->proxy, "Ip4Config", G_VARIANT_TYPE ("(a{sv})"),
G_CALLBACK (ip4_config_cb), self);
_nm_dbus_signal_connect (priv->proxy, "Ip6Config", G_VARIANT_TYPE ("(a{sv})"),
G_CALLBACK (ip6_config_cb), self);
_set_vpn_state (self, STATE_NEED_AUTH, NM_VPN_CONNECTION_STATE_REASON_NONE, FALSE);
@@ -1810,7 +1851,7 @@ plugin_need_secrets_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_d
gs_free_error GError *error = NULL;
const char *setting_name;
reply = g_dbus_proxy_call_finish (proxy, result, &error);
reply = _nm_dbus_proxy_call_finish (proxy, result, G_VARIANT_TYPE ("(s)"), &error);
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return;