On Mon, 2018-05-07 at 20:19 +0200, Andrej Shadura wrote: > From: Mathieu Trudel-Lapierre <mathieu.trudel-lapierre@xxxxxxxxxxxxx> > > 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. It looks like this patch changes the signal signature of StaAuthorized/StaDeauthorized, is that correct? That won't be backwards compatible with existing D-Bus clients and we should probably choose new signal names to allow old clients to continue working. Also, you'll want to update doc/dbus.doxygen with any changes you make to the D-Bus API, including additions. Dan > Signed-off-by: Mathieu Trudel-Lapierre <mathieu.trudel- > lapierre@xxxxxxxxxxxxx> > > Rebased by Julian Andres Klode <juliank@xxxxxxxxxx> 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 <andrew.shadura@xxxxxxxxxxxxxxx> > --- > 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) This is just a bool, so maybe dbus_bool_t would be more appropriate. > { > 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_IF > ACE_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_O > BJECT_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); > } > > _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap