[PATCH v3] Add rx_bytes64 and tx_bytes64 and use them for RADIUS accounting
Nick Lowe
nick.lowe at lugatech.com
Fri Feb 19 07:28:34 PST 2016
Having a bad day, screwed up in this v3. Sorry. Ignore again. :(
On Fri, Feb 19, 2016 at 2:55 PM, Nick Lowe <nick.lowe at lugatech.com> wrote:
> Add rx_bytes64 and tx_bytes64 and populate them using
> NL80211_STA_INFO_RX_BYTES64 and NL80211_STA_INFO_TX_BYTES64 where support for
> these are available. This resolves the race vulnerable 32-bit value
> wrap/overflow. Rework RADIUS accounting to use these for Acct-Input-Octets,
> Acct-Input-Gigawords, Acct-Output-Octets and Acct-Output-Gigawords, these
> values are often used for billing purposes.
>
> Signed-off-by: Nick Lowe <nick.lowe at lugatech.com>
> ---
> src/ap/accounting.c | 75 ++++++++++++++++++++++++++------------------
> src/ap/ctrl_iface_ap.c | 7 +++--
> src/ap/sta_info.h | 10 +++---
> src/drivers/driver.h | 1 +
> src/drivers/driver_hostap.c | 14 +++++----
> src/drivers/driver_nl80211.c | 6 ++++
> 6 files changed, 70 insertions(+), 43 deletions(-)
>
> diff --git a/src/ap/accounting.c b/src/ap/accounting.c
> index f3ce121..ae6d26b 100644
> --- a/src/ap/accounting.c
> +++ b/src/ap/accounting.c
> @@ -167,19 +167,30 @@ static int accounting_sta_update_stats(struct
> hostapd_data *hapd,
> if (hostapd_drv_read_sta_data(hapd, data, sta->addr))
> return -1;
>
> - if (sta->last_rx_bytes > data->rx_bytes)
> - sta->acct_input_gigawords++;
> - if (sta->last_tx_bytes > data->tx_bytes)
> - sta->acct_output_gigawords++;
> - sta->last_rx_bytes = data->rx_bytes;
> - sta->last_tx_bytes = data->tx_bytes;
> + 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;
> +
> + sta->last_rx_bytes64 = data->rx_bytes64;
> + sta->last_tx_bytes64 = data->tx_bytes64;
>
> hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
> HOSTAPD_LEVEL_DEBUG, "updated TX/RX stats: "
> - "Acct-Input-Octets=%lu Acct-Input-Gigawords=%u "
> - "Acct-Output-Octets=%lu Acct-Output-Gigawords=%u",
> - sta->last_rx_bytes, sta->acct_input_gigawords,
> - sta->last_tx_bytes, sta->acct_output_gigawords);
> + "last_rx_bytes_lo=%lu last_rx_bytes_hi=%lu "
> + "last_tx_bytes_lo=%lu last_tx_bytes_hi=%lu "
> + "last_rx_bytes64=%llu "
> + "last_tx_bytes64=%llu",
> + (unsigned long)sta->last_rx_bytes_lo,
> + (unsigned long)(sta->last_rx_bytes_hi >> 32),
> + (unsigned long)sta->last_tx_bytes_lo,
> + (unsigned long)(sta->last_tx_bytes_hi >> 32),
> + (unsigned long long)sta->last_rx_bytes64,
> + (unsigned long long)sta->last_tx_bytes64
> + );
>
> return 0;
> }
> @@ -224,8 +235,12 @@ void accounting_sta_start(struct hostapd_data
> *hapd, struct sta_info *sta)
> (long unsigned int) sta->acct_session_id);
>
> os_get_reltime(&sta->acct_session_start);
> - sta->last_rx_bytes = sta->last_tx_bytes = 0;
> - sta->acct_input_gigawords = sta->acct_output_gigawords = 0;
> + sta->last_rx_bytes_hi = 0;
> + sta->last_rx_bytes_lo = 0;
> + sta->last_tx_bytes_hi = 0;
> + sta->last_tx_bytes_lo = 0;
> + sta->last_rx_bytes64 = 0;
> + sta->last_tx_bytes64 = 0;
> hostapd_drv_sta_clear_stats(hapd, sta->addr);
>
> if (!hapd->conf->radius->acct_server)
> @@ -254,7 +269,7 @@ static void accounting_sta_report(struct hostapd_data *hapd,
> int cause = sta->acct_terminate_cause;
> struct hostap_sta_driver_data data;
> struct os_reltime now_r, diff;
> - u32 gigawords;
> + unsigned long long bytes;
>
> if (!hapd->conf->radius->acct_server)
> return;
> @@ -288,37 +303,35 @@ static void accounting_sta_report(struct
> hostapd_data *hapd,
> wpa_printf(MSG_INFO, "Could not add Acct-Output-Packets");
> goto fail;
> }
> + if (data.rx_bytes64 > 0)
> + bytes = data.rx_bytes64;
> + else
> + bytes = ((unsigned long long)sta->last_rx_bytes_hi << 32)
> | data.rx_bytes;
> if (!radius_msg_add_attr_int32(msg,
> RADIUS_ATTR_ACCT_INPUT_OCTETS,
> - data.rx_bytes)) {
> + (u32)bytes)) {
> wpa_printf(MSG_INFO, "Could not add Acct-Input-Octets");
> goto fail;
> }
> - gigawords = sta->acct_input_gigawords;
> -#if __WORDSIZE == 64
> - gigawords += data.rx_bytes >> 32;
> -#endif
> - if (gigawords &&
> - !radius_msg_add_attr_int32(
> - msg, RADIUS_ATTR_ACCT_INPUT_GIGAWORDS,
> - gigawords)) {
> + if (!radius_msg_add_attr_int32(msg,
> + RADIUS_ATTR_ACCT_INPUT_GIGAWORDS,
> + (u32)(bytes >> 32))) {
> wpa_printf(MSG_INFO, "Could not add Acct-Input-Gigawords");
> goto fail;
> }
> + if (data.tx_bytes64 > 0)
> + bytes = data.tx_bytes64;
> + else
> + bytes = ((unsigned long long)sta->last_tx_bytes_hi << 32)
> | data.tx_bytes;
> if (!radius_msg_add_attr_int32(msg,
> RADIUS_ATTR_ACCT_OUTPUT_OCTETS,
> - data.tx_bytes)) {
> + (u32)bytes)) {
> wpa_printf(MSG_INFO, "Could not add Acct-Output-Octets");
> goto fail;
> }
> - gigawords = sta->acct_output_gigawords;
> -#if __WORDSIZE == 64
> - gigawords += data.tx_bytes >> 32;
> -#endif
> - if (gigawords &&
> - !radius_msg_add_attr_int32(
> - msg, RADIUS_ATTR_ACCT_OUTPUT_GIGAWORDS,
> - gigawords)) {
> + if (!radius_msg_add_attr_int32(msg,
> + RADIUS_ATTR_ACCT_OUTPUT_GIGAWORDS,
> + (u32)(bytes >> 32))) {
> wpa_printf(MSG_INFO, "Could not add Acct-Output-Gigawords");
> goto fail;
> }
> diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c
> index c98978f..bce48a7 100644
> --- a/src/ap/ctrl_iface_ap.c
> +++ b/src/ap/ctrl_iface_ap.c
> @@ -35,9 +35,12 @@ static int hostapd_get_sta_tx_rx(struct hostapd_data *hapd,
> return 0;
>
> ret = os_snprintf(buf, buflen, "rx_packets=%lu\ntx_packets=%lu\n"
> - "rx_bytes=%lu\ntx_bytes=%lu\n",
> + "rx_bytes=%lu\ntx_bytes=%lu\n"
> + "rx_bytes64=%llu\ntx_bytes64=%llu\n",
> data.rx_packets, data.tx_packets,
> - data.rx_bytes, data.tx_bytes);
> + data.rx_bytes, data.tx_bytes,
> + data.rx_bytes64, data.tx_bytes64
> + );
> if (os_snprintf_error(buflen, ret))
> return 0;
> return ret;
> diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h
> index 359f480..d818afb 100644
> --- a/src/ap/sta_info.h
> +++ b/src/ap/sta_info.h
> @@ -107,10 +107,12 @@ struct sta_info {
> int acct_terminate_cause; /* Acct-Terminate-Cause */
> int acct_interim_interval; /* Acct-Interim-Interval */
>
> - unsigned long last_rx_bytes;
> - unsigned long last_tx_bytes;
> - u32 acct_input_gigawords; /* Acct-Input-Gigawords */
> - u32 acct_output_gigawords; /* Acct-Output-Gigawords */
> + unsigned long last_rx_bytes_hi;
> + unsigned long last_rx_bytes_lo;
> + unsigned long last_tx_bytes_hi;
> + unsigned long last_tx_bytes_lo;
> + unsigned long long last_rx_bytes64;
> + unsigned long long last_tx_bytes64;
>
> u8 *challenge; /* IEEE 802.11 Shared Key Authentication Challenge */
>
> diff --git a/src/drivers/driver.h b/src/drivers/driver.h
> index a4f6704..c2a81fe 100644
> --- a/src/drivers/driver.h
> +++ b/src/drivers/driver.h
> @@ -1377,6 +1377,7 @@ struct hostap_sta_driver_data {
> unsigned long tx_retry_count;
> int last_rssi;
> int last_ack_rssi;
> + unsigned long long rx_bytes64, tx_bytes64;
> };
>
> struct hostapd_sta_add_params {
> diff --git a/src/drivers/driver_hostap.c b/src/drivers/driver_hostap.c
> index 517a3bb..e1b7dc9 100644
> --- a/src/drivers/driver_hostap.c
> +++ b/src/drivers/driver_hostap.c
> @@ -579,7 +579,6 @@ static int hostap_read_sta_data(void *priv,
> struct hostap_driver_data *drv = priv;
> char buf[1024], line[128], *pos;
> FILE *f;
> - unsigned long val;
>
> memset(data, 0, sizeof(*data));
> snprintf(buf, sizeof(buf), "/proc/net/hostap/%s/" MACSTR,
> @@ -597,15 +596,18 @@ static int hostap_read_sta_data(void *priv,
> if (!pos)
> continue;
> *pos++ = '\0';
> - val = strtoul(pos, NULL, 10);
> if (strcmp(line, "rx_packets") == 0)
> - data->rx_packets = val;
> + data->rx_packets = strtoul(pos, NULL, 10);
> else if (strcmp(line, "tx_packets") == 0)
> - data->tx_packets = val;
> + data->tx_packets = strtoul(pos, NULL, 10);
> else if (strcmp(line, "rx_bytes") == 0)
> - data->rx_bytes = val;
> + data->rx_bytes = strtoul(pos, NULL, 10);
> else if (strcmp(line, "tx_bytes") == 0)
> - data->tx_bytes = val;
> + data->tx_bytes = strtoul(pos, NULL, 10);
> + else if (strcmp(line, "rx_bytes64") == 0)
> + data->rx_bytes64 = strtoull(pos, NULL, 20);
> + else if (strcmp(line, "tx_bytes64") == 0)
> + data->tx_bytes64 = strtoull(pos, NULL, 20);
> }
>
> fclose(f);
> diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
> index 0f312a0..9916bc6 100644
> --- a/src/drivers/driver_nl80211.c
> +++ b/src/drivers/driver_nl80211.c
> @@ -5327,6 +5327,8 @@ static int get_sta_handler(struct nl_msg *msg, void *arg)
> [NL80211_STA_INFO_RX_PACKETS] = { .type = NLA_U32 },
> [NL80211_STA_INFO_TX_PACKETS] = { .type = NLA_U32 },
> [NL80211_STA_INFO_TX_FAILED] = { .type = NLA_U32 },
> + [NL80211_STA_INFO_RX_BYTES64] = { .type = NLA_U64 },
> + [NL80211_STA_INFO_TX_BYTES64] = { .type = NLA_U64 },
> };
>
> nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
> @@ -5365,6 +5367,10 @@ static int get_sta_handler(struct nl_msg *msg, void *arg)
> if (stats[NL80211_STA_INFO_TX_FAILED])
> data->tx_retry_failed =
> nla_get_u32(stats[NL80211_STA_INFO_TX_FAILED]);
> + if (stats[NL80211_STA_INFO_RX_BYTES64])
> + data->rx_bytes64 = nla_get_u64(stats[NL80211_STA_INFO_RX_BYTES64]);
> + if (stats[NL80211_STA_INFO_TX_BYTES64])
> + data->tx_bytes64 = nla_get_u64(stats[NL80211_STA_INFO_TX_BYTES64]);
>
> return NL_SKIP;
> }
> --
> 2.7.1
More information about the Hostap
mailing list