From patchwork Mon May 7 18:19:49 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrej Shadura X-Patchwork-Id: 909883 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.infradead.org (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=hostap-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=collabora.co.uk Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="Qz53oQEa"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40frX10t75z9s1w for ; Tue, 8 May 2018 04:20:33 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:List-Subscribe:List-Help: List-Post:List-Archive:List-Unsubscribe:List-Id:Message-Id:Date:Subject:To: From:Reply-To:Cc:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References: List-Owner; bh=kNC0CLzMYGjtn7q7HTcLLNonnhJU1ablTJYAOmI47is=; b=Qz53oQEagOAkCn 4jihC0SqCUOZ+YUxFBYGW/6JihRaOrGU7Ysfrq3fOyygso5Ltw1zOa72ObszVbqf4pWq7Ew4WF7o1 rg9LMtX1hUqAnKoN4U8Vs9PXmcTAGtWHTydmbedDUGOFRVIDPd2FJEjkzAA+nEaXlE+2onqMm+436 b287NvasiQIZbYfDvcX5QpKGE6HxpLZL4uiQRDVTcn8XuYA59WLJNNegdLw4yPELK0YqC3bZoIGzG yrweI/2NgZEU7KZvVw/dKbtI+kQu2HU4qv2nQmF5iGYOMcjji5uP448iYyApBcQE3dnBUXsAfj2ul +N3Cdx1Z8QhbN1rE/W+w==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1fFkkL-00083l-VK; Mon, 07 May 2018 18:20:25 +0000 Received: from bhuna.collabora.co.uk ([46.235.227.227]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1fFkkI-0007aK-6H for hostap@lists.infradead.org; Mon, 07 May 2018 18:20:25 +0000 Received: from localhost (unknown [IPv6:2a02:ab04:3b9:5e00::4]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) (Authenticated sender: andrewsh) by bhuna.collabora.co.uk (Postfix) with ESMTPSA id 6B0ED286C3D; Mon, 7 May 2018 19:20:07 +0100 (BST) From: Andrej Shadura To: hostap@lists.infradead.org Subject: [PATCH] dbus: Expose connected stations on D-Bus Date: Mon, 7 May 2018 20:19:49 +0200 Message-Id: <20180507181949.7094-1-andrew.shadura@collabora.co.uk> X-Mailer: git-send-email 2.17.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20180507_112022_549624_42D64555 X-CRM114-Status: GOOD ( 21.27 ) X-Spam-Score: -0.0 (/) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [46.235.227.227 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record -0.0 SPF_HELO_PASS SPF: HELO matches SPF record X-BeenThere: hostap@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "Hostap" Errors-To: hostap-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Mathieu Trudel-Lapierre Make it possible to list connected stations in AP mode over D-Bus, along with some of their properties: rx/tx packets, bytes, capabilities, etc. Signed-off-by: Mathieu Trudel-Lapierre Rebased by Julian Andres Klode and updated to use the new getter API. Further modified by Andrej Shadura to not error out when not in AP mode. Signed-off-by: Andrej Shadura --- wpa_supplicant/dbus/dbus_new.c | 245 +++++++++++++++++-- wpa_supplicant/dbus/dbus_new.h | 25 ++ wpa_supplicant/dbus/dbus_new_handlers.c | 313 ++++++++++++++++++++++++ wpa_supplicant/dbus/dbus_new_handlers.h | 14 ++ wpa_supplicant/notify.c | 6 + 5 files changed, 589 insertions(+), 14 deletions(-) diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c index e0f16bbda..4139131e9 100644 --- a/wpa_supplicant/dbus/dbus_new.c +++ b/wpa_supplicant/dbus/dbus_new.c @@ -25,6 +25,7 @@ #include "dbus_new_handlers_p2p.h" #include "p2p/p2p.h" #include "../p2p_supplicant.h" +#include "ap/sta_info.h" #ifdef CONFIG_AP /* until needed by something else */ @@ -1016,15 +1017,19 @@ void wpas_dbus_signal_eap_status(struct wpa_supplicant *wpa_s, * Notify listeners about event related with station */ static void wpas_dbus_signal_sta(struct wpa_supplicant *wpa_s, - const u8 *sta, const char *sig_name) + const u8 *sta, const char *sig_name, + int properties) { struct wpas_dbus_priv *iface; DBusMessage *msg; - char sta_mac[WPAS_DBUS_OBJECT_PATH_MAX]; - char *dev_mac; + DBusMessageIter iter; + char sta_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; + char *path; - os_snprintf(sta_mac, WPAS_DBUS_OBJECT_PATH_MAX, MACSTR, MAC2STR(sta)); - dev_mac = sta_mac; + os_snprintf(sta_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, + "%s/" WPAS_DBUS_NEW_STAS_PART "/" COMPACT_MACSTR, + wpa_s->dbus_new_path, MAC2STR(sta)); + path = sta_obj_path; iface = wpa_s->global->dbus; @@ -1037,15 +1042,28 @@ static void wpas_dbus_signal_sta(struct wpa_supplicant *wpa_s, if (msg == NULL) return; - if (dbus_message_append_args(msg, DBUS_TYPE_STRING, &dev_mac, - DBUS_TYPE_INVALID)) - dbus_connection_send(iface->con, msg, NULL); - else - wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); + dbus_message_iter_init_append(msg, &iter); + if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, + &path)) + goto err; + + if (properties) { + if (!wpa_dbus_get_object_properties(iface, path, + WPAS_DBUS_NEW_IFACE_STA, + &iter)) + goto err; + } + + wpa_printf(MSG_DEBUG, "dbus: Station MAC address '" MACSTR "' '%s'", + MAC2STR(sta), sig_name); + + dbus_connection_send(iface->con, msg, NULL); dbus_message_unref(msg); + return; - wpa_printf(MSG_DEBUG, "dbus: Station MAC address '%s' '%s'", - sta_mac, sig_name); +err: + wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); + dbus_message_unref(msg); } @@ -1059,7 +1077,7 @@ static void wpas_dbus_signal_sta(struct wpa_supplicant *wpa_s, void wpas_dbus_signal_sta_authorized(struct wpa_supplicant *wpa_s, const u8 *sta) { - wpas_dbus_signal_sta(wpa_s, sta, "StaAuthorized"); + wpas_dbus_signal_sta(wpa_s, sta, "StaAuthorized", TRUE); } @@ -1073,7 +1091,7 @@ void wpas_dbus_signal_sta_authorized(struct wpa_supplicant *wpa_s, void wpas_dbus_signal_sta_deauthorized(struct wpa_supplicant *wpa_s, const u8 *sta) { - wpas_dbus_signal_sta(wpa_s, sta, "StaDeauthorized"); + wpas_dbus_signal_sta(wpa_s, sta, "StaDeauthorized", FALSE); } @@ -2151,6 +2169,9 @@ void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s, case WPAS_DBUS_PROP_BSSS: prop = "BSSs"; break; + case WPAS_DBUS_PROP_STAS: + prop = "Stations"; + break; case WPAS_DBUS_PROP_CURRENT_AUTH_MODE: prop = "CurrentAuthMode"; break; @@ -2243,6 +2264,39 @@ void wpas_dbus_bss_signal_prop_changed(struct wpa_supplicant *wpa_s, } +/** + * wpas_dbus_sta_signal_prop_changed - Signals change of STA property + * @wpa_s: %wpa_supplicant network interface data + * @property: indicates which property has changed + * @address: unique BSS identifier + * + * Sends PropertyChanged signals with path, interface, and arguments depending + * on which property has changed. + */ +void wpas_dbus_sta_signal_prop_changed(struct wpa_supplicant *wpa_s, + enum wpas_dbus_bss_prop property, + u8 address[ETH_ALEN]) +{ + char path[WPAS_DBUS_OBJECT_PATH_MAX]; + char *prop; + + switch (property) { + case WPAS_DBUS_STA_PROP_ADDRESS: + prop = "Address"; + break; + default: + wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d", + __func__, property); + return; + } + + os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX, + "%s/" WPAS_DBUS_NEW_STAS_PART "/" COMPACT_MACSTR, + wpa_s->dbus_new_path, MAC2STR(address)); + + wpa_dbus_mark_property_changed(wpa_s->global->dbus, path, + WPAS_DBUS_NEW_IFACE_STA, prop); +} /** * wpas_dbus_signal_debug_level_changed - Signals change of debug param * @global: wpa_global structure @@ -2857,6 +2911,164 @@ err: } +static const struct wpa_dbus_property_desc wpas_dbus_sta_properties[] = { + { "Address", WPAS_DBUS_NEW_IFACE_STA, "ay", + wpas_dbus_getter_sta_address, + NULL + }, + { "AID", WPAS_DBUS_NEW_IFACE_STA, "q", + wpas_dbus_getter_sta_aid, + NULL + }, + { "Flags", WPAS_DBUS_NEW_IFACE_STA, "u", + wpas_dbus_getter_sta_flags, + NULL + }, + { "Capabilities", WPAS_DBUS_NEW_IFACE_STA, "q", + wpas_dbus_getter_sta_caps, + NULL + }, + { "RxPackets", WPAS_DBUS_NEW_IFACE_STA, "t", + wpas_dbus_getter_sta_rx_packets, + NULL + }, + { "TxPackets", WPAS_DBUS_NEW_IFACE_STA, "t", + wpas_dbus_getter_sta_tx_packets, + NULL + }, + { "RxBytes", WPAS_DBUS_NEW_IFACE_STA, "t", + wpas_dbus_getter_sta_rx_bytes, + NULL + }, + { "TxBytes", WPAS_DBUS_NEW_IFACE_STA, "t", + wpas_dbus_getter_sta_tx_bytes, + NULL + }, + { NULL, NULL, NULL, NULL, NULL } +}; + + +static const struct wpa_dbus_signal_desc wpas_dbus_sta_signals[] = { + /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */ + { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_STA, + { + { "properties", "a{sv}", ARG_OUT }, + END_ARGS + } + }, + { NULL, NULL, { END_ARGS } } +}; + + +/** + * wpas_dbus_unregister_sta - Unregister a connected station from dbus + * @wpa_s: wpa_supplicant interface structure + * @bssid: connected station bssid + * @id: unique station identifier + * Returns: 0 on success, -1 on failure + * + * Unregisters STA representing object from dbus + */ +int wpas_dbus_unregister_sta(struct wpa_supplicant *wpa_s, + const u8 *sta) +{ + struct wpas_dbus_priv *ctrl_iface; + char sta_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; + + /* 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; + if (ctrl_iface == NULL) + return 0; + + os_snprintf(sta_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, + "%s/" WPAS_DBUS_NEW_STAS_PART "/" COMPACT_MACSTR, + wpa_s->dbus_new_path, MAC2STR(sta)); + + wpa_printf(MSG_DEBUG, "dbus: Unregister STA object '%s'", + sta_obj_path); + if (wpa_dbus_unregister_object_per_iface(ctrl_iface, sta_obj_path)) { + wpa_printf(MSG_ERROR, "dbus: Cannot unregister STA object %s", + sta_obj_path); + return -1; + } + + wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_STAS); + + return 0; +} + + +/** + * wpas_dbus_register_sta - Register a scanned station with dbus + * @wpa_s: wpa_supplicant interface structure + * @bssid: connection network station + * @id: unique STA identifier + * Returns: 0 on success, -1 on failure + * + * Registers STA representing object with dbus + */ +int wpas_dbus_register_sta(struct wpa_supplicant *wpa_s, + const u8 *sta) +{ + struct wpas_dbus_priv *ctrl_iface; + struct wpa_dbus_object_desc *obj_desc; + char sta_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; + struct sta_handler_args *arg; + + /* 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; + if (ctrl_iface == NULL) + return 0; + + os_snprintf(sta_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, + "%s/" WPAS_DBUS_NEW_STAS_PART "/" COMPACT_MACSTR, + wpa_s->dbus_new_path, MAC2STR(sta)); + + obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc)); + if (!obj_desc) { + wpa_printf(MSG_ERROR, "Not enough memory " + "to create object description"); + goto err; + } + + arg = os_zalloc(sizeof(struct sta_handler_args)); + if (!arg) { + wpa_printf(MSG_ERROR, "Not enough memory " + "to create arguments for handler"); + goto err; + } + arg->wpa_s = wpa_s; + arg->sta = sta; + + wpas_dbus_register(obj_desc, arg, wpa_dbus_free, + NULL, + wpas_dbus_sta_properties, + wpas_dbus_sta_signals); + + wpa_printf(MSG_DEBUG, "dbus: Register STA object '%s'", + sta_obj_path); + if (wpa_dbus_register_object_per_iface(ctrl_iface, sta_obj_path, + wpa_s->ifname, obj_desc)) { + wpa_printf(MSG_ERROR, + "Cannot register STA dbus object %s.", + sta_obj_path); + goto err; + } + + wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_STAS); + + return 0; + +err: + free_dbus_object_desc(obj_desc); + return -1; +} + + static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = { { "Scan", WPAS_DBUS_NEW_IFACE_INTERFACE, (WPADBusMethodHandler) wpas_dbus_handler_scan, @@ -3501,6 +3713,11 @@ static const struct wpa_dbus_property_desc wpas_dbus_interface_properties[] = { NULL }, #endif /* CONFIG_MESH */ + { "Stations", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao", + wpas_dbus_getter_stas, + NULL, + NULL + }, { NULL, NULL, NULL, NULL, NULL, NULL } }; diff --git a/wpa_supplicant/dbus/dbus_new.h b/wpa_supplicant/dbus/dbus_new.h index e68acb7a1..f434cc147 100644 --- a/wpa_supplicant/dbus/dbus_new.h +++ b/wpa_supplicant/dbus/dbus_new.h @@ -12,6 +12,7 @@ #include "common/defs.h" #include "p2p/p2p.h" +#include "ap/sta_info.h" struct wpa_global; struct wpa_supplicant; @@ -29,6 +30,7 @@ enum wpas_dbus_prop { WPAS_DBUS_PROP_CURRENT_NETWORK, WPAS_DBUS_PROP_CURRENT_AUTH_MODE, WPAS_DBUS_PROP_BSSS, + WPAS_DBUS_PROP_STAS, WPAS_DBUS_PROP_DISCONNECT_REASON, WPAS_DBUS_PROP_ASSOC_STATUS_CODE, }; @@ -46,6 +48,10 @@ enum wpas_dbus_bss_prop { WPAS_DBUS_BSS_PROP_AGE, }; +enum wpas_dbus_sta_prop { + WPAS_DBUS_STA_PROP_ADDRESS, +}; + #define WPAS_DBUS_OBJECT_PATH_MAX 150 #define WPAS_DBUS_NEW_SERVICE "fi.w1.wpa_supplicant1" @@ -62,6 +68,9 @@ enum wpas_dbus_bss_prop { #define WPAS_DBUS_NEW_BSSIDS_PART "BSSs" #define WPAS_DBUS_NEW_IFACE_BSS WPAS_DBUS_NEW_INTERFACE ".BSS" +#define WPAS_DBUS_NEW_STAS_PART "Stations" +#define WPAS_DBUS_NEW_IFACE_STA WPAS_DBUS_NEW_INTERFACE ".Station" + #define WPAS_DBUS_NEW_IFACE_P2PDEVICE \ WPAS_DBUS_NEW_IFACE_INTERFACE ".P2PDevice" @@ -164,6 +173,10 @@ int wpas_dbus_unregister_bss(struct wpa_supplicant *wpa_s, u8 bssid[ETH_ALEN], unsigned int id); int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s, u8 bssid[ETH_ALEN], unsigned int id); +int wpas_dbus_unregister_sta(struct wpa_supplicant *wpa_s, + const u8 *sta); +int wpas_dbus_register_sta(struct wpa_supplicant *wpa_s, + const u8 *sta); void wpas_dbus_signal_blob_added(struct wpa_supplicant *wpa_s, const char *name); void wpas_dbus_signal_blob_removed(struct wpa_supplicant *wpa_s, @@ -346,6 +359,18 @@ static inline int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s, return 0; } +static inline int wpas_dbus_unregister_sta(struct wpa_supplicant *wpa_s, + const u8 *sta) +{ + return 0; +} + +static inline int wpas_dbus_register_sta(struct wpa_supplicant *wpa_s, + const u8 *sta) +{ + return 0; +} + static inline void wpas_dbus_signal_blob_added(struct wpa_supplicant *wpa_s, const char *name) { diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c index a3c98fadd..01a5bdb86 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers.c +++ b/wpa_supplicant/dbus/dbus_new_handlers.c @@ -22,6 +22,10 @@ #include "../bss.h" #include "../scan.h" #include "../autoscan.h" +#include "../ap.h" +#include "ap/hostapd.h" +#include "ap/sta_info.h" +#include "ap/ap_drv_ops.h" #include "dbus_new_helpers.h" #include "dbus_new.h" #include "dbus_new_handlers.h" @@ -3854,6 +3858,315 @@ dbus_bool_t wpas_dbus_setter_iface_global( } +/** + * wpas_dbus_getter_stas - Get connected stations for an interface + * @iter: Pointer to incoming dbus message iter + * @error: Location to store error on failure + * @user_data: Function specific data + * Returns: a list of stations + * + * Getter for "Stations" property. + */ +dbus_bool_t wpas_dbus_getter_stas( + const struct wpa_dbus_property_desc *property_desc, + DBusMessageIter *iter, DBusError *error, void *user_data) +{ + struct wpa_supplicant *wpa_s = user_data; + struct hostapd_data *hapd; + struct sta_info *sta = NULL; + char **paths = NULL; + unsigned int i = 0, num = 0; + dbus_bool_t success = FALSE; + + if (!wpa_s->dbus_new_path) { + dbus_set_error(error, DBUS_ERROR_FAILED, + "%s: no D-Bus interface", __func__); + return FALSE; + } + + if (wpa_s->ap_iface) { + hapd = wpa_s->ap_iface->bss[0]; + sta = hapd->sta_list; + num = hapd->num_sta; + } + + paths = os_calloc(num, sizeof(char *)); + if (!paths) { + dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); + return FALSE; + } + + /* Loop through scan results and append each result's object path */ + for (; sta; sta = sta->next) { + paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX); + if (paths[i] == NULL) { + dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, + "no memory"); + goto out; + } + /* Construct the object path for this BSS. */ + os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX, + "%s/" WPAS_DBUS_NEW_STAS_PART "/" COMPACT_MACSTR, + wpa_s->dbus_new_path, MAC2STR(sta->addr)); + } + + success = wpas_dbus_simple_array_property_getter(iter, + DBUS_TYPE_OBJECT_PATH, + paths, num, + error); + +out: + while (i) + os_free(paths[--i]); + os_free(paths); + return success; +} + + +/** + * wpas_dbus_getter_sta_address - Return the BSSID of a connected station + * @iter: Pointer to incoming dbus message iter + * @error: Location to store error on failure + * @user_data: Function specific data + * Returns: TRUE on success, FALSE on failure + * + * Getter for "Address" property. + */ +dbus_bool_t wpas_dbus_getter_sta_address( + const struct wpa_dbus_property_desc *property_desc, + DBusMessageIter *iter, DBusError *error, void *user_data) +{ + struct sta_handler_args *args = user_data; + struct sta_info *sta; + + sta = ap_get_sta(args->wpa_s->ap_iface->bss[0], args->sta); + if (!sta) + return FALSE; + + return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE, + sta->addr, ETH_ALEN, + error); +} + + +/** + * wpas_dbus_getter_sta_aid - Return the AID of a connected station + * @iter: Pointer to incoming dbus message iter + * @error: Location to store error on failure + * @user_data: Function specific data + * Returns: TRUE on success, FALSE on failure + * + * Getter for "AID" property. + */ +dbus_bool_t wpas_dbus_getter_sta_aid( + const struct wpa_dbus_property_desc *property_desc, + DBusMessageIter *iter, DBusError *error, void *user_data) +{ + struct sta_handler_args *args = user_data; + struct sta_info *sta; + + sta = ap_get_sta(args->wpa_s->ap_iface->bss[0], args->sta); + if (!sta) + return FALSE; + + return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16, + &sta->aid, + error); +} + + +/** + * wpas_dbus_getter_sta_flags - Return the flags of a connected station + * @iter: Pointer to incoming dbus message iter + * @error: Location to store error on failure + * @user_data: Function specific data + * Returns: TRUE on success, FALSE on failure + * + * Getter for "Flags" property. + */ +dbus_bool_t wpas_dbus_getter_sta_flags( + const struct wpa_dbus_property_desc *property_desc, + DBusMessageIter *iter, DBusError *error, void *user_data) +{ + struct sta_handler_args *args = user_data; + struct sta_info *sta; + + sta = ap_get_sta(args->wpa_s->ap_iface->bss[0], args->sta); + if (!sta) + return FALSE; + + return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32, + &sta->flags, + error); +} + + +/** + * wpas_dbus_getter_sta_caps - Return the capabilities of a station + * @iter: Pointer to incoming dbus message iter + * @error: Location to store error on failure + * @user_data: Function specific data + * Returns: TRUE on success, FALSE on failure + * + * Getter for "Capabilities" property. + */ +dbus_bool_t wpas_dbus_getter_sta_caps( + const struct wpa_dbus_property_desc *property_desc, + DBusMessageIter *iter, DBusError *error, void *user_data) +{ + struct sta_handler_args *args = user_data; + struct sta_info *sta; + + sta = ap_get_sta(args->wpa_s->ap_iface->bss[0], args->sta); + if (!sta) + return FALSE; + + return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16, + &sta->capability, + error); +} + + +/** + * wpas_dbus_getter_rx_packets - Return the received packets for a station + * @iter: Pointer to incoming dbus message iter + * @error: Location to store error on failure + * @user_data: Function specific data + * Returns: TRUE on success, FALSE on failure + * + * Getter for "RxPackets" property. + */ +dbus_bool_t wpas_dbus_getter_sta_rx_packets( + const struct wpa_dbus_property_desc *property_desc, + DBusMessageIter *iter, DBusError *error, void *user_data) +{ + struct sta_handler_args *args = user_data; + struct sta_info *sta; + struct hostap_sta_driver_data data; + struct hostapd_data *hapd; + + if (!args->wpa_s->ap_iface) + return FALSE; + + hapd = args->wpa_s->ap_iface->bss[0]; + sta = ap_get_sta(hapd, args->sta); + if (!sta) + return FALSE; + + if (hostapd_drv_read_sta_data(hapd, &data, sta->addr) < 0) + return FALSE; + + return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT64, + &data.rx_packets, + error); +} + + +/** + * wpas_dbus_getter_tx_packets - Return the transmitted packets for a station + * @iter: Pointer to incoming dbus message iter + * @error: Location to store error on failure + * @user_data: Function specific data + * Returns: TRUE on success, FALSE on failure + * + * Getter for "TxPackets" property. + */ +dbus_bool_t wpas_dbus_getter_sta_tx_packets( + const struct wpa_dbus_property_desc *property_desc, + DBusMessageIter *iter, DBusError *error, void *user_data) +{ + struct sta_handler_args *args = user_data; + struct sta_info *sta; + struct hostap_sta_driver_data data; + struct hostapd_data *hapd; + + if (!args->wpa_s->ap_iface) + return FALSE; + + hapd = args->wpa_s->ap_iface->bss[0]; + sta = ap_get_sta(hapd, args->sta); + if (!sta) + return FALSE; + + if (hostapd_drv_read_sta_data(hapd, &data, sta->addr) < 0) + return FALSE; + + return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT64, + &data.tx_packets, + error); +} + + +/** + * wpas_dbus_getter_tx_bytes - Return the transmitted bytes for a station + * @iter: Pointer to incoming dbus message iter + * @error: Location to store error on failure + * @user_data: Function specific data + * Returns: TRUE on success, FALSE on failure + * + * Getter for "TxBytes" property. + */ +dbus_bool_t wpas_dbus_getter_sta_tx_bytes( + const struct wpa_dbus_property_desc *property_desc, + DBusMessageIter *iter, DBusError *error, void *user_data) +{ + struct sta_handler_args *args = user_data; + struct sta_info *sta; + struct hostap_sta_driver_data data; + struct hostapd_data *hapd; + + if (!args->wpa_s->ap_iface) + return FALSE; + + hapd = args->wpa_s->ap_iface->bss[0]; + sta = ap_get_sta(hapd, args->sta); + if (!sta) + return FALSE; + + if (hostapd_drv_read_sta_data(hapd, &data, sta->addr) < 0) + return FALSE; + + return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT64, + &data.tx_bytes, + error); +} + + +/** + * wpas_dbus_getter_rx_bytes - Return the received bytes for a station + * @iter: Pointer to incoming dbus message iter + * @error: Location to store error on failure + * @user_data: Function specific data + * Returns: TRUE on success, FALSE on failure + * + * Getter for "RxBytes" property. + */ +dbus_bool_t wpas_dbus_getter_sta_rx_bytes( + const struct wpa_dbus_property_desc *property_desc, + DBusMessageIter *iter, DBusError *error, void *user_data) +{ + struct sta_handler_args *args = user_data; + struct sta_info *sta; + struct hostap_sta_driver_data data; + struct hostapd_data *hapd; + + if (!args->wpa_s->ap_iface) + return FALSE; + + hapd = args->wpa_s->ap_iface->bss[0]; + sta = ap_get_sta(hapd, args->sta); + if (!sta) + return FALSE; + + if (hostapd_drv_read_sta_data(hapd, &data, sta->addr) < 0) + return FALSE; + + return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT64, + &data.rx_bytes, + error); +} + + static struct wpa_bss * get_bss_helper(struct bss_handler_args *args, DBusError *error, const char *func_name) { diff --git a/wpa_supplicant/dbus/dbus_new_handlers.h b/wpa_supplicant/dbus/dbus_new_handlers.h index 26652ad3d..9a4f66171 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers.h +++ b/wpa_supplicant/dbus/dbus_new_handlers.h @@ -22,6 +22,11 @@ struct bss_handler_args { unsigned int id; }; +struct sta_handler_args { + struct wpa_supplicant *wpa_s; + const u8 *sta; +}; + dbus_bool_t wpas_dbus_simple_property_getter(DBusMessageIter *iter, const int type, const void *val, @@ -168,6 +173,15 @@ DECLARE_ACCESSOR(wpas_dbus_getter_networks); DECLARE_ACCESSOR(wpas_dbus_getter_pkcs11_engine_path); DECLARE_ACCESSOR(wpas_dbus_getter_pkcs11_module_path); DECLARE_ACCESSOR(wpas_dbus_getter_blobs); +DECLARE_ACCESSOR(wpas_dbus_getter_stas); +DECLARE_ACCESSOR(wpas_dbus_getter_sta_address); +DECLARE_ACCESSOR(wpas_dbus_getter_sta_aid); +DECLARE_ACCESSOR(wpas_dbus_getter_sta_flags); +DECLARE_ACCESSOR(wpas_dbus_getter_sta_caps); +DECLARE_ACCESSOR(wpas_dbus_getter_sta_rx_packets); +DECLARE_ACCESSOR(wpas_dbus_getter_sta_tx_packets); +DECLARE_ACCESSOR(wpas_dbus_getter_sta_tx_bytes); +DECLARE_ACCESSOR(wpas_dbus_getter_sta_rx_bytes); DECLARE_ACCESSOR(wpas_dbus_getter_bss_bssid); DECLARE_ACCESSOR(wpas_dbus_getter_bss_ssid); DECLARE_ACCESSOR(wpas_dbus_getter_bss_privacy); diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c index 83df04f39..b9bbe260a 100644 --- a/wpa_supplicant/notify.c +++ b/wpa_supplicant/notify.c @@ -720,6 +720,9 @@ static void wpas_notify_ap_sta_authorized(struct wpa_supplicant *wpa_s, wpas_dbus_signal_p2p_peer_joined(wpa_s, p2p_dev_addr); #endif /* CONFIG_P2P */ + /* Unregister the station */ + wpas_dbus_register_sta(wpa_s, sta); + /* Notify listeners a new station has been authorized */ wpas_dbus_signal_sta_authorized(wpa_s, sta); } @@ -740,6 +743,9 @@ static void wpas_notify_ap_sta_deauthorized(struct wpa_supplicant *wpa_s, /* Notify listeners a station has been deauthorized */ wpas_dbus_signal_sta_deauthorized(wpa_s, sta); + + /* Unregister the station */ + wpas_dbus_unregister_sta(wpa_s, sta); }