This implements ubus accounting events. This accounting works the same manner
as the RADIUS accounting, except the interim (see below).

There tree types of messages: start, stop and interim.
Start sent when new client connected. There just current time, address
and session_id of client in message.
Stop sent when client disconnected. This message contains extra counters
and terminate_cause.
Interim sent by timeout, configured with ubus_accounting_interval
variable. This message contains an information about all connected to
bss clients.

Payload example:

    {
      "clients": [
        {
          "session_time": 9,
          "address": "68:3e:34:f5:61:3f",
          "session_id": "A6367C8F6C0662C1",
          "accounting": {
            "rx_bytes": 2336,
            "tx_packets": 5,
            "tx_bytes": 533,
            "rx_packets": 17
          },
          "terminate_cause": 1
        }
      ],
      "device": "radio0",
      "bssid": "44:d1:fa:12:4c:74",
      "freq": 5260,
      "iface": "wlan0"
    }

Signed-off-by: Yury Shvedov <yshve...@wimarksystems.com>
---
 .../hostapd/patches/600-ubus_support.patch    | 165 +++++++++++-
 .../services/hostapd/src/src/ap/ubus.c        | 238 +++++++++++++++++-
 .../services/hostapd/src/src/ap/ubus.h        |  14 ++
 3 files changed, 405 insertions(+), 12 deletions(-)

diff --git a/package/network/services/hostapd/patches/600-ubus_support.patch 
b/package/network/services/hostapd/patches/600-ubus_support.patch
index c63b85c079..c0db5be4e9 100644
--- a/package/network/services/hostapd/patches/600-ubus_support.patch
+++ b/package/network/services/hostapd/patches/600-ubus_support.patch
@@ -99,7 +99,15 @@
        hostapd_interface_deinit(iface);
        wpa_printf(MSG_DEBUG, "%s: driver=%p drv_priv=%p -> hapd_deinit",
                   __func__, driver, drv_priv);
