aboutsummaryrefslogtreecommitdiffstats
path: root/wpa_supplicant
diff options
context:
space:
mode:
authorAndrej Shadura <andrew.shadura@collabora.co.uk>2018-10-07 12:31:51 (GMT)
committerJouni Malinen <j@w1.fi>2018-12-23 15:25:11 (GMT)
commitc3f23ad6c75642d241ade9cdb2b526289df2da65 (patch)
tree35be6be765ede060b02418cf48a530c8277fbcd5 /wpa_supplicant
parentf5f4c11aa1a5de7401dfe94e39255104a17aad3d (diff)
downloadhostap-c3f23ad6c75642d241ade9cdb2b526289df2da65.zip
hostap-c3f23ad6c75642d241ade9cdb2b526289df2da65.tar.gz
hostap-c3f23ad6c75642d241ade9cdb2b526289df2da65.tar.bz2
dbus: Expose connected stations on D-Bus
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 <mathieu.trudel-lapierre@canonical.com> Rebased by Julian Andres Klode <juliank@ubuntu.com> 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 <andrew.shadura@collabora.co.uk>
Diffstat (limited to 'wpa_supplicant')
-rw-r--r--wpa_supplicant/dbus/dbus_new.c281
-rw-r--r--wpa_supplicant/dbus/dbus_new.h22
-rw-r--r--wpa_supplicant/dbus/dbus_new_handlers.c287
-rw-r--r--wpa_supplicant/dbus/dbus_new_handlers.h13
-rw-r--r--wpa_supplicant/notify.c6
5 files changed, 609 insertions, 0 deletions
diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c
index 97655d5..96ab444 100644
--- a/wpa_supplicant/dbus/dbus_new.c
+++ b/wpa_supplicant/dbus/dbus_new.c
@@ -13,6 +13,7 @@
#include "common.h"
#include "common/ieee802_11_defs.h"
#include "wps/wps.h"
+#include "ap/sta_info.h"
#include "../config.h"
#include "../wpa_supplicant_i.h"
#include "../bss.h"
@@ -1078,6 +1079,79 @@ 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 || !wpa_s->dbus_new_path)
+ return;
+
+ wpa_printf(MSG_DEBUG, "dbus: STA signal %s", sig_name);
+ msg = dbus_message_new_signal(wpa_s->dbus_new_path,
+ WPAS_DBUS_NEW_IFACE_INTERFACE, sig_name);
+ if (!msg)
+ return;
+
+ dbus_message_iter_init_append(msg, &iter);
+ 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
/**
@@ -2147,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;
@@ -2240,6 +2317,41 @@ 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
*
@@ -2853,6 +2965,157 @@ 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, NULL
+ },
+ { "AID", WPAS_DBUS_NEW_IFACE_STA, "q",
+ wpas_dbus_getter_sta_aid,
+ NULL, NULL
+ },
+ { "Capabilities", WPAS_DBUS_NEW_IFACE_STA, "q",
+ wpas_dbus_getter_sta_caps,
+ NULL, NULL
+ },
+ { "RxPackets", WPAS_DBUS_NEW_IFACE_STA, "t",
+ wpas_dbus_getter_sta_rx_packets,
+ NULL, NULL
+ },
+ { "TxPackets", WPAS_DBUS_NEW_IFACE_STA, "t",
+ wpas_dbus_getter_sta_tx_packets,
+ NULL, NULL
+ },
+ { "RxBytes", WPAS_DBUS_NEW_IFACE_STA, "t",
+ wpas_dbus_getter_sta_rx_bytes,
+ NULL, NULL
+ },
+ { "TxBytes", WPAS_DBUS_NEW_IFACE_STA, "t",
+ wpas_dbus_getter_sta_tx_bytes,
+ NULL, NULL
+ },
+ { 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
+ * @sta: station MAC address
+ * 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 || !wpa_s->global)
+ return 0;
+ ctrl_iface = wpa_s->global->dbus;
+ if (!ctrl_iface)
+ 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_removed(wpa_s, station_obj_path);
+ wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_STATIONS);
+
+ return 0;
+}
+
+
+/**
+ * wpas_dbus_register_sta - Register a connected station with dbus
+ * @wpa_s: wpa_supplicant interface structure
+ * @sta: station MAC address
+ * 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 || !wpa_s->global)
+ return 0;
+ ctrl_iface = wpa_s->global->dbus;
+ if (!ctrl_iface)
+ 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_added(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,
@@ -3490,6 +3753,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 }
};
@@ -3759,6 +4027,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 40ae133..be2ce0d 100644
--- a/wpa_supplicant/dbus/dbus_new.h
+++ b/wpa_supplicant/dbus/dbus_new.h
@@ -28,6 +28,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,
};
@@ -45,6 +46,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"
@@ -61,6 +66,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"
@@ -163,6 +171,8 @@ 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,
@@ -345,6 +355,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 94773b3..2a6ad58 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers.c
@@ -15,6 +15,9 @@
#include "eap_peer/eap_methods.h"
#include "eapol_supp/eapol_supp_sm.h"
#include "rsn_supp/wpa.h"
+#include "ap/hostapd.h"
+#include "ap/sta_info.h"
+#include "ap/ap_drv_ops.h"
#include "../config.h"
#include "../wpa_supplicant_i.h"
#include "../driver_i.h"
@@ -22,6 +25,7 @@
#include "../bss.h"
#include "../scan.h"
#include "../autoscan.h"
+#include "../ap.h"
#include "dbus_new_helpers.h"
#include "dbus_new.h"
#include "dbus_new_handlers.h"
@@ -3805,6 +3809,289 @@ 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]) {
+ 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 address 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_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 6f952cc..1907a8a 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,
@@ -166,6 +171,14 @@ 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_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 83df04f..75f762d 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);
}