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_build)/nm-core-enum-types.c \
$(core)/crypto.c \ $(core)/crypto.c \
$(core)/nm-connection.c \ $(core)/nm-connection.c \
$(core)/nm-dbus-utils.c \
$(core)/nm-errors.c \ $(core)/nm-errors.c \
$(core)/nm-keyfile-reader.c \ $(core)/nm-keyfile-reader.c \
$(core)/nm-keyfile-utils.c \ $(core)/nm-keyfile-utils.c \

View File

@@ -33,6 +33,8 @@
* and some test programs. * and some test programs.
**/ **/
#include <gio/gio.h>
#include "nm-connection.h" #include "nm-connection.h"
#include "nm-core-enum-types.h" #include "nm-core-enum-types.h"
#include "nm-dbus-interface.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); 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 #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-glib-compat.h"
#include "nm-dbus-helpers.h" #include "nm-dbus-helpers.h"
#include "nm-client.h" #include "nm-client.h"
#include "nm-core-internal.h"
static gboolean debug = FALSE; static gboolean debug = FALSE;
#define dbgmsg(f,...) if (G_UNLIKELY (debug)) { g_message (f, ## __VA_ARGS__ ); } #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; GError *error = NULL;
GType type; 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) { if (ret) {
g_variant_get (ret, "(v)", &value); g_variant_get (ret, "(v)", &value);
type = type_data->type_func (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); g_variant_unref (ret);
} else { } else {
dbgmsg ("Could not fetch property '%s' of interface '%s' on %s: %s\n", dbgmsg ("Could not fetch property '%s' of interface '%s' on %s: %s\n",
type_data->property, type_data->interface, async_data->path, type_data->property, type_data->interface, async_data->path,
error->message); error->message);
g_clear_error (&error); g_clear_error (&error);
type = G_TYPE_INVALID; type = G_TYPE_INVALID;
} }
@@ -961,20 +963,11 @@ process_properties_changed (NMObject *self, GVariant *properties, gboolean synch
} }
static void static void
property_proxy_signal (GDBusProxy *proxy, properties_changed (GDBusProxy *proxy,
const char *sender_name, GVariant *properties,
const char *signal_name, gpointer user_data)
GVariant *parameters,
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); process_properties_changed (NM_OBJECT (user_data), properties, FALSE);
g_variant_unref (properties);
} }
#define HANDLE_TYPE(vtype, ctype, getter) \ #define HANDLE_TYPE(vtype, ctype, getter) \
@@ -1117,8 +1110,8 @@ _nm_object_register_properties (NMObject *object,
proxy = _nm_object_get_proxy (object, interface); proxy = _nm_object_get_proxy (object, interface);
g_return_if_fail (proxy != NULL); g_return_if_fail (proxy != NULL);
g_signal_connect (proxy, "g-signal", _nm_dbus_signal_connect (proxy, "PropertiesChanged", G_VARIANT_TYPE ("(a{sv})"),
G_CALLBACK (property_proxy_signal), object); G_CALLBACK (properties_changed), object);
instance = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); 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); 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); g_hash_table_iter_init (&iter, priv->proxies);
while (g_hash_table_iter_next (&iter, (gpointer *) &interface, (gpointer *) &proxy)) { while (g_hash_table_iter_next (&iter, (gpointer *) &interface, (gpointer *) &proxy)) {
ret = g_dbus_proxy_call_sync (priv->properties_proxy, ret = _nm_dbus_proxy_call_sync (priv->properties_proxy,
"GetAll", "GetAll",
g_variant_new ("(s)", interface), g_variant_new ("(s)", interface),
G_DBUS_CALL_FLAGS_NONE, -1, G_VARIANT_TYPE ("(a{sv})"),
NULL, error); G_DBUS_CALL_FLAGS_NONE, -1,
NULL, error);
if (!ret) { if (!ret) {
if (error && *error) if (error && *error)
g_dbus_error_strip_remote_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) if (!NM_OBJECT_GET_PRIVATE (object)->nm_running)
return; return;
ret = g_dbus_proxy_call_sync (NM_OBJECT_GET_PRIVATE (object)->properties_proxy, ret = _nm_dbus_proxy_call_sync (NM_OBJECT_GET_PRIVATE (object)->properties_proxy,
"Get", "Get",
g_variant_new ("(ss)", interface, prop_name), g_variant_new ("(ss)", interface, prop_name),
G_DBUS_CALL_FLAGS_NONE, 15000, G_VARIANT_TYPE ("(v)"),
NULL, &err); G_DBUS_CALL_FLAGS_NONE, 15000,
NULL, &err);
if (!ret) { if (!ret) {
dbgmsg ("%s: Error getting '%s' for %s: (%d) %s\n", dbgmsg ("%s: Error getting '%s' for %s: (%d) %s\n",
__func__, __func__,
@@ -1305,7 +1300,9 @@ reload_got_properties (GObject *proxy,
GVariant *ret, *props; GVariant *ret, *props;
GError *error = NULL; 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) { if (ret) {
g_variant_get (ret, "(@a{sv})", &props); g_variant_get (ret, "(@a{sv})", &props);
process_properties_changed (object, props, FALSE); 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 * static char *
get_new_connection_name (const GSList *existing, get_new_connection_name (const GSList *existing,
const char *preferred, 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); 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, const char *nm_utils_get_ip_config_method (NMConnection *connection,
GType ip_setting_type); GType ip_setting_type);

View File

@@ -864,21 +864,14 @@ properties_changed (GDBusProxy *proxy,
static void static void
bluez4_property_changed (GDBusProxy *proxy, bluez4_property_changed (GDBusProxy *proxy,
const char *sender, const char *property,
const char *signal_name, GVariant *v,
GVariant *parameters, gpointer user_data)
gpointer user_data)
{ {
NMBluezDevice *self = NM_BLUEZ_DEVICE (user_data); NMBluezDevice *self = NM_BLUEZ_DEVICE (user_data);
if (g_strcmp0 (signal_name, "PropertyChanged") == 0) { _take_one_variant_property (self, property, v);
const char *property = NULL; check_emit_usable (self);
GVariant *v = NULL;
g_variant_get (parameters, "(&sv)", &property, &v);
_take_one_variant_property (self, property, v);
check_emit_usable (self);
}
} }
static void 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); NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self);
GError *err = NULL; GError *err = NULL;
GVariant *v_properties, *v_dict; 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) { if (!v_properties) {
nm_log_warn (LOGD_BT, "bluez[%s] error getting device properties: %s", 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_error_free (err);
g_signal_emit (self, signals[INITIALIZED], 0, FALSE); g_signal_emit (self, signals[INITIALIZED], 0, FALSE);
goto END; goto END;
} }
v_type = g_variant_type_new ("(a{sv})"); v_dict = g_variant_get_child_value (v_properties, 0);
if (g_variant_is_of_type (v_properties, v_type)) { _set_properties (self, v_dict);
v_dict = g_variant_get_child_value (v_properties, 0); g_variant_unref (v_dict);
_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);
g_variant_unref (v_properties); g_variant_unref (v_properties);
/* Check if any connections match this device */ /* 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; priv->initialized = TRUE;
g_signal_emit (self, signals[INITIALIZED], 0, TRUE); g_signal_emit (self, signals[INITIALIZED], 0, TRUE);
check_emit_usable (self); check_emit_usable (self);
END: END:
@@ -985,8 +971,8 @@ on_proxy_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self)
G_CALLBACK (properties_changed), self); G_CALLBACK (properties_changed), self);
if (priv->bluez_version == 4) { if (priv->bluez_version == 4) {
/* Watch for custom Bluez4 PropertyChanged signals */ /* Watch for custom Bluez4 PropertyChanged signals */
g_signal_connect (priv->proxy, "g-signal", _nm_dbus_signal_connect (priv->proxy, "PropertyChanged", G_VARIANT_TYPE ("(sv)"),
G_CALLBACK (bluez4_property_changed), self); G_CALLBACK (bluez4_property_changed), self);
} }
query_properties (self); query_properties (self);

View File

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

View File

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

View File

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

View File

@@ -34,6 +34,7 @@
#include "nm-bluez-common.h" #include "nm-bluez-common.h"
#include "nm-dbus-manager.h" #include "nm-dbus-manager.h"
#include "nm-core-internal.h"
typedef struct { typedef struct {
NMDBusManager *dbus_mgr; NMDBusManager *dbus_mgr;
@@ -170,39 +171,23 @@ device_removed (GDBusProxy *proxy, const gchar *path, NMBluez5Manager *self)
} }
static void static void
object_manager_g_signal (GDBusProxy *proxy, object_manager_interfaces_added (GDBusProxy *proxy,
gchar *sender_name, const char *path,
gchar *signal_name, GVariant *dict,
GVariant *parameters, NMBluez5Manager *self)
NMBluez5Manager *self)
{ {
GVariant *variant; if (g_variant_lookup (dict, BLUEZ5_DEVICE_INTERFACE, "a{sv}", NULL))
const gchar *path; device_added (proxy, path, self);
}
if (!strcmp (signal_name, "InterfacesRemoved")) { static void
const gchar **ifaces; object_manager_interfaces_removed (GDBusProxy *proxy,
gsize i, length; const char *path,
const char **ifaces,
g_variant_get (parameters, "(&o*)", &path, &variant); NMBluez5Manager *self)
{
ifaces = g_variant_get_strv (variant, &length); if (_nm_utils_string_in_list (BLUEZ5_DEVICE_INTERFACE, ifaces))
device_removed (proxy, path, self);
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 static void
@@ -215,8 +200,9 @@ get_managed_objects_cb (GDBusProxy *proxy,
GError *error = NULL; GError *error = NULL;
const char *path; 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 (!variant) {
if (g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD)) 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?"); 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, (GAsyncReadyCallback) get_managed_objects_cb,
self); self);
g_signal_connect (priv->proxy, "g-signal", _nm_dbus_signal_connect (priv->proxy, "InterfacesAdded", G_VARIANT_TYPE ("(oa{sa{sv}})"),
G_CALLBACK (object_manager_g_signal), self); 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 static void

View File

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

View File

@@ -35,12 +35,17 @@
#include "nm-device.h" #include "nm-device.h"
#include "nm-dhcp4-config.h" #include "nm-dhcp4-config.h"
#include "nm-dhcp6-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-dbus-glib-types.h"
#include "nm-glib-compat.h" #include "nm-glib-compat.h"
#include "nm-settings-connection.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 */ #define CALL_TIMEOUT (1000 * 60 * 10) /* 10 minutes for all scripts */
static GDBusProxy *dispatcher_proxy;
static GHashTable *requests = NULL; static GHashTable *requests = NULL;
typedef struct { typedef struct {
@@ -80,24 +85,145 @@ _get_monitor_by_action (DispatcherAction action)
} }
static void static void
dump_object_to_props (GObject *object, GHashTable *hash) dump_ip4_to_props (NMIP4Config *ip4, GVariantBuilder *builder)
{ {
GParamSpec **pspecs; GVariantBuilder int_builder;
guint len = 0, i; guint n, i;
const NMPlatformIP4Address *addr;
const NMPlatformIP4Route *route;
guint32 array[4];
pspecs = g_object_class_list_properties (G_OBJECT_GET_CLASS (object), &len); /* Addresses */
for (i = 0; i < len; i++) { g_variant_builder_init (&int_builder, G_VARIANT_TYPE ("aau"));
value_hash_add_object_property (hash, n = nm_ip4_config_get_num_addresses (ip4);
pspecs[i]->name, for (i = 0; i < n; i++) {
object, addr = nm_ip4_config_get_address (ip4, i);
pspecs[i]->name, array[0] = addr->address;
pspecs[i]->value_type); 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 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; GSList *options, *iter;
@@ -107,13 +233,13 @@ dump_dhcp4_to_props (NMDhcp4Config *config, GHashTable *hash)
const char *val; const char *val;
val = nm_dhcp4_config_get_option (config, option); 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); g_slist_free (options);
} }
static void static void
dump_dhcp6_to_props (NMDhcp6Config *config, GHashTable *hash) dump_dhcp6_to_props (NMDhcp6Config *config, GVariantBuilder *builder)
{ {
GSList *options, *iter; GSList *options, *iter;
@@ -123,18 +249,18 @@ dump_dhcp6_to_props (NMDhcp6Config *config, GHashTable *hash)
const char *val; const char *val;
val = nm_dhcp6_config_get_option (config, option); 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); g_slist_free (options);
} }
static void static void
fill_device_props (NMDevice *device, fill_device_props (NMDevice *device,
GHashTable *dev_hash, GVariantBuilder *dev_builder,
GHashTable *ip4_hash, GVariantBuilder *ip4_builder,
GHashTable *ip6_hash, GVariantBuilder *ip6_builder,
GHashTable *dhcp4_hash, GVariantBuilder *dhcp4_builder,
GHashTable *dhcp6_hash) GVariantBuilder *dhcp6_builder)
{ {
NMIP4Config *ip4_config; NMIP4Config *ip4_config;
NMIP6Config *ip6_config; NMIP6Config *ip6_config;
@@ -142,39 +268,44 @@ fill_device_props (NMDevice *device,
NMDhcp6Config *dhcp6_config; NMDhcp6Config *dhcp6_config;
/* If the action is for a VPN, send the VPN's IP interface instead of the device's */ /* 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)); g_variant_builder_add (dev_builder, "{sv}", NMD_DEVICE_PROPS_IP_INTERFACE,
value_hash_add_str (dev_hash, NMD_DEVICE_PROPS_INTERFACE, nm_device_get_iface (device)); g_variant_new_string (nm_device_get_ip_iface (device)));
value_hash_add_uint (dev_hash, NMD_DEVICE_PROPS_TYPE, nm_device_get_device_type (device)); g_variant_builder_add (dev_builder, "{sv}", NMD_DEVICE_PROPS_INTERFACE,
value_hash_add_uint (dev_hash, NMD_DEVICE_PROPS_STATE, nm_device_get_state (device)); g_variant_new_string (nm_device_get_iface (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_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); ip4_config = nm_device_get_ip4_config (device);
if (ip4_config) 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); ip6_config = nm_device_get_ip6_config (device);
if (ip6_config) 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); dhcp4_config = nm_device_get_dhcp4_config (device);
if (dhcp4_config) 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); dhcp6_config = nm_device_get_dhcp6_config (device);
if (dhcp6_config) if (dhcp6_config)
dump_dhcp6_to_props (dhcp6_config, dhcp6_hash); dump_dhcp6_to_props (dhcp6_config, dhcp6_builder);
} }
static void static void
fill_vpn_props (NMIP4Config *ip4_config, fill_vpn_props (NMIP4Config *ip4_config,
NMIP6Config *ip6_config, NMIP6Config *ip6_config,
GHashTable *ip4_hash, GVariantBuilder *ip4_builder,
GHashTable *ip6_hash) GVariantBuilder *ip6_builder)
{ {
if (ip4_config) if (ip4_config)
dump_object_to_props (G_OBJECT (ip4_config), ip4_hash); dump_ip4_to_props (ip4_config, ip4_builder);
if (ip6_config) if (ip6_config)
dump_object_to_props (G_OBJECT (ip6_config), ip6_hash); dump_ip6_to_props (ip6_config, ip6_builder);
} }
typedef struct { typedef struct {
@@ -228,51 +359,25 @@ dispatch_result_to_string (DispatchResult result)
g_assert_not_reached (); 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 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); const Monitor *monitor = _get_monitor_by_action (action);
g_return_if_fail (results != NULL); 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", nm_log_dbg (LOGD_DISPATCH, "(%u) succeeded but no scripts invoked",
request_id); request_id);
return; return;
} }
for (i = 0; i < results->len; i++) { while (g_variant_iter_next (results, "(&su&s)", &script, &result, &err)) {
GValueArray *item = g_ptr_array_index (results, i);
GValue *tmp;
const char *script, *err;
DispatchResult result;
const char *script_validation_msg = ""; const char *script_validation_msg = "";
if (item->n_values != 3) { if (!*script) {
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) {
script_validation_msg = " (path is NULL)"; script_validation_msg = " (path is NULL)";
script = "(unknown)"; script = "(unknown)";
} else if (!strncmp (script, monitor->dir, monitor->dir_len) /* check: prefixed by script directory */ } 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 } else
script_validation_msg = " (unexpected path)"; 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) { if (result == DISPATCH_RESULT_SUCCESS) {
nm_log_dbg (LOGD_DISPATCH, "(%u) %s succeeded%s", nm_log_dbg (LOGD_DISPATCH, "(%u) %s succeeded%s",
request_id, request_id,
@@ -307,52 +398,43 @@ dispatcher_results_process (guint request_id, DispatcherAction action, GPtrArray
request_id, request_id,
script, script,
dispatch_result_to_string (result), dispatch_result_to_string (result),
err ? err : "", script_validation_msg); err, script_validation_msg);
} }
} }
} }
static void static void
free_results (GPtrArray *results) dispatcher_done_cb (GObject *proxy, GAsyncResult *result, gpointer user_data)
{
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)
{ {
DispatchInfo *info = user_data; DispatchInfo *info = user_data;
GVariant *ret;
GVariantIter *results;
GError *error = NULL; GError *error = NULL;
GPtrArray *results = NULL;
if (dbus_g_proxy_end_call (proxy, call, &error, ret = _nm_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result,
DISPATCHER_TYPE_RESULT_ARRAY, &results, G_VARIANT_TYPE ("(a(sus))"),
G_TYPE_INVALID)) { &error);
if (ret) {
g_variant_get (ret, "(a(sus))", &results);
dispatcher_results_process (info->request_id, info->action, results); dispatcher_results_process (info->request_id, info->action, results);
free_results (results); g_variant_iter_free (results);
g_variant_unref (ret);
} else { } else {
g_assert (error); if (_nm_dbus_error_has_name (error, "org.freedesktop.systemd1.LoadFailed")) {
g_dbus_error_strip_remote_error (error);
if (!g_error_matches (error, DBUS_GERROR, DBUS_GERROR_REMOTE_EXCEPTION)) { nm_log_warn (LOGD_DISPATCH, "(%u) failed to call dispatcher scripts: %s",
nm_log_warn (LOGD_DISPATCH, "(%u) failed to call dispatcher scripts: (%s:%d) %s", info->request_id, error->message);
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);
} else { } else {
nm_log_dbg (LOGD_DISPATCH, "(%u) failed to call dispatcher scripts: (%s) %s", nm_log_dbg (LOGD_DISPATCH, "(%u) failed to call dispatcher scripts: %s",
info->request_id, dbus_g_error_get_name (error), error->message); info->request_id, error->message);
} }
g_clear_error (&error);
} }
if (info->callback) if (info->callback)
info->callback (info->request_id, info->user_data); info->callback (info->request_id, info->user_data);
g_clear_error (&error); dispatcher_info_cleanup (info);
g_object_unref (proxy);
} }
static const char *action_table[] = { static const char *action_table[] = {
@@ -400,23 +482,24 @@ _dispatcher_call (DispatcherAction action,
gpointer user_data, gpointer user_data,
guint *out_call_id) guint *out_call_id)
{ {
DBusGProxy *proxy; GVariant *connection_dict;
DBusGConnection *g_connection; GVariantBuilder connection_props;
GHashTable *connection_hash; GVariantBuilder device_props;
GHashTable *connection_props; GVariantBuilder device_ip4_props;
GHashTable *device_props; GVariantBuilder device_ip6_props;
GHashTable *device_ip4_props; GVariantBuilder device_dhcp4_props;
GHashTable *device_ip6_props; GVariantBuilder device_dhcp6_props;
GHashTable *device_dhcp4_props; GVariantBuilder vpn_ip4_props;
GHashTable *device_dhcp6_props; GVariantBuilder vpn_ip6_props;
GHashTable *vpn_ip4_props;
GHashTable *vpn_ip6_props;
DispatchInfo *info = NULL; DispatchInfo *info = NULL;
gboolean success = FALSE; gboolean success = FALSE;
GError *error = NULL; GError *error = NULL;
static guint request_counter = 0; static guint request_counter = 0;
guint reqid = ++request_counter; guint reqid = ++request_counter;
if (!dispatcher_proxy)
return FALSE;
/* Wrapping protection */ /* Wrapping protection */
if (G_UNLIKELY (!reqid)) if (G_UNLIKELY (!reqid))
reqid = ++request_counter; reqid = ++request_counter;
@@ -463,92 +546,87 @@ _dispatcher_call (DispatcherAction action,
goto done; 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) { if (connection) {
GVariant *connection_dict;
const char *filename; const char *filename;
connection_dict = nm_connection_to_dbus (connection, NM_CONNECTION_SERIALIZE_NO_SECRETS); 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 (); g_variant_builder_init (&connection_props, G_VARIANT_TYPE_VARDICT);
value_hash_add_object_path (connection_props, g_variant_builder_add (&connection_props, "{sv}",
NMD_CONNECTION_PROPS_PATH, NMD_CONNECTION_PROPS_PATH,
nm_connection_get_path (connection)); g_variant_new_object_path (nm_connection_get_path (connection)));
filename = nm_settings_connection_get_filename (NM_SETTINGS_CONNECTION (connection)); filename = nm_settings_connection_get_filename (NM_SETTINGS_CONNECTION (connection));
if (filename) { if (filename) {
value_hash_add_str (connection_props, g_variant_builder_add (&connection_props, "{sv}",
NMD_CONNECTION_PROPS_FILENAME, NMD_CONNECTION_PROPS_FILENAME,
filename); g_variant_new_string (filename));
} }
if (nm_settings_connection_get_nm_generated_assumed (NM_SETTINGS_CONNECTION (connection))) { if (nm_settings_connection_get_nm_generated_assumed (NM_SETTINGS_CONNECTION (connection))) {
value_hash_add_bool (connection_props, g_variant_builder_add (&connection_props, "{sv}",
NMD_CONNECTION_PROPS_EXTERNAL, NMD_CONNECTION_PROPS_EXTERNAL,
TRUE); g_variant_new_boolean (TRUE));
} }
} else { } else {
connection_hash = value_hash_create (); connection_dict = g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0);
connection_props = value_hash_create (); g_variant_builder_init (&connection_props, G_VARIANT_TYPE_VARDICT);
} }
device_props = value_hash_create (); g_variant_builder_init (&device_props, G_VARIANT_TYPE_VARDICT);
device_ip4_props = value_hash_create (); g_variant_builder_init (&device_ip4_props, G_VARIANT_TYPE_VARDICT);
device_ip6_props = value_hash_create (); g_variant_builder_init (&device_ip6_props, G_VARIANT_TYPE_VARDICT);
device_dhcp4_props = value_hash_create (); g_variant_builder_init (&device_dhcp4_props, G_VARIANT_TYPE_VARDICT);
device_dhcp6_props = value_hash_create (); g_variant_builder_init (&device_dhcp6_props, G_VARIANT_TYPE_VARDICT);
vpn_ip4_props = value_hash_create (); g_variant_builder_init (&vpn_ip4_props, G_VARIANT_TYPE_VARDICT);
vpn_ip6_props = value_hash_create (); g_variant_builder_init (&vpn_ip6_props, G_VARIANT_TYPE_VARDICT);
/* hostname actions only send the hostname */ /* hostname actions only send the hostname */
if (action != DISPATCHER_ACTION_HOSTNAME) { if (action != DISPATCHER_ACTION_HOSTNAME) {
fill_device_props (device, fill_device_props (device,
device_props, &device_props,
device_ip4_props, &device_ip4_props,
device_ip6_props, &device_ip6_props,
device_dhcp4_props, &device_dhcp4_props,
device_dhcp6_props); &device_dhcp6_props);
if (vpn_ip4_config || vpn_ip6_config) if (vpn_ip4_config || vpn_ip6_config) {
fill_vpn_props (vpn_ip4_config, vpn_ip6_config, vpn_ip4_props, vpn_ip6_props); fill_vpn_props (vpn_ip4_config,
vpn_ip6_config,
&vpn_ip4_props,
&vpn_ip6_props);
}
} }
/* Send the action to the dispatcher */ /* Send the action to the dispatcher */
if (blocking) { if (blocking) {
GPtrArray *results = NULL; GVariant *ret;
GVariantIter *results;
success = dbus_g_proxy_call_with_timeout (proxy, "Action", ret = _nm_dbus_proxy_call_sync (dispatcher_proxy, "Action",
CALL_TIMEOUT, g_variant_new ("(s@a{sa{sv}}a{sv}a{sv}a{sv}a{sv}a{sv}a{sv}sa{sv}a{sv}b)",
&error, action_to_string (action),
G_TYPE_STRING, action_to_string (action), connection_dict,
DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, connection_hash, &connection_props,
DBUS_TYPE_G_MAP_OF_VARIANT, connection_props, &device_props,
DBUS_TYPE_G_MAP_OF_VARIANT, device_props, &device_ip4_props,
DBUS_TYPE_G_MAP_OF_VARIANT, device_ip4_props, &device_ip6_props,
DBUS_TYPE_G_MAP_OF_VARIANT, device_ip6_props, &device_dhcp4_props,
DBUS_TYPE_G_MAP_OF_VARIANT, device_dhcp4_props, &device_dhcp6_props,
DBUS_TYPE_G_MAP_OF_VARIANT, device_dhcp6_props, vpn_iface ? vpn_iface : "",
G_TYPE_STRING, vpn_iface ? vpn_iface : "", &vpn_ip4_props,
DBUS_TYPE_G_MAP_OF_VARIANT, vpn_ip4_props, &vpn_ip6_props,
DBUS_TYPE_G_MAP_OF_VARIANT, vpn_ip6_props, nm_logging_enabled (LOGL_DEBUG, LOGD_DISPATCH)),
G_TYPE_BOOLEAN, nm_logging_enabled (LOGL_DEBUG, LOGD_DISPATCH), G_VARIANT_TYPE ("(a(sus))"),
G_TYPE_INVALID, G_DBUS_CALL_FLAGS_NONE, CALL_TIMEOUT,
DISPATCHER_TYPE_RESULT_ARRAY, &results, NULL, &error);
G_TYPE_INVALID); if (ret) {
if (success) { g_variant_get (ret, "(a(sus))", &results);
dispatcher_results_process (reqid, action, results); dispatcher_results_process (reqid, action, results);
free_results (results); g_variant_iter_free (results);
g_variant_unref (ret);
success = TRUE;
} else { } else {
nm_log_warn (LOGD_DISPATCH, "(%u) failed: (%d) %s", reqid, error->code, error->message); nm_log_warn (LOGD_DISPATCH, "(%u) failed: %s", reqid, error->message);
g_error_free (error); g_clear_error (&error);
success = FALSE;
} }
} else { } else {
info = g_malloc0 (sizeof (*info)); info = g_malloc0 (sizeof (*info));
@@ -556,37 +634,25 @@ _dispatcher_call (DispatcherAction action,
info->request_id = reqid; info->request_id = reqid;
info->callback = callback; info->callback = callback;
info->user_data = user_data; info->user_data = user_data;
dbus_g_proxy_begin_call_with_timeout (proxy, "Action", g_dbus_proxy_call (dispatcher_proxy, "Action",
dispatcher_done_cb, g_variant_new ("(s@a{sa{sv}}a{sv}a{sv}a{sv}a{sv}a{sv}a{sv}sa{sv}a{sv}b)",
info, action_to_string (action),
(GDestroyNotify) dispatcher_info_cleanup, connection_dict,
CALL_TIMEOUT, &connection_props,
G_TYPE_STRING, action_to_string (action), &device_props,
DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, connection_hash, &device_ip4_props,
DBUS_TYPE_G_MAP_OF_VARIANT, connection_props, &device_ip6_props,
DBUS_TYPE_G_MAP_OF_VARIANT, device_props, &device_dhcp4_props,
DBUS_TYPE_G_MAP_OF_VARIANT, device_ip4_props, &device_dhcp6_props,
DBUS_TYPE_G_MAP_OF_VARIANT, device_ip6_props, vpn_iface ? vpn_iface : "",
DBUS_TYPE_G_MAP_OF_VARIANT, device_dhcp4_props, &vpn_ip4_props,
DBUS_TYPE_G_MAP_OF_VARIANT, device_dhcp6_props, &vpn_ip6_props,
G_TYPE_STRING, vpn_iface ? vpn_iface : "", nm_logging_enabled (LOGL_DEBUG, LOGD_DISPATCH)),
DBUS_TYPE_G_MAP_OF_VARIANT, vpn_ip4_props, G_DBUS_CALL_FLAGS_NONE, CALL_TIMEOUT,
DBUS_TYPE_G_MAP_OF_VARIANT, vpn_ip6_props, NULL, dispatcher_done_cb, info);
G_TYPE_BOOLEAN, nm_logging_enabled (LOGL_DEBUG, LOGD_DISPATCH),
G_TYPE_INVALID);
success = TRUE; 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: done:
if (success && info) { if (success && info) {
/* Track the request in case of cancelation */ /* Track the request in case of cancelation */
@@ -777,6 +843,7 @@ nm_dispatcher_init (void)
{ {
GFile *file; GFile *file;
guint i; guint i;
GError *error = NULL;
for (i = 0; i < G_N_ELEMENTS (monitors); i++) { for (i = 0; i < G_N_ELEMENTS (monitors); i++) {
file = g_file_new_for_path (monitors[i].dir); file = g_file_new_for_path (monitors[i].dir);
@@ -787,5 +854,18 @@ nm_dispatcher_init (void)
} }
g_object_unref (file); 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 <string.h>
#include <glib.h> #include <glib.h>
#include <gio/gio.h> #include <gio/gio.h>
#include <dbus/dbus.h>
#include "nm-firewall-manager.h" #include "nm-firewall-manager.h"
#include "nm-dbus-manager.h"
#include "nm-logging.h" #include "nm-logging.h"
#include "gsystem-local-alloc.h"
#define NM_FIREWALL_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ #define NM_FIREWALL_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
NM_TYPE_FIREWALL_MANAGER, \ NM_TYPE_FIREWALL_MANAGER, \
@@ -43,9 +42,7 @@ enum {
}; };
typedef struct { typedef struct {
NMDBusManager * dbus_mgr; GDBusProxy * proxy;
guint name_owner_id;
DBusGProxy * proxy;
gboolean running; gboolean running;
GSList *pending_calls; GSList *pending_calls;
@@ -70,36 +67,50 @@ typedef struct {
FwAddToZoneFunc callback; FwAddToZoneFunc callback;
gpointer user_data; gpointer user_data;
guint id; guint id;
gboolean completed;
guint idle_id; guint idle_id;
DBusGProxyCall *dbus_call; GCancellable *cancellable;
} CBInfo; } CBInfo;
static void 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 (info != NULL);
g_return_if_fail (tag != NULL);
if (!info->completed) { /* A cancelled idle call won't set the error; catch that here */
nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone call cancelled [%u]", info->iface, info->id); if (!error && g_cancellable_is_cancelled (info->cancellable)) {
if (info->callback) { error = local = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_CANCELLED,
GError *error; "Operation was cancelled");
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);
}
} }
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); g_free (info->iface);
g_object_unref (info->cancellable);
priv = NM_FIREWALL_MANAGER_GET_PRIVATE (info->self);
priv->pending_calls = g_slist_remove (priv->pending_calls, info);
g_object_unref (info->self);
g_slice_free (CBInfo, info); g_slice_free (CBInfo, info);
} }
@@ -107,16 +118,14 @@ static CBInfo *
_cb_info_create (NMFirewallManager *self, const char *iface, FwAddToZoneFunc callback, gpointer user_data) _cb_info_create (NMFirewallManager *self, const char *iface, FwAddToZoneFunc callback, gpointer user_data)
{ {
NMFirewallManagerPrivate *priv = NM_FIREWALL_MANAGER_GET_PRIVATE (self); NMFirewallManagerPrivate *priv = NM_FIREWALL_MANAGER_GET_PRIVATE (self);
static guint id; static guint id = 1;
CBInfo *info; CBInfo *info;
info = g_slice_new0 (CBInfo); info = g_slice_new0 (CBInfo);
if (++id == 0)
++id;
info->self = g_object_ref (self); info->self = g_object_ref (self);
info->id = id; info->id = id++;
info->iface = g_strdup (iface); info->iface = g_strdup (iface);
info->completed = FALSE; info->cancellable = g_cancellable_new ();
info->callback = callback; info->callback = callback;
info->user_data = user_data; info->user_data = user_data;
@@ -129,50 +138,20 @@ add_or_change_idle_cb (gpointer user_data)
{ {
CBInfo *info = user_data; CBInfo *info = user_data;
if (info->idle_id == 0) { info->idle_id = 0;
/* operation was cancelled. _cb_info_free will invoke callback. */ _cb_info_complete_and_free (info, "idle call", NULL, NULL);
} 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);
return G_SOURCE_REMOVE; return G_SOURCE_REMOVE;
} }
static void 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; CBInfo *info = user_data;
GError *error = NULL; gs_free_error GError *error = NULL;
char *zone = NULL; gs_unref_variant GVariant *ret = NULL;
if (!dbus_g_proxy_end_call (proxy, call_id, &error, ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result, &error);
G_TYPE_STRING, &zone, _cb_info_complete_and_free (info, "add/change", "ZONE_ALREADY_SET", error);
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);
} }
NMFirewallPendingCall 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", nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone %s -> %s%s%s [%u]", iface, add ? "add" : "change",
zone?"\"":"", zone ? zone : "default", zone?"\"":"", info->id); zone?"\"":"", zone ? zone : "default", zone?"\"":"", info->id);
info->dbus_call = dbus_g_proxy_begin_call_with_timeout (priv->proxy, g_dbus_proxy_call (priv->proxy,
add ? "addInterface" : "changeZone", add ? "addInterface" : "changeZone",
add_or_change_cb, g_variant_new ("(ss)", zone ? zone : "", iface),
info, G_DBUS_CALL_FLAGS_NONE, 10000,
(GDestroyNotify) _cb_info_free, info->cancellable,
10000, /* timeout */ add_or_change_cb, info);
G_TYPE_STRING, zone ? zone : "", return (NMFirewallPendingCall) info;
G_TYPE_STRING, iface,
G_TYPE_INVALID);
return PENDING_CALL_FROM_INFO (info);
} }
static void 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; CBInfo *info = user_data;
GError *error = NULL; gs_free_error GError *error = NULL;
char * zone = NULL; gs_unref_variant GVariant *ret = NULL;
if (!dbus_g_proxy_end_call (proxy, call_id, &error, ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result, &error);
G_TYPE_STRING, &zone, _cb_info_complete_and_free (info, "remove", "UNKNOWN_INTERFACE", error);
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);
} }
NMFirewallPendingCall 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, nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone remove -> %s%s%s [%u]", iface,
zone?"\"":"", zone ? zone : "*", zone?"\"":"", info->id); zone?"\"":"", zone ? zone : "*", zone?"\"":"", info->id);
info->dbus_call = dbus_g_proxy_begin_call_with_timeout (priv->proxy, g_dbus_proxy_call (priv->proxy,
"removeInterface", "removeInterface",
remove_cb, g_variant_new ("(ss)", zone ? zone : "", iface),
info, G_DBUS_CALL_FLAGS_NONE, 10000,
(GDestroyNotify) _cb_info_free, info->cancellable,
10000, /* timeout */ remove_cb, info);
G_TYPE_STRING, zone ? zone : "", return (NMFirewallPendingCall) info;
G_TYPE_STRING, iface,
G_TYPE_INVALID);
return PENDING_CALL_FROM_INFO (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); CBInfo *info = (CBInfo *) call;
GSList *pending;
CBInfo *info;
g_return_if_fail (NM_IS_FIREWALL_MANAGER (self)); g_return_if_fail (NM_IS_FIREWALL_MANAGER (self));
if (call == PENDING_CALL_DUMMY) info->callback = NULL;
return; info->idle_id = 0;
g_cancellable_cancel (info->cancellable);
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);
}
} }
static void static void
@@ -311,25 +252,19 @@ set_running (NMFirewallManager *self, gboolean now_running)
} }
static void static void
name_owner_changed (NMDBusManager *dbus_mgr, name_owner_changed (GObject *object,
const char *name, GParamSpec *pspec,
const char *old_owner, gpointer user_data)
const char *new_owner,
gpointer user_data)
{ {
NMFirewallManager *self = NM_FIREWALL_MANAGER (user_data); NMFirewallManager *self = NM_FIREWALL_MANAGER (user_data);
gboolean old_owner_good = (old_owner && strlen (old_owner)); gs_free char *owner = NULL;
gboolean new_owner_good = (new_owner && strlen (new_owner));
/* We only care about the firewall here */ owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (object));
if (strcmp (FIREWALL_DBUS_SERVICE, name) != 0) if (owner) {
return;
if (!old_owner_good && new_owner_good) {
nm_log_dbg (LOGD_FIREWALL, "firewall started"); nm_log_dbg (LOGD_FIREWALL, "firewall started");
set_running (self, TRUE); set_running (self, TRUE);
g_signal_emit (self, signals[STARTED], 0); g_signal_emit (self, signals[STARTED], 0);
} else if (old_owner_good && !new_owner_good) { } else {
nm_log_dbg (LOGD_FIREWALL, "firewall stopped"); nm_log_dbg (LOGD_FIREWALL, "firewall stopped");
set_running (self, FALSE); set_running (self, FALSE);
} }
@@ -343,21 +278,23 @@ static void
nm_firewall_manager_init (NMFirewallManager * self) nm_firewall_manager_init (NMFirewallManager * self)
{ {
NMFirewallManagerPrivate *priv = NM_FIREWALL_MANAGER_GET_PRIVATE (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->proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
priv->name_owner_id = g_signal_connect (priv->dbus_mgr, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
NM_DBUS_MANAGER_NAME_OWNER_CHANGED, G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
G_CALLBACK (name_owner_changed), NULL,
self); FIREWALL_DBUS_SERVICE,
priv->running = nm_dbus_manager_name_has_owner (priv->dbus_mgr, 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" ); 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 static void
@@ -386,12 +323,6 @@ dispose (GObject *object)
g_assert (priv->pending_calls == NULL); 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); g_clear_object (&priv->proxy);
/* Chain up to the parent class */ /* Chain up to the parent class */

View File

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

View File

@@ -28,6 +28,7 @@
#include "nm-logging.h" #include "nm-logging.h"
#include "nm-dbus-manager.h" #include "nm-dbus-manager.h"
#include "nm-core-internal.h"
#include "nm-sleep-monitor.h" #include "nm-sleep-monitor.h"
@@ -123,19 +124,12 @@ take_inhibitor (NMSleepMonitor *self)
} }
static void static void
signal_cb (GDBusProxy *proxy, prepare_for_sleep_cb (GDBusProxy *proxy,
const gchar *sendername, gboolean is_about_to_suspend,
const gchar *signalname, gpointer data)
GVariant *args,
gpointer data)
{ {
NMSleepMonitor *self = 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); nm_log_dbg (LOGD_SUSPEND, "Received PrepareForSleep signal: %d", is_about_to_suspend);
if (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, "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); owner = g_dbus_proxy_get_name_owner (self->sd_proxy);
if (owner) if (owner)

View File

@@ -22,33 +22,32 @@
#include <errno.h> #include <errno.h>
#include <string.h> #include <string.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <dbus/dbus-glib.h>
#include <gio/gio.h> #include <gio/gio.h>
#include "nm-logging.h" #include "nm-logging.h"
#include "nm-dbus-manager.h" #include "nm-core-internal.h"
#include "nm-sleep-monitor.h" #include "nm-sleep-monitor.h"
#define UPOWER_DBUS_SERVICE "org.freedesktop.UPower" #define UPOWER_DBUS_SERVICE "org.freedesktop.UPower"
struct _NMSleepMonitor { struct _NMSleepMonitor {
GObject parent_instance; GObject parent_instance;
DBusGProxy *upower_proxy; GDBusProxy *upower_proxy;
}; };
struct _NMSleepMonitorClass { struct _NMSleepMonitorClass {
GObjectClass parent_class; GObjectClass parent_class;
void (*sleeping) (NMSleepMonitor *monitor); void (*sleeping) (NMSleepMonitor *monitor);
void (*resuming) (NMSleepMonitor *monitor); void (*resuming) (NMSleepMonitor *monitor);
}; };
enum { enum {
SLEEPING, SLEEPING,
RESUMING, RESUMING,
LAST_SIGNAL, LAST_SIGNAL,
}; };
static guint signals[LAST_SIGNAL] = {0}; static guint signals[LAST_SIGNAL] = {0};
@@ -57,80 +56,78 @@ G_DEFINE_TYPE (NMSleepMonitor, nm_sleep_monitor, G_TYPE_OBJECT);
/********************************************************************/ /********************************************************************/
static void 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"); nm_log_dbg (LOGD_SUSPEND, "Received UPower sleeping signal");
g_signal_emit (user_data, signals[SLEEPING], 0); g_signal_emit (user_data, signals[SLEEPING], 0);
} }
static void 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"); nm_log_dbg (LOGD_SUSPEND, "Received UPower resuming signal");
g_signal_emit (user_data, signals[RESUMING], 0); g_signal_emit (user_data, signals[RESUMING], 0);
} }
static void static void
nm_sleep_monitor_init (NMSleepMonitor *self) nm_sleep_monitor_init (NMSleepMonitor *self)
{ {
DBusGConnection *bus; GError *error = NULL;
bus = nm_dbus_manager_get_connection (nm_dbus_manager_get ()); self->upower_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
self->upower_proxy = dbus_g_proxy_new_for_name (bus, G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START |
UPOWER_DBUS_SERVICE, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
"/org/freedesktop/UPower", NULL,
"org.freedesktop.UPower"); UPOWER_DBUS_SERVICE,
if (self->upower_proxy) { "/org/freedesktop/UPower",
dbus_g_proxy_add_signal (self->upower_proxy, "Sleeping", G_TYPE_INVALID); "org.freedesktop.UPower",
dbus_g_proxy_connect_signal (self->upower_proxy, "Sleeping", NULL, &error);
G_CALLBACK (upower_sleeping_cb), if (self->upower_proxy) {
self, NULL); _nm_dbus_signal_connect (self->upower_proxy, "Sleeping", NULL,
G_CALLBACK (upower_sleeping_cb), self);
dbus_g_proxy_add_signal (self->upower_proxy, "Resuming", G_TYPE_INVALID); _nm_dbus_signal_connect (self->upower_proxy, "Resuming", NULL,
dbus_g_proxy_connect_signal (self->upower_proxy, "Resuming", G_CALLBACK (upower_resuming_cb), self);
G_CALLBACK (upower_resuming_cb), } else {
self, NULL); nm_log_warn (LOGD_SUSPEND, "could not initialize UPower D-Bus proxy: %s", error->message);
} else g_error_free (error);
nm_log_warn (LOGD_SUSPEND, "could not initialize UPower D-Bus proxy"); }
} }
static void static void
finalize (GObject *object) finalize (GObject *object)
{ {
NMSleepMonitor *self = NM_SLEEP_MONITOR (object); NMSleepMonitor *self = NM_SLEEP_MONITOR (object);
if (self->upower_proxy) g_clear_object (&self->upower_proxy);
g_object_unref (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 static void
nm_sleep_monitor_class_init (NMSleepMonitorClass *klass) 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, signals[SLEEPING] = g_signal_new (NM_SLEEP_MONITOR_SLEEPING,
NM_TYPE_SLEEP_MONITOR, NM_TYPE_SLEEP_MONITOR,
G_SIGNAL_RUN_LAST, G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (NMSleepMonitorClass, sleeping), G_STRUCT_OFFSET (NMSleepMonitorClass, sleeping),
NULL, /* accumulator */ NULL, /* accumulator */
NULL, /* accumulator data */ NULL, /* accumulator data */
g_cclosure_marshal_VOID__VOID, g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0); G_TYPE_NONE, 0);
signals[RESUMING] = g_signal_new (NM_SLEEP_MONITOR_RESUMING, signals[RESUMING] = g_signal_new (NM_SLEEP_MONITOR_RESUMING,
NM_TYPE_SLEEP_MONITOR, NM_TYPE_SLEEP_MONITOR,
G_SIGNAL_RUN_LAST, G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (NMSleepMonitorClass, resuming), G_STRUCT_OFFSET (NMSleepMonitorClass, resuming),
NULL, /* accumulator */ NULL, /* accumulator */
NULL, /* accumulator data */ NULL, /* accumulator data */
g_cclosure_marshal_VOID__VOID, g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0); G_TYPE_NONE, 0);
} }
NM_DEFINE_SINGLETON_GETTER (NMSleepMonitor, nm_sleep_monitor_get, NM_TYPE_SLEEP_MONITOR); 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; 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 static void
iface_check_netreply_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) 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); self = NM_SUPPLICANT_INTERFACE (user_data);
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); 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; priv->has_credreq = TRUE;
nm_log_dbg (LOGD_SUPPLICANT, "Supplicant %s network credentials requests", 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; const char *data;
/* The ProbeRequest method only exists if AP mode has been enabled */ /* 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)) if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return; return;
self = NM_SUPPLICANT_INTERFACE (user_data); self = NM_SUPPLICANT_INTERFACE (user_data);
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); 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); g_variant_get (variant, "(&s)", &data);
if (strstr (data, "ProbeRequest")) if (strstr (data, "ProbeRequest"))
priv->ap_support = AP_SUPPORT_YES; 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); iface_check_ready (self);
} }
#define MATCH_SIGNAL(s, n, v, t) (!strcmp (s, n) && g_variant_is_of_type (v, t))
static void static void
signal_cb (GDBusProxy *proxy, wpas_iface_scan_done (GDBusProxy *proxy,
const gchar *sender, gboolean success,
const gchar *signal, gpointer user_data)
GVariant *args,
gpointer user_data)
{ {
NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data); NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); 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 (); priv->last_scan = nm_utils_get_monotonic_timestamp_s ();
g_variant_get (args, "(b)", &success); handle_new_bss (self, path);
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 ();
g_variant_get (args, "(&oa{sv})", &path, NULL); static void
handle_new_bss (self, path); wpas_iface_bss_removed (GDBusProxy *proxy,
} else if (MATCH_SIGNAL (signal, "BSSRemoved", args, G_VARIANT_TYPE ("(o)"))) { const char *path,
g_variant_get (args, "(&o)", &path); gpointer user_data)
g_signal_emit (self, signals[BSS_REMOVED], 0, path); {
g_hash_table_remove (priv->bss_proxies, path); NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
} else if (MATCH_SIGNAL (signal, "NetworkRequest", args, G_VARIANT_TYPE ("(oss)"))) { NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
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[BSS_REMOVED], 0, path);
g_signal_emit (self, signals[CREDENTIALS_REQUEST], 0, field, message); 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 static void
@@ -602,7 +609,14 @@ on_iface_proxy_acquired (GDBusProxy *proxy, GAsyncResult *result, gpointer user_
self = NM_SUPPLICANT_INTERFACE (user_data); self = NM_SUPPLICANT_INTERFACE (user_data);
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); 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 */ /* Check whether NetworkReply and AP mode are supported */
priv->ready_count = 1; priv->ready_count = 1;
@@ -666,19 +680,20 @@ interface_get_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
NMSupplicantInterfacePrivate *priv; NMSupplicantInterfacePrivate *priv;
gs_unref_variant GVariant *variant = NULL; gs_unref_variant GVariant *variant = NULL;
gs_free_error GError *error = 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)) if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return; return;
self = NM_SUPPLICANT_INTERFACE (user_data); self = NM_SUPPLICANT_INTERFACE (user_data);
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
if (variant && g_variant_is_of_type (variant, G_VARIANT_TYPE ("(o)"))) { if (variant) {
g_variant_get (variant, "(o)", &path); g_variant_get (variant, "(&o)", &path);
interface_add_done (self, path); interface_add_done (self, path);
g_free (path);
} else { } else {
nm_log_err (LOGD_SUPPLICANT, "(%s): error getting interface: %s", priv->dev, error->message); nm_log_err (LOGD_SUPPLICANT, "(%s): error getting interface: %s", priv->dev, error->message);
set_state (self, NM_SUPPLICANT_INTERFACE_STATE_DOWN); set_state (self, NM_SUPPLICANT_INTERFACE_STATE_DOWN);
@@ -692,20 +707,21 @@ interface_add_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
NMSupplicantInterfacePrivate *priv; NMSupplicantInterfacePrivate *priv;
gs_free_error GError *error = NULL; gs_free_error GError *error = NULL;
gs_unref_variant GVariant *variant = 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)) if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return; return;
self = NM_SUPPLICANT_INTERFACE (user_data); self = NM_SUPPLICANT_INTERFACE (user_data);
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
if (variant && g_variant_is_of_type (variant, G_VARIANT_TYPE ("(o)"))) { if (variant) {
g_variant_get (variant, "(o)", &path); g_variant_get (variant, "(&o)", &path);
interface_add_done (self, path); interface_add_done (self, path);
g_free (path); } else if (_nm_dbus_error_has_name (error, WPAS_ERROR_EXISTS_ERROR)) {
} else if (_dbus_error_has_name (error, WPAS_ERROR_EXISTS_ERROR)) {
/* Interface already added, just get its object path */ /* Interface already added, just get its object path */
g_dbus_proxy_call (priv->wpas_proxy, g_dbus_proxy_call (priv->wpas_proxy,
"GetInterface", "GetInterface",
@@ -963,19 +979,15 @@ add_network_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
const char *blob_name; const char *blob_name;
GByteArray *blob_data; 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)) if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return; return;
self = NM_SUPPLICANT_INTERFACE (user_data); self = NM_SUPPLICANT_INTERFACE (user_data);
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); 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); g_free (priv->net_path);
priv->net_path = NULL; 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_variant_get (reply, "(o)", &priv->net_path);
g_assert (priv->net_path);
/* Send blobs first; otherwise jump to selecting the network */ /* Send blobs first; otherwise jump to selecting the network */
blobs = nm_supplicant_config_get_blobs (priv->cfg); 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); _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 static void
signal_cb (GDBusProxy *proxy, state_changed_cb (GDBusProxy *proxy,
const gchar *sender, guint32 new_service_state,
const gchar *signal, gpointer user_data)
GVariant *args, {
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); NMVpnConnection *self = NM_VPN_CONNECTION (user_data);
NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (self); 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)"))) { /* Only list to this signals during and after connection */
g_variant_get (args, "(u)", &u32); if (priv->vpn_state >= STATE_NEED_AUTH)
plugin_failed (self, u32); nm_vpn_connection_config_get (self, dict);
} else if (MATCH_SIGNAL (signal, "StateChanged", args, G_VARIANT_TYPE ("(u)"))) { }
g_variant_get (args, "(u)", &u32);
plugin_state_changed (self, u32); static void
} else if (MATCH_SIGNAL (signal, "SecretsRequired", args, G_VARIANT_TYPE ("(sas)"))) { ip4_config_cb (GDBusProxy *proxy,
g_variant_get (args, "(&s^a&s)", &message, &secrets); GVariant *dict,
plugin_interactive_secrets_required (self, message, secrets); gpointer user_data)
g_free (secrets); {
} else if (priv->vpn_state >= STATE_NEED_AUTH) { NMVpnConnection *self = NM_VPN_CONNECTION (user_data);
/* Only list to these signals during and after connection */ NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (self);
if (MATCH_SIGNAL (signal, "Config", args, G_VARIANT_TYPE ("(a{sv})"))) {
g_variant_get (args, "(@a{sv})", &dict); /* Only list to this signals during and after connection */
nm_vpn_connection_config_get (self, dict); if (priv->vpn_state >= STATE_NEED_AUTH)
} else if (MATCH_SIGNAL (signal, "Ip4Config", args, G_VARIANT_TYPE ("(a{sv})"))) { nm_vpn_connection_ip4_config_get (self, dict);
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})"))) { static void
g_variant_get (args, "(@a{sv})", &dict); ip6_config_cb (GDBusProxy *proxy,
nm_vpn_connection_ip6_config_get (self, dict); 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 static void
@@ -1648,7 +1678,18 @@ on_proxy_acquired (GObject *object, GAsyncResult *result, gpointer user_data)
} }
priv->proxy = proxy; 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); _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; gs_free_error GError *error = NULL;
const char *setting_name; 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)) if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return; return;