-@@ -3114,6 +3120,7 @@ void hostapd_set_state(struct hostapd_if
+@@ -3050,6 +3056,7 @@ void hostapd_new_assoc_sta(struct hostap
+               ap_sta_set_authorized(hapd, sta, 1);
+               os_get_reltime(&sta->connected_time);
+               accounting_sta_start(hapd, sta);
++              hostapd_ubus_event_sta_account_start(hapd,sta);
+       }
+ 
+       /* Start IEEE 802.1X authentication process for new stations */
+@@ -3114,6 +3121,7 @@ void hostapd_set_state(struct hostapd_if
        wpa_printf(MSG_INFO, "%s: interface state %s->%s",
                   iface->conf ? iface->conf->bss[0]->iface : "N/A",
                   hostapd_state_text(iface->state), hostapd_state_text(s));
@@ -201,7 +209,15 @@
  
        sta = ap_get_sta(hapd, mgmt->sa);
        if (sta == NULL) {
-@@ -3630,6 +3657,8 @@ static void handle_deauth(struct hostapd
+@@ -3584,6 +3611,7 @@ static void handle_disassoc(struct hosta
+       /* Stop Accounting and IEEE 802.1X sessions, but leave the STA
+        * authenticated. */
+       accounting_sta_stop(hapd, sta);
++      hostapd_ubus_event_sta_account_stop(hapd, sta);
+       ieee802_1x_free_station(hapd, sta);
+       if (sta->ipaddr)
+               hostapd_drv_br_delete_ip_neigh(hapd, 4, (u8 *) &sta->ipaddr);
+@@ -3630,6 +3658,8 @@ static void handle_deauth(struct hostapd
                " reason_code=%d",
                MAC2STR(mgmt->sa), le_to_host16(mgmt->u.deauth.reason_code));
  
@@ -210,7 +226,7 @@
        sta = ap_get_sta(hapd, mgmt->sa);
        if (sta == NULL) {
                wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Station " MACSTR " trying "
-@@ -3949,7 +3978,7 @@ int ieee802_11_mgmt(struct hostapd_data
+@@ -3949,7 +3979,7 @@ int ieee802_11_mgmt(struct hostapd_data
  
  
        if (stype == WLAN_FC_STYPE_PROBE_REQ) {
@@ -219,7 +235,7 @@
                return 1;
        }
  
-@@ -3969,17 +3998,17 @@ int ieee802_11_mgmt(struct hostapd_data
+@@ -3969,17 +3999,17 @@ int ieee802_11_mgmt(struct hostapd_data
        switch (stype) {
        case WLAN_FC_STYPE_AUTH:
                wpa_printf(MSG_DEBUG, "mgmt::auth");
@@ -240,6 +256,14 @@
                ret = 1;
                break;
        case WLAN_FC_STYPE_DISASSOC:
+@@ -4128,6 +4158,7 @@ static void handle_assoc_cb(struct hosta
+       /* Stop previous accounting session, if one is started, and allocate
+        * new session id for the new session. */
+       accounting_sta_stop(hapd, sta);
++      hostapd_ubus_event_sta_account_stop(hapd, sta);
+ 
+       hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
+                      HOSTAPD_LEVEL_INFO,
 --- a/src/ap/beacon.c
 +++ b/src/ap/beacon.c
 @@ -720,7 +720,7 @@ void sta_track_claim_taxonomy_info(struc
@@ -309,7 +333,15 @@
  
        if (addr == NULL) {
                /*
-@@ -195,6 +199,12 @@ int hostapd_notif_assoc(struct hostapd_d
+@@ -164,6 +168,7 @@ int hostapd_notif_assoc(struct hostapd_d
+       if (sta) {
+               ap_sta_no_session_timeout(hapd, sta);
+               accounting_sta_stop(hapd, sta);
++              hostapd_ubus_event_sta_account_stop(hapd, sta);
+ 
+               /*
+                * Make sure that the previously registered inactivity timer
+@@ -195,6 +200,12 @@ int hostapd_notif_assoc(struct hostapd_d
                goto fail;
        }
  
@@ -324,7 +356,15 @@
                wpabuf_free(sta->p2p_ie);
 --- a/src/ap/sta_info.c
 +++ b/src/ap/sta_info.c
-@@ -415,6 +415,7 @@ void ap_handle_timer(void *eloop_ctx, vo
+@@ -162,6 +162,7 @@ void ap_free_sta(struct hostapd_data *ha
+       int set_beacon = 0;
+ 
+       accounting_sta_stop(hapd, sta);
++      hostapd_ubus_event_sta_account_stop(hapd, sta);
+ 
+       /* just in case */
+       ap_sta_set_authorized(hapd, sta, 0);
+@@ -415,6 +416,7 @@ void ap_handle_timer(void *eloop_ctx, vo
                               HOSTAPD_LEVEL_INFO, "deauthenticated due to "
                               "local deauth request");
                ap_free_sta(hapd, sta);
@@ -332,7 +372,15 @@
                return;
        }
  
-@@ -562,6 +563,7 @@ skip_poll:
+@@ -535,6 +537,7 @@ skip_poll:
+                       sta->acct_terminate_cause =
+                               RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT;
+               accounting_sta_stop(hapd, sta);
++              hostapd_ubus_event_sta_account_stop(hapd, sta);
+               ieee802_1x_free_station(hapd, sta);
+               hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
+                              HOSTAPD_LEVEL_INFO, "disassociated due to "
+@@ -562,6 +565,7 @@ skip_poll:
                        hapd, sta,
                        WLAN_REASON_PREV_AUTH_NOT_VALID);
                ap_free_sta(hapd, sta);
@@ -340,7 +388,23 @@
                break;
        }
  }
-@@ -1223,6 +1225,7 @@ void ap_sta_set_authorized(struct hostap
+@@ -796,6 +800,7 @@ void ap_sta_disassociate(struct hostapd_
+       eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DISASSOC, 0,
+                              ap_handle_timer, hapd, sta);
+       accounting_sta_stop(hapd, sta);
++      hostapd_ubus_event_sta_account_stop(hapd, sta);
+       ieee802_1x_free_station(hapd, sta);
+ 
+       sta->disassoc_reason = reason;
+@@ -845,6 +850,7 @@ void ap_sta_deauthenticate(struct hostap
+       eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DEAUTH, 0,
+                              ap_handle_timer, hapd, sta);
+       accounting_sta_stop(hapd, sta);
++      hostapd_ubus_event_sta_account_stop(hapd, sta);
+       ieee802_1x_free_station(hapd, sta);
+ 
+       sta->deauth_reason = reason;
+@@ -1223,6 +1229,7 @@ void ap_sta_set_authorized(struct hostap
                                          buf, ip_addr);
        } else {
                wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED "%s", buf);
@@ -360,7 +424,7 @@
  
 --- a/hostapd/config_file.c
 +++ b/hostapd/config_file.c
-@@ -2663,6 +2663,11 @@ static int hostapd_config_fill(struct ho
+@@ -2663,6 +2663,13 @@ static int hostapd_config_fill(struct ho
                   0) {
                bss->radius_das_require_message_authenticator = atoi(pos);
  #endif /* CONFIG_NO_RADIUS */
@@ -368,6 +432,8 @@
 +      } else if (os_strcmp(buf, "uci_device") == 0) {
 +              os_free(bss->uci_device);
 +              bss->uci_device = os_strdup(pos);
++      } else if (os_strcmp(buf, "ubus_acct_interim_interval") == 0) {
++              bss->ubus_acct_interim_interval = atoi(pos);
 +#endif /* UBUS_SUPPORT */
        } else if (os_strcmp(buf, "auth_algs") == 0) {
                bss->auth_algs = atoi(pos);
@@ -384,12 +450,91 @@
  
 --- a/src/ap/ap_config.h
 +++ b/src/ap/ap_config.h
-@@ -470,6 +470,8 @@ struct hostapd_bss_config {
+@@ -470,6 +470,9 @@ struct hostapd_bss_config {
        int pbc_in_m1;
        char *server_id;
  
 +      char *uci_device;
++      int ubus_acct_interim_interval;
 +
  #define P2P_ENABLED BIT(0)
  #define P2P_GROUP_OWNER BIT(1)
  #define P2P_GROUP_FORMATION BIT(2)
+--- a/src/ap/accounting.c
++++ b/src/ap/accounting.c
+@@ -164,7 +164,7 @@ static struct radius_msg * accounting_ms
+ }
+ 
+ 
+-static int accounting_sta_update_stats(struct hostapd_data *hapd,
++int accounting_sta_update_stats(struct hostapd_data *hapd,
+                                      struct sta_info *sta,
+                                      struct hostap_sta_driver_data *data)
+ {
+--- a/src/ap/accounting.h
++++ b/src/ap/accounting.h
+@@ -10,19 +10,13 @@
+ #define ACCOUNTING_H
+ 
+ #ifdef CONFIG_NO_ACCOUNTING
+-static inline int accounting_sta_get_id(struct hostapd_data *hapd,
+-                                      struct sta_info *sta)
+-{
+-      return 0;
+-}
+-
+ static inline void accounting_sta_start(struct hostapd_data *hapd,
+                                       struct sta_info *sta)
+ {
+ }
+ 
+ static inline void accounting_sta_stop(struct hostapd_data *hapd,
+-                                     struct sta_info *sta)
++                                      struct sta_info *sta)
+ {
+ }
+ 
+@@ -35,11 +29,32 @@ static inline void accounting_deinit(str
+ {
+ }
+ #else /* CONFIG_NO_ACCOUNTING */
+-int accounting_sta_get_id(struct hostapd_data *hapd, struct sta_info *sta);
+ void accounting_sta_start(struct hostapd_data *hapd, struct sta_info *sta);
+ void accounting_sta_stop(struct hostapd_data *hapd, struct sta_info *sta);
+ int accounting_init(struct hostapd_data *hapd);
+ void accounting_deinit(struct hostapd_data *hapd);
+ #endif /* CONFIG_NO_ACCOUNTING */
+ 
++#if defined (CONFIG_NO_ACCOUNTING ) && !defined (UBUS_SUPPORT)
++static inline int accounting_sta_get_id(struct hostapd_data *hapd,
++                                      struct sta_info *sta)
++{
++      return 0;
++}
++static int accounting_sta_update_stats(struct hostapd_data *hapd,
++                                      struct sta_info *sta,
++                                      struct hostap_sta_driver_data *data)
++{
++      return 0;
++}
++
++#else
++
++int accounting_sta_get_id(struct hostapd_data *hapd, struct sta_info *sta);
++int accounting_sta_update_stats(struct hostapd_data *hapd,
++                                      struct sta_info *sta,
++                                      struct hostap_sta_driver_data *data);
++
++#endif /* CONFIG_NO_ACCOUNTING && UBUS_SUPPORT */
++
+ #endif /* ACCOUNTING_H */
+--- a/src/ap/sta_info.h
++++ b/src/ap/sta_info.h
+@@ -139,6 +139,7 @@ struct sta_info {
+       int acct_terminate_cause; /* Acct-Terminate-Cause */
+       int acct_interim_interval; /* Acct-Interim-Interval */
+       unsigned int acct_interim_errors;
++      int ubus_acct_session_started;
+ 
+       /* For extending 32-bit driver counters to 64-bit counters */
+       u32 last_rx_bytes_hi;
diff --git a/package/network/services/hostapd/src/src/ap/ubus.c 
b/package/network/services/hostapd/src/src/ap/ubus.c
index 6d12126a1a..2ceb2de159 100644
--- a/package/network/services/hostapd/src/src/ap/ubus.c
+++ b/package/network/services/hostapd/src/src/ap/ubus.c
@@ -18,10 +18,14 @@
 #include "ubus.h"
 #include "ap_drv_ops.h"
 #include "beacon.h"
+#include "accounting.h"
+#include "radius/radius.h"
 #include "rrm.h"
 #include "wnm_ap.h"
 #include "taxonomy.h"
 
+#define ACCT_DEFAULT_UPDATE_INTERVAL 300
+
 static struct ubus_context *ctx;
 static struct blob_buf b;
 static int ctx_ref;
@@ -1099,6 +1103,21 @@ static int avl_compare_macaddr(const void *k1, const 
void *k2, void *ptr)
        return memcmp(k1, k2, ETH_ALEN);
 }
 
+static void hostapd_ubus_accounting_interim_update(void *eloop_ctx,    void *);
+static bool hostapd_ubus_accounting_init(struct hostapd_data *hapd)
+{
+       int interval = hapd->conf->ubus_acct_interim_interval;
+       if (!interval)
+               interval = ACCT_DEFAULT_UPDATE_INTERVAL;
+       eloop_register_timeout(interval, 0, 
hostapd_ubus_accounting_interim_update,
+                       hapd, NULL);
+       return true;
+}
+static void hostapd_ubus_accounting_stop(struct hostapd_data *hapd)
+{
+       eloop_cancel_timeout(hostapd_ubus_accounting_interim_update, hapd, 
NULL);
+}
+
 void hostapd_ubus_add_bss(struct hostapd_data *hapd)
 {
        struct ubus_object *obj = &hapd->ubus.obj;
@@ -1113,9 +1132,16 @@ void hostapd_ubus_add_bss(struct hostapd_data *hapd)
        if (!hostapd_ubus_init())
                return;
 
+       if (obj->id) {
+               return;
+       }
+
        if (asprintf(&name, "hostapd.%s", hapd->conf->iface) < 0)
                return;
 
+       if (!hostapd_ubus_accounting_init(hapd))
+               return;
+
        avl_init(&hapd->ubus.banned, avl_compare_macaddr, false, NULL);
        obj->name = name;
        obj->type = &bss_object_type;
@@ -1133,6 +1159,8 @@ void hostapd_ubus_free_bss(struct hostapd_data *hapd)
        if (!ctx)
                return;
 
+       hostapd_ubus_accounting_stop(hapd);
+
        if (obj->id) {
                ubus_remove_object(ctx, obj);
                hostapd_ubus_ref_dec();
@@ -1207,7 +1235,7 @@ int hostapd_ubus_handle_event(struct hostapd_data *hapd, 
struct hostapd_ubus_req
                        ht_capabilities = (struct ieee80211_ht_capabilities*) 
req->elems->ht_capabilities;
                        ht_cap = blobmsg_open_table(&b, "ht_capabilities");
                        blobmsg_add_u16(&b, "ht_capabilities_info", 
ht_capabilities->ht_capabilities_info);
-                       ht_cap_mcs_set = blobmsg_open_table(&b, 
"supported_mcs_set");           
+                       ht_cap_mcs_set = blobmsg_open_table(&b, 
"supported_mcs_set");
                        blobmsg_add_u16(&b, "a_mpdu_params", 
ht_capabilities->a_mpdu_params);
                        blobmsg_add_u16(&b, "ht_extended_capabilities", 
ht_capabilities->ht_extended_capabilities);
                        blobmsg_add_u32(&b, "tx_bf_capability_info", 
ht_capabilities->tx_bf_capability_info);
@@ -1218,7 +1246,7 @@ int hostapd_ubus_handle_event(struct hostapd_data *hapd, 
struct hostapd_ubus_req
                        }
                        blobmsg_close_array(&b, mcs_set);
                        blobmsg_close_table(&b, ht_cap_mcs_set);
-                       blobmsg_close_table(&b, ht_cap);                
+                       blobmsg_close_table(&b, ht_cap);
                }
                if(req->elems->vht_capabilities)
                {
@@ -1294,3 +1322,209 @@ void hostapd_ubus_event_iface_state(struct 
hostapd_iface *iface, int s)
        blobmsg_add_string(&b, "state", hostapd_state_text(s));
        ubus_send_event(ctx, "hostapd.iface_state", b.head);
 }
+static void
+blobmsg_add_sta_data(struct blob_buf *buf, const char *name,
+               struct sta_info *sta,
+               const struct hostap_sta_driver_data *data)
+{
+       u64 bytes;
+       void *tbl = blobmsg_open_table(buf, name);
+
+       blobmsg_add_u32(buf, "rx_packets", data->rx_packets);
+       blobmsg_add_u32(buf, "tx_packets", data->tx_packets);
+
+       if (data->bytes_64bit)
+               bytes = data->rx_bytes;
+       else
+               bytes = ((u64) sta->last_rx_bytes_hi << 32) |
+                       sta->last_rx_bytes_lo;
+       blobmsg_add_u64(buf, "rx_bytes", bytes);
+       if (data->bytes_64bit)
+               bytes = data->tx_bytes;
+       else
+               bytes = ((u64) sta->last_tx_bytes_hi << 32) |
+                       sta->last_tx_bytes_lo;
+       blobmsg_add_u64(buf, "tx_bytes", bytes);
+       blobmsg_add_double(buf, "rssi", data->last_ack_rssi);
+       blobmsg_add_double(buf, "signal", data->signal);
+
+       blobmsg_close_table(buf, tbl);
+}
+static void
+blobmsg_add_reltime(struct blob_buf *buf, const char *name,
+               const struct os_reltime *reltime)
+{
+       blobmsg_add_u32(buf, name, reltime->sec);
+}
+static void
+blobmsg_add_session_id(struct blob_buf *buf, const char *name,
+               struct sta_info *sta)
+{
+       blobmsg_printf(buf, name, "%016llX",
+                       (unsigned long long) sta->acct_session_id);
+}
+static void
+blobmsg_add_station_accounting(struct blob_buf *buf,
+               const char *name,
+               struct sta_info *sta,
+               const struct hostap_sta_driver_data *data,
+               const struct os_reltime *session_time,
+               int cause)
+{
+       void *tbl = blobmsg_open_table(buf, name);
+       blobmsg_add_macaddr(buf, "address", sta->addr);
+       blobmsg_add_session_id(buf, "session_id", sta);
+       if(data)
+               blobmsg_add_sta_data(buf, "accounting", sta, data);
+       if(session_time)
+               blobmsg_add_reltime(buf, "session_time", session_time);
+       if (sta->identity)
+               blobmsg_add_string(buf, "identity", sta->identity);
+       if (cause > 0)
+               blobmsg_add_u32(buf, "terminate_cause", cause);
+       blobmsg_close_table(buf, tbl);
+}
+static void hostapd_ubus_event_sta_account(struct hostapd_data *hapd,
+               struct sta_info *sta, const char *status,
+               const struct hostap_sta_driver_data *data,
+               const struct os_reltime *session_time,
+               int cause)
+{
+       void *arr;
+
+       if (!ctx)
+               return;
+       blob_buf_init(&b, 0);
+
+       arr = blobmsg_open_array(&b, "clients");
+       blobmsg_add_station_accounting(&b, NULL, sta, data, session_time, 
cause);
+       blobmsg_close_array(&b, arr);
+       blobmsg_add_u32(&b, "freq", hapd->iface->freq);
+
+       blobmsg_add_hapd_id(&b, hapd);
+       ubus_notify(ctx, &hapd->ubus.obj, status, b.head, -1);
+}
+void hostapd_ubus_event_sta_account_start(struct hostapd_data *hapd,
+               struct sta_info *sta)
+{
+       if (sta->ubus_acct_session_started || !hapd->ubus.obj.has_subscribers)
+               return;
+#ifdef CONFIG_NO_ACCOUNTING
+       os_get_reltime(&sta->acct_session_start);
+       sta->last_rx_bytes_hi = 0;
+       sta->last_rx_bytes_lo = 0;
+       sta->last_tx_bytes_hi = 0;
+       sta->last_tx_bytes_lo = 0;
+       hostapd_drv_sta_clear_stats(hapd, sta->addr);
+#endif
+       sta->ubus_acct_session_started = 1;
+       hostapd_ubus_event_sta_account(hapd, sta, "start", NULL, NULL, 0);
+}
+void hostapd_ubus_event_sta_account_stop(struct hostapd_data *hapd,
+               struct sta_info *sta)
+{
+       struct hostap_sta_driver_data data, *pdata = NULL;
+       struct os_reltime now_r, diff;
+       int cause = sta->acct_terminate_cause;
+
+       if (!sta->ubus_acct_session_started || !hapd->ubus.obj.has_subscribers)
+               return;
+       sta->ubus_acct_session_started = 0;
+       if (!ctx)
+               return;
+       if (eloop_terminated())
+               cause = RADIUS_ACCT_TERMINATE_CAUSE_ADMIN_REBOOT;
+       os_get_reltime(&now_r);
+       os_reltime_sub(&now_r, &sta->acct_session_start, &diff);
+       if (accounting_sta_update_stats(hapd, sta, &data) == 0)
+               pdata = &data;
+       hostapd_ubus_event_sta_account(hapd, sta, "stop", pdata, &diff, cause);
+}
+struct ubus_sta_acct_counter {
+       struct blob_buf *buf;
+       int counter;
+       struct os_reltime now;
+};
+static int hostapd_ubus_event_sta_account_interim(struct hostapd_data *hapd,
+               struct sta_info *sta, void *ctx)
+{
+       struct ubus_sta_acct_counter *counter = ctx;
+       struct os_reltime diff;
+       struct hostap_sta_driver_data data, *pdata = NULL;
+
+       if (!sta->ubus_acct_session_started)
+               return 0;
+       os_reltime_sub(&counter->now, &sta->acct_session_start, &diff);
+       if (accounting_sta_update_stats(hapd, sta, &data) == 0)
+               pdata = &data;
+       blobmsg_add_station_accounting(counter->buf, NULL, sta, pdata, &diff, 
0);
+       ++counter->counter;
+}
+static void hostapd_ubus_accounting_interim(struct hostapd_data *hapd,
+               struct sta_info *sta)
+{
+       struct ubus_sta_acct_counter counter = { &b, 0 };
+       void *arr;
+
+       if (!hapd->ubus.obj.has_subscribers)
+               return;
+       blob_buf_init(&b, 0);
+
+       os_get_reltime(&counter.now);
+       blobmsg_add_u32(&b, "freq", hapd->iface->freq);
+       blobmsg_add_hapd_id(&b, hapd);
+       arr = blobmsg_open_array(&b, "clients");
+
+       if (sta != NULL)
+               hostapd_ubus_event_sta_account_interim(hapd, sta, &counter);
+       else
+               ap_for_each_sta(hapd, hostapd_ubus_event_sta_account_interim, 
&counter);
+       blobmsg_close_array(&b, arr);
+       if (counter.counter > 0)
+               ubus_notify(ctx, &hapd->ubus.obj, "interim", b.head, -1);
+}
+static void hostapd_ubus_accounting_interim_update(void *eloop_ctx,
+               void *timer_ctx)
+{
+       struct hostapd_data *hapd = eloop_ctx;
+       hostapd_ubus_accounting_interim(hapd, NULL);
+       hostapd_ubus_accounting_init(hapd);
+}
+
+#ifdef CONFIG_NO_ACCOUNTING
+int accounting_sta_update_stats(struct hostapd_data *hapd,
+                                          struct sta_info *sta,
+                                          struct hostap_sta_driver_data *data)
+{
+       if (hostapd_drv_read_sta_data(hapd, data, sta->addr))
+               return -1;
+
+       if (!data->bytes_64bit) {
+               /* Extend 32-bit counters from the driver to 64-bit counters */
+               if (sta->last_rx_bytes_lo > data->rx_bytes)
+                       sta->last_rx_bytes_hi++;
+               sta->last_rx_bytes_lo = data->rx_bytes;
+
+               if (sta->last_tx_bytes_lo > data->tx_bytes)
+                       sta->last_tx_bytes_hi++;
+               sta->last_tx_bytes_lo = data->tx_bytes;
+       }
+
+       hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
+                          HOSTAPD_LEVEL_DEBUG,
+                          "updated TX/RX stats: rx_bytes=%llu [%u:%u] 
tx_bytes=%llu [%u:%u] bytes_64bit=%d",
+                          data->rx_bytes, sta->last_rx_bytes_hi,
+                          sta->last_rx_bytes_lo,
+                          data->tx_bytes, sta->last_tx_bytes_hi,
+                          sta->last_tx_bytes_lo,
+                          data->bytes_64bit);
+
+       return 0;
+}
+int accounting_sta_get_id(struct hostapd_data *hapd, struct sta_info *sta)
+{
+       /* Copied from radius_gen_session_id */
+       return os_get_random((u8 *) &sta->acct_session_id,
+                       sizeof(sta->acct_session_id));
+}
+#endif
diff --git a/package/network/services/hostapd/src/src/ap/ubus.h 
b/package/network/services/hostapd/src/src/ap/ubus.h
index 840b000180..cc4b5fcb0f 100644
--- a/package/network/services/hostapd/src/src/ap/ubus.h
+++ b/package/network/services/hostapd/src/src/ap/ubus.h
@@ -27,6 +27,7 @@ struct hostapd_ubus_request {
 
 struct hostapd_iface;
 struct hostapd_data;
+struct sta_info;
 
 #ifdef UBUS_SUPPORT
 
@@ -53,6 +54,11 @@ void hostapd_ubus_notify(struct hostapd_data *hapd, const 
char *type, const u8 *
 
 void hostapd_ubus_event_iface_state(struct hostapd_iface *iface, int s);
 
+void hostapd_ubus_event_sta_account_start(struct hostapd_data *hapd,
+               struct sta_info *sta);
+void hostapd_ubus_event_sta_account_stop(struct hostapd_data *hapd,
+               struct sta_info *sta);
+
 #else
 
 struct hostapd_ubus_iface {};
@@ -86,6 +92,14 @@ static inline void hostapd_ubus_notify(struct hostapd_data 
*hapd, const char *ty
 static inline void hostapd_ubus_event_iface_state(struct hostapd_iface *iface, 
int s)
 {
 }
+static inline void hostapd_ubus_event_sta_account_start(struct hostapd_data 
*hapd,
+               struct sta_info *sta)
+{
+}
+static inline void hostapd_ubus_event_sta_account_stop(struct hostapd_data 
*hapd,
+               struct sta_info *sta)
+{
+}
 #endif
 
 #endif
-- 
2.19.0


_______________________________________________
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
https://lists.openwrt.org/mailman/listinfo/openwrt-devel

Reply via email to