diff options
Diffstat (limited to 'contrib/wpa/src/ap/accounting.c')
-rw-r--r-- | contrib/wpa/src/ap/accounting.c | 153 |
1 files changed, 65 insertions, 88 deletions
diff --git a/contrib/wpa/src/ap/accounting.c b/contrib/wpa/src/ap/accounting.c index 7939c68..9540531 100644 --- a/contrib/wpa/src/ap/accounting.c +++ b/contrib/wpa/src/ap/accounting.c @@ -1,15 +1,9 @@ /* * hostapd / RADIUS Accounting - * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi> + * Copyright (c) 2002-2009, 2012, Jouni Malinen <j@w1.fi> * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. + * This software may be distributed under the terms of the BSD license. + * See README for more details. */ #include "utils/includes.h" @@ -23,6 +17,7 @@ #include "ieee802_1x.h" #include "ap_config.h" #include "sta_info.h" +#include "ap_drv_ops.h" #include "accounting.h" @@ -31,8 +26,8 @@ * input/output octets and updates Acct-{Input,Output}-Gigawords. */ #define ACCT_DEFAULT_UPDATE_INTERVAL 300 -static void accounting_sta_get_id(struct hostapd_data *hapd, - struct sta_info *sta); +static void accounting_sta_interim(struct hostapd_data *hapd, + struct sta_info *sta); static struct radius_msg * accounting_msg(struct hostapd_data *hapd, @@ -44,6 +39,7 @@ static struct radius_msg * accounting_msg(struct hostapd_data *hapd, u8 *val; size_t len; int i; + struct wpabuf *b; msg = radius_msg_new(RADIUS_CODE_ACCOUNTING_REQUEST, radius_client_get_id(hapd->radius)); @@ -72,7 +68,9 @@ static struct radius_msg * accounting_msg(struct hostapd_data *hapd, goto fail; } - if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_AUTHENTIC, + if (!hostapd_config_get_radius_attr(hapd->conf->radius_acct_req_attr, + RADIUS_ATTR_ACCT_AUTHENTIC) && + !radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_AUTHENTIC, hapd->conf->ieee802_1x ? RADIUS_ACCT_AUTHENTIC_RADIUS : RADIUS_ACCT_AUTHENTIC_LOCAL)) { @@ -81,7 +79,17 @@ static struct radius_msg * accounting_msg(struct hostapd_data *hapd, } if (sta) { + /* Use 802.1X identity if available */ val = ieee802_1x_get_identity(sta->eapol_sm, &len); + + /* Use RADIUS ACL identity if 802.1X provides no identity */ + if (!val && sta->identity) { + val = (u8 *) sta->identity; + len = os_strlen(sta->identity); + } + + /* Use STA MAC if neither 802.1X nor RADIUS ACL provided + * identity */ if (!val) { os_snprintf(buf, sizeof(buf), RADIUS_ADDR_FORMAT, MAC2STR(sta->addr)); @@ -96,70 +104,11 @@ static struct radius_msg * accounting_msg(struct hostapd_data *hapd, } } - if (hapd->conf->own_ip_addr.af == AF_INET && - !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS, - (u8 *) &hapd->conf->own_ip_addr.u.v4, 4)) { - printf("Could not add NAS-IP-Address\n"); - goto fail; - } - -#ifdef CONFIG_IPV6 - if (hapd->conf->own_ip_addr.af == AF_INET6 && - !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IPV6_ADDRESS, - (u8 *) &hapd->conf->own_ip_addr.u.v6, 16)) { - printf("Could not add NAS-IPv6-Address\n"); - goto fail; - } -#endif /* CONFIG_IPV6 */ - - if (hapd->conf->nas_identifier && - !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IDENTIFIER, - (u8 *) hapd->conf->nas_identifier, - os_strlen(hapd->conf->nas_identifier))) { - printf("Could not add NAS-Identifier\n"); - goto fail; - } - - if (sta && - !radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT, sta->aid)) { - printf("Could not add NAS-Port\n"); - goto fail; - } - - os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT ":%s", - MAC2STR(hapd->own_addr), hapd->conf->ssid.ssid); - if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLED_STATION_ID, - (u8 *) buf, os_strlen(buf))) { - printf("Could not add Called-Station-Id\n"); + if (add_common_radius_attr(hapd, hapd->conf->radius_acct_req_attr, sta, + msg) < 0) goto fail; - } if (sta) { - os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT, - MAC2STR(sta->addr)); - if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID, - (u8 *) buf, os_strlen(buf))) { - printf("Could not add Calling-Station-Id\n"); - goto fail; - } - - if (!radius_msg_add_attr_int32( - msg, RADIUS_ATTR_NAS_PORT_TYPE, - RADIUS_NAS_PORT_TYPE_IEEE_802_11)) { - printf("Could not add NAS-Port-Type\n"); - goto fail; - } - - os_snprintf(buf, sizeof(buf), "CONNECT %d%sMbps %s", - radius_sta_rate(hapd, sta) / 2, - (radius_sta_rate(hapd, sta) & 1) ? ".5" : "", - radius_mode_txt(hapd)); - if (!radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO, - (u8 *) buf, os_strlen(buf))) { - printf("Could not add Connect-Info\n"); - goto fail; - } - for (i = 0; ; i++) { val = ieee802_1x_get_radius_class(sta->eapol_sm, &len, i); @@ -172,6 +121,24 @@ static struct radius_msg * accounting_msg(struct hostapd_data *hapd, goto fail; } } + + b = ieee802_1x_get_radius_cui(sta->eapol_sm); + if (b && + !radius_msg_add_attr(msg, + RADIUS_ATTR_CHARGEABLE_USER_IDENTITY, + wpabuf_head(b), wpabuf_len(b))) { + wpa_printf(MSG_ERROR, "Could not add CUI"); + goto fail; + } + + if (!b && sta->radius_cui && + !radius_msg_add_attr(msg, + RADIUS_ATTR_CHARGEABLE_USER_IDENTITY, + (u8 *) sta->radius_cui, + os_strlen(sta->radius_cui))) { + wpa_printf(MSG_ERROR, "Could not add CUI from ACL"); + goto fail; + } } return msg; @@ -186,7 +153,7 @@ static int accounting_sta_update_stats(struct hostapd_data *hapd, struct sta_info *sta, struct hostap_sta_driver_data *data) { - if (hapd->drv.read_sta_data(hapd, data, sta->addr)) + if (hostapd_drv_read_sta_data(hapd, data, sta->addr)) return -1; if (sta->last_rx_bytes > data->rx_bytes) @@ -235,21 +202,22 @@ static void accounting_interim_update(void *eloop_ctx, void *timeout_ctx) void accounting_sta_start(struct hostapd_data *hapd, struct sta_info *sta) { struct radius_msg *msg; + struct os_time t; int interval; if (sta->acct_session_started) return; - accounting_sta_get_id(hapd, sta); hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS, HOSTAPD_LEVEL_INFO, "starting accounting session %08X-%08X", sta->acct_session_id_hi, sta->acct_session_id_lo); - time(&sta->acct_session_start); + os_get_time(&t); + sta->acct_session_start = t.sec; sta->last_rx_bytes = sta->last_tx_bytes = 0; sta->acct_input_gigawords = sta->acct_output_gigawords = 0; - hapd->drv.sta_clear_stats(hapd, sta->addr); + hostapd_drv_sta_clear_stats(hapd, sta->addr); if (!hapd->conf->radius->acct_server) return; @@ -262,8 +230,9 @@ void accounting_sta_start(struct hostapd_data *hapd, struct sta_info *sta) hapd, sta); msg = accounting_msg(hapd, sta, RADIUS_ACCT_STATUS_TYPE_START); - if (msg) - radius_client_send(hapd->radius, msg, RADIUS_ACCT, sta->addr); + if (msg && + radius_client_send(hapd->radius, msg, RADIUS_ACCT, sta->addr) < 0) + radius_msg_free(msg); sta->acct_session_started = 1; } @@ -275,6 +244,7 @@ static void accounting_sta_report(struct hostapd_data *hapd, struct radius_msg *msg; int cause = sta->acct_terminate_cause; struct hostap_sta_driver_data data; + struct os_time now; u32 gigawords; if (!hapd->conf->radius->acct_server) @@ -288,8 +258,9 @@ static void accounting_sta_report(struct hostapd_data *hapd, return; } + os_get_time(&now); if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_SESSION_TIME, - time(NULL) - sta->acct_session_start)) { + now.sec - sta->acct_session_start)) { printf("Could not add Acct-Session-Time\n"); goto fail; } @@ -344,7 +315,7 @@ static void accounting_sta_report(struct hostapd_data *hapd, } if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_EVENT_TIMESTAMP, - time(NULL))) { + now.sec)) { printf("Could not add Event-Timestamp\n"); goto fail; } @@ -359,9 +330,10 @@ static void accounting_sta_report(struct hostapd_data *hapd, goto fail; } - radius_client_send(hapd->radius, msg, - stop ? RADIUS_ACCT : RADIUS_ACCT_INTERIM, - sta->addr); + if (radius_client_send(hapd->radius, msg, + stop ? RADIUS_ACCT : RADIUS_ACCT_INTERIM, + sta->addr) < 0) + goto fail; return; fail: @@ -374,7 +346,8 @@ static void accounting_sta_report(struct hostapd_data *hapd, * @hapd: hostapd BSS data * @sta: The station */ -void accounting_sta_interim(struct hostapd_data *hapd, struct sta_info *sta) +static void accounting_sta_interim(struct hostapd_data *hapd, + struct sta_info *sta) { if (sta->acct_session_started) accounting_sta_report(hapd, sta, 0); @@ -401,7 +374,7 @@ void accounting_sta_stop(struct hostapd_data *hapd, struct sta_info *sta) } -static void accounting_sta_get_id(struct hostapd_data *hapd, +void accounting_sta_get_id(struct hostapd_data *hapd, struct sta_info *sta) { sta->acct_session_id_lo = hapd->acct_session_id_lo++; @@ -464,7 +437,8 @@ static void accounting_report_state(struct hostapd_data *hapd, int on) return; } - radius_client_send(hapd->radius, msg, RADIUS_ACCT, NULL); + if (radius_client_send(hapd->radius, msg, RADIUS_ACCT, NULL) < 0) + radius_msg_free(msg); } @@ -475,9 +449,12 @@ static void accounting_report_state(struct hostapd_data *hapd, int on) */ int accounting_init(struct hostapd_data *hapd) { + struct os_time now; + /* Acct-Session-Id should be unique over reboots. If reliable clock is * not available, this could be replaced with reboot counter, etc. */ - hapd->acct_session_id_hi = time(NULL); + os_get_time(&now); + hapd->acct_session_id_hi = now.sec; if (radius_client_register(hapd->radius, RADIUS_ACCT, accounting_receive, hapd)) |