diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile index f02d3b27d..5a9cc522c 100644 --- a/wpa_supplicant/Makefile +++ b/wpa_supplicant/Makefile @@ -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) diff --git a/wpa_supplicant/dbus/dbus.c b/wpa_supplicant/dbus/dbus.c index 53ac089b7..e171a074b 100644 --- a/wpa_supplicant/dbus/dbus.c +++ b/wpa_supplicant/dbus/dbus.c @@ -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; diff --git a/wpa_supplicant/dbus/dbus.h b/wpa_supplicant/dbus/dbus.h index cab7faf74..4013e5c1f 100644 --- a/wpa_supplicant/dbus/dbus.h +++ b/wpa_supplicant/dbus/dbus.h @@ -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, diff --git a/wpa_supplicant/dbus/dbus_common.c b/wpa_supplicant/dbus/dbus_common.c new file mode 100644 index 000000000..77319f30c --- /dev/null +++ b/wpa_supplicant/dbus/dbus_common.c @@ -0,0 +1,411 @@ +/* + * wpa_supplicant D-Bus control interface - common functionality + * Copyright (c) 2006, Dan Williams and Red Hat, Inc. + * Copyright (c) 2009, Witold Sowa + * Copyright (c) 2009, Jouni Malinen + * + * 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 + +#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); +} diff --git a/wpa_supplicant/dbus/dbus_common.h b/wpa_supplicant/dbus/dbus_common.h new file mode 100644 index 000000000..50da09b9c --- /dev/null +++ b/wpa_supplicant/dbus/dbus_common.h @@ -0,0 +1,26 @@ +/* + * wpa_supplicant D-Bus control interface - common definitions + * Copyright (c) 2006, Dan Williams and Red Hat, Inc. + * Copyright (c) 2009, Witold Sowa + * Copyright (c) 2009, Jouni Malinen + * + * 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 */ diff --git a/wpa_supplicant/dbus/dbus_common_i.h b/wpa_supplicant/dbus/dbus_common_i.h new file mode 100644 index 000000000..2db8421c7 --- /dev/null +++ b/wpa_supplicant/dbus/dbus_common_i.h @@ -0,0 +1,29 @@ +/* + * wpa_supplicant D-Bus control interface - internal definitions + * Copyright (c) 2006, Dan Williams and Red Hat, Inc. + * Copyright (c) 2009, Witold Sowa + * Copyright (c) 2009, Jouni Malinen + * + * 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 + +struct wpas_dbus_priv { + DBusConnection *con; + int should_dispatch; + struct wpa_global *global; + u32 next_objid; +}; + +#endif /* DBUS_COMMON_I_H */ diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c index 56a34c0f4..8c5b01b98 100644 --- a/wpa_supplicant/dbus/dbus_new.c +++ b/wpa_supplicant/dbus/dbus_new.c @@ -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, diff --git a/wpa_supplicant/dbus/dbus_new.h b/wpa_supplicant/dbus/dbus_new.h index 7ec4560a3..699fa4e3f 100644 --- a/wpa_supplicant/dbus/dbus_new.h +++ b/wpa_supplicant/dbus/dbus_new.h @@ -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) diff --git a/wpa_supplicant/dbus/dbus_new_handlers_wps.c b/wpa_supplicant/dbus/dbus_new_handlers_wps.c index 5f3581e7a..2c6317adf 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers_wps.c +++ b/wpa_supplicant/dbus/dbus_new_handlers_wps.c @@ -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), diff --git a/wpa_supplicant/dbus/dbus_new_helpers.c b/wpa_supplicant/dbus/dbus_new_helpers.c index b2bad658b..4c0ba6525 100644 --- a/wpa_supplicant/dbus/dbus_new_helpers.c +++ b/wpa_supplicant/dbus/dbus_new_helpers.c @@ -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, diff --git a/wpa_supplicant/dbus/dbus_new_helpers.h b/wpa_supplicant/dbus/dbus_new_helpers.h index ad3f50f41..c73ec4f32 100644 --- a/wpa_supplicant/dbus/dbus_new_helpers.h +++ b/wpa_supplicant/dbus/dbus_new_helpers.h @@ -18,14 +18,6 @@ #include -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) diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c index 03f752127..7dd945f07 100644 --- a/wpa_supplicant/notify.c +++ b/wpa_supplicant/notify.c @@ -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); } diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 24c349d5c..4eedac079 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -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; };