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