]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
dbus: Expose connected stations on D-Bus
authorAndrej Shadura <andrew.shadura@collabora.co.uk>
Sun, 7 Oct 2018 12:31:51 +0000 (14:31 +0200)
committerJouni Malinen <j@w1.fi>
Sun, 23 Dec 2018 15:25:11 +0000 (17:25 +0200)
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>
doc/dbus.doxygen
wpa_supplicant/dbus/dbus_new.c
wpa_supplicant/dbus/dbus_new.h
wpa_supplicant/dbus/dbus_new_handlers.c
wpa_supplicant/dbus/dbus_new_handlers.h
wpa_supplicant/notify.c

index 2ca40ae9b5f75bae48ce881b9ea89f73baa003cd..940f469d1f83bf98efe0ac924a59d87fffbf4754 100644 (file)
@@ -734,6 +734,11 @@ fi.w1.wpa_supplicant1.CreateInterface.
        <p>List of D-Bus objects paths representing BSSs known to the interface, i.e., scan results.</p>
       </li>
 
+      <li>
+       <h3>Stations - ao - (read)</h3>
+       <p>List of D-Bus objects paths representing connected stations in AP mode.</p>
+      </li>
+
       <li>
        <h3>Networks - ao - (read)</h3>
        <p>List of D-Bus objects paths representing configured networks.</p>
@@ -1126,6 +1131,32 @@ fi.w1.wpa_supplicant1.CreateInterface.
        </dl>
       </li>
 
+      <li>
+       <h3>StationAdded ( o : Station, a{sv} : properties )</h3>
+       <p>A new station has been added to the interface.</p>
+       <p>This signal complements StaAuthorized, passing the Station object and its properties.</p>
+       <h4>Arguments</h4>
+       <dl>
+         <dt>o : Station</dt>
+         <dd>A D-Bus path to an object representing the new Station.</dd>
+       </dl>
+       <dl>
+         <dt>a{sv} : properties</dt>
+         <dd>A dictionary containing properties of added Station.</dd>
+       </dl>
+      </li>
+
+      <li>
+       <h3>StationRemoved ( o : Station )</h3>
+       <p>The station has been removed from the interface.</p>
+       <p>This signal complements StaDeauthorized, passing the Station object.</p>
+       <h4>Arguments</h4>
+       <dl>
+         <dt>o : Station</dt>
+         <dd>A D-Bus path to an object representing the Station.</dd>
+       </dl>
+      </li>
+
       <li>
        <h3>PropertiesChanged ( a{sv} : properties )</h3>
        <p>Some properties have changed.</p>
index 97655d5696fab0d407ac1ad840609d28e2232cb7..96ab444d3de771c6e3acced9312b047e30f51014 100644 (file)
@@ -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;
@@ -2239,6 +2316,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 },
index 40ae133b225e5cb02b1b074a4c89017420350fdd..be2ce0d335b99eba8c600b82b3f3c011c737addc 100644 (file)
@@ -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)
 {
index 94773b329133026fdf3f1942a823117c7023670c..2a6ad5818a965d41e9cdf4ae0c64d541906795e3 100644 (file)
@@ -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)
 {
index 6f952cc390919b4b527b13e9edce5ebd7c10a959..1907a8a516e26565598695255cae4d1b611d0ebe 100644 (file)
@@ -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);
index 83df04f394c749da8b03ee326c3ed03aa9101427..75f762dafc10fe8d7ee367bc86c904babcac6d3f 100644 (file)
@@ -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);
 }