xref: /aosp_15_r20/external/wpa_supplicant_8/src/ap/accounting.c (revision 03f9172ca588f91df233974f4258bab95191f931)
1*03f9172cSAndroid Build Coastguard Worker /*
2*03f9172cSAndroid Build Coastguard Worker  * hostapd / RADIUS Accounting
3*03f9172cSAndroid Build Coastguard Worker  * Copyright (c) 2002-2009, 2012-2015, Jouni Malinen <[email protected]>
4*03f9172cSAndroid Build Coastguard Worker  *
5*03f9172cSAndroid Build Coastguard Worker  * This software may be distributed under the terms of the BSD license.
6*03f9172cSAndroid Build Coastguard Worker  * See README for more details.
7*03f9172cSAndroid Build Coastguard Worker  */
8*03f9172cSAndroid Build Coastguard Worker 
9*03f9172cSAndroid Build Coastguard Worker #include "utils/includes.h"
10*03f9172cSAndroid Build Coastguard Worker 
11*03f9172cSAndroid Build Coastguard Worker #include "utils/common.h"
12*03f9172cSAndroid Build Coastguard Worker #include "utils/eloop.h"
13*03f9172cSAndroid Build Coastguard Worker #include "eapol_auth/eapol_auth_sm.h"
14*03f9172cSAndroid Build Coastguard Worker #include "eapol_auth/eapol_auth_sm_i.h"
15*03f9172cSAndroid Build Coastguard Worker #include "radius/radius.h"
16*03f9172cSAndroid Build Coastguard Worker #include "radius/radius_client.h"
17*03f9172cSAndroid Build Coastguard Worker #include "hostapd.h"
18*03f9172cSAndroid Build Coastguard Worker #include "ieee802_1x.h"
19*03f9172cSAndroid Build Coastguard Worker #include "ap_config.h"
20*03f9172cSAndroid Build Coastguard Worker #include "sta_info.h"
21*03f9172cSAndroid Build Coastguard Worker #include "ap_drv_ops.h"
22*03f9172cSAndroid Build Coastguard Worker #include "accounting.h"
23*03f9172cSAndroid Build Coastguard Worker 
24*03f9172cSAndroid Build Coastguard Worker 
25*03f9172cSAndroid Build Coastguard Worker /* Default interval in seconds for polling TX/RX octets from the driver if
26*03f9172cSAndroid Build Coastguard Worker  * STA is not using interim accounting. This detects wrap arounds for
27*03f9172cSAndroid Build Coastguard Worker  * input/output octets and updates Acct-{Input,Output}-Gigawords. */
28*03f9172cSAndroid Build Coastguard Worker #define ACCT_DEFAULT_UPDATE_INTERVAL 300
29*03f9172cSAndroid Build Coastguard Worker 
30*03f9172cSAndroid Build Coastguard Worker static void accounting_sta_interim(struct hostapd_data *hapd,
31*03f9172cSAndroid Build Coastguard Worker 				   struct sta_info *sta);
32*03f9172cSAndroid Build Coastguard Worker 
33*03f9172cSAndroid Build Coastguard Worker 
accounting_msg(struct hostapd_data * hapd,struct sta_info * sta,int status_type)34*03f9172cSAndroid Build Coastguard Worker static struct radius_msg * accounting_msg(struct hostapd_data *hapd,
35*03f9172cSAndroid Build Coastguard Worker 					  struct sta_info *sta,
36*03f9172cSAndroid Build Coastguard Worker 					  int status_type)
37*03f9172cSAndroid Build Coastguard Worker {
38*03f9172cSAndroid Build Coastguard Worker 	struct radius_msg *msg;
39*03f9172cSAndroid Build Coastguard Worker 	char buf[128];
40*03f9172cSAndroid Build Coastguard Worker 	u8 *val;
41*03f9172cSAndroid Build Coastguard Worker 	size_t len;
42*03f9172cSAndroid Build Coastguard Worker 	int i;
43*03f9172cSAndroid Build Coastguard Worker 	struct wpabuf *b;
44*03f9172cSAndroid Build Coastguard Worker 	struct os_time now;
45*03f9172cSAndroid Build Coastguard Worker 
46*03f9172cSAndroid Build Coastguard Worker 	msg = radius_msg_new(RADIUS_CODE_ACCOUNTING_REQUEST,
47*03f9172cSAndroid Build Coastguard Worker 			     radius_client_get_id(hapd->radius));
48*03f9172cSAndroid Build Coastguard Worker 	if (msg == NULL) {
49*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_INFO, "Could not create new RADIUS packet");
50*03f9172cSAndroid Build Coastguard Worker 		return NULL;
51*03f9172cSAndroid Build Coastguard Worker 	}
52*03f9172cSAndroid Build Coastguard Worker 
53*03f9172cSAndroid Build Coastguard Worker 	if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_STATUS_TYPE,
54*03f9172cSAndroid Build Coastguard Worker 				       status_type)) {
55*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_INFO, "Could not add Acct-Status-Type");
56*03f9172cSAndroid Build Coastguard Worker 		goto fail;
57*03f9172cSAndroid Build Coastguard Worker 	}
58*03f9172cSAndroid Build Coastguard Worker 
59*03f9172cSAndroid Build Coastguard Worker 	if (sta) {
60*03f9172cSAndroid Build Coastguard Worker 		if (!hostapd_config_get_radius_attr(
61*03f9172cSAndroid Build Coastguard Worker 			    hapd->conf->radius_acct_req_attr,
62*03f9172cSAndroid Build Coastguard Worker 			    RADIUS_ATTR_ACCT_AUTHENTIC) &&
63*03f9172cSAndroid Build Coastguard Worker 		    !radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_AUTHENTIC,
64*03f9172cSAndroid Build Coastguard Worker 					       hapd->conf->ieee802_1x ?
65*03f9172cSAndroid Build Coastguard Worker 					       RADIUS_ACCT_AUTHENTIC_RADIUS :
66*03f9172cSAndroid Build Coastguard Worker 					       RADIUS_ACCT_AUTHENTIC_LOCAL)) {
67*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_INFO, "Could not add Acct-Authentic");
68*03f9172cSAndroid Build Coastguard Worker 			goto fail;
69*03f9172cSAndroid Build Coastguard Worker 		}
70*03f9172cSAndroid Build Coastguard Worker 
71*03f9172cSAndroid Build Coastguard Worker 		/* Use 802.1X identity if available */
72*03f9172cSAndroid Build Coastguard Worker 		val = ieee802_1x_get_identity(sta->eapol_sm, &len);
73*03f9172cSAndroid Build Coastguard Worker 
74*03f9172cSAndroid Build Coastguard Worker 		/* Use RADIUS ACL identity if 802.1X provides no identity */
75*03f9172cSAndroid Build Coastguard Worker 		if (!val && sta->identity) {
76*03f9172cSAndroid Build Coastguard Worker 			val = (u8 *) sta->identity;
77*03f9172cSAndroid Build Coastguard Worker 			len = os_strlen(sta->identity);
78*03f9172cSAndroid Build Coastguard Worker 		}
79*03f9172cSAndroid Build Coastguard Worker 
80*03f9172cSAndroid Build Coastguard Worker 		/* Use STA MAC if neither 802.1X nor RADIUS ACL provided
81*03f9172cSAndroid Build Coastguard Worker 		 * identity */
82*03f9172cSAndroid Build Coastguard Worker 		if (!val) {
83*03f9172cSAndroid Build Coastguard Worker 			os_snprintf(buf, sizeof(buf), RADIUS_ADDR_FORMAT,
84*03f9172cSAndroid Build Coastguard Worker 				    MAC2STR(sta->addr));
85*03f9172cSAndroid Build Coastguard Worker 			val = (u8 *) buf;
86*03f9172cSAndroid Build Coastguard Worker 			len = os_strlen(buf);
87*03f9172cSAndroid Build Coastguard Worker 		}
88*03f9172cSAndroid Build Coastguard Worker 
89*03f9172cSAndroid Build Coastguard Worker 		if (!radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME, val,
90*03f9172cSAndroid Build Coastguard Worker 					 len)) {
91*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_INFO, "Could not add User-Name");
92*03f9172cSAndroid Build Coastguard Worker 			goto fail;
93*03f9172cSAndroid Build Coastguard Worker 		}
94*03f9172cSAndroid Build Coastguard Worker 	}
95*03f9172cSAndroid Build Coastguard Worker 
96*03f9172cSAndroid Build Coastguard Worker 	if (add_common_radius_attr(hapd, hapd->conf->radius_acct_req_attr, sta,
97*03f9172cSAndroid Build Coastguard Worker 				   msg) < 0)
98*03f9172cSAndroid Build Coastguard Worker 		goto fail;
99*03f9172cSAndroid Build Coastguard Worker 
100*03f9172cSAndroid Build Coastguard Worker 	if (sta && add_sqlite_radius_attr(hapd, sta, msg, 1) < 0)
101*03f9172cSAndroid Build Coastguard Worker 		goto fail;
102*03f9172cSAndroid Build Coastguard Worker 
103*03f9172cSAndroid Build Coastguard Worker 	if (sta) {
104*03f9172cSAndroid Build Coastguard Worker 		for (i = 0; ; i++) {
105*03f9172cSAndroid Build Coastguard Worker 			val = ieee802_1x_get_radius_class(sta->eapol_sm, &len,
106*03f9172cSAndroid Build Coastguard Worker 							  i);
107*03f9172cSAndroid Build Coastguard Worker 			if (val == NULL)
108*03f9172cSAndroid Build Coastguard Worker 				break;
109*03f9172cSAndroid Build Coastguard Worker 
110*03f9172cSAndroid Build Coastguard Worker 			if (!radius_msg_add_attr(msg, RADIUS_ATTR_CLASS,
111*03f9172cSAndroid Build Coastguard Worker 						 val, len)) {
112*03f9172cSAndroid Build Coastguard Worker 				wpa_printf(MSG_INFO, "Could not add Class");
113*03f9172cSAndroid Build Coastguard Worker 				goto fail;
114*03f9172cSAndroid Build Coastguard Worker 			}
115*03f9172cSAndroid Build Coastguard Worker 		}
116*03f9172cSAndroid Build Coastguard Worker 
117*03f9172cSAndroid Build Coastguard Worker 		b = ieee802_1x_get_radius_cui(sta->eapol_sm);
118*03f9172cSAndroid Build Coastguard Worker 		if (b &&
119*03f9172cSAndroid Build Coastguard Worker 		    !radius_msg_add_attr(msg,
120*03f9172cSAndroid Build Coastguard Worker 					 RADIUS_ATTR_CHARGEABLE_USER_IDENTITY,
121*03f9172cSAndroid Build Coastguard Worker 					 wpabuf_head(b), wpabuf_len(b))) {
122*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_ERROR, "Could not add CUI");
123*03f9172cSAndroid Build Coastguard Worker 			goto fail;
124*03f9172cSAndroid Build Coastguard Worker 		}
125*03f9172cSAndroid Build Coastguard Worker 
126*03f9172cSAndroid Build Coastguard Worker 		if (!b && sta->radius_cui &&
127*03f9172cSAndroid Build Coastguard Worker 		    !radius_msg_add_attr(msg,
128*03f9172cSAndroid Build Coastguard Worker 					 RADIUS_ATTR_CHARGEABLE_USER_IDENTITY,
129*03f9172cSAndroid Build Coastguard Worker 					 (u8 *) sta->radius_cui,
130*03f9172cSAndroid Build Coastguard Worker 					 os_strlen(sta->radius_cui))) {
131*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_ERROR, "Could not add CUI from ACL");
132*03f9172cSAndroid Build Coastguard Worker 			goto fail;
133*03f9172cSAndroid Build Coastguard Worker 		}
134*03f9172cSAndroid Build Coastguard Worker 
135*03f9172cSAndroid Build Coastguard Worker 		if (sta->ipaddr &&
136*03f9172cSAndroid Build Coastguard Worker 		    !radius_msg_add_attr_int32(msg,
137*03f9172cSAndroid Build Coastguard Worker 					       RADIUS_ATTR_FRAMED_IP_ADDRESS,
138*03f9172cSAndroid Build Coastguard Worker 					       be_to_host32(sta->ipaddr))) {
139*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_ERROR,
140*03f9172cSAndroid Build Coastguard Worker 				   "Could not add Framed-IP-Address");
141*03f9172cSAndroid Build Coastguard Worker 			goto fail;
142*03f9172cSAndroid Build Coastguard Worker 		}
143*03f9172cSAndroid Build Coastguard Worker 	}
144*03f9172cSAndroid Build Coastguard Worker 
145*03f9172cSAndroid Build Coastguard Worker 	os_get_time(&now);
146*03f9172cSAndroid Build Coastguard Worker 	if (now.sec > 1000000000 &&
147*03f9172cSAndroid Build Coastguard Worker 	    !radius_msg_add_attr_int32(msg, RADIUS_ATTR_EVENT_TIMESTAMP,
148*03f9172cSAndroid Build Coastguard Worker 				       now.sec)) {
149*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_INFO, "Could not add Event-Timestamp");
150*03f9172cSAndroid Build Coastguard Worker 		goto fail;
151*03f9172cSAndroid Build Coastguard Worker 	}
152*03f9172cSAndroid Build Coastguard Worker 
153*03f9172cSAndroid Build Coastguard Worker 	/*
154*03f9172cSAndroid Build Coastguard Worker 	 * Add Acct-Delay-Time with zero value for the first transmission. This
155*03f9172cSAndroid Build Coastguard Worker 	 * will be updated within radius_client.c when retransmitting the frame.
156*03f9172cSAndroid Build Coastguard Worker 	 */
157*03f9172cSAndroid Build Coastguard Worker 	if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_DELAY_TIME, 0)) {
158*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_INFO, "Could not add Acct-Delay-Time");
159*03f9172cSAndroid Build Coastguard Worker 		goto fail;
160*03f9172cSAndroid Build Coastguard Worker 	}
161*03f9172cSAndroid Build Coastguard Worker 
162*03f9172cSAndroid Build Coastguard Worker 	return msg;
163*03f9172cSAndroid Build Coastguard Worker 
164*03f9172cSAndroid Build Coastguard Worker  fail:
165*03f9172cSAndroid Build Coastguard Worker 	radius_msg_free(msg);
166*03f9172cSAndroid Build Coastguard Worker 	return NULL;
167*03f9172cSAndroid Build Coastguard Worker }
168*03f9172cSAndroid Build Coastguard Worker 
169*03f9172cSAndroid Build Coastguard Worker 
accounting_sta_update_stats(struct hostapd_data * hapd,struct sta_info * sta,struct hostap_sta_driver_data * data)170*03f9172cSAndroid Build Coastguard Worker static int accounting_sta_update_stats(struct hostapd_data *hapd,
171*03f9172cSAndroid Build Coastguard Worker 				       struct sta_info *sta,
172*03f9172cSAndroid Build Coastguard Worker 				       struct hostap_sta_driver_data *data)
173*03f9172cSAndroid Build Coastguard Worker {
174*03f9172cSAndroid Build Coastguard Worker 	if (hostapd_drv_read_sta_data(hapd, data, sta->addr))
175*03f9172cSAndroid Build Coastguard Worker 		return -1;
176*03f9172cSAndroid Build Coastguard Worker 
177*03f9172cSAndroid Build Coastguard Worker 	if (!data->bytes_64bit) {
178*03f9172cSAndroid Build Coastguard Worker 		/* Extend 32-bit counters from the driver to 64-bit counters */
179*03f9172cSAndroid Build Coastguard Worker 		if (sta->last_rx_bytes_lo > data->rx_bytes)
180*03f9172cSAndroid Build Coastguard Worker 			sta->last_rx_bytes_hi++;
181*03f9172cSAndroid Build Coastguard Worker 		sta->last_rx_bytes_lo = data->rx_bytes;
182*03f9172cSAndroid Build Coastguard Worker 
183*03f9172cSAndroid Build Coastguard Worker 		if (sta->last_tx_bytes_lo > data->tx_bytes)
184*03f9172cSAndroid Build Coastguard Worker 			sta->last_tx_bytes_hi++;
185*03f9172cSAndroid Build Coastguard Worker 		sta->last_tx_bytes_lo = data->tx_bytes;
186*03f9172cSAndroid Build Coastguard Worker 	}
187*03f9172cSAndroid Build Coastguard Worker 
188*03f9172cSAndroid Build Coastguard Worker 	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
189*03f9172cSAndroid Build Coastguard Worker 		       HOSTAPD_LEVEL_DEBUG,
190*03f9172cSAndroid Build Coastguard Worker 		       "updated TX/RX stats: rx_bytes=%llu [%u:%u] tx_bytes=%llu [%u:%u] bytes_64bit=%d",
191*03f9172cSAndroid Build Coastguard Worker 		       data->rx_bytes, sta->last_rx_bytes_hi,
192*03f9172cSAndroid Build Coastguard Worker 		       sta->last_rx_bytes_lo,
193*03f9172cSAndroid Build Coastguard Worker 		       data->tx_bytes, sta->last_tx_bytes_hi,
194*03f9172cSAndroid Build Coastguard Worker 		       sta->last_tx_bytes_lo,
195*03f9172cSAndroid Build Coastguard Worker 		       data->bytes_64bit);
196*03f9172cSAndroid Build Coastguard Worker 
197*03f9172cSAndroid Build Coastguard Worker 	return 0;
198*03f9172cSAndroid Build Coastguard Worker }
199*03f9172cSAndroid Build Coastguard Worker 
200*03f9172cSAndroid Build Coastguard Worker 
accounting_interim_update(void * eloop_ctx,void * timeout_ctx)201*03f9172cSAndroid Build Coastguard Worker static void accounting_interim_update(void *eloop_ctx, void *timeout_ctx)
202*03f9172cSAndroid Build Coastguard Worker {
203*03f9172cSAndroid Build Coastguard Worker 	struct hostapd_data *hapd = eloop_ctx;
204*03f9172cSAndroid Build Coastguard Worker 	struct sta_info *sta = timeout_ctx;
205*03f9172cSAndroid Build Coastguard Worker 	int interval;
206*03f9172cSAndroid Build Coastguard Worker 
207*03f9172cSAndroid Build Coastguard Worker 	if (sta->acct_interim_interval) {
208*03f9172cSAndroid Build Coastguard Worker 		accounting_sta_interim(hapd, sta);
209*03f9172cSAndroid Build Coastguard Worker 		interval = sta->acct_interim_interval;
210*03f9172cSAndroid Build Coastguard Worker 	} else {
211*03f9172cSAndroid Build Coastguard Worker 		struct hostap_sta_driver_data data;
212*03f9172cSAndroid Build Coastguard Worker 		accounting_sta_update_stats(hapd, sta, &data);
213*03f9172cSAndroid Build Coastguard Worker 		interval = ACCT_DEFAULT_UPDATE_INTERVAL;
214*03f9172cSAndroid Build Coastguard Worker 	}
215*03f9172cSAndroid Build Coastguard Worker 
216*03f9172cSAndroid Build Coastguard Worker 	eloop_register_timeout(interval, 0, accounting_interim_update,
217*03f9172cSAndroid Build Coastguard Worker 			       hapd, sta);
218*03f9172cSAndroid Build Coastguard Worker }
219*03f9172cSAndroid Build Coastguard Worker 
220*03f9172cSAndroid Build Coastguard Worker 
221*03f9172cSAndroid Build Coastguard Worker /**
222*03f9172cSAndroid Build Coastguard Worker  * accounting_sta_start - Start STA accounting
223*03f9172cSAndroid Build Coastguard Worker  * @hapd: hostapd BSS data
224*03f9172cSAndroid Build Coastguard Worker  * @sta: The station
225*03f9172cSAndroid Build Coastguard Worker  */
accounting_sta_start(struct hostapd_data * hapd,struct sta_info * sta)226*03f9172cSAndroid Build Coastguard Worker void accounting_sta_start(struct hostapd_data *hapd, struct sta_info *sta)
227*03f9172cSAndroid Build Coastguard Worker {
228*03f9172cSAndroid Build Coastguard Worker 	struct radius_msg *msg;
229*03f9172cSAndroid Build Coastguard Worker 	int interval;
230*03f9172cSAndroid Build Coastguard Worker 
231*03f9172cSAndroid Build Coastguard Worker 	if (sta->acct_session_started)
232*03f9172cSAndroid Build Coastguard Worker 		return;
233*03f9172cSAndroid Build Coastguard Worker 
234*03f9172cSAndroid Build Coastguard Worker 	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
235*03f9172cSAndroid Build Coastguard Worker 		       HOSTAPD_LEVEL_INFO,
236*03f9172cSAndroid Build Coastguard Worker 		       "starting accounting session %016llX",
237*03f9172cSAndroid Build Coastguard Worker 		       (unsigned long long) sta->acct_session_id);
238*03f9172cSAndroid Build Coastguard Worker 
239*03f9172cSAndroid Build Coastguard Worker 	os_get_reltime(&sta->acct_session_start);
240*03f9172cSAndroid Build Coastguard Worker 	sta->last_rx_bytes_hi = 0;
241*03f9172cSAndroid Build Coastguard Worker 	sta->last_rx_bytes_lo = 0;
242*03f9172cSAndroid Build Coastguard Worker 	sta->last_tx_bytes_hi = 0;
243*03f9172cSAndroid Build Coastguard Worker 	sta->last_tx_bytes_lo = 0;
244*03f9172cSAndroid Build Coastguard Worker 	hostapd_drv_sta_clear_stats(hapd, sta->addr);
245*03f9172cSAndroid Build Coastguard Worker 
246*03f9172cSAndroid Build Coastguard Worker 	if (!hapd->conf->radius->acct_server)
247*03f9172cSAndroid Build Coastguard Worker 		return;
248*03f9172cSAndroid Build Coastguard Worker 
249*03f9172cSAndroid Build Coastguard Worker 	if (sta->acct_interim_interval)
250*03f9172cSAndroid Build Coastguard Worker 		interval = sta->acct_interim_interval;
251*03f9172cSAndroid Build Coastguard Worker 	else
252*03f9172cSAndroid Build Coastguard Worker 		interval = ACCT_DEFAULT_UPDATE_INTERVAL;
253*03f9172cSAndroid Build Coastguard Worker 	eloop_register_timeout(interval, 0, accounting_interim_update,
254*03f9172cSAndroid Build Coastguard Worker 			       hapd, sta);
255*03f9172cSAndroid Build Coastguard Worker 
256*03f9172cSAndroid Build Coastguard Worker 	msg = accounting_msg(hapd, sta, RADIUS_ACCT_STATUS_TYPE_START);
257*03f9172cSAndroid Build Coastguard Worker 	if (msg &&
258*03f9172cSAndroid Build Coastguard Worker 	    radius_client_send(hapd->radius, msg, RADIUS_ACCT, sta->addr) < 0)
259*03f9172cSAndroid Build Coastguard Worker 		radius_msg_free(msg);
260*03f9172cSAndroid Build Coastguard Worker 
261*03f9172cSAndroid Build Coastguard Worker 	sta->acct_session_started = 1;
262*03f9172cSAndroid Build Coastguard Worker }
263*03f9172cSAndroid Build Coastguard Worker 
264*03f9172cSAndroid Build Coastguard Worker 
accounting_sta_report(struct hostapd_data * hapd,struct sta_info * sta,int stop)265*03f9172cSAndroid Build Coastguard Worker static void accounting_sta_report(struct hostapd_data *hapd,
266*03f9172cSAndroid Build Coastguard Worker 				  struct sta_info *sta, int stop)
267*03f9172cSAndroid Build Coastguard Worker {
268*03f9172cSAndroid Build Coastguard Worker 	struct radius_msg *msg;
269*03f9172cSAndroid Build Coastguard Worker 	int cause = sta->acct_terminate_cause;
270*03f9172cSAndroid Build Coastguard Worker 	struct hostap_sta_driver_data data;
271*03f9172cSAndroid Build Coastguard Worker 	struct os_reltime now_r, diff;
272*03f9172cSAndroid Build Coastguard Worker 	u64 bytes;
273*03f9172cSAndroid Build Coastguard Worker 
274*03f9172cSAndroid Build Coastguard Worker 	if (!hapd->conf->radius->acct_server)
275*03f9172cSAndroid Build Coastguard Worker 		return;
276*03f9172cSAndroid Build Coastguard Worker 
277*03f9172cSAndroid Build Coastguard Worker 	msg = accounting_msg(hapd, sta,
278*03f9172cSAndroid Build Coastguard Worker 			     stop ? RADIUS_ACCT_STATUS_TYPE_STOP :
279*03f9172cSAndroid Build Coastguard Worker 			     RADIUS_ACCT_STATUS_TYPE_INTERIM_UPDATE);
280*03f9172cSAndroid Build Coastguard Worker 	if (!msg) {
281*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_INFO, "Could not create RADIUS Accounting message");
282*03f9172cSAndroid Build Coastguard Worker 		return;
283*03f9172cSAndroid Build Coastguard Worker 	}
284*03f9172cSAndroid Build Coastguard Worker 
285*03f9172cSAndroid Build Coastguard Worker 	os_get_reltime(&now_r);
286*03f9172cSAndroid Build Coastguard Worker 	os_reltime_sub(&now_r, &sta->acct_session_start, &diff);
287*03f9172cSAndroid Build Coastguard Worker 	if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_SESSION_TIME,
288*03f9172cSAndroid Build Coastguard Worker 				       diff.sec)) {
289*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_INFO, "Could not add Acct-Session-Time");
290*03f9172cSAndroid Build Coastguard Worker 		goto fail;
291*03f9172cSAndroid Build Coastguard Worker 	}
292*03f9172cSAndroid Build Coastguard Worker 
293*03f9172cSAndroid Build Coastguard Worker 	if (accounting_sta_update_stats(hapd, sta, &data) == 0) {
294*03f9172cSAndroid Build Coastguard Worker 		if (!radius_msg_add_attr_int32(msg,
295*03f9172cSAndroid Build Coastguard Worker 					       RADIUS_ATTR_ACCT_INPUT_PACKETS,
296*03f9172cSAndroid Build Coastguard Worker 					       data.rx_packets)) {
297*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_INFO, "Could not add Acct-Input-Packets");
298*03f9172cSAndroid Build Coastguard Worker 			goto fail;
299*03f9172cSAndroid Build Coastguard Worker 		}
300*03f9172cSAndroid Build Coastguard Worker 		if (!radius_msg_add_attr_int32(msg,
301*03f9172cSAndroid Build Coastguard Worker 					       RADIUS_ATTR_ACCT_OUTPUT_PACKETS,
302*03f9172cSAndroid Build Coastguard Worker 					       data.tx_packets)) {
303*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_INFO, "Could not add Acct-Output-Packets");
304*03f9172cSAndroid Build Coastguard Worker 			goto fail;
305*03f9172cSAndroid Build Coastguard Worker 		}
306*03f9172cSAndroid Build Coastguard Worker 		if (data.bytes_64bit)
307*03f9172cSAndroid Build Coastguard Worker 			bytes = data.rx_bytes;
308*03f9172cSAndroid Build Coastguard Worker 		else
309*03f9172cSAndroid Build Coastguard Worker 			bytes = ((u64) sta->last_rx_bytes_hi << 32) |
310*03f9172cSAndroid Build Coastguard Worker 				sta->last_rx_bytes_lo;
311*03f9172cSAndroid Build Coastguard Worker 		if (!radius_msg_add_attr_int32(msg,
312*03f9172cSAndroid Build Coastguard Worker 					       RADIUS_ATTR_ACCT_INPUT_OCTETS,
313*03f9172cSAndroid Build Coastguard Worker 					       (u32) bytes)) {
314*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_INFO, "Could not add Acct-Input-Octets");
315*03f9172cSAndroid Build Coastguard Worker 			goto fail;
316*03f9172cSAndroid Build Coastguard Worker 		}
317*03f9172cSAndroid Build Coastguard Worker 		if (!radius_msg_add_attr_int32(msg,
318*03f9172cSAndroid Build Coastguard Worker 					       RADIUS_ATTR_ACCT_INPUT_GIGAWORDS,
319*03f9172cSAndroid Build Coastguard Worker 					       (u32) (bytes >> 32))) {
320*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_INFO, "Could not add Acct-Input-Gigawords");
321*03f9172cSAndroid Build Coastguard Worker 			goto fail;
322*03f9172cSAndroid Build Coastguard Worker 		}
323*03f9172cSAndroid Build Coastguard Worker 		if (data.bytes_64bit)
324*03f9172cSAndroid Build Coastguard Worker 			bytes = data.tx_bytes;
325*03f9172cSAndroid Build Coastguard Worker 		else
326*03f9172cSAndroid Build Coastguard Worker 			bytes = ((u64) sta->last_tx_bytes_hi << 32) |
327*03f9172cSAndroid Build Coastguard Worker 				sta->last_tx_bytes_lo;
328*03f9172cSAndroid Build Coastguard Worker 		if (!radius_msg_add_attr_int32(msg,
329*03f9172cSAndroid Build Coastguard Worker 					       RADIUS_ATTR_ACCT_OUTPUT_OCTETS,
330*03f9172cSAndroid Build Coastguard Worker 					       (u32) bytes)) {
331*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_INFO, "Could not add Acct-Output-Octets");
332*03f9172cSAndroid Build Coastguard Worker 			goto fail;
333*03f9172cSAndroid Build Coastguard Worker 		}
334*03f9172cSAndroid Build Coastguard Worker 		if (!radius_msg_add_attr_int32(msg,
335*03f9172cSAndroid Build Coastguard Worker 					       RADIUS_ATTR_ACCT_OUTPUT_GIGAWORDS,
336*03f9172cSAndroid Build Coastguard Worker 					       (u32) (bytes >> 32))) {
337*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_INFO, "Could not add Acct-Output-Gigawords");
338*03f9172cSAndroid Build Coastguard Worker 			goto fail;
339*03f9172cSAndroid Build Coastguard Worker 		}
340*03f9172cSAndroid Build Coastguard Worker 	}
341*03f9172cSAndroid Build Coastguard Worker 
342*03f9172cSAndroid Build Coastguard Worker 	if (eloop_terminated())
343*03f9172cSAndroid Build Coastguard Worker 		cause = RADIUS_ACCT_TERMINATE_CAUSE_ADMIN_REBOOT;
344*03f9172cSAndroid Build Coastguard Worker 
345*03f9172cSAndroid Build Coastguard Worker 	if (stop && cause &&
346*03f9172cSAndroid Build Coastguard Worker 	    !radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_TERMINATE_CAUSE,
347*03f9172cSAndroid Build Coastguard Worker 				       cause)) {
348*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_INFO, "Could not add Acct-Terminate-Cause");
349*03f9172cSAndroid Build Coastguard Worker 		goto fail;
350*03f9172cSAndroid Build Coastguard Worker 	}
351*03f9172cSAndroid Build Coastguard Worker 
352*03f9172cSAndroid Build Coastguard Worker 	if (radius_client_send(hapd->radius, msg,
353*03f9172cSAndroid Build Coastguard Worker 			       stop ? RADIUS_ACCT : RADIUS_ACCT_INTERIM,
354*03f9172cSAndroid Build Coastguard Worker 			       sta->addr) < 0)
355*03f9172cSAndroid Build Coastguard Worker 		goto fail;
356*03f9172cSAndroid Build Coastguard Worker 	return;
357*03f9172cSAndroid Build Coastguard Worker 
358*03f9172cSAndroid Build Coastguard Worker  fail:
359*03f9172cSAndroid Build Coastguard Worker 	radius_msg_free(msg);
360*03f9172cSAndroid Build Coastguard Worker }
361*03f9172cSAndroid Build Coastguard Worker 
362*03f9172cSAndroid Build Coastguard Worker 
363*03f9172cSAndroid Build Coastguard Worker /**
364*03f9172cSAndroid Build Coastguard Worker  * accounting_sta_interim - Send a interim STA accounting report
365*03f9172cSAndroid Build Coastguard Worker  * @hapd: hostapd BSS data
366*03f9172cSAndroid Build Coastguard Worker  * @sta: The station
367*03f9172cSAndroid Build Coastguard Worker  */
accounting_sta_interim(struct hostapd_data * hapd,struct sta_info * sta)368*03f9172cSAndroid Build Coastguard Worker static void accounting_sta_interim(struct hostapd_data *hapd,
369*03f9172cSAndroid Build Coastguard Worker 				   struct sta_info *sta)
370*03f9172cSAndroid Build Coastguard Worker {
371*03f9172cSAndroid Build Coastguard Worker 	if (sta->acct_session_started)
372*03f9172cSAndroid Build Coastguard Worker 		accounting_sta_report(hapd, sta, 0);
373*03f9172cSAndroid Build Coastguard Worker }
374*03f9172cSAndroid Build Coastguard Worker 
375*03f9172cSAndroid Build Coastguard Worker 
376*03f9172cSAndroid Build Coastguard Worker /**
377*03f9172cSAndroid Build Coastguard Worker  * accounting_sta_stop - Stop STA accounting
378*03f9172cSAndroid Build Coastguard Worker  * @hapd: hostapd BSS data
379*03f9172cSAndroid Build Coastguard Worker  * @sta: The station
380*03f9172cSAndroid Build Coastguard Worker  */
accounting_sta_stop(struct hostapd_data * hapd,struct sta_info * sta)381*03f9172cSAndroid Build Coastguard Worker void accounting_sta_stop(struct hostapd_data *hapd, struct sta_info *sta)
382*03f9172cSAndroid Build Coastguard Worker {
383*03f9172cSAndroid Build Coastguard Worker 	if (sta->acct_session_started) {
384*03f9172cSAndroid Build Coastguard Worker 		accounting_sta_report(hapd, sta, 1);
385*03f9172cSAndroid Build Coastguard Worker 		eloop_cancel_timeout(accounting_interim_update, hapd, sta);
386*03f9172cSAndroid Build Coastguard Worker 		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
387*03f9172cSAndroid Build Coastguard Worker 			       HOSTAPD_LEVEL_INFO,
388*03f9172cSAndroid Build Coastguard Worker 			       "stopped accounting session %016llX",
389*03f9172cSAndroid Build Coastguard Worker 			       (unsigned long long) sta->acct_session_id);
390*03f9172cSAndroid Build Coastguard Worker 		sta->acct_session_started = 0;
391*03f9172cSAndroid Build Coastguard Worker 	}
392*03f9172cSAndroid Build Coastguard Worker }
393*03f9172cSAndroid Build Coastguard Worker 
394*03f9172cSAndroid Build Coastguard Worker 
accounting_sta_get_id(struct hostapd_data * hapd,struct sta_info * sta)395*03f9172cSAndroid Build Coastguard Worker int accounting_sta_get_id(struct hostapd_data *hapd, struct sta_info *sta)
396*03f9172cSAndroid Build Coastguard Worker {
397*03f9172cSAndroid Build Coastguard Worker 	return radius_gen_session_id((u8 *) &sta->acct_session_id,
398*03f9172cSAndroid Build Coastguard Worker 				     sizeof(sta->acct_session_id));
399*03f9172cSAndroid Build Coastguard Worker }
400*03f9172cSAndroid Build Coastguard Worker 
401*03f9172cSAndroid Build Coastguard Worker 
402*03f9172cSAndroid Build Coastguard Worker /**
403*03f9172cSAndroid Build Coastguard Worker  * accounting_receive - Process the RADIUS frames from Accounting Server
404*03f9172cSAndroid Build Coastguard Worker  * @msg: RADIUS response message
405*03f9172cSAndroid Build Coastguard Worker  * @req: RADIUS request message
406*03f9172cSAndroid Build Coastguard Worker  * @shared_secret: RADIUS shared secret
407*03f9172cSAndroid Build Coastguard Worker  * @shared_secret_len: Length of shared_secret in octets
408*03f9172cSAndroid Build Coastguard Worker  * @data: Context data (struct hostapd_data *)
409*03f9172cSAndroid Build Coastguard Worker  * Returns: Processing status
410*03f9172cSAndroid Build Coastguard Worker  */
411*03f9172cSAndroid Build Coastguard Worker static RadiusRxResult
accounting_receive(struct radius_msg * msg,struct radius_msg * req,const u8 * shared_secret,size_t shared_secret_len,void * data)412*03f9172cSAndroid Build Coastguard Worker accounting_receive(struct radius_msg *msg, struct radius_msg *req,
413*03f9172cSAndroid Build Coastguard Worker 		   const u8 *shared_secret, size_t shared_secret_len,
414*03f9172cSAndroid Build Coastguard Worker 		   void *data)
415*03f9172cSAndroid Build Coastguard Worker {
416*03f9172cSAndroid Build Coastguard Worker 	if (radius_msg_get_hdr(msg)->code != RADIUS_CODE_ACCOUNTING_RESPONSE) {
417*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_INFO, "Unknown RADIUS message code");
418*03f9172cSAndroid Build Coastguard Worker 		return RADIUS_RX_UNKNOWN;
419*03f9172cSAndroid Build Coastguard Worker 	}
420*03f9172cSAndroid Build Coastguard Worker 
421*03f9172cSAndroid Build Coastguard Worker 	if (radius_msg_verify(msg, shared_secret, shared_secret_len, req, 0)) {
422*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_INFO, "Incoming RADIUS packet did not have correct Authenticator - dropped");
423*03f9172cSAndroid Build Coastguard Worker 		return RADIUS_RX_INVALID_AUTHENTICATOR;
424*03f9172cSAndroid Build Coastguard Worker 	}
425*03f9172cSAndroid Build Coastguard Worker 
426*03f9172cSAndroid Build Coastguard Worker 	return RADIUS_RX_PROCESSED;
427*03f9172cSAndroid Build Coastguard Worker }
428*03f9172cSAndroid Build Coastguard Worker 
429*03f9172cSAndroid Build Coastguard Worker 
accounting_report_state(struct hostapd_data * hapd,int on)430*03f9172cSAndroid Build Coastguard Worker static void accounting_report_state(struct hostapd_data *hapd, int on)
431*03f9172cSAndroid Build Coastguard Worker {
432*03f9172cSAndroid Build Coastguard Worker 	struct radius_msg *msg;
433*03f9172cSAndroid Build Coastguard Worker 
434*03f9172cSAndroid Build Coastguard Worker 	if (!hapd->conf->radius->acct_server || hapd->radius == NULL)
435*03f9172cSAndroid Build Coastguard Worker 		return;
436*03f9172cSAndroid Build Coastguard Worker 
437*03f9172cSAndroid Build Coastguard Worker 	/* Inform RADIUS server that accounting will start/stop so that the
438*03f9172cSAndroid Build Coastguard Worker 	 * server can close old accounting sessions. */
439*03f9172cSAndroid Build Coastguard Worker 	msg = accounting_msg(hapd, NULL,
440*03f9172cSAndroid Build Coastguard Worker 			     on ? RADIUS_ACCT_STATUS_TYPE_ACCOUNTING_ON :
441*03f9172cSAndroid Build Coastguard Worker 			     RADIUS_ACCT_STATUS_TYPE_ACCOUNTING_OFF);
442*03f9172cSAndroid Build Coastguard Worker 	if (!msg)
443*03f9172cSAndroid Build Coastguard Worker 		return;
444*03f9172cSAndroid Build Coastguard Worker 
445*03f9172cSAndroid Build Coastguard Worker 	if (hapd->acct_session_id) {
446*03f9172cSAndroid Build Coastguard Worker 		char buf[20];
447*03f9172cSAndroid Build Coastguard Worker 
448*03f9172cSAndroid Build Coastguard Worker 		os_snprintf(buf, sizeof(buf), "%016llX",
449*03f9172cSAndroid Build Coastguard Worker 			    (unsigned long long) hapd->acct_session_id);
450*03f9172cSAndroid Build Coastguard Worker 		if (!radius_msg_add_attr(msg, RADIUS_ATTR_ACCT_SESSION_ID,
451*03f9172cSAndroid Build Coastguard Worker 					 (u8 *) buf, os_strlen(buf)))
452*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_ERROR, "Could not add Acct-Session-Id");
453*03f9172cSAndroid Build Coastguard Worker 	}
454*03f9172cSAndroid Build Coastguard Worker 
455*03f9172cSAndroid Build Coastguard Worker 	if (radius_client_send(hapd->radius, msg, RADIUS_ACCT, NULL) < 0)
456*03f9172cSAndroid Build Coastguard Worker 		radius_msg_free(msg);
457*03f9172cSAndroid Build Coastguard Worker }
458*03f9172cSAndroid Build Coastguard Worker 
459*03f9172cSAndroid Build Coastguard Worker 
accounting_interim_error_cb(const u8 * addr,void * ctx)460*03f9172cSAndroid Build Coastguard Worker static void accounting_interim_error_cb(const u8 *addr, void *ctx)
461*03f9172cSAndroid Build Coastguard Worker {
462*03f9172cSAndroid Build Coastguard Worker 	struct hostapd_data *hapd = ctx;
463*03f9172cSAndroid Build Coastguard Worker 	struct sta_info *sta;
464*03f9172cSAndroid Build Coastguard Worker 	unsigned int i, wait_time;
465*03f9172cSAndroid Build Coastguard Worker 	int res;
466*03f9172cSAndroid Build Coastguard Worker 
467*03f9172cSAndroid Build Coastguard Worker 	sta = ap_get_sta(hapd, addr);
468*03f9172cSAndroid Build Coastguard Worker 	if (!sta)
469*03f9172cSAndroid Build Coastguard Worker 		return;
470*03f9172cSAndroid Build Coastguard Worker 	sta->acct_interim_errors++;
471*03f9172cSAndroid Build Coastguard Worker 	if (sta->acct_interim_errors > 10 /* RADIUS_CLIENT_MAX_RETRIES */) {
472*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_DEBUG,
473*03f9172cSAndroid Build Coastguard Worker 			   "Interim RADIUS accounting update failed for " MACSTR
474*03f9172cSAndroid Build Coastguard Worker 			   " - too many errors, abandon this interim accounting update",
475*03f9172cSAndroid Build Coastguard Worker 			   MAC2STR(addr));
476*03f9172cSAndroid Build Coastguard Worker 		sta->acct_interim_errors = 0;
477*03f9172cSAndroid Build Coastguard Worker 		/* Next update will be tried after normal update interval */
478*03f9172cSAndroid Build Coastguard Worker 		return;
479*03f9172cSAndroid Build Coastguard Worker 	}
480*03f9172cSAndroid Build Coastguard Worker 
481*03f9172cSAndroid Build Coastguard Worker 	/*
482*03f9172cSAndroid Build Coastguard Worker 	 * Use a shorter update interval as an improved retransmission mechanism
483*03f9172cSAndroid Build Coastguard Worker 	 * for failed interim accounting updates. This allows the statistics to
484*03f9172cSAndroid Build Coastguard Worker 	 * be updated for each retransmission.
485*03f9172cSAndroid Build Coastguard Worker 	 *
486*03f9172cSAndroid Build Coastguard Worker 	 * RADIUS client code has already waited RADIUS_CLIENT_FIRST_WAIT.
487*03f9172cSAndroid Build Coastguard Worker 	 * Schedule the first retry attempt immediately and every following one
488*03f9172cSAndroid Build Coastguard Worker 	 * with exponential backoff.
489*03f9172cSAndroid Build Coastguard Worker 	 */
490*03f9172cSAndroid Build Coastguard Worker 	if (sta->acct_interim_errors == 1) {
491*03f9172cSAndroid Build Coastguard Worker 		wait_time = 0;
492*03f9172cSAndroid Build Coastguard Worker 	} else {
493*03f9172cSAndroid Build Coastguard Worker 		wait_time = 3; /* RADIUS_CLIENT_FIRST_WAIT */
494*03f9172cSAndroid Build Coastguard Worker 		for (i = 1; i < sta->acct_interim_errors; i++)
495*03f9172cSAndroid Build Coastguard Worker 			wait_time *= 2;
496*03f9172cSAndroid Build Coastguard Worker 	}
497*03f9172cSAndroid Build Coastguard Worker 	res = eloop_deplete_timeout(wait_time, 0, accounting_interim_update,
498*03f9172cSAndroid Build Coastguard Worker 				    hapd, sta);
499*03f9172cSAndroid Build Coastguard Worker 	if (res == 1)
500*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_DEBUG,
501*03f9172cSAndroid Build Coastguard Worker 			   "Interim RADIUS accounting update failed for " MACSTR
502*03f9172cSAndroid Build Coastguard Worker 			   " (error count: %u) - schedule next update in %u seconds",
503*03f9172cSAndroid Build Coastguard Worker 			   MAC2STR(addr), sta->acct_interim_errors, wait_time);
504*03f9172cSAndroid Build Coastguard Worker 	else if (res == 0)
505*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_DEBUG,
506*03f9172cSAndroid Build Coastguard Worker 			   "Interim RADIUS accounting update failed for " MACSTR
507*03f9172cSAndroid Build Coastguard Worker 			   " (error count: %u)", MAC2STR(addr),
508*03f9172cSAndroid Build Coastguard Worker 			   sta->acct_interim_errors);
509*03f9172cSAndroid Build Coastguard Worker 	else
510*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_DEBUG,
511*03f9172cSAndroid Build Coastguard Worker 			   "Interim RADIUS accounting update failed for " MACSTR
512*03f9172cSAndroid Build Coastguard Worker 			   " (error count: %u) - no timer found", MAC2STR(addr),
513*03f9172cSAndroid Build Coastguard Worker 			   sta->acct_interim_errors);
514*03f9172cSAndroid Build Coastguard Worker }
515*03f9172cSAndroid Build Coastguard Worker 
516*03f9172cSAndroid Build Coastguard Worker 
517*03f9172cSAndroid Build Coastguard Worker /**
518*03f9172cSAndroid Build Coastguard Worker  * accounting_init: Initialize accounting
519*03f9172cSAndroid Build Coastguard Worker  * @hapd: hostapd BSS data
520*03f9172cSAndroid Build Coastguard Worker  * Returns: 0 on success, -1 on failure
521*03f9172cSAndroid Build Coastguard Worker  */
accounting_init(struct hostapd_data * hapd)522*03f9172cSAndroid Build Coastguard Worker int accounting_init(struct hostapd_data *hapd)
523*03f9172cSAndroid Build Coastguard Worker {
524*03f9172cSAndroid Build Coastguard Worker 	if (radius_gen_session_id((u8 *) &hapd->acct_session_id,
525*03f9172cSAndroid Build Coastguard Worker 				  sizeof(hapd->acct_session_id)) < 0)
526*03f9172cSAndroid Build Coastguard Worker 		return -1;
527*03f9172cSAndroid Build Coastguard Worker 
528*03f9172cSAndroid Build Coastguard Worker 	if (radius_client_register(hapd->radius, RADIUS_ACCT,
529*03f9172cSAndroid Build Coastguard Worker 				   accounting_receive, hapd))
530*03f9172cSAndroid Build Coastguard Worker 		return -1;
531*03f9172cSAndroid Build Coastguard Worker 	radius_client_set_interim_error_cb(hapd->radius,
532*03f9172cSAndroid Build Coastguard Worker 					   accounting_interim_error_cb, hapd);
533*03f9172cSAndroid Build Coastguard Worker 
534*03f9172cSAndroid Build Coastguard Worker 	accounting_report_state(hapd, 1);
535*03f9172cSAndroid Build Coastguard Worker 
536*03f9172cSAndroid Build Coastguard Worker 	return 0;
537*03f9172cSAndroid Build Coastguard Worker }
538*03f9172cSAndroid Build Coastguard Worker 
539*03f9172cSAndroid Build Coastguard Worker 
540*03f9172cSAndroid Build Coastguard Worker /**
541*03f9172cSAndroid Build Coastguard Worker  * accounting_deinit: Deinitialize accounting
542*03f9172cSAndroid Build Coastguard Worker  * @hapd: hostapd BSS data
543*03f9172cSAndroid Build Coastguard Worker  */
accounting_deinit(struct hostapd_data * hapd)544*03f9172cSAndroid Build Coastguard Worker void accounting_deinit(struct hostapd_data *hapd)
545*03f9172cSAndroid Build Coastguard Worker {
546*03f9172cSAndroid Build Coastguard Worker 	accounting_report_state(hapd, 0);
547*03f9172cSAndroid Build Coastguard Worker }
548