dbus: Share common initialization code for both old and new interface

This was mostly identical code that had been copied for the new D-Bus
API implementation and as such, should really have been shared from
the beginning. In addition, the copied code ended up generating
interesting stack traces since the actual D-Bus connection was being
shared even though the pointer to it was stored in two distinct
data structures. The old D-Bus code ended up dispatching some
D-Bus callbacks which ended up running the new D-Bus code.

Since the private context pointers were mostly identical, everything
seemed to more or less work, but this design was just making things
more complex and potentially very easy to break.
This commit is contained in:
Jouni Malinen 2009-12-31 00:15:56 +02:00
parent 0474686514
commit 8ddef94bd4
13 changed files with 583 additions and 875 deletions

View file

@ -1040,6 +1040,7 @@ OBJS += ctrl_iface.o ctrl_iface_$(CONFIG_CTRL_IFACE).o
endif
ifdef CONFIG_CTRL_IFACE_DBUS
DBUS=y
DBUS_CFLAGS += -DCONFIG_CTRL_IFACE_DBUS -DDBUS_API_SUBJECT_TO_CHANGE
DBUS_OBJS += dbus/dbus.o dbus/dbus_handlers.o
ifdef CONFIG_WPS
@ -1067,6 +1068,7 @@ DBUS_CFLAGS += $(DBUS_INCLUDE)
endif
ifdef CONFIG_CTRL_IFACE_DBUS_NEW
DBUS=y
DBUS_CFLAGS += -DCONFIG_CTRL_IFACE_DBUS_NEW
DBUS_OBJS ?= dbus/dbus_dict_helpers.o
DBUS_OBJS += dbus/dbus_new_helpers.o
@ -1088,6 +1090,11 @@ endif
DBUS_CFLAGS += $(DBUS_INCLUDE)
endif
ifdef DBUS
DBUS_CFLAGS += -DCONFIG_DBUS
DBUS_OBJS += dbus/dbus_common.o
endif
OBJS += $(DBUS_OBJS)
CFLAGS += $(DBUS_CFLAGS)
LIBS += $(DBUS_LIBS)

View file

@ -22,255 +22,8 @@
#include "../wpa_supplicant_i.h"
#include "dbus.h"
#include "dbus_handlers.h"
#define _DBUS_VERSION (DBUS_VERSION_MAJOR << 8 | DBUS_VERSION_MINOR)
#define DBUS_VER(major, minor) ((major) << 8 | (minor))
#if _DBUS_VERSION < DBUS_VER(1,1)
#define dbus_watch_get_unix_fd dbus_watch_get_fd
#endif
struct ctrl_iface_dbus_priv {
DBusConnection *con;
int should_dispatch;
struct wpa_global *global;
u32 next_objid;
};
static void process_watch(struct ctrl_iface_dbus_priv *iface,
DBusWatch *watch, eloop_event_type type)
{
dbus_connection_ref(iface->con);
iface->should_dispatch = 0;
if (type == EVENT_TYPE_READ)
dbus_watch_handle(watch, DBUS_WATCH_READABLE);
else if (type == EVENT_TYPE_WRITE)
dbus_watch_handle(watch, DBUS_WATCH_WRITABLE);
else if (type == EVENT_TYPE_EXCEPTION)
dbus_watch_handle(watch, DBUS_WATCH_ERROR);
if (iface->should_dispatch) {
while (dbus_connection_get_dispatch_status(iface->con) ==
DBUS_DISPATCH_DATA_REMAINS)
dbus_connection_dispatch(iface->con);
iface->should_dispatch = 0;
}
dbus_connection_unref(iface->con);
}
static void process_watch_exception(int sock, void *eloop_ctx, void *sock_ctx)
{
process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_EXCEPTION);
}
static void process_watch_read(int sock, void *eloop_ctx, void *sock_ctx)
{
process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_READ);
}
static void process_watch_write(int sock, void *eloop_ctx, void *sock_ctx)
{
process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_WRITE);
}
static void connection_setup_add_watch(struct ctrl_iface_dbus_priv *iface,
DBusWatch *watch)
{
unsigned int flags;
int fd;
if (!dbus_watch_get_enabled(watch))
return;
flags = dbus_watch_get_flags(watch);
fd = dbus_watch_get_unix_fd(watch);
eloop_register_sock(fd, EVENT_TYPE_EXCEPTION, process_watch_exception,
iface, watch);
if (flags & DBUS_WATCH_READABLE) {
eloop_register_sock(fd, EVENT_TYPE_READ, process_watch_read,
iface, watch);
}
if (flags & DBUS_WATCH_WRITABLE) {
eloop_register_sock(fd, EVENT_TYPE_WRITE, process_watch_write,
iface, watch);
}
dbus_watch_set_data(watch, iface, NULL);
}
static void connection_setup_remove_watch(struct ctrl_iface_dbus_priv *iface,
DBusWatch *watch)
{
unsigned int flags;
int fd;
flags = dbus_watch_get_flags(watch);
fd = dbus_watch_get_unix_fd(watch);
eloop_unregister_sock(fd, EVENT_TYPE_EXCEPTION);
if (flags & DBUS_WATCH_READABLE)
eloop_unregister_sock(fd, EVENT_TYPE_READ);
if (flags & DBUS_WATCH_WRITABLE)
eloop_unregister_sock(fd, EVENT_TYPE_WRITE);
dbus_watch_set_data(watch, NULL, NULL);
}
static dbus_bool_t add_watch(DBusWatch *watch, void *data)
{
connection_setup_add_watch(data, watch);
return TRUE;
}
static void remove_watch(DBusWatch *watch, void *data)
{
connection_setup_remove_watch(data, watch);
}
static void watch_toggled(DBusWatch *watch, void *data)
{
if (dbus_watch_get_enabled(watch))
add_watch(watch, data);
else
remove_watch(watch, data);
}
static void process_timeout(void *eloop_ctx, void *sock_ctx)
{
DBusTimeout *timeout = sock_ctx;
dbus_timeout_handle(timeout);
}
static void connection_setup_add_timeout(struct ctrl_iface_dbus_priv *iface,
DBusTimeout *timeout)
{
if (!dbus_timeout_get_enabled(timeout))
return;
eloop_register_timeout(0, dbus_timeout_get_interval(timeout) * 1000,
process_timeout, iface, timeout);
dbus_timeout_set_data(timeout, iface, NULL);
}
static void connection_setup_remove_timeout(struct ctrl_iface_dbus_priv *iface,
DBusTimeout *timeout)
{
eloop_cancel_timeout(process_timeout, iface, timeout);
dbus_timeout_set_data(timeout, NULL, NULL);
}
static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data)
{
if (!dbus_timeout_get_enabled(timeout))
return TRUE;
connection_setup_add_timeout(data, timeout);
return TRUE;
}
static void remove_timeout(DBusTimeout *timeout, void *data)
{
connection_setup_remove_timeout(data, timeout);
}
static void timeout_toggled(DBusTimeout *timeout, void *data)
{
if (dbus_timeout_get_enabled(timeout))
add_timeout(timeout, data);
else
remove_timeout(timeout, data);
}
static void process_wakeup_main(int sig, void *signal_ctx)
{
struct ctrl_iface_dbus_priv *iface = signal_ctx;
if (sig != SIGPOLL || !iface->con)
return;
if (dbus_connection_get_dispatch_status(iface->con) !=
DBUS_DISPATCH_DATA_REMAINS)
return;
/* Only dispatch once - we do not want to starve other events */
dbus_connection_ref(iface->con);
dbus_connection_dispatch(iface->con);
dbus_connection_unref(iface->con);
}
/**
* wakeup_main - Attempt to wake our mainloop up
* @data: dbus control interface private data
*
* Try to wake up the main eloop so it will process
* dbus events that may have happened.
*/
static void wakeup_main(void *data)
{
struct ctrl_iface_dbus_priv *iface = data;
/* Use SIGPOLL to break out of the eloop select() */
raise(SIGPOLL);
iface->should_dispatch = 1;
}
/**
* connection_setup_wakeup_main - Tell dbus about our wakeup_main function
* @iface: dbus control interface private data
* Returns: 0 on success, -1 on failure
*
* Register our wakeup_main handler with dbus
*/
static int connection_setup_wakeup_main(struct ctrl_iface_dbus_priv *iface)
{
if (eloop_register_signal(SIGPOLL, process_wakeup_main, iface))
return -1;
dbus_connection_set_wakeup_main_function(iface->con, wakeup_main,
iface, NULL);
return 0;
}
/**
* wpa_supplicant_dbus_next_objid - Return next available object id
* @iface: dbus control interface private data
* Returns: Object id
*/
u32 wpa_supplicant_dbus_next_objid (struct ctrl_iface_dbus_priv *iface)
{
return iface->next_objid++;
}
#include "dbus_common.h"
#include "dbus_common_i.h"
/**
@ -587,7 +340,7 @@ out:
static DBusHandlerResult wpas_message_handler(DBusConnection *connection,
DBusMessage *message, void *user_data)
{
struct ctrl_iface_dbus_priv *ctrl_iface = user_data;
struct wpas_dbus_priv *ctrl_iface = user_data;
const char *method;
const char *path;
const char *msg_interface;
@ -641,7 +394,7 @@ static DBusHandlerResult wpas_message_handler(DBusConnection *connection,
*/
void wpa_supplicant_dbus_notify_scan_results(struct wpa_supplicant *wpa_s)
{
struct ctrl_iface_dbus_priv *iface = wpa_s->global->dbus_ctrl_iface;
struct wpas_dbus_priv *iface = wpa_s->global->dbus;
DBusMessage *_signal;
const char *path;
@ -686,7 +439,7 @@ void wpa_supplicant_dbus_notify_state_change(struct wpa_supplicant *wpa_s,
enum wpa_states new_state,
enum wpa_states old_state)
{
struct ctrl_iface_dbus_priv *iface;
struct wpas_dbus_priv *iface;
DBusMessage *_signal = NULL;
const char *path;
const char *new_state_str, *old_state_str;
@ -694,7 +447,7 @@ void wpa_supplicant_dbus_notify_state_change(struct wpa_supplicant *wpa_s,
/* Do nothing if the control interface is not turned on */
if (wpa_s->global == NULL)
return;
iface = wpa_s->global->dbus_ctrl_iface;
iface = wpa_s->global->dbus;
if (iface == NULL)
return;
@ -764,7 +517,7 @@ out:
*/
void wpa_supplicant_dbus_notify_scanning(struct wpa_supplicant *wpa_s)
{
struct ctrl_iface_dbus_priv *iface = wpa_s->global->dbus_ctrl_iface;
struct wpas_dbus_priv *iface = wpa_s->global->dbus;
DBusMessage *_signal;
const char *path;
dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE;
@ -811,14 +564,14 @@ void wpa_supplicant_dbus_notify_scanning(struct wpa_supplicant *wpa_s)
void wpa_supplicant_dbus_notify_wps_cred(struct wpa_supplicant *wpa_s,
const struct wps_credential *cred)
{
struct ctrl_iface_dbus_priv *iface;
struct wpas_dbus_priv *iface;
DBusMessage *_signal = NULL;
const char *path;
/* Do nothing if the control interface is not turned on */
if (wpa_s->global == NULL)
return;
iface = wpa_s->global->dbus_ctrl_iface;
iface = wpa_s->global->dbus;
if (iface == NULL)
return;
@ -869,102 +622,22 @@ void wpa_supplicant_dbus_notify_wps_cred(struct wpa_supplicant *wpa_s,
#endif /* CONFIG_WPS */
/**
* integrate_with_eloop - Register our mainloop integration with dbus
* @connection: connection to the system message bus
* @iface: a dbus control interface data structure
* Returns: 0 on success, -1 on failure
*
* We register our mainloop integration functions with dbus here.
*/
static int integrate_with_eloop(DBusConnection *connection,
struct ctrl_iface_dbus_priv *iface)
{
if (!dbus_connection_set_watch_functions(connection, add_watch,
remove_watch, watch_toggled,
iface, NULL)) {
perror("dbus_connection_set_watch_functions[dbus]");
wpa_printf(MSG_ERROR, "Not enough memory to set up dbus.");
return -1;
}
if (!dbus_connection_set_timeout_functions(connection, add_timeout,
remove_timeout,
timeout_toggled, iface,
NULL)) {
perror("dbus_connection_set_timeout_functions[dbus]");
wpa_printf(MSG_ERROR, "Not enough memory to set up dbus.");
return -1;
}
if (connection_setup_wakeup_main(iface) < 0) {
perror("connection_setup_wakeup_main[dbus]");
wpa_printf(MSG_ERROR, "Could not setup main wakeup function.");
return -1;
}
return 0;
}
/**
* dispatch_initial_dbus_messages - Dispatch initial dbus messages after
* claiming bus name
* @eloop_ctx: the DBusConnection to dispatch on
* @timeout_ctx: unused
*
* If clients are quick to notice that wpa_supplicant claimed its bus name,
* there may have been messages that came in before initialization was
* all finished. Dispatch those here.
*/
static void dispatch_initial_dbus_messages(void *eloop_ctx, void *timeout_ctx)
{
DBusConnection *con = eloop_ctx;
while (dbus_connection_get_dispatch_status(con) ==
DBUS_DISPATCH_DATA_REMAINS)
dbus_connection_dispatch(con);
}
/**
* wpa_supplicant_dbus_ctrl_iface_init - Initialize dbus control interface
* @global: Pointer to global data from wpa_supplicant_init()
* Returns: Pointer to dbus_ctrl_iface date or %NULL on failure
* Returns: 0 on success, -1 on failure
*
* Initialize the dbus control interface and start receiving commands from
* external programs over the bus.
*/
struct ctrl_iface_dbus_priv *
wpa_supplicant_dbus_ctrl_iface_init(struct wpa_global *global)
int wpa_supplicant_dbus_ctrl_iface_init(struct wpas_dbus_priv *iface)
{
struct ctrl_iface_dbus_priv *iface;
DBusError error;
int ret = -1;
DBusObjectPathVTable wpas_vtable = {
NULL, &wpas_message_handler, NULL, NULL, NULL, NULL
};
iface = os_zalloc(sizeof(struct ctrl_iface_dbus_priv));
if (iface == NULL)
return NULL;
iface->global = global;
/* Get a reference to the system bus */
dbus_error_init(&error);
iface->con = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
dbus_error_free(&error);
if (!iface->con) {
perror("dbus_bus_get[ctrl_iface_dbus]");
wpa_printf(MSG_ERROR, "Could not acquire the system bus.");
goto fail;
}
/* Tell dbus about our mainloop integration functions */
if (integrate_with_eloop(iface->con, iface))
goto fail;
/* Register the message handler for the global dbus interface */
if (!dbus_connection_register_object_path(iface->con,
WPAS_DBUS_PATH, &wpas_vtable,
@ -972,7 +645,7 @@ wpa_supplicant_dbus_ctrl_iface_init(struct wpa_global *global)
perror("dbus_connection_register_object_path[dbus]");
wpa_printf(MSG_ERROR, "Could not set up DBus message "
"handler.");
goto fail;
return -1;
}
/* Register our service with the message bus */
@ -998,54 +671,12 @@ wpa_supplicant_dbus_ctrl_iface_init(struct wpa_global *global)
dbus_error_free(&error);
if (ret != 0)
goto fail;
return -1;
wpa_printf(MSG_DEBUG, "Providing DBus service '" WPAS_DBUS_SERVICE
"'.");
/*
* Dispatch initial DBus messages that may have come in since the bus
* name was claimed above. Happens when clients are quick to notice the
* wpa_supplicant service.
*
* FIXME: is there a better solution to this problem?
*/
eloop_register_timeout(0, 50, dispatch_initial_dbus_messages,
iface->con, NULL);
return iface;
fail:
wpa_supplicant_dbus_ctrl_iface_deinit(iface);
return NULL;
}
/**
* wpa_supplicant_dbus_ctrl_iface_deinit - Deinitialize dbus ctrl interface
* @iface: Pointer to dbus private data from
* wpa_supplicant_dbus_ctrl_iface_init()
*
* Deinitialize the dbus control interface that was initialized with
* wpa_supplicant_dbus_ctrl_iface_init().
*/
void wpa_supplicant_dbus_ctrl_iface_deinit(struct ctrl_iface_dbus_priv *iface)
{
if (iface == NULL)
return;
if (iface->con) {
eloop_cancel_timeout(dispatch_initial_dbus_messages,
iface->con, NULL);
dbus_connection_set_watch_functions(iface->con, NULL, NULL,
NULL, NULL, NULL);
dbus_connection_set_timeout_functions(iface->con, NULL, NULL,
NULL, NULL, NULL);
dbus_connection_unref(iface->con);
}
memset(iface, 0, sizeof(struct ctrl_iface_dbus_priv));
os_free(iface);
return 0;
}
@ -1058,8 +689,7 @@ void wpa_supplicant_dbus_ctrl_iface_deinit(struct ctrl_iface_dbus_priv *iface)
*/
int wpas_dbus_register_iface(struct wpa_supplicant *wpa_s)
{
struct ctrl_iface_dbus_priv *ctrl_iface =
wpa_s->global->dbus_ctrl_iface;
struct wpas_dbus_priv *ctrl_iface = wpa_s->global->dbus;
DBusConnection * con;
u32 next;
DBusObjectPathVTable vtable = {
@ -1073,7 +703,7 @@ int wpas_dbus_register_iface(struct wpa_supplicant *wpa_s)
return 0;
con = ctrl_iface->con;
next = wpa_supplicant_dbus_next_objid(ctrl_iface);
next = ctrl_iface->next_objid++;
/* Create and set the interface's object path */
path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
@ -1113,14 +743,14 @@ out:
*/
int wpas_dbus_unregister_iface(struct wpa_supplicant *wpa_s)
{
struct ctrl_iface_dbus_priv *ctrl_iface;
struct wpas_dbus_priv *ctrl_iface;
DBusConnection *con;
const char *path;
/* Do nothing if the control interface is not turned on */
if (wpa_s == NULL || wpa_s->global == NULL)
return 0;
ctrl_iface = wpa_s->global->dbus_ctrl_iface;
ctrl_iface = wpa_s->global->dbus;
if (ctrl_iface == NULL)
return 0;

View file

@ -86,9 +86,7 @@ struct wps_credential;
struct wpa_global;
struct wpa_supplicant;
struct ctrl_iface_dbus_priv *
wpa_supplicant_dbus_ctrl_iface_init(struct wpa_global *global);
void wpa_supplicant_dbus_ctrl_iface_deinit(struct ctrl_iface_dbus_priv *iface);
int wpa_supplicant_dbus_ctrl_iface_init(struct wpas_dbus_priv *iface);
void wpa_supplicant_dbus_notify_scan_results(struct wpa_supplicant *wpa_s);
void wpa_supplicant_dbus_notify_scanning(struct wpa_supplicant *wpa_s);
void wpa_supplicant_dbus_notify_state_change(struct wpa_supplicant *wpa_s,
@ -105,8 +103,6 @@ int wpas_dbus_unregister_iface(struct wpa_supplicant *wpa_s);
/* Methods internal to the dbus control interface */
u32 wpa_supplicant_dbus_next_objid(struct ctrl_iface_dbus_priv *iface);
int wpa_supplicant_set_dbus_path(struct wpa_supplicant *wpa_s,
const char *path);
const char *wpa_supplicant_get_dbus_path(struct wpa_supplicant *wpa_s);
@ -139,12 +135,7 @@ wpa_supplicant_dbus_notify_scanning(struct wpa_supplicant *wpa_s)
{
}
static inline void
wpa_supplicant_dbus_notify_state_change(struct wpa_supplicant *wpa_s,
enum wpa_states new_state,
enum wpa_states old_state)
{
}
#define wpa_supplicant_dbus_notify_state_change(w,n,o) do { } while (0)
static inline void
wpa_supplicant_dbus_notify_wps_cred(struct wpa_supplicant *wpa_s,

View file

@ -0,0 +1,411 @@
/*
* wpa_supplicant D-Bus control interface - common functionality
* Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
* Copyright (c) 2009, Witold Sowa <witold.sowa@gmail.com>
* Copyright (c) 2009, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
*/
#include "utils/includes.h"
#include <dbus/dbus.h>
#include "utils/common.h"
#include "utils/eloop.h"
#include "dbus_common.h"
#include "dbus_common_i.h"
#include "dbus_new.h"
#include "dbus.h"
/**
* dispatch_initial_dbus_messages - Dispatch initial dbus messages after
* claiming bus name
* @eloop_ctx: the DBusConnection to dispatch on
* @timeout_ctx: unused
*
* If clients are quick to notice that service claimed its bus name,
* there may have been messages that came in before initialization was
* all finished. Dispatch those here.
*/
static void dispatch_initial_dbus_messages(void *eloop_ctx, void *timeout_ctx)
{
DBusConnection *con = eloop_ctx;
while (dbus_connection_get_dispatch_status(con) ==
DBUS_DISPATCH_DATA_REMAINS)
dbus_connection_dispatch(con);
}
static void process_watch(struct wpas_dbus_priv *priv,
DBusWatch *watch, eloop_event_type type)
{
dbus_connection_ref(priv->con);
priv->should_dispatch = 0;
if (type == EVENT_TYPE_READ)
dbus_watch_handle(watch, DBUS_WATCH_READABLE);
else if (type == EVENT_TYPE_WRITE)
dbus_watch_handle(watch, DBUS_WATCH_WRITABLE);
else if (type == EVENT_TYPE_EXCEPTION)
dbus_watch_handle(watch, DBUS_WATCH_ERROR);
if (priv->should_dispatch) {
while (dbus_connection_get_dispatch_status(priv->con) ==
DBUS_DISPATCH_DATA_REMAINS)
dbus_connection_dispatch(priv->con);
priv->should_dispatch = 0;
}
dbus_connection_unref(priv->con);
}
static void process_watch_exception(int sock, void *eloop_ctx, void *sock_ctx)
{
process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_EXCEPTION);
}
static void process_watch_read(int sock, void *eloop_ctx, void *sock_ctx)
{
process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_READ);
}
static void process_watch_write(int sock, void *eloop_ctx, void *sock_ctx)
{
process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_WRITE);
}
static void connection_setup_add_watch(struct wpas_dbus_priv *priv,
DBusWatch *watch)
{
unsigned int flags;
int fd;
if (!dbus_watch_get_enabled(watch))
return;
flags = dbus_watch_get_flags(watch);
fd = dbus_watch_get_unix_fd(watch);
eloop_register_sock(fd, EVENT_TYPE_EXCEPTION, process_watch_exception,
priv, watch);
if (flags & DBUS_WATCH_READABLE) {
eloop_register_sock(fd, EVENT_TYPE_READ, process_watch_read,
priv, watch);
}
if (flags & DBUS_WATCH_WRITABLE) {
eloop_register_sock(fd, EVENT_TYPE_WRITE, process_watch_write,
priv, watch);
}
dbus_watch_set_data(watch, priv, NULL);
}
static void connection_setup_remove_watch(struct wpas_dbus_priv *priv,
DBusWatch *watch)
{
unsigned int flags;
int fd;
flags = dbus_watch_get_flags(watch);
fd = dbus_watch_get_unix_fd(watch);
eloop_unregister_sock(fd, EVENT_TYPE_EXCEPTION);
if (flags & DBUS_WATCH_READABLE)
eloop_unregister_sock(fd, EVENT_TYPE_READ);
if (flags & DBUS_WATCH_WRITABLE)
eloop_unregister_sock(fd, EVENT_TYPE_WRITE);
dbus_watch_set_data(watch, NULL, NULL);
}
static dbus_bool_t add_watch(DBusWatch *watch, void *data)
{
connection_setup_add_watch(data, watch);
return TRUE;
}
static void remove_watch(DBusWatch *watch, void *data)
{
connection_setup_remove_watch(data, watch);
}
static void watch_toggled(DBusWatch *watch, void *data)
{
if (dbus_watch_get_enabled(watch))
add_watch(watch, data);
else
remove_watch(watch, data);
}
static void process_timeout(void *eloop_ctx, void *sock_ctx)
{
DBusTimeout *timeout = sock_ctx;
dbus_timeout_handle(timeout);
}
static void connection_setup_add_timeout(struct wpas_dbus_priv *priv,
DBusTimeout *timeout)
{
if (!dbus_timeout_get_enabled(timeout))
return;
eloop_register_timeout(0, dbus_timeout_get_interval(timeout) * 1000,
process_timeout, priv, timeout);
dbus_timeout_set_data(timeout, priv, NULL);
}
static void connection_setup_remove_timeout(struct wpas_dbus_priv *priv,
DBusTimeout *timeout)
{
eloop_cancel_timeout(process_timeout, priv, timeout);
dbus_timeout_set_data(timeout, NULL, NULL);
}
static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data)
{
if (!dbus_timeout_get_enabled(timeout))
return TRUE;
connection_setup_add_timeout(data, timeout);
return TRUE;
}
static void remove_timeout(DBusTimeout *timeout, void *data)
{
connection_setup_remove_timeout(data, timeout);
}
static void timeout_toggled(DBusTimeout *timeout, void *data)
{
if (dbus_timeout_get_enabled(timeout))
add_timeout(timeout, data);
else
remove_timeout(timeout, data);
}
static void process_wakeup_main(int sig, void *signal_ctx)
{
struct wpas_dbus_priv *priv = signal_ctx;
if (sig != SIGPOLL || !priv->con)
return;
if (dbus_connection_get_dispatch_status(priv->con) !=
DBUS_DISPATCH_DATA_REMAINS)
return;
/* Only dispatch once - we do not want to starve other events */
dbus_connection_ref(priv->con);
dbus_connection_dispatch(priv->con);
dbus_connection_unref(priv->con);
}
/**
* wakeup_main - Attempt to wake our mainloop up
* @data: dbus control interface private data
*
* Try to wake up the main eloop so it will process
* dbus events that may have happened.
*/
static void wakeup_main(void *data)
{
struct wpas_dbus_priv *priv = data;
/* Use SIGPOLL to break out of the eloop select() */
raise(SIGPOLL);
priv->should_dispatch = 1;
}
/**
* connection_setup_wakeup_main - Tell dbus about our wakeup_main function
* @priv: dbus control interface private data
* Returns: 0 on success, -1 on failure
*
* Register our wakeup_main handler with dbus
*/
static int connection_setup_wakeup_main(struct wpas_dbus_priv *priv)
{
if (eloop_register_signal(SIGPOLL, process_wakeup_main, priv))
return -1;
dbus_connection_set_wakeup_main_function(priv->con, wakeup_main,
priv, NULL);
return 0;
}
/**
* integrate_with_eloop - Register our mainloop integration with dbus
* @connection: connection to the system message bus
* @priv: a dbus control interface data structure
* Returns: 0 on success, -1 on failure
*
* We register our mainloop integration functions with dbus here.
*/
static int integrate_with_eloop(struct wpas_dbus_priv *priv)
{
if (!dbus_connection_set_watch_functions(priv->con, add_watch,
remove_watch, watch_toggled,
priv, NULL)) {
perror("dbus_connection_set_watch_functions[dbus]");
wpa_printf(MSG_ERROR, "Not enough memory to set up dbus.");
return -1;
}
if (!dbus_connection_set_timeout_functions(priv->con, add_timeout,
remove_timeout,
timeout_toggled, priv,
NULL)) {
perror("dbus_connection_set_timeout_functions[dbus]");
wpa_printf(MSG_ERROR, "Not enough memory to set up dbus.");
return -1;
}
if (connection_setup_wakeup_main(priv) < 0) {
perror("connection_setup_wakeup_main[dbus]");
wpa_printf(MSG_ERROR, "Could not setup main wakeup function.");
return -1;
}
return 0;
}
static int wpas_dbus_init_common(struct wpas_dbus_priv *priv)
{
DBusError error;
/* Get a reference to the system bus */
dbus_error_init(&error);
priv->con = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
dbus_error_free(&error);
if (!priv->con) {
wpa_printf(MSG_ERROR, "dbus: Could not acquire the system "
"bus: %s", strerror(errno));
return -1;
}
return 0;
}
static int wpas_dbus_init_common_finish(struct wpas_dbus_priv *priv)
{
/* Tell dbus about our mainloop integration functions */
integrate_with_eloop(priv);
/*
* Dispatch initial DBus messages that may have come in since the bus
* name was claimed above. Happens when clients are quick to notice the
* service.
*
* FIXME: is there a better solution to this problem?
*/
eloop_register_timeout(0, 50, dispatch_initial_dbus_messages,
priv->con, NULL);
return 0;
}
static void wpas_dbus_deinit_common(struct wpas_dbus_priv *priv)
{
if (priv->con) {
eloop_cancel_timeout(dispatch_initial_dbus_messages,
priv->con, NULL);
dbus_connection_set_watch_functions(priv->con, NULL, NULL,
NULL, NULL, NULL);
dbus_connection_set_timeout_functions(priv->con, NULL, NULL,
NULL, NULL, NULL);
dbus_connection_unref(priv->con);
}
os_free(priv);
}
struct wpas_dbus_priv * wpas_dbus_init(struct wpa_global *global)
{
struct wpas_dbus_priv *priv;
priv = os_zalloc(sizeof(*priv));
if (priv == NULL)
return NULL;
priv->global = global;
if (wpas_dbus_init_common(priv) < 0) {
wpas_dbus_deinit(priv);
return NULL;
}
#ifdef CONFIG_CTRL_IFACE_DBUS_NEW
if (wpas_dbus_ctrl_iface_init(priv) < 0) {
wpas_dbus_deinit(priv);
return NULL;
}
#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
#ifdef CONFIG_CTRL_IFACE_DBUS
if (wpa_supplicant_dbus_ctrl_iface_init(priv) < 0) {
wpas_dbus_deinit(priv);
return NULL;
}
#endif /* CONFIG_CTRL_IFACE_DBUS */
if (wpas_dbus_init_common_finish(priv) < 0) {
wpas_dbus_deinit(priv);
return NULL;
}
return priv;
}
void wpas_dbus_deinit(struct wpas_dbus_priv *priv)
{
if (priv == NULL)
return;
#ifdef CONFIG_CTRL_IFACE_DBUS_NEW
wpas_dbus_ctrl_iface_deinit(priv);
#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
#ifdef CONFIG_CTRL_IFACE_DBUS
/* TODO: is any deinit needed? */
#endif /* CONFIG_CTRL_IFACE_DBUS */
wpas_dbus_deinit_common(priv);
}

View file

@ -0,0 +1,26 @@
/*
* wpa_supplicant D-Bus control interface - common definitions
* Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
* Copyright (c) 2009, Witold Sowa <witold.sowa@gmail.com>
* Copyright (c) 2009, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
*/
#ifndef DBUS_COMMON_H
#define DBUS_COMMON_H
struct wpas_dbus_priv;
struct wpa_global;
struct wpas_dbus_priv * wpas_dbus_init(struct wpa_global *global);
void wpas_dbus_deinit(struct wpas_dbus_priv *priv);
#endif /* DBUS_COMMON_H */

View file

@ -0,0 +1,29 @@
/*
* wpa_supplicant D-Bus control interface - internal definitions
* Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
* Copyright (c) 2009, Witold Sowa <witold.sowa@gmail.com>
* Copyright (c) 2009, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
*/
#ifndef DBUS_COMMON_I_H
#define DBUS_COMMON_I_H
#include <dbus/dbus.h>
struct wpas_dbus_priv {
DBusConnection *con;
int should_dispatch;
struct wpa_global *global;
u32 next_objid;
};
#endif /* DBUS_COMMON_I_H */

View file

@ -25,6 +25,8 @@
#include "dbus_dict_helpers.h"
#include "dbus_new.h"
#include "dbus_new_handlers.h"
#include "dbus_common.h"
#include "dbus_common_i.h"
/**
* wpas_dbus_set_path - Assign a dbus path to an interface
@ -55,11 +57,11 @@ static int wpas_dbus_set_path(struct wpa_supplicant *wpa_s,
static void wpas_dbus_signal_interface(struct wpa_supplicant *wpa_s,
const char *sig_name)
{
struct ctrl_iface_dbus_new_priv *iface;
struct wpas_dbus_priv *iface;
DBusMessage *_signal;
const char *path;
iface = wpa_s->global->dbus_new_ctrl_iface;
iface = wpa_s->global->dbus;
/* Do nothing if the control interface is not turned on */
if (iface == NULL)
@ -126,12 +128,12 @@ static void wpas_dbus_signal_interface_removed(struct wpa_supplicant *wpa_s)
static void wpas_dbus_signal_scan_done(struct wpa_supplicant *wpa_s,
int success)
{
struct ctrl_iface_dbus_new_priv *iface;
struct wpas_dbus_priv *iface;
DBusMessage *_signal;
const char *path;
dbus_bool_t succ;
iface = wpa_s->global->dbus_new_ctrl_iface;
iface = wpa_s->global->dbus;
/* Do nothing if the control interface is not turned on */
if (iface == NULL)
@ -176,11 +178,11 @@ static void wpas_dbus_signal_bss(struct wpa_supplicant *wpa_s,
const char *bss_obj_path,
const char *sig_name)
{
struct ctrl_iface_dbus_new_priv *iface;
struct wpas_dbus_priv *iface;
DBusMessage *_signal;
const char *path;
iface = wpa_s->global->dbus_new_ctrl_iface;
iface = wpa_s->global->dbus;
/* Do nothing if the control interface is not turned on */
if (iface == NULL)
@ -251,11 +253,11 @@ static void wpas_dbus_signal_bss_removed(struct wpa_supplicant *wpa_s,
static void wpas_dbus_signal_blob(struct wpa_supplicant *wpa_s,
const char *name, const char *sig_name)
{
struct ctrl_iface_dbus_new_priv *iface;
struct wpas_dbus_priv *iface;
DBusMessage *_signal;
const char *path;
iface = wpa_s->global->dbus_new_ctrl_iface;
iface = wpa_s->global->dbus;
/* Do nothing if the control interface is not turned on */
if (iface == NULL)
@ -326,12 +328,12 @@ static void wpas_dbus_signal_blob_removed(struct wpa_supplicant *wpa_s,
static void wpas_dbus_signal_network(struct wpa_supplicant *wpa_s,
int id, const char *sig_name)
{
struct ctrl_iface_dbus_new_priv *iface;
struct wpas_dbus_priv *iface;
DBusMessage *_signal;
const char *path;
char *net_obj_path;
iface = wpa_s->global->dbus_new_ctrl_iface;
iface = wpa_s->global->dbus;
/* Do nothing if the control interface is not turned on */
if (iface == NULL)
@ -427,7 +429,7 @@ static void wpas_dbus_signal_state_changed(struct wpa_supplicant *wpa_s,
enum wpa_states new_state,
enum wpa_states old_state)
{
struct ctrl_iface_dbus_new_priv *iface;
struct wpas_dbus_priv *iface;
DBusMessage *_signal = NULL;
const char *path;
char *new_state_str, *old_state_str;
@ -436,7 +438,7 @@ static void wpas_dbus_signal_state_changed(struct wpa_supplicant *wpa_s,
/* Do nothing if the control interface is not turned on */
if (wpa_s->global == NULL)
return;
iface = wpa_s->global->dbus_new_ctrl_iface;
iface = wpa_s->global->dbus;
if (iface == NULL)
return;
@ -530,7 +532,7 @@ static void wpas_dbus_signal_network_enabled_changed(
"%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
wpas_dbus_get_path(wpa_s), ssid->id);
wpa_dbus_signal_property_changed(wpa_s->global->dbus_new_ctrl_iface,
wpa_dbus_signal_property_changed(wpa_s->global->dbus,
(WPADBusPropertyAccessor)
wpas_dbus_getter_enabled, &args,
path, WPAS_DBUS_NEW_IFACE_NETWORK,
@ -551,11 +553,11 @@ static void wpas_dbus_signal_wps_event_success(struct wpa_supplicant *wpa_s)
DBusMessage *_signal = NULL;
DBusMessageIter iter, dict_iter;
struct ctrl_iface_dbus_new_priv *iface;
struct wpas_dbus_priv *iface;
char *key = "success";
const char *path;
iface = wpa_s->global->dbus_new_ctrl_iface;
iface = wpa_s->global->dbus;
/* Do nothing if the control interface is not turned on */
if (iface == NULL)
@ -605,11 +607,11 @@ static void wpas_dbus_signal_wps_event_fail(struct wpa_supplicant *wpa_s,
DBusMessage *_signal = NULL;
DBusMessageIter iter, dict_iter;
struct ctrl_iface_dbus_new_priv *iface;
struct wpas_dbus_priv *iface;
char *key = "fail";
const char *path;
iface = wpa_s->global->dbus_new_ctrl_iface;
iface = wpa_s->global->dbus;
/* Do nothing if the control interface is not turned on */
if (iface == NULL)
@ -660,11 +662,11 @@ static void wpas_dbus_signal_wps_event_m2d(struct wpa_supplicant *wpa_s,
DBusMessage *_signal = NULL;
DBusMessageIter iter, dict_iter;
struct ctrl_iface_dbus_new_priv *iface;
struct wpas_dbus_priv *iface;
char *key = "m2d";
const char *path;
iface = wpa_s->global->dbus_new_ctrl_iface;
iface = wpa_s->global->dbus;
/* Do nothing if the control interface is not turned on */
if (iface == NULL)
@ -737,14 +739,14 @@ static void wpas_dbus_signal_wps_cred(struct wpa_supplicant *wpa_s,
{
DBusMessage *_signal = NULL;
DBusMessageIter iter, dict_iter;
struct ctrl_iface_dbus_new_priv *iface;
struct wpas_dbus_priv *iface;
const char *path;
char *auth_type[6]; /* we have six possible authorization types */
int at_num = 0;
char *encr_type[4]; /* we have four possible encryption types */
int et_num = 0;
iface = wpa_s->global->dbus_new_ctrl_iface;
iface = wpa_s->global->dbus;
/* Do nothing if the control interface is not turned on */
if (iface == NULL)
@ -890,7 +892,7 @@ static void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s,
return;
}
wpa_dbus_signal_property_changed(wpa_s->global->dbus_new_ctrl_iface,
wpa_dbus_signal_property_changed(wpa_s->global->dbus,
getter, arg,
wpas_dbus_get_path(wpa_s), iface,
prop);
@ -906,7 +908,7 @@ static void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s,
static void wpas_dbus_signal_debug_params_changed(struct wpa_global *global)
{
wpa_dbus_signal_property_changed(global->dbus_new_ctrl_iface,
wpa_dbus_signal_property_changed(global->dbus,
(WPADBusPropertyAccessor)
wpas_dbus_getter_debug_params,
global, WPAS_DBUS_NEW_PATH,
@ -1040,58 +1042,53 @@ static const struct wpas_dbus_signal wpas_dbus_global_signals[] = {
/**
* wpas_dbus_ctrl_iface_init - Initialize dbus control interface
* @global: Pointer to global data from wpa_supplicant_init()
* Returns: Pointer to dbus_new_ctrl_iface date or %NULL on failure
* Returns: 0 on success or -1 on failure
*
* Initialize the dbus control interface for wpa_supplicantand and start
* receiving commands from external programs over the bus.
*/
static struct ctrl_iface_dbus_new_priv * wpas_dbus_ctrl_iface_init(
struct wpa_global *global)
int wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv *priv)
{
struct ctrl_iface_dbus_new_priv *ctrl_iface;
struct wpa_dbus_object_desc *obj_desc;
int ret;
obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
if (!obj_desc) {
wpa_printf(MSG_ERROR, "Not enough memory "
"to create object description");
return NULL;
return -1;
}
wpas_dbus_register(obj_desc, global, wpas_dbus_global_methods,
wpas_dbus_register(obj_desc, priv->global, wpas_dbus_global_methods,
wpas_dbus_global_properties,
wpas_dbus_global_signals);
wpa_printf(MSG_DEBUG, "dbus: Register D-Bus object '%s'",
WPAS_DBUS_NEW_PATH);
ctrl_iface = wpa_dbus_ctrl_iface_init(global, WPAS_DBUS_NEW_PATH,
WPAS_DBUS_NEW_SERVICE,
obj_desc);
if (!ctrl_iface)
ret = wpa_dbus_ctrl_iface_init(priv, WPAS_DBUS_NEW_PATH,
WPAS_DBUS_NEW_SERVICE,
obj_desc);
if (ret < 0)
free_dbus_object_desc(obj_desc);
return ctrl_iface;
return ret;
}
/**
* wpas_dbus_ctrl_iface_deinit - Deinitialize dbus ctrl interface for
* wpa_supplicant
* @iface: Pointer to dbus private data from
* wpas_dbus_ctrl_iface_init()
* @iface: Pointer to dbus private data from wpas_dbus_init()
*
* Deinitialize the dbus control interface that was initialized with
* wpas_dbus_ctrl_iface_init().
*/
static void wpas_dbus_ctrl_iface_deinit(struct ctrl_iface_dbus_new_priv *iface)
void wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv *iface)
{
if (iface) {
wpa_printf(MSG_DEBUG, "dbus: Unregister D-Bus object '%s'",
WPAS_DBUS_NEW_PATH);
dbus_connection_unregister_object_path(iface->con,
WPAS_DBUS_NEW_PATH);
wpa_dbus_ctrl_iface_deinit(iface);
}
wpa_printf(MSG_DEBUG, "dbus: Unregister D-Bus object '%s'",
WPAS_DBUS_NEW_PATH);
dbus_connection_unregister_object_path(iface->con,
WPAS_DBUS_NEW_PATH);
}
@ -1112,7 +1109,7 @@ static void wpa_dbus_free(void *ptr)
static int wpas_dbus_register_network(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid)
{
struct ctrl_iface_dbus_new_priv *ctrl_iface;
struct wpas_dbus_priv *ctrl_iface;
struct wpa_dbus_object_desc *obj_desc;
struct network_handler_args *arg1 = NULL;
@ -1128,7 +1125,7 @@ static int wpas_dbus_register_network(struct wpa_supplicant *wpa_s,
/* Do nothing if the control interface is not turned on */
if (wpa_s == NULL || wpa_s->global == NULL)
return 0;
ctrl_iface = wpa_s->global->dbus_new_ctrl_iface;
ctrl_iface = wpa_s->global->dbus;
if (ctrl_iface == NULL)
return 0;
@ -1217,14 +1214,14 @@ err:
*/
static int wpas_dbus_unregister_network(struct wpa_supplicant *wpa_s, int nid)
{
struct ctrl_iface_dbus_new_priv *ctrl_iface;
struct wpas_dbus_priv *ctrl_iface;
char *net_obj_path;
int ret;
/* Do nothing if the control interface is not turned on */
if (wpa_s == NULL || wpa_s->global == NULL)
return 0;
ctrl_iface = wpa_s->global->dbus_new_ctrl_iface;
ctrl_iface = wpa_s->global->dbus;
if (ctrl_iface == NULL)
return 0;
@ -1259,13 +1256,13 @@ static int wpas_dbus_unregister_network(struct wpa_supplicant *wpa_s, int nid)
static int wpas_dbus_unregister_bss(struct wpa_supplicant *wpa_s,
u8 bssid[ETH_ALEN], unsigned int id)
{
struct ctrl_iface_dbus_new_priv *ctrl_iface;
struct wpas_dbus_priv *ctrl_iface;
char *bss_obj_path;
/* Do nothing if the control interface is not turned on */
if (wpa_s == NULL || wpa_s->global == NULL)
return 0;
ctrl_iface = wpa_s->global->dbus_new_ctrl_iface;
ctrl_iface = wpa_s->global->dbus;
if (ctrl_iface == NULL)
return 0;
@ -1306,7 +1303,7 @@ static int wpas_dbus_unregister_bss(struct wpa_supplicant *wpa_s,
static int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s,
u8 bssid[ETH_ALEN], unsigned int id)
{
struct ctrl_iface_dbus_new_priv *ctrl_iface;
struct wpas_dbus_priv *ctrl_iface;
struct wpa_dbus_object_desc *obj_desc;
char *bss_obj_path;
@ -1315,7 +1312,7 @@ static int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s,
/* Do nothing if the control interface is not turned on */
if (wpa_s == NULL || wpa_s->global == NULL)
return 0;
ctrl_iface = wpa_s->global->dbus_new_ctrl_iface;
ctrl_iface = wpa_s->global->dbus;
if (ctrl_iface == NULL)
return 0;
@ -1597,8 +1594,7 @@ static int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s)
struct wpa_dbus_object_desc *obj_desc = NULL;
char *path;
struct ctrl_iface_dbus_new_priv *ctrl_iface =
wpa_s->global->dbus_new_ctrl_iface;
struct wpas_dbus_priv *ctrl_iface = wpa_s->global->dbus;
int next;
/* Do nothing if the control interface is not turned on */
@ -1609,7 +1605,7 @@ static int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s)
path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
if (path == NULL)
return -1;
next = wpa_dbus_next_objid(ctrl_iface);
next = ctrl_iface->next_objid++;
os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
WPAS_DBUS_NEW_PATH_INTERFACES "/%u",
next);
@ -1650,12 +1646,12 @@ err:
static int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s)
{
struct ctrl_iface_dbus_new_priv *ctrl_iface;
struct wpas_dbus_priv *ctrl_iface;
/* Do nothing if the control interface is not turned on */
if (wpa_s == NULL || wpa_s->global == NULL)
return 0;
ctrl_iface = wpa_s->global->dbus_new_ctrl_iface;
ctrl_iface = wpa_s->global->dbus;
if (ctrl_iface == NULL)
return 0;
@ -1676,9 +1672,6 @@ static int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s)
static struct wpas_dbus_callbacks callbacks =
{
.dbus_ctrl_init = wpas_dbus_ctrl_iface_init,
.dbus_ctrl_deinit = wpas_dbus_ctrl_iface_deinit,
.signal_interface_created = wpas_dbus_signal_interface_created,
.signal_interface_removed = wpas_dbus_signal_interface_removed,

View file

@ -22,6 +22,7 @@ struct wpa_ssid;
struct wps_event_m2d;
struct wps_event_fail;
struct wps_credential;
enum wpa_states;
enum wpas_dbus_prop {
WPAS_DBUS_PROP_AP_SCAN,
@ -31,11 +32,6 @@ enum wpas_dbus_prop {
};
struct wpas_dbus_callbacks {
struct ctrl_iface_dbus_new_priv * (*dbus_ctrl_init)(
struct wpa_global *global);
void (*dbus_ctrl_deinit)(struct ctrl_iface_dbus_new_priv *iface);
void (*signal_interface_created)(struct wpa_supplicant *wpa_s);
void (*signal_interface_removed)(struct wpa_supplicant *wpa_s);
@ -127,6 +123,9 @@ struct wpas_dbus_callbacks {
struct wpas_dbus_callbacks * wpas_dbus_get_callbacks(void);
const char * wpas_dbus_get_path(struct wpa_supplicant *wpa_s);
int wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv *priv);
void wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv *iface);
#else /* CONFIG_CTRL_IFACE_DBUS_NEW */
static inline struct wpas_dbus_callbacks * wpas_dbus_get_callbacks(void)

View file

@ -332,7 +332,7 @@ DBusMessage * wpas_dbus_setter_process_credentials(
if ((wpa_s->conf->wps_cred_processing != 1) != old_pc)
wpa_dbus_signal_property_changed(
wpa_s->global->dbus_new_ctrl_iface,
wpa_s->global->dbus,
(WPADBusPropertyAccessor)
wpas_dbus_getter_process_credentials,
wpa_s, wpas_dbus_get_path(wpa_s),

View file

@ -17,6 +17,8 @@
#include "common.h"
#include "eloop.h"
#include "dbus_common.h"
#include "dbus_common_i.h"
#include "dbus_new_helpers.h"
/**
@ -102,296 +104,6 @@ struct interfaces {
};
#endif /* CONFIG_CTRL_IFACE_DBUS_INTRO */
static void process_watch(struct ctrl_iface_dbus_new_priv *iface,
DBusWatch *watch, eloop_event_type type)
{
dbus_connection_ref(iface->con);
iface->should_dispatch = 0;
if (type == EVENT_TYPE_READ)
dbus_watch_handle(watch, DBUS_WATCH_READABLE);
else if (type == EVENT_TYPE_WRITE)
dbus_watch_handle(watch, DBUS_WATCH_WRITABLE);
else if (type == EVENT_TYPE_EXCEPTION)
dbus_watch_handle(watch, DBUS_WATCH_ERROR);
if (iface->should_dispatch) {
while (dbus_connection_get_dispatch_status(iface->con) ==
DBUS_DISPATCH_DATA_REMAINS)
dbus_connection_dispatch(iface->con);
iface->should_dispatch = 0;
}
dbus_connection_unref(iface->con);
}
static void process_watch_exception(int sock, void *eloop_ctx, void *sock_ctx)
{
process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_EXCEPTION);
}
static void process_watch_read(int sock, void *eloop_ctx, void *sock_ctx)
{
process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_READ);
}
static void process_watch_write(int sock, void *eloop_ctx, void *sock_ctx)
{
process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_WRITE);
}
static void connection_setup_add_watch(struct ctrl_iface_dbus_new_priv *iface,
DBusWatch *watch)
{
unsigned int flags;
int fd;
if (!dbus_watch_get_enabled(watch))
return;
flags = dbus_watch_get_flags(watch);
fd = dbus_watch_get_unix_fd(watch);
eloop_register_sock(fd, EVENT_TYPE_EXCEPTION, process_watch_exception,
iface, watch);
if (flags & DBUS_WATCH_READABLE) {
eloop_register_sock(fd, EVENT_TYPE_READ, process_watch_read,
iface, watch);
}
if (flags & DBUS_WATCH_WRITABLE) {
eloop_register_sock(fd, EVENT_TYPE_WRITE, process_watch_write,
iface, watch);
}
dbus_watch_set_data(watch, iface, NULL);
}
static void connection_setup_remove_watch(
struct ctrl_iface_dbus_new_priv *iface, DBusWatch *watch)
{
unsigned int flags;
int fd;
flags = dbus_watch_get_flags(watch);
fd = dbus_watch_get_unix_fd(watch);
eloop_unregister_sock(fd, EVENT_TYPE_EXCEPTION);
if (flags & DBUS_WATCH_READABLE)
eloop_unregister_sock(fd, EVENT_TYPE_READ);
if (flags & DBUS_WATCH_WRITABLE)
eloop_unregister_sock(fd, EVENT_TYPE_WRITE);
dbus_watch_set_data(watch, NULL, NULL);
}
static dbus_bool_t add_watch(DBusWatch *watch, void *data)
{
connection_setup_add_watch(data, watch);
return TRUE;
}
static void remove_watch(DBusWatch *watch, void *data)
{
connection_setup_remove_watch(data, watch);
}
static void watch_toggled(DBusWatch *watch, void *data)
{
if (dbus_watch_get_enabled(watch))
add_watch(watch, data);
else
remove_watch(watch, data);
}
static void process_timeout(void *eloop_ctx, void *sock_ctx)
{
DBusTimeout *timeout = sock_ctx;
dbus_timeout_handle(timeout);
}
static void connection_setup_add_timeout(
struct ctrl_iface_dbus_new_priv *iface, DBusTimeout *timeout)
{
if (!dbus_timeout_get_enabled(timeout))
return;
eloop_register_timeout(0, dbus_timeout_get_interval(timeout) * 1000,
process_timeout, iface, timeout);
dbus_timeout_set_data(timeout, iface, NULL);
}
static void connection_setup_remove_timeout(
struct ctrl_iface_dbus_new_priv *iface, DBusTimeout *timeout)
{
eloop_cancel_timeout(process_timeout, iface, timeout);
dbus_timeout_set_data(timeout, NULL, NULL);
}
static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data)
{
if (!dbus_timeout_get_enabled(timeout))
return TRUE;
connection_setup_add_timeout(data, timeout);
return TRUE;
}
static void remove_timeout(DBusTimeout *timeout, void *data)
{
connection_setup_remove_timeout(data, timeout);
}
static void timeout_toggled(DBusTimeout *timeout, void *data)
{
if (dbus_timeout_get_enabled(timeout))
add_timeout(timeout, data);
else
remove_timeout(timeout, data);
}
static void process_wakeup_main(int sig, void *signal_ctx)
{
struct ctrl_iface_dbus_new_priv *iface = signal_ctx;
if (sig != SIGPOLL || !iface->con)
return;
if (dbus_connection_get_dispatch_status(iface->con) !=
DBUS_DISPATCH_DATA_REMAINS)
return;
/* Only dispatch once - we do not want to starve other events */
dbus_connection_ref(iface->con);
dbus_connection_dispatch(iface->con);
dbus_connection_unref(iface->con);
}
/**
* wakeup_main - Attempt to wake our mainloop up
* @data: dbus control interface private data
*
* Try to wake up the main eloop so it will process
* dbus events that may have happened.
*/
static void wakeup_main(void *data)
{
struct ctrl_iface_dbus_new_priv *iface = data;
/* Use SIGPOLL to break out of the eloop select() */
raise(SIGPOLL);
iface->should_dispatch = 1;
}
/**
* connection_setup_wakeup_main - Tell dbus about our wakeup_main function
* @iface: dbus control interface private data
* Returns: 0 on success, -1 on failure
*
* Register our wakeup_main handler with dbus
*/
static int connection_setup_wakeup_main(struct ctrl_iface_dbus_new_priv *iface)
{
if (eloop_register_signal(SIGPOLL, process_wakeup_main, iface))
return -1;
dbus_connection_set_wakeup_main_function(iface->con, wakeup_main,
iface, NULL);
return 0;
}
/**
* wpa_dbus_next_objid - Return next available object id
* @iface: dbus control interface private data
* Returns: Object id
*/
u32 wpa_dbus_next_objid(struct ctrl_iface_dbus_new_priv *iface)
{
return iface->next_objid++;
}
/**
* integrate_with_eloop - Register our mainloop integration with dbus
* @connection: connection to the system message bus
* @iface: a dbus control interface data structure
* Returns: 0 on success, -1 on failure
*
* We register our mainloop integration functions with dbus here.
*/
static int integrate_with_eloop(DBusConnection *connection,
struct ctrl_iface_dbus_new_priv *iface)
{
if (!dbus_connection_set_watch_functions(connection, add_watch,
remove_watch, watch_toggled,
iface, NULL)) {
perror("dbus_connection_set_watch_functions[dbus]");
wpa_printf(MSG_ERROR, "Not enough memory to set up dbus.");
return -1;
}
if (!dbus_connection_set_timeout_functions(connection, add_timeout,
remove_timeout,
timeout_toggled, iface,
NULL)) {
perror("dbus_connection_set_timeout_functions[dbus]");
wpa_printf(MSG_ERROR, "Not enough memory to set up dbus.");
return -1;
}
if (connection_setup_wakeup_main(iface) < 0) {
perror("connection_setup_wakeup_main[dbus]");
wpa_printf(MSG_ERROR, "Could not setup main wakeup function.");
return -1;
}
return 0;
}
/**
* dispatch_initial_dbus_messages - Dispatch initial dbus messages after
* claiming bus name
* @eloop_ctx: the DBusConnection to dispatch on
* @timeout_ctx: unused
*
* If clients are quick to notice that service claimed its bus name,
* there may have been messages that came in before initialization was
* all finished. Dispatch those here.
*/
static void dispatch_initial_dbus_messages(void *eloop_ctx, void *timeout_ctx)
{
DBusConnection *con = eloop_ctx;
while (dbus_connection_get_dispatch_status(con) ==
DBUS_DISPATCH_DATA_REMAINS)
dbus_connection_dispatch(con);
}
#ifdef CONFIG_CTRL_IFACE_DBUS_INTRO
@ -1320,17 +1032,15 @@ static void free_dbus_object_desc_cb(DBusConnection *connection, void *obj_dsc)
* @dbus_service: DBus service name to register with
* @messageHandler: a pointer to function which will handle dbus messages
* coming on interface
* Returns: Pointer to dbus_new_ctrl_iface date or %NULL on failure
* Returns: 0 on success, -1 on failure
*
* Initialize the dbus control interface and start receiving commands from
* external programs over the bus.
*/
struct ctrl_iface_dbus_new_priv *
wpa_dbus_ctrl_iface_init(void *application_data,
char *dbus_path, char *dbus_service,
struct wpa_dbus_object_desc *obj_desc)
int wpa_dbus_ctrl_iface_init(struct wpas_dbus_priv *iface,
char *dbus_path, char *dbus_service,
struct wpa_dbus_object_desc *obj_desc)
{
struct ctrl_iface_dbus_new_priv *iface;
DBusError error;
int ret = -1;
DBusObjectPathVTable wpa_vtable = {
@ -1338,28 +1048,8 @@ wpa_dbus_ctrl_iface_init(void *application_data,
NULL, NULL, NULL, NULL
};
iface = os_zalloc(sizeof(struct ctrl_iface_dbus_new_priv));
if (iface == NULL)
return NULL;
iface->application_data = application_data;
/* Get a reference to the system bus */
dbus_error_init(&error);
iface->con = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
dbus_error_free(&error);
if (!iface->con) {
perror("dbus_bus_get[ctrl_iface_dbus]");
wpa_printf(MSG_ERROR, "Could not acquire the system bus.");
goto fail;
}
obj_desc->connection = iface->con;
/* Tell dbus about our mainloop integration functions */
if (integrate_with_eloop(iface->con, iface))
goto fail;
/* Register the message handler for the global dbus interface */
if (!dbus_connection_register_object_path(iface->con,
dbus_path, &wpa_vtable,
@ -1367,7 +1057,7 @@ wpa_dbus_ctrl_iface_init(void *application_data,
perror("dbus_connection_register_object_path[dbus]");
wpa_printf(MSG_ERROR, "Could not set up DBus message "
"handler.");
goto fail;
return -1;
}
/* Register our service with the message bus */
@ -1393,52 +1083,11 @@ wpa_dbus_ctrl_iface_init(void *application_data,
dbus_error_free(&error);
if (ret != 0)
goto fail;
return -1;
wpa_printf(MSG_DEBUG, "Providing DBus service '%s'.", dbus_service);
/*
* Dispatch initial DBus messages that may have come in since the bus
* name was claimed above. Happens when clients are quick to notice the
* service.
*
* FIXME: is there a better solution to this problem?
*/
eloop_register_timeout(0, 50, dispatch_initial_dbus_messages,
iface->con, NULL);
return iface;
fail:
wpa_dbus_ctrl_iface_deinit(iface);
return NULL;
}
/**
* wpa_dbus_ctrl_iface_deinit - Deinitialize dbus ctrl interface
* @iface: Pointer to dbus private data from wpa_dbus_ctrl_iface_init()
*
* Deinitialize the dbus control interface that was initialized with
* wpa_dbus_ctrl_iface_init().
*/
void wpa_dbus_ctrl_iface_deinit(struct ctrl_iface_dbus_new_priv *iface)
{
if (iface == NULL)
return;
if (iface->con) {
eloop_cancel_timeout(dispatch_initial_dbus_messages,
iface->con, NULL);
dbus_connection_set_watch_functions(iface->con, NULL, NULL,
NULL, NULL, NULL);
dbus_connection_set_timeout_functions(iface->con, NULL, NULL,
NULL, NULL, NULL);
dbus_connection_unref(iface->con);
}
os_memset(iface, 0, sizeof(struct ctrl_iface_dbus_new_priv));
os_free(iface);
return 0;
}
@ -1453,7 +1102,7 @@ void wpa_dbus_ctrl_iface_deinit(struct ctrl_iface_dbus_new_priv *iface)
* Registers a new interface with dbus and assigns it a dbus object path.
*/
int wpa_dbus_register_object_per_iface(
struct ctrl_iface_dbus_new_priv *ctrl_iface,
struct wpas_dbus_priv *ctrl_iface,
const char *path, const char *ifname,
struct wpa_dbus_object_desc *obj_desc)
{
@ -1494,7 +1143,7 @@ int wpa_dbus_register_object_per_iface(
* Unregisters DBus object given by its path
*/
int wpa_dbus_unregister_object_per_iface(
struct ctrl_iface_dbus_new_priv *ctrl_iface, const char *path)
struct wpas_dbus_priv *ctrl_iface, const char *path)
{
DBusConnection *con = ctrl_iface->con;
if (!dbus_connection_unregister_object_path(con, path))
@ -1849,7 +1498,7 @@ err:
* contains property name and its value fetched using given property
* getter.
*/
void wpa_dbus_signal_property_changed(struct ctrl_iface_dbus_new_priv *iface,
void wpa_dbus_signal_property_changed(struct wpas_dbus_priv *iface,
WPADBusPropertyAccessor property_getter,
void *getter_arg,
const char *path,

View file

@ -18,14 +18,6 @@
#include <dbus/dbus.h>
struct ctrl_iface_dbus_new_priv {
DBusConnection *con;
int should_dispatch;
void *application_data;
u32 next_objid;
};
typedef DBusMessage * (* WPADBusMethodHandler)(DBusMessage *message,
void *user_data);
typedef void (* WPADBusArgumentFreeFunction)(void *handler_arg);
@ -77,20 +69,17 @@ struct wpa_dbus_argument {
void free_dbus_object_desc(struct wpa_dbus_object_desc *obj_dsc);
struct ctrl_iface_dbus_new_priv *
wpa_dbus_ctrl_iface_init(void *application_data, char *dbus_path,
char *dbus_service,
struct wpa_dbus_object_desc *obj_desc);
void wpa_dbus_ctrl_iface_deinit(struct ctrl_iface_dbus_new_priv *iface);
int wpa_dbus_ctrl_iface_init(struct wpas_dbus_priv *iface, char *dbus_path,
char *dbus_service,
struct wpa_dbus_object_desc *obj_desc);
int wpa_dbus_register_object_per_iface(
struct ctrl_iface_dbus_new_priv *ctrl_iface,
struct wpas_dbus_priv *ctrl_iface,
const char *path, const char *ifname,
struct wpa_dbus_object_desc *obj_desc);
int wpa_dbus_unregister_object_per_iface(
struct ctrl_iface_dbus_new_priv *ctrl_iface,
struct wpas_dbus_priv *ctrl_iface,
const char *path);
int wpa_dbus_method_register(struct wpa_dbus_object_desc *obj_dsc,
@ -116,21 +105,18 @@ int wpa_dbus_property_register(
WPADBusArgumentFreeFunction user_data_free_func,
enum dbus_prop_access _access);
void wpa_dbus_signal_property_changed(struct ctrl_iface_dbus_new_priv *iface,
void wpa_dbus_signal_property_changed(struct wpas_dbus_priv *iface,
WPADBusPropertyAccessor property_getter,
void *getter_arg,
const char *path,
const char *interface_name,
const char *property_name);
/* Methods internal to the dbus control interface */
u32 wpa_dbus_next_objid(struct ctrl_iface_dbus_new_priv *iface);
#else /* CONFIG_CTRL_IFACE_DBUS_NEW */
static inline void wpa_dbus_signal_property_changed(
struct ctrl_iface_dbus_new_priv *iface,
struct wpas_dbus_priv *iface,
WPADBusPropertyAccessor property_getter, void *getter_arg,
const char *path, const char *interface_name,
const char *property_name)

View file

@ -19,27 +19,20 @@
#include "config.h"
#include "wpa_supplicant_i.h"
#include "wps_supplicant.h"
#include "dbus/dbus_common.h"
#include "dbus/dbus.h"
#include "dbus/dbus_new.h"
#include "notify.h"
int wpas_notify_supplicant_initialized(struct wpa_global *global)
{
struct wpas_dbus_callbacks *cbs = wpas_dbus_get_callbacks();
#ifdef CONFIG_DBUS
if (global->params.dbus_ctrl_interface) {
if (cbs) {
global->dbus_new_ctrl_iface =
cbs->dbus_ctrl_init(global);
if (global->dbus_new_ctrl_iface == NULL)
return -1;
}
global->dbus_ctrl_iface =
wpa_supplicant_dbus_ctrl_iface_init(global);
if (global->dbus_ctrl_iface == NULL)
global->dbus = wpas_dbus_init(global);
if (global->dbus == NULL)
return -1;
}
#endif /* CONFIG_DBUS */
return 0;
}
@ -47,13 +40,10 @@ int wpas_notify_supplicant_initialized(struct wpa_global *global)
void wpas_notify_supplicant_deinitialized(struct wpa_global *global)
{
struct wpas_dbus_callbacks *cbs = wpas_dbus_get_callbacks();
if (cbs && global->dbus_new_ctrl_iface)
cbs->dbus_ctrl_deinit(global->dbus_new_ctrl_iface);
if (global->dbus_ctrl_iface)
wpa_supplicant_dbus_ctrl_iface_deinit(global->dbus_ctrl_iface);
#ifdef CONFIG_DBUS
if (global->dbus)
wpas_dbus_deinit(global->dbus);
#endif /* CONFIG_DBUS */
}
@ -225,7 +215,7 @@ void wpas_notify_network_added(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid)
{
struct wpas_dbus_callbacks *cbs = wpas_dbus_get_callbacks();
if (wpa_s->global->dbus_new_ctrl_iface && cbs)
if (wpa_s->global->dbus && cbs)
cbs->register_network(wpa_s, ssid);
}
@ -234,7 +224,7 @@ void wpas_notify_network_removed(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid)
{
struct wpas_dbus_callbacks *cbs = wpas_dbus_get_callbacks();
if (wpa_s->global->dbus_new_ctrl_iface && cbs)
if (wpa_s->global->dbus && cbs)
cbs->unregister_network(wpa_s, ssid->id);
}

View file

@ -41,7 +41,7 @@ struct ibss_rsn;
*/
struct ctrl_iface_priv;
struct ctrl_iface_global_priv;
struct ctrl_iface_dbus_priv;
struct wpas_dbus_priv;
/**
* struct wpa_interface - Parameters for wpa_supplicant_add_iface()
@ -191,10 +191,7 @@ struct wpa_global {
struct wpa_supplicant *ifaces;
struct wpa_params params;
struct ctrl_iface_global_priv *ctrl_iface;
/* old DBus API data */
struct ctrl_iface_dbus_priv *dbus_ctrl_iface;
/* new DBus API data */
struct ctrl_iface_dbus_new_priv *dbus_new_ctrl_iface;
struct wpas_dbus_priv *dbus;
void **drv_priv;
size_t drv_count;
};