18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_supplicant D-Bus control interface - common functionality
38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2009, Witold Sowa <witold.sowa@gmail.com>
58d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
68d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * This software may be distributed under the terms of the BSD license.
804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * See README for more details.
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/includes.h"
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <dbus/dbus.h>
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/common.h"
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/eloop.h"
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "dbus_common.h"
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "dbus_common_i.h"
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "dbus_new.h"
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "dbus_old.h"
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef SIGPOLL
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef SIGIO
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * If we do not have SIGPOLL, try to use SIGIO instead. This is needed for
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * FreeBSD.
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define SIGPOLL SIGIO
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void dispatch_data(DBusConnection *con)
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (dbus_connection_get_dispatch_status(con) ==
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       DBUS_DISPATCH_DATA_REMAINS)
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dbus_connection_dispatch(con);
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * dispatch_initial_dbus_messages - Dispatch initial dbus messages after
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *     claiming bus name
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @eloop_ctx: the DBusConnection to dispatch on
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @timeout_ctx: unused
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * If clients are quick to notice that service claimed its bus name,
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * there may have been messages that came in before initialization was
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * all finished.  Dispatch those here.
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void dispatch_initial_dbus_messages(void *eloop_ctx, void *timeout_ctx)
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DBusConnection *con = eloop_ctx;
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dispatch_data(con);
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void process_watch(struct wpas_dbus_priv *priv,
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  DBusWatch *watch, eloop_event_type type)
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dbus_connection_ref(priv->con);
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	priv->should_dispatch = 0;
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (type == EVENT_TYPE_READ)
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dbus_watch_handle(watch, DBUS_WATCH_READABLE);
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (type == EVENT_TYPE_WRITE)
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dbus_watch_handle(watch, DBUS_WATCH_WRITABLE);
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (type == EVENT_TYPE_EXCEPTION)
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dbus_watch_handle(watch, DBUS_WATCH_ERROR);
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (priv->should_dispatch) {
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dispatch_data(priv->con);
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		priv->should_dispatch = 0;
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dbus_connection_unref(priv->con);
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void process_watch_exception(int sock, void *eloop_ctx, void *sock_ctx)
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_EXCEPTION);
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void process_watch_read(int sock, void *eloop_ctx, void *sock_ctx)
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_READ);
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void process_watch_write(int sock, void *eloop_ctx, void *sock_ctx)
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_WRITE);
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic dbus_bool_t add_watch(DBusWatch *watch, void *data)
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpas_dbus_priv *priv = data;
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned int flags;
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int fd;
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!dbus_watch_get_enabled(watch))
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return TRUE;
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	flags = dbus_watch_get_flags(watch);
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	fd = dbus_watch_get_unix_fd(watch);
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_sock(fd, EVENT_TYPE_EXCEPTION, process_watch_exception,
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    priv, watch);
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (flags & DBUS_WATCH_READABLE) {
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_sock(fd, EVENT_TYPE_READ, process_watch_read,
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    priv, watch);
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (flags & DBUS_WATCH_WRITABLE) {
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_sock(fd, EVENT_TYPE_WRITE, process_watch_write,
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    priv, watch);
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dbus_watch_set_data(watch, priv, NULL);
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return TRUE;
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void remove_watch(DBusWatch *watch, void *data)
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned int flags;
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int fd;
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	flags = dbus_watch_get_flags(watch);
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	fd = dbus_watch_get_unix_fd(watch);
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_unregister_sock(fd, EVENT_TYPE_EXCEPTION);
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (flags & DBUS_WATCH_READABLE)
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_unregister_sock(fd, EVENT_TYPE_READ);
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (flags & DBUS_WATCH_WRITABLE)
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_unregister_sock(fd, EVENT_TYPE_WRITE);
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dbus_watch_set_data(watch, NULL, NULL);
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void watch_toggled(DBusWatch *watch, void *data)
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dbus_watch_get_enabled(watch))
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		add_watch(watch, data);
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		remove_watch(watch, data);
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void process_timeout(void *eloop_ctx, void *sock_ctx)
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DBusTimeout *timeout = sock_ctx;
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dbus_timeout_handle(timeout);
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic dbus_bool_t add_timeout(DBusTimeout *timeout, void *data)
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpas_dbus_priv *priv = data;
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!dbus_timeout_get_enabled(timeout))
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return TRUE;
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(0, dbus_timeout_get_interval(timeout) * 1000,
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       process_timeout, priv, timeout);
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dbus_timeout_set_data(timeout, priv, NULL);
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return TRUE;
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void remove_timeout(DBusTimeout *timeout, void *data)
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpas_dbus_priv *priv = data;
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(process_timeout, priv, timeout);
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dbus_timeout_set_data(timeout, NULL, NULL);
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void timeout_toggled(DBusTimeout *timeout, void *data)
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dbus_timeout_get_enabled(timeout))
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		add_timeout(timeout, data);
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		remove_timeout(timeout, data);
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void process_wakeup_main(int sig, void *signal_ctx)
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpas_dbus_priv *priv = signal_ctx;
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sig != SIGPOLL || !priv->con)
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dbus_connection_get_dispatch_status(priv->con) !=
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    DBUS_DISPATCH_DATA_REMAINS)
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Only dispatch once - we do not want to starve other events */
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dbus_connection_ref(priv->con);
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dbus_connection_dispatch(priv->con);
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dbus_connection_unref(priv->con);
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wakeup_main - Attempt to wake our mainloop up
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: dbus control interface private data
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Try to wake up the main eloop so it will process
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * dbus events that may have happened.
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wakeup_main(void *data)
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpas_dbus_priv *priv = data;
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Use SIGPOLL to break out of the eloop select() */
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	raise(SIGPOLL);
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	priv->should_dispatch = 1;
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * integrate_with_eloop - Register our mainloop integration with dbus
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @connection: connection to the system message bus
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @priv: a dbus control interface data structure
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int integrate_with_eloop(struct wpas_dbus_priv *priv)
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!dbus_connection_set_watch_functions(priv->con, add_watch,
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 remove_watch, watch_toggled,
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 priv, NULL) ||
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    !dbus_connection_set_timeout_functions(priv->con, add_timeout,
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						   remove_timeout,
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						   timeout_toggled, priv,
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						   NULL)) {
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "dbus: Failed to set callback "
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "functions");
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eloop_register_signal(SIGPOLL, process_wakeup_main, priv))
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dbus_connection_set_wakeup_main_function(priv->con, wakeup_main,
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 priv, NULL);
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpas_dbus_init_common(struct wpas_dbus_priv *priv)
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DBusError error;
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret = 0;
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Get a reference to the system bus */
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dbus_error_init(&error);
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	priv->con = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!priv->con) {
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "dbus: Could not acquire the system "
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "bus: %s - %s", error.name, error.message);
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = -1;
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dbus_error_free(&error);
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpas_dbus_init_common_finish(struct wpas_dbus_priv *priv)
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Tell dbus about our mainloop integration functions */
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	integrate_with_eloop(priv);
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Dispatch initial DBus messages that may have come in since the bus
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * name was claimed above. Happens when clients are quick to notice the
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * service.
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * FIXME: is there a better solution to this problem?
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(0, 50, dispatch_initial_dbus_messages,
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	                       priv->con, NULL);
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpas_dbus_deinit_common(struct wpas_dbus_priv *priv)
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (priv->con) {
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_cancel_timeout(dispatch_initial_dbus_messages,
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     priv->con, NULL);
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dbus_connection_set_watch_functions(priv->con, NULL, NULL,
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						    NULL, NULL, NULL);
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dbus_connection_set_timeout_functions(priv->con, NULL, NULL,
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						      NULL, NULL, NULL);
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dbus_connection_unref(priv->con);
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(priv);
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpas_dbus_priv * wpas_dbus_init(struct wpa_global *global)
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpas_dbus_priv *priv;
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	priv = os_zalloc(sizeof(*priv));
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (priv == NULL)
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	priv->global = global;
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpas_dbus_init_common(priv) < 0) {
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpas_dbus_deinit(priv);
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_CTRL_IFACE_DBUS_NEW
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpas_dbus_ctrl_iface_init(priv) < 0) {
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpas_dbus_deinit(priv);
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_CTRL_IFACE_DBUS
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_supplicant_dbus_ctrl_iface_init(priv) < 0) {
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpas_dbus_deinit(priv);
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE_DBUS */
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpas_dbus_init_common_finish(priv) < 0) {
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpas_dbus_deinit(priv);
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return priv;
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpas_dbus_deinit(struct wpas_dbus_priv *priv)
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (priv == NULL)
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_CTRL_IFACE_DBUS_NEW
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpas_dbus_ctrl_iface_deinit(priv);
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_CTRL_IFACE_DBUS
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: is any deinit needed? */
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE_DBUS */
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpas_dbus_deinit_common(priv);
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
366