From patchwork Sun Oct 7 12:31:51 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrej Shadura X-Patchwork-Id: 980151 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="UtAACqWk"; 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 42SjZW2XjHzB4MW for ; Sun, 7 Oct 2018 23:33:07 +1100 (AEDT) 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:References:In-Reply-To: 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: List-Owner; bh=hEaTAkaxGMIQOMyyhy/RuozqI4B7WgSlLaO01WhVHfQ=; b=UtAACqWkhbjQ36 usESJOyoKcqaew6z/SFg9j4BgYUA8lt/H9OV/tOr1Gt5MZLWcLhULOPggU5JHxUmNxkfdV8ozB+8q XRCxKngSBlCgFjcp4LWX+h08wzdgJ34uZg1IFuKnPLEhkryFmbBGoNHH3uDDslijVqLVepvL59wl2 /N6c6QUO1jNNrE7QKiFYt07cPIxXzTR4pMk12tXFbAOTRwKBD6r9Kf7FYObkbT1pKPeWFVbkRVIGP pTkXLB1+YdthnUe2l4R4D4o8VHN2o3WHVX9CgeJLl0CD43Hoe827s1vq1sWi75kg+POv3OKTi27BT Nwubmg+2AYau58ZmUn0Q==; 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 1g98En-0003M8-Ag; Sun, 07 Oct 2018 12:32:45 +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 1g98EK-0003FD-TP for hostap@lists.infradead.org; Sun, 07 Oct 2018 12:32:19 +0000 Received: from [127.0.0.1] (localhost [127.0.0.1]) (Authenticated sender: andrewsh) with ESMTPSA id AB14F27DBA7 From: Andrej Shadura To: hostap@lists.infradead.org Subject: [PATCH v2 2/2] dbus: Expose connected stations on D-Bus Date: Sun, 7 Oct 2018 14:31:51 +0200 Message-Id: <20181007123151.27506-2-andrew.shadura@collabora.co.uk> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181007123151.27506-1-andrew.shadura@collabora.co.uk> References: <20181007123151.27506-1-andrew.shadura@collabora.co.uk> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181007_053217_247417_C56669D6 X-CRM114-Status: GOOD ( 18.19 ) 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 0.0 UNPARSEABLE_RELAY Informational: message has unparseable relay lines 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 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 and to send separate StationAdded/StationRemoved signals instead of changing signatures of existing StaAuthorized/StaDeauthorized signals. Signed-off-by: Andrej Shadura --- doc/dbus.doxygen | 31 +++ wpa_supplicant/dbus/dbus_new.c | 284 +++++++++++++++++++++ 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 + 6 files changed, 673 insertions(+) diff --git a/doc/dbus.doxygen b/doc/dbus.doxygen index 2ca40ae9b..940f469d1 100644 --- a/doc/dbus.doxygen +++ b/doc/dbus.doxygen @@ -734,6 +734,11 @@ fi.w1.wpa_supplicant1.CreateInterface.

List of D-Bus objects paths representing BSSs known to the interface, i.e., scan results.

+
  • +

    Stations - ao - (read)

    +

    List of D-Bus objects paths representing connected stations in AP mode.

    +
  • +
  • Networks - ao - (read)

    List of D-Bus objects paths representing configured networks.

    @@ -1126,6 +1131,32 @@ fi.w1.wpa_supplicant1.CreateInterface.
  • +
  • +

    StationAdded ( o : Station, a{sv} : properties )

    +

    A new station has been added to the interface.

    +

    This signal complements StaAuthorized, passing the Station object and its properties.

    +

    Arguments

    +
    +
    o : Station
    +
    A D-Bus path to an object representing the new Station.
    +
    +
    +
    a{sv} : properties
    +
    A dictionary containing properties of added Station.
    +
    +
  • + +
  • +

    StationRemoved ( o : Station )

    +

    The station has been removed from the interface.

    +

    This signal complements StaDeauthorized, passing the Station object.

    +

    Arguments

    +
    +
    o : Station
    +
    A D-Bus path to an object representing the Station.
    +
    +
  • +
  • PropertiesChanged ( a{sv} : properties )

    Some properties have changed.

    diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c index 24115fcbc..7884f8747 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 */ @@ -1077,6 +1078,75 @@ void wpas_dbus_signal_sta_deauthorized(struct wpa_supplicant *wpa_s, } +/** + * wpas_dbus_signal_station - Send an event signal related to a station object + * @wpa_s: %wpa_supplicant network interface data + * @station_obj_path: Station object path + * @sig_name: signal name - StationAdded or StationRemoved + * @properties: Whether to add second argument with object properties + * + * Notify listeners about event related with station + */ +static void wpas_dbus_signal_station(struct wpa_supplicant *wpa_s, + const char *station_obj_path, + const char *sig_name, dbus_bool_t properties) +{ + struct wpas_dbus_priv *iface; + DBusMessage *msg; + DBusMessageIter iter; + + iface = wpa_s->global->dbus; + + /* Do nothing if the control interface is not turned on */ + if (iface == NULL || !wpa_s->dbus_new_path) + return; + + msg = dbus_message_new_signal(wpa_s->dbus_new_path, + WPAS_DBUS_NEW_IFACE_INTERFACE, sig_name); + if (msg == NULL) + return; + + if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, + &station_obj_path) || + (properties && + !wpa_dbus_get_object_properties(iface, station_obj_path, + WPAS_DBUS_NEW_IFACE_STA, + &iter))) + wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); + else + dbus_connection_send(iface->con, msg, NULL); + dbus_message_unref(msg); +} + + +/** + * wpas_dbus_signal_station_added - Send a Station added signal + * @wpa_s: %wpa_supplicant network interface data + * @station_obj_path: new Station object path + * + * Notify listeners about adding new Station + */ +static void wpas_dbus_signal_station_added(struct wpa_supplicant *wpa_s, + const char *station_obj_path) +{ + wpas_dbus_signal_station(wpa_s, station_obj_path, "StationAdded", TRUE); +} + + +/** + * wpas_dbus_signal_station_removed - Send a Station removed signal + * @wpa_s: %wpa_supplicant network interface data + * @station_obj_path: Station object path + * + * Notify listeners about removing Station + */ +static void wpas_dbus_signal_station_removed(struct wpa_supplicant *wpa_s, + const char *station_obj_path) +{ + wpas_dbus_signal_station(wpa_s, station_obj_path, "StationRemoved", FALSE); +} + + #ifdef CONFIG_P2P /** @@ -2151,6 +2221,9 @@ void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s, case WPAS_DBUS_PROP_BSSS: prop = "BSSs"; break; + case WPAS_DBUS_PROP_STATIONS: + prop = "Stations"; + break; case WPAS_DBUS_PROP_CURRENT_AUTH_MODE: prop = "CurrentAuthMode"; break; @@ -2243,6 +2316,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 +2963,166 @@ 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 station_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(station_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'", + station_obj_path); + if (wpa_dbus_unregister_object_per_iface(ctrl_iface, station_obj_path)) { + wpa_printf(MSG_ERROR, "dbus: Cannot unregister STA object %s", + station_obj_path); + return -1; + } + + wpas_dbus_signal_station_added(wpa_s, station_obj_path); + wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_STATIONS); + + 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 station_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(station_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'", + station_obj_path); + if (wpa_dbus_register_object_per_iface(ctrl_iface, station_obj_path, + wpa_s->ifname, obj_desc)) { + wpa_printf(MSG_ERROR, + "Cannot register STA dbus object %s.", + station_obj_path); + goto err; + } + + wpas_dbus_signal_station_removed(wpa_s, station_obj_path); + wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_STATIONS); + + 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 +3767,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 } }; @@ -3770,6 +4041,19 @@ static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = { END_ARGS } }, + { "StationAdded", WPAS_DBUS_NEW_IFACE_INTERFACE, + { + { "path", "o", ARG_OUT }, + { "properties", "a{sv}", ARG_OUT }, + END_ARGS + } + }, + { "StationRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE, + { + { "path", "o", ARG_OUT }, + END_ARGS + } + }, { "NetworkRequest", WPAS_DBUS_NEW_IFACE_INTERFACE, { { "path", "o", ARG_OUT }, diff --git a/wpa_supplicant/dbus/dbus_new.h b/wpa_supplicant/dbus/dbus_new.h index e68acb7a1..e34d04327 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_STATIONS, 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..75f762daf 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 */ + /* Register 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); }