1 /*
2  * wpa_supplicant - Radio Measurements
3  * Copyright (c) 2003-2016, Jouni Malinen <j@w1.fi>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8 
9 #include "utils/includes.h"
10 
11 #include "utils/common.h"
12 #include "utils/bitfield.h"
13 #include "common/ieee802_11_defs.h"
14 #include "common/ieee802_11_common.h"
15 #include "wpa_supplicant_i.h"
16 #include "bss.h"
17 #include "rrm.h"
18 #include "scan.h"
19 #include <sys/errno.h>
20 #ifdef ESP_SUPPLICANT
21 #include "esp_common_i.h"
22 #endif
23 
wpas_rrm_neighbor_rep_timeout_handler(void * data,void * user_ctx)24 static void wpas_rrm_neighbor_rep_timeout_handler(void *data, void *user_ctx)
25 {
26 	struct rrm_data *rrm = data;
27 
28 	if (!rrm->notify_neighbor_rep) {
29 		wpa_printf(MSG_ERROR,
30 			   "RRM: Unexpected neighbor report timeout");
31 		return;
32 	}
33 
34 	wpa_printf(MSG_DEBUG, "RRM: Notifying neighbor report - NONE");
35 	rrm->notify_neighbor_rep(rrm->neighbor_rep_cb_ctx, NULL, 0);
36 
37 	rrm->notify_neighbor_rep = NULL;
38 	rrm->neighbor_rep_cb_ctx = NULL;
39 }
40 
41 
42 /*
43  * wpas_rrm_reset - Clear and reset all RRM data in wpa_supplicant
44  * @wpa_s: Pointer to wpa_supplicant
45  */
wpas_rrm_reset(struct wpa_supplicant * wpa_s)46 void wpas_rrm_reset(struct wpa_supplicant *wpa_s)
47 {
48 	wpa_s->rrm.rrm_used = 0;
49 
50 	eloop_cancel_timeout(wpas_rrm_neighbor_rep_timeout_handler, &wpa_s->rrm,
51 			     NULL);
52 	if (wpa_s->rrm.notify_neighbor_rep)
53 		wpas_rrm_neighbor_rep_timeout_handler(&wpa_s->rrm, NULL);
54 	wpa_s->rrm.next_neighbor_rep_token = 1;
55 	wpas_clear_beacon_rep_data(wpa_s);
56 }
57 
58 
59 /*
60  * wpas_rrm_process_neighbor_rep - Handle incoming neighbor report
61  * @wpa_s: Pointer to wpa_supplicant
62  * @report: Neighbor report buffer, prefixed by a 1-byte dialog token
63  * @report_len: Length of neighbor report buffer
64  */
wpas_rrm_process_neighbor_rep(struct wpa_supplicant * wpa_s,const u8 * report,size_t report_len)65 void wpas_rrm_process_neighbor_rep(struct wpa_supplicant *wpa_s,
66 				   const u8 *report, size_t report_len)
67 {
68 
69 	wpa_hexdump(MSG_DEBUG, "RRM: New Neighbor Report", report, report_len);
70 	if (report_len < 1)
71 		return;
72 
73 	if (report[0] != wpa_s->rrm.next_neighbor_rep_token - 1) {
74 		wpa_printf(MSG_DEBUG,
75 			   "RRM: Discarding neighbor report with token %d (expected %d)",
76 			   report[0], wpa_s->rrm.next_neighbor_rep_token - 1);
77 		return;
78 	}
79 
80 	eloop_cancel_timeout(wpas_rrm_neighbor_rep_timeout_handler, &wpa_s->rrm,
81 			     NULL);
82 
83 	if (!wpa_s->rrm.notify_neighbor_rep) {
84 		wpa_msg(wpa_s, MSG_INFO, "RRM: Unexpected neighbor report");
85 		return;
86 	}
87 
88 	wpa_printf(MSG_DEBUG, "RRM: Notifying neighbor report (token = %d)",
89 		report[0]);
90 	wpa_s->rrm.notify_neighbor_rep(wpa_s->rrm.neighbor_rep_cb_ctx,
91 				       report, report_len);
92 	wpa_s->rrm.notify_neighbor_rep = NULL;
93 	wpa_s->rrm.neighbor_rep_cb_ctx = NULL;
94 }
95 
96 
97 #if defined(__CYGWIN__) || defined(CONFIG_NATIVE_WINDOWS)
98 /* Workaround different, undefined for Windows, error codes used here */
99 #ifndef ENOTCONN
100 #define ENOTCONN -1
101 #endif
102 #ifndef EOPNOTSUPP
103 #define EOPNOTSUPP -1
104 #endif
105 #ifndef ECANCELED
106 #define ECANCELED -1
107 #endif
108 #endif
109 
110 /* Measurement Request element + Location Subject + Maximum Age subelement */
111 #define MEASURE_REQUEST_LCI_LEN (3 + 1 + 4)
112 /* Measurement Request element + Location Civic Request */
113 #define MEASURE_REQUEST_CIVIC_LEN (3 + 5)
114 
115 
116 /**
117  * wpas_rrm_send_neighbor_rep_request - Request a neighbor report from our AP
118  * @wpa_s: Pointer to wpa_supplicant
119  * @ssid: if not null, this is sent in the request. Otherwise, no SSID IE
120  *	  is sent in the request.
121  * @lci: if set, neighbor request will include LCI request
122  * @civic: if set, neighbor request will include civic location request
123  * @cb: Callback function to be called once the requested report arrives, or
124  *	timed out after RRM_NEIGHBOR_REPORT_TIMEOUT seconds.
125  *	In the former case, 'neighbor_rep' is a newly allocated wpabuf, and it's
126  *	the requester's responsibility to free it.
127  *	In the latter case NULL will be sent in 'neighbor_rep'.
128  * @cb_ctx: Context value to send the callback function
129  * Returns: 0 in case of success, negative error code otherwise
130  *
131  * In case there is a previous request which has not been answered yet, the
132  * new request fails. The caller may retry after RRM_NEIGHBOR_REPORT_TIMEOUT.
133  * Request must contain a callback function.
134  */
wpas_rrm_send_neighbor_rep_request(struct wpa_supplicant * wpa_s,const struct wpa_ssid_value * ssid,int lci,int civic,void (* cb)(void * ctx,const u8 * neighbor_rep,size_t len),void * cb_ctx)135 int wpas_rrm_send_neighbor_rep_request(struct wpa_supplicant *wpa_s,
136 				       const struct wpa_ssid_value *ssid,
137 				       int lci, int civic,
138 				       void (*cb)(void *ctx,
139 						  const u8 *neighbor_rep, size_t len),
140 				       void *cb_ctx)
141 {
142 	struct wpabuf *buf;
143 
144 	if (!(wpa_s->rrm_ie[0] & WLAN_RRM_CAPS_NEIGHBOR_REPORT)) {
145 		wpa_printf(MSG_ERROR,
146 			"RRM: No network support for Neighbor Report.");
147 		return -EOPNOTSUPP;
148 	}
149 
150 	/* Refuse if there's a live request */
151 	if (wpa_s->rrm.notify_neighbor_rep) {
152 		wpas_rrm_neighbor_rep_timeout_handler(&wpa_s->rrm, NULL);
153 #if 0
154 		wpa_dbg(wpa_s, MSG_DEBUG,
155 			"RRM: Currently handling previous Neighbor Report.");
156 		return -EBUSY;
157 #endif
158 	}
159 
160 	/* 3 = action category + action code + dialog token */
161 	buf = wpabuf_alloc(3 + (ssid ? 2 + ssid->ssid_len : 0) +
162 			   (lci ? 2 + MEASURE_REQUEST_LCI_LEN : 0) +
163 			   (civic ? 2 + MEASURE_REQUEST_CIVIC_LEN : 0));
164 	if (buf == NULL) {
165 		wpa_dbg(wpa_s, MSG_DEBUG,
166 			"RRM: Failed to allocate Neighbor Report Request");
167 		return -ENOMEM;
168 	}
169 
170 	wpa_dbg(wpa_s, MSG_DEBUG,
171 		"RRM: Neighbor report request (for %s), token=%d",
172 		(ssid ? wpa_ssid_txt(ssid->ssid, ssid->ssid_len) : ""),
173 		wpa_s->rrm.next_neighbor_rep_token);
174 
175 	wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
176 	wpabuf_put_u8(buf, WLAN_RRM_NEIGHBOR_REPORT_REQUEST);
177 	wpabuf_put_u8(buf, wpa_s->rrm.next_neighbor_rep_token);
178 	if (ssid) {
179 		wpabuf_put_u8(buf, WLAN_EID_SSID);
180 		wpabuf_put_u8(buf, ssid->ssid_len);
181 		wpabuf_put_data(buf, ssid->ssid, ssid->ssid_len);
182 	}
183 
184 	if (lci) {
185 		/* IEEE P802.11-REVmc/D5.0 9.4.2.21 */
186 		wpabuf_put_u8(buf, WLAN_EID_MEASURE_REQUEST);
187 		wpabuf_put_u8(buf, MEASURE_REQUEST_LCI_LEN);
188 
189 		/*
190 		 * Measurement token; nonzero number that is unique among the
191 		 * Measurement Request elements in a particular frame.
192 		 */
193 		wpabuf_put_u8(buf, 1); /* Measurement Token */
194 
195 		/*
196 		 * Parallel, Enable, Request, and Report bits are 0, Duration is
197 		 * reserved.
198 		 */
199 		wpabuf_put_u8(buf, 0); /* Measurement Request Mode */
200 		wpabuf_put_u8(buf, MEASURE_TYPE_LCI); /* Measurement Type */
201 
202 		/* IEEE P802.11-REVmc/D5.0 9.4.2.21.10 - LCI request */
203 		/* Location Subject */
204 		wpabuf_put_u8(buf, LOCATION_SUBJECT_REMOTE);
205 
206 		/* Optional Subelements */
207 		/*
208 		 * IEEE P802.11-REVmc/D5.0 Figure 9-170
209 		 * The Maximum Age subelement is required, otherwise the AP can
210 		 * send only data that was determined after receiving the
211 		 * request. Setting it here to unlimited age.
212 		 */
213 		wpabuf_put_u8(buf, LCI_REQ_SUBELEM_MAX_AGE);
214 		wpabuf_put_u8(buf, 2);
215 		wpabuf_put_le16(buf, 0xffff);
216 	}
217 
218 	if (civic) {
219 		/* IEEE P802.11-REVmc/D5.0 9.4.2.21 */
220 		wpabuf_put_u8(buf, WLAN_EID_MEASURE_REQUEST);
221 		wpabuf_put_u8(buf, MEASURE_REQUEST_CIVIC_LEN);
222 
223 		/*
224 		 * Measurement token; nonzero number that is unique among the
225 		 * Measurement Request elements in a particular frame.
226 		 */
227 		wpabuf_put_u8(buf, 2); /* Measurement Token */
228 
229 		/*
230 		 * Parallel, Enable, Request, and Report bits are 0, Duration is
231 		 * reserved.
232 		 */
233 		wpabuf_put_u8(buf, 0); /* Measurement Request Mode */
234 		/* Measurement Type */
235 		wpabuf_put_u8(buf, MEASURE_TYPE_LOCATION_CIVIC);
236 
237 		/* IEEE P802.11-REVmc/D5.0 9.4.2.21.14:
238 		 * Location Civic request */
239 		/* Location Subject */
240 		wpabuf_put_u8(buf, LOCATION_SUBJECT_REMOTE);
241 		wpabuf_put_u8(buf, 0); /* Civic Location Type: IETF RFC 4776 */
242 		/* Location Service Interval Units: Seconds */
243 		wpabuf_put_u8(buf, 0);
244 		/* Location Service Interval: 0 - Only one report is requested
245 		 */
246 		wpabuf_put_le16(buf, 0);
247 		/* No optional subelements */
248 	}
249 
250 	wpa_s->rrm.next_neighbor_rep_token++;
251 
252 	if (wpa_drv_send_action(wpa_s, 0, 0,
253 				wpabuf_head(buf), wpabuf_len(buf), 0) < 0) {
254 		wpa_dbg(wpa_s, MSG_DEBUG,
255 			"RRM: Failed to send Neighbor Report Request");
256 		wpabuf_free(buf);
257 		return -ECANCELED;
258 	}
259 
260 	wpa_s->rrm.neighbor_rep_cb_ctx = cb_ctx;
261 	wpa_s->rrm.notify_neighbor_rep = cb;
262 	eloop_register_timeout(RRM_NEIGHBOR_REPORT_TIMEOUT, 0,
263 			       wpas_rrm_neighbor_rep_timeout_handler,
264 			       &wpa_s->rrm, NULL);
265 
266 	wpabuf_free(buf);
267 	return 0;
268 }
269 
270 
wpas_rrm_report_elem(struct wpabuf ** buf,u8 token,u8 mode,u8 type,const u8 * data,size_t data_len)271 static int wpas_rrm_report_elem(struct wpabuf **buf, u8 token, u8 mode, u8 type,
272 				const u8 *data, size_t data_len)
273 {
274 	if (wpabuf_resize(buf, 5 + data_len))
275 		return -1;
276 
277 	wpabuf_put_u8(*buf, WLAN_EID_MEASURE_REPORT);
278 	wpabuf_put_u8(*buf, 3 + data_len);
279 	wpabuf_put_u8(*buf, token);
280 	wpabuf_put_u8(*buf, mode);
281 	wpabuf_put_u8(*buf, type);
282 
283 	if (data_len)
284 		wpabuf_put_data(*buf, data, data_len);
285 
286 	return 0;
287 }
288 
wpas_rrm_send_msr_report_mpdu(struct wpa_supplicant * wpa_s,const u8 * data,size_t len)289 static void wpas_rrm_send_msr_report_mpdu(struct wpa_supplicant *wpa_s,
290 					  const u8 *data, size_t len)
291 {
292 	struct wpabuf *report = wpabuf_alloc(len + 3);
293 
294 	if (!report)
295 		return;
296 
297 	wpabuf_put_u8(report, WLAN_ACTION_RADIO_MEASUREMENT);
298 	wpabuf_put_u8(report, WLAN_RRM_RADIO_MEASUREMENT_REPORT);
299 	wpabuf_put_u8(report, wpa_s->rrm.token);
300 
301 	wpabuf_put_data(report, data, len);
302 
303 	if (wpa_drv_send_action(wpa_s, 0, 0,
304 				wpabuf_head(report), wpabuf_len(report), 0)) {
305 		wpa_printf(MSG_ERROR,
306 			   "RRM: Radio measurement report failed: Sending Action frame failed");
307 	}
308 
309 	wpabuf_free(report);
310 }
311 
312 
wpas_rrm_beacon_rep_update_last_frame(u8 * pos,size_t len)313 static int wpas_rrm_beacon_rep_update_last_frame(u8 *pos, size_t len)
314 {
315 	struct rrm_measurement_report_element *msr_rep;
316 	u8 *end = pos + len;
317 	u8 *msr_rep_end;
318 	struct rrm_measurement_beacon_report *rep = NULL;
319 	u8 *subelem;
320 
321 	/* Find the last beacon report element */
322 	while (end - pos >= (int) sizeof(*msr_rep)) {
323 		msr_rep = (struct rrm_measurement_report_element *) pos;
324 		msr_rep_end = pos + msr_rep->len + 2;
325 
326 		if (msr_rep->eid != WLAN_EID_MEASURE_REPORT ||
327 		    msr_rep_end > end) {
328 			/* Should not happen. This indicates a bug. */
329 			wpa_printf(MSG_ERROR,
330 				   "RRM: non-measurement report element in measurement report frame");
331 			return -1;
332 		}
333 
334 		if (msr_rep->type == MEASURE_TYPE_BEACON)
335 			rep = (struct rrm_measurement_beacon_report *)
336 				msr_rep->variable;
337 
338 		pos += pos[1] + 2;
339 	}
340 
341 	if (!rep)
342 		return 0;
343 
344 	subelem = rep->variable;
345 	while (subelem + 2 < msr_rep_end &&
346 	       subelem[0] != WLAN_BEACON_REPORT_SUBELEM_LAST_INDICATION)
347 		subelem += 2 + subelem[1];
348 
349 	if (subelem + 2 < msr_rep_end &&
350 	    subelem[0] == WLAN_BEACON_REPORT_SUBELEM_LAST_INDICATION &&
351 	    subelem[1] == 1 &&
352 	    subelem + BEACON_REPORT_LAST_INDICATION_SUBELEM_LEN <= end)
353 		subelem[2] = 1;
354 
355 	return 0;
356 }
357 
358 
wpas_rrm_send_msr_report(struct wpa_supplicant * wpa_s,struct wpabuf * buf)359 static void wpas_rrm_send_msr_report(struct wpa_supplicant *wpa_s,
360 				     struct wpabuf *buf)
361 {
362 	int len = wpabuf_len(buf);
363 	u8 *pos = wpabuf_mhead_u8(buf), *next = pos;
364 
365 #define MPDU_REPORT_LEN (int) (IEEE80211_MAX_MMPDU_SIZE - IEEE80211_HDRLEN - 3)
366 
367 	while (len) {
368 		int send_len = (len > MPDU_REPORT_LEN) ? next - pos : len;
369 
370 		if (send_len == len)
371 			wpas_rrm_beacon_rep_update_last_frame(pos, len);
372 
373 		if (send_len == len ||
374 		    (send_len + next[1] + 2) > MPDU_REPORT_LEN) {
375 			wpas_rrm_send_msr_report_mpdu(wpa_s, pos, send_len);
376 			len -= send_len;
377 			pos = next;
378 		}
379 
380 		if (len)
381 			next += next[1] + 2;
382 	}
383 #undef MPDU_REPORT_LEN
384 }
385 
wpas_get_op_chan_phy(int channel,const u8 * ies,size_t ies_len,u8 * op_class,u8 * chan,u8 * phy_type)386 static int wpas_get_op_chan_phy(int channel, const u8 *ies, size_t ies_len,
387 				u8 *op_class, u8 *chan, u8 *phy_type)
388 {
389 	const u8 *ie;
390 	int sec_chan = 0;
391 	struct ieee80211_ht_operation *ht_oper = NULL;
392 
393 	ie = get_ie(ies, ies_len, WLAN_EID_HT_OPERATION);
394 	if (ie && ie[1] >= 2) {
395 		ht_oper = (struct ieee80211_ht_operation *) (ie + 2);
396 
397 		if (ht_oper->ht_param & HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE)
398 			sec_chan = 1;
399 		else if (ht_oper->ht_param &
400 			 HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW)
401 			sec_chan = -1;
402 	}
403 
404 	*op_class = get_operating_class(channel, sec_chan);
405 
406 	*phy_type = (sec_chan != 0) ? PHY_TYPE_HT : PHY_TYPE_ERP;
407 
408 	return 0;
409 }
410 
411 
wpas_beacon_rep_add_frame_body(struct bitfield * eids,enum beacon_report_detail detail,struct wpa_bss * bss,u8 * buf,size_t buf_len,u8 ** ies_buf,size_t * ie_len,int add_fixed)412 static int wpas_beacon_rep_add_frame_body(struct bitfield *eids,
413 					  enum beacon_report_detail detail,
414 					  struct wpa_bss *bss, u8 *buf,
415 					  size_t buf_len, u8 **ies_buf,
416 					  size_t *ie_len, int add_fixed)
417 {
418 	u8 *ies = *ies_buf;
419 	size_t ies_len = *ie_len;
420 	u8 *pos = buf;
421 	int rem_len;
422 
423 	rem_len = 255 - sizeof(struct rrm_measurement_beacon_report) -
424 		sizeof(struct rrm_measurement_report_element) - 2 -
425 		REPORTED_FRAME_BODY_SUBELEM_LEN;
426 
427 	if (detail > BEACON_REPORT_DETAIL_ALL_FIELDS_AND_ELEMENTS) {
428 		wpa_printf(MSG_DEBUG,
429 			   "Beacon Request: Invalid reporting detail: %d",
430 			   detail);
431 		return -1;
432 	}
433 
434 	if (detail == BEACON_REPORT_DETAIL_NONE)
435 		return 0;
436 
437 	/*
438 	 * Minimal frame body subelement size: EID(1) + length(1) + TSF(8) +
439 	 * beacon interval(2) + capabilities(2) = 14 bytes
440 	 */
441 	if (add_fixed && buf_len < 14)
442 		return -1;
443 
444 	*pos++ = WLAN_BEACON_REPORT_SUBELEM_FRAME_BODY;
445 	/* The length will be filled later */
446 	pos++;
447 
448 	if (add_fixed) {
449 		WPA_PUT_LE64(pos, bss->tsf);
450 		pos += sizeof(bss->tsf);
451 		WPA_PUT_LE16(pos, bss->beacon_int);
452 		pos += 2;
453 		WPA_PUT_LE16(pos, bss->caps);
454 		pos += 2;
455 	}
456 
457 	rem_len -= pos - buf;
458 
459 	/*
460 	 * According to IEEE Std 802.11-2016, 9.4.2.22.7, if the reported frame
461 	 * body subelement causes the element to exceed the maximum element
462 	 * size, the subelement is truncated so that the last IE is a complete
463 	 * IE. So even when required to report all IEs, add elements one after
464 	 * the other and stop once there is no more room in the measurement
465 	 * element.
466 	 */
467 	while (ies_len > 2 && 2U + ies[1] <= ies_len && rem_len > 0) {
468 		if (detail == BEACON_REPORT_DETAIL_ALL_FIELDS_AND_ELEMENTS ||
469 		    (eids && bitfield_is_set(eids, ies[0]))) {
470 			u8 elen = ies[1];
471 
472 			if (2 + elen > buf + buf_len - pos ||
473 			    2 + elen > rem_len)
474 				break;
475 
476 			*pos++ = ies[0];
477 			*pos++ = elen;
478 			os_memcpy(pos, ies + 2, elen);
479 			pos += elen;
480 			rem_len -= 2 + elen;
481 		}
482 
483 		ies_len -= 2 + ies[1];
484 		ies += 2 + ies[1];
485 	}
486 
487 	*ie_len = ies_len;
488 	*ies_buf = ies;
489 
490 	/* Now the length is known */
491 	buf[1] = pos - buf - 2;
492 	return pos - buf;
493 }
494 
495 
wpas_add_beacon_rep_elem(struct beacon_rep_data * data,struct wpa_bss * bss,struct wpabuf ** wpa_buf,struct rrm_measurement_beacon_report * rep,u8 ** ie,size_t * ie_len,u8 idx)496 static int wpas_add_beacon_rep_elem(struct beacon_rep_data *data,
497 				    struct wpa_bss *bss,
498 				    struct wpabuf **wpa_buf,
499 				    struct rrm_measurement_beacon_report *rep,
500 				    u8 **ie, size_t *ie_len, u8 idx)
501 {
502 	int ret;
503 	u8 *buf, *pos;
504 	u32 subelems_len = REPORTED_FRAME_BODY_SUBELEM_LEN +
505 		(data->last_indication ?
506 		 BEACON_REPORT_LAST_INDICATION_SUBELEM_LEN : 0);
507 
508 	/* Maximum element length: Beacon Report element + Reported Frame Body
509 	 * subelement + all IEs of the reported Beacon frame + Reported Frame
510 	 * Body Fragment ID subelement */
511 	buf = os_malloc(sizeof(*rep) + 14 + *ie_len + subelems_len);
512 	if (!buf)
513 		return -1;
514 
515 	os_memcpy(buf, rep, sizeof(*rep));
516 
517 	ret = wpas_beacon_rep_add_frame_body(data->eids, data->report_detail,
518 					     bss, buf + sizeof(*rep),
519 					     14 + *ie_len, ie, ie_len,
520 					     idx == 0);
521 	if (ret < 0)
522 		goto out;
523 
524 	pos = buf + ret + sizeof(*rep);
525 	pos[0] = WLAN_BEACON_REPORT_SUBELEM_FRAME_BODY_FRAGMENT_ID;
526 	pos[1] = 2;
527 
528 	/*
529 	 * Only one Beacon Report Measurement is supported at a time, so
530 	 * the Beacon Report ID can always be set to 1.
531 	 */
532 	pos[2] = 1;
533 
534 	/* Fragment ID Number (bits 0..6) and More Frame Body Fragments (bit 7)
535  */
536 	pos[3] = idx;
537 	if (data->report_detail != BEACON_REPORT_DETAIL_NONE && *ie_len)
538 		pos[3] |= REPORTED_FRAME_BODY_MORE_FRAGMENTS;
539 	else
540 		pos[3] &= ~REPORTED_FRAME_BODY_MORE_FRAGMENTS;
541 
542 	pos += REPORTED_FRAME_BODY_SUBELEM_LEN;
543 
544 	if (data->last_indication) {
545 		pos[0] = WLAN_BEACON_REPORT_SUBELEM_LAST_INDICATION;
546 		pos[1] = 1;
547 
548 		/* This field will be updated later if this is the last frame */
549 		pos[2] = 0;
550 	}
551 
552 	ret = wpas_rrm_report_elem(wpa_buf, data->token,
553 				   MEASUREMENT_REPORT_MODE_ACCEPT,
554 				   MEASURE_TYPE_BEACON, buf,
555 				   ret + sizeof(*rep) + subelems_len);
556 out:
557 	os_free(buf);
558 	return ret;
559 }
560 
561 
wpas_add_beacon_rep(struct wpa_supplicant * wpa_s,struct wpabuf ** wpa_buf,struct wpa_bss * bss,u64 start,u64 parent_tsf)562 static int wpas_add_beacon_rep(struct wpa_supplicant *wpa_s,
563 			       struct wpabuf **wpa_buf, struct wpa_bss *bss,
564 			       u64 start, u64 parent_tsf)
565 {
566 	struct beacon_rep_data *data = &wpa_s->beacon_rep_data;
567 	u8 *ies = (u8 *) (bss + 1);
568 	u8 *pos = ies;
569 	size_t ies_len = bss->ie_len ? bss->ie_len : bss->beacon_ie_len;
570 	struct rrm_measurement_beacon_report rep;
571 	u8 idx = 0;
572 
573 	if (os_memcmp(data->bssid, broadcast_ether_addr, ETH_ALEN) != 0 &&
574 	    os_memcmp(data->bssid, bss->bssid, ETH_ALEN) != 0)
575 		return 0;
576 
577 	if (data->ssid_len &&
578 	    (data->ssid_len != bss->ssid_len ||
579 	     os_memcmp(data->ssid, bss->ssid, bss->ssid_len) != 0))
580 		return 0;
581 
582 	if (wpas_get_op_chan_phy(bss->channel, ies, ies_len, &rep.op_class,
583 				 &rep.channel, &rep.report_info) < 0)
584 		return 0;
585 
586 	rep.channel = bss->channel;
587 	rep.start_time = host_to_le64(start);
588 	rep.duration = host_to_le16(data->scan_params.duration);
589 	rep.rcpi = rssi_to_rcpi(bss->level);
590 	rep.rsni = 255; /* 255 indicates that RSNI is not available */
591 	os_memcpy(rep.bssid, bss->bssid, ETH_ALEN);
592 	rep.antenna_id = 0; /* unknown */
593 	rep.parent_tsf = host_to_le32(parent_tsf);
594 
595 	do {
596 		int ret;
597 
598 		ret = wpas_add_beacon_rep_elem(data, bss, wpa_buf, &rep,
599 					       &pos, &ies_len, idx++);
600 		if (ret)
601 			return ret;
602 	} while (data->report_detail != BEACON_REPORT_DETAIL_NONE &&
603 		 ies_len >= 2);
604 
605 	return 0;
606 }
607 
608 
wpas_beacon_rep_no_results(struct wpa_supplicant * wpa_s,struct wpabuf ** buf)609 static int wpas_beacon_rep_no_results(struct wpa_supplicant *wpa_s,
610 				      struct wpabuf **buf)
611 {
612 	return wpas_rrm_report_elem(buf, wpa_s->beacon_rep_data.token,
613 				    MEASUREMENT_REPORT_MODE_ACCEPT,
614 				    MEASURE_TYPE_BEACON, NULL, 0);
615 }
616 
617 
wpas_beacon_rep_table(struct wpa_supplicant * wpa_s,struct wpabuf ** buf)618 static void wpas_beacon_rep_table(struct wpa_supplicant *wpa_s,
619 				  struct wpabuf **buf)
620 {
621 	size_t i;
622 
623 	for (i = 0; i < wpa_s->last_scan_res_used; i++) {
624 		if (wpas_add_beacon_rep(wpa_s, buf, wpa_s->last_scan_res[i],
625 					0, 0) < 0)
626 			break;
627 	}
628 
629 	if (!(*buf))
630 		wpas_beacon_rep_no_results(wpa_s, buf);
631 
632 	wpa_hexdump_buf(MSG_DEBUG, "RRM: Radio Measurement report", *buf);
633 }
634 
635 
wpas_rrm_refuse_request(struct wpa_supplicant * wpa_s)636 static void wpas_rrm_refuse_request(struct wpa_supplicant *wpa_s)
637 {
638 	if (!is_multicast_ether_addr(wpa_s->rrm.dst_addr)) {
639 		struct wpabuf *buf = NULL;
640 
641 		if (wpas_rrm_report_elem(&buf, wpa_s->beacon_rep_data.token,
642 					 MEASUREMENT_REPORT_MODE_REJECT_REFUSED,
643 					 MEASURE_TYPE_BEACON, NULL, 0)) {
644 			wpa_printf(MSG_ERROR, "RRM: Memory allocation failed");
645 			wpabuf_free(buf);
646 			return;
647 		}
648 
649 		wpas_rrm_send_msr_report(wpa_s, buf);
650 		wpabuf_free(buf);
651 	}
652 
653 	wpas_clear_beacon_rep_data(wpa_s);
654 }
655 
656 
wpas_rrm_scan_timeout(void * eloop_ctx,void * timeout_ctx)657 static void wpas_rrm_scan_timeout(void *eloop_ctx, void *timeout_ctx)
658 {
659 	struct wpa_supplicant *wpa_s = eloop_ctx;
660 	struct wpa_driver_scan_params *params =
661 		&wpa_s->beacon_rep_data.scan_params;
662 	u16 prev_duration = params->duration;
663 
664 	if (!wpa_s->current_bss)
665 		return;
666 
667 	os_get_reltime(&wpa_s->beacon_rep_scan);
668 	wpa_s->scan_reason = REASON_RRM_BEACON_REPORT;
669 	if (wpa_supplicant_trigger_scan(wpa_s, params) < 0)
670 		wpas_rrm_refuse_request(wpa_s);
671 	params->duration = prev_duration;
672 }
673 
674 
wpas_rm_handle_beacon_req_subelem(struct wpa_supplicant * wpa_s,struct beacon_rep_data * data,u8 sid,u8 slen,const u8 * subelem)675 static int wpas_rm_handle_beacon_req_subelem(struct wpa_supplicant *wpa_s,
676 					     struct beacon_rep_data *data,
677 					     u8 sid, u8 slen, const u8 *subelem)
678 {
679 	u8 report_info, i;
680 
681 	switch (sid) {
682 	case WLAN_BEACON_REQUEST_SUBELEM_SSID:
683 		if (!slen) {
684 			wpa_printf(MSG_DEBUG,
685 				   "SSID subelement with zero length - wildcard SSID");
686 			break;
687 		}
688 
689 		if (slen > SSID_MAX_LEN) {
690 			wpa_printf(MSG_DEBUG,
691 				   "Invalid SSID subelement length: %u", slen);
692 			return -1;
693 		}
694 
695 		data->ssid_len = slen;
696 		os_memcpy(data->ssid, subelem, data->ssid_len);
697 		break;
698 	case WLAN_BEACON_REQUEST_SUBELEM_INFO:
699 		if (slen != 2) {
700 			wpa_printf(MSG_DEBUG,
701 				   "Invalid reporting information subelement length: %u",
702 				   slen);
703 			return -1;
704 		}
705 
706 		report_info = subelem[0];
707 		if (report_info != 0) {
708 			wpa_printf(MSG_DEBUG,
709 				   "reporting information=%u is not supported",
710 				   report_info);
711 			return 0;
712 		}
713 		break;
714 	case WLAN_BEACON_REQUEST_SUBELEM_DETAIL:
715 		if (slen != 1) {
716 			wpa_printf(MSG_DEBUG,
717 				   "Invalid reporting detail subelement length: %u",
718 				   slen);
719 			return -1;
720 		}
721 
722 		data->report_detail = subelem[0];
723 		if (data->report_detail >
724 		    BEACON_REPORT_DETAIL_ALL_FIELDS_AND_ELEMENTS) {
725 			wpa_printf(MSG_DEBUG, "Invalid reporting detail: %u",
726 				   subelem[0]);
727 			return -1;
728 		}
729 
730 		break;
731 	case WLAN_BEACON_REQUEST_SUBELEM_REQUEST:
732 		if (data->report_detail !=
733 		    BEACON_REPORT_DETAIL_REQUESTED_ONLY) {
734 			wpa_printf(MSG_DEBUG,
735 				   "Beacon request: request subelement is present but report detail is %u",
736 				   data->report_detail);
737 			return -1;
738 		}
739 
740 		if (!slen) {
741 			wpa_printf(MSG_DEBUG,
742 				   "Invalid request subelement length: %u",
743 				   slen);
744 			return -1;
745 		}
746 
747 		if (data->eids) {
748 			wpa_printf(MSG_DEBUG,
749 				   "Beacon Request: Request subelement appears more than once");
750 			return -1;
751 		}
752 
753 		data->eids = bitfield_alloc(255);
754 		if (!data->eids) {
755 			wpa_printf(MSG_DEBUG, "Failed to allocate EIDs bitmap");
756 			return -1;
757 		}
758 
759 		for (i = 0; i < slen; i++)
760 			bitfield_set(data->eids, subelem[i]);
761 		break;
762 	case WLAN_BEACON_REQUEST_SUBELEM_AP_CHANNEL:
763 		/* Skip - it will be processed when freqs are added */
764 		break;
765 	case WLAN_BEACON_REQUEST_SUBELEM_LAST_INDICATION:
766 		if (slen != 1) {
767 			wpa_printf(MSG_DEBUG,
768 				   "Beacon request: Invalid last indication request subelement length: %u",
769 				   slen);
770 			return -1;
771 		}
772 
773 		data->last_indication = subelem[0];
774 		break;
775 	default:
776 		wpa_printf(MSG_DEBUG,
777 			   "Beacon request: Unknown subelement id %u", sid);
778 		break;
779 	}
780 
781 	return 1;
782 }
783 
784 
785 /**
786  * Returns 0 if the next element can be processed, 1 if some operation was
787  * triggered, and -1 if processing failed (i.e., the element is in invalid
788  * format or an internal error occurred).
789  */
790 static int
wpas_rm_handle_beacon_req(struct wpa_supplicant * wpa_s,u8 elem_token,int duration_mandatory,const struct rrm_measurement_beacon_request * req,size_t len,struct wpabuf ** buf)791 wpas_rm_handle_beacon_req(struct wpa_supplicant *wpa_s,
792 			  u8 elem_token, int duration_mandatory,
793 			  const struct rrm_measurement_beacon_request *req,
794 			  size_t len, struct wpabuf **buf)
795 {
796 	struct beacon_rep_data *data = &wpa_s->beacon_rep_data;
797 	struct wpa_driver_scan_params *params = &data->scan_params;
798 	const u8 *subelems;
799 	size_t elems_len;
800 	u16 rand_interval;
801 	u32 interval_usec;
802 	u32 _rand;
803 	int ret = 0, res;
804 	u8 reject_mode;
805 
806 	if (len < sizeof(*req))
807 		return -1;
808 
809 	if (req->mode != BEACON_REPORT_MODE_PASSIVE &&
810 	    req->mode != BEACON_REPORT_MODE_ACTIVE &&
811 	    req->mode != BEACON_REPORT_MODE_TABLE)
812 		return 0;
813 
814 	subelems = req->variable;
815 	elems_len = len - sizeof(*req);
816 	rand_interval = le_to_host16(req->rand_interval);
817 
818 	os_memset(data, 0, sizeof(*data));
819 
820 	data->token = elem_token;
821 
822 	/* default reporting detail is all fixed length fields and all
823 	 * elements */
824 	data->report_detail = BEACON_REPORT_DETAIL_ALL_FIELDS_AND_ELEMENTS;
825 	os_memcpy(data->bssid, req->bssid, ETH_ALEN);
826 
827 	while (elems_len >= 2) {
828 		if (subelems[1] > elems_len - 2) {
829 			wpa_printf(MSG_DEBUG,
830 				   "Beacon Request: Truncated subelement");
831 			ret = -1;
832 			goto out;
833 		}
834 
835 		res = wpas_rm_handle_beacon_req_subelem(
836 			wpa_s, data, subelems[0], subelems[1], &subelems[2]);
837 		if (res < 0) {
838 			ret = res;
839 			goto out;
840 		} else if (!res) {
841 			reject_mode = MEASUREMENT_REPORT_MODE_REJECT_INCAPABLE;
842 			goto out_reject;
843 		}
844 
845 		elems_len -= 2 + subelems[1];
846 		subelems += 2 + subelems[1];
847 	}
848 
849 	if (req->mode == BEACON_REPORT_MODE_TABLE) {
850 		wpas_beacon_rep_table(wpa_s, buf);
851 		goto out;
852 	}
853 	params->channel = req->channel;
854 #ifdef ESP_SUPPLICANT
855 	if (params->channel == 0xff) {
856 		/* set it to zero */
857 		params->channel = 0;
858 	}
859 #endif
860 	params->duration = le_to_host16(req->duration);
861 	params->duration_mandatory = duration_mandatory;
862 	params->mode = req->mode;
863 	if (!params->duration) {
864 		wpa_printf(MSG_DEBUG, "Beacon request: Duration is 0");
865 		ret = -1;
866 		goto out;
867 	}
868 
869 	if (data->ssid_len) {
870 		params->ssids[params->num_ssids].ssid = data->ssid;
871 		params->ssids[params->num_ssids++].ssid_len = data->ssid_len;
872 	}
873 
874 	if (os_get_random((u8 *) &_rand, sizeof(_rand)) < 0)
875 		_rand = os_random();
876 	interval_usec = (_rand % (rand_interval + 1)) * 1024;
877 	os_sleep(0, interval_usec);
878 	wpas_rrm_scan_timeout(wpa_s, NULL);
879 	return 1;
880 out_reject:
881 	if (!is_multicast_ether_addr(wpa_s->rrm.dst_addr) &&
882 	    wpas_rrm_report_elem(buf, elem_token, reject_mode,
883 				 MEASURE_TYPE_BEACON, NULL, 0) < 0) {
884 		wpa_printf(MSG_DEBUG, "RRM: Failed to add report element");
885 		ret = -1;
886 	}
887 out:
888 	wpas_clear_beacon_rep_data(wpa_s);
889 	return ret;
890 }
891 
892 
893 static int
wpas_rrm_handle_msr_req_element(struct wpa_supplicant * wpa_s,const struct rrm_measurement_request_element * req,struct wpabuf ** buf)894 wpas_rrm_handle_msr_req_element(
895 	struct wpa_supplicant *wpa_s,
896 	const struct rrm_measurement_request_element *req,
897 	struct wpabuf **buf)
898 {
899 	int duration_mandatory;
900 
901 	wpa_printf(MSG_DEBUG, "Measurement request type %d token %d",
902 		   req->type, req->token);
903 
904 	if (req->mode & MEASUREMENT_REQUEST_MODE_ENABLE) {
905 		/* Enable bit is not supported for now */
906 		wpa_printf(MSG_DEBUG, "RRM: Enable bit not supported, ignore");
907 		return 0;
908 	}
909 
910 	if ((req->mode & MEASUREMENT_REQUEST_MODE_PARALLEL) &&
911 	    req->type > MEASURE_TYPE_RPI_HIST) {
912 		/* Parallel measurements are not supported for now */
913 		wpa_printf(MSG_DEBUG,
914 			   "RRM: Parallel measurements are not supported, reject");
915 		goto reject;
916 	}
917 
918 	duration_mandatory =
919 		!!(req->mode & MEASUREMENT_REQUEST_MODE_DURATION_MANDATORY);
920 
921 	switch (req->type) {
922 	case MEASURE_TYPE_BEACON:
923 		return wpas_rm_handle_beacon_req(wpa_s, req->token,
924 						 duration_mandatory,
925 						 (const void *) req->variable,
926 						 req->len - 3, buf);
927 	default:
928 		wpa_printf(MSG_INFO,
929 			   "RRM: Unsupported radio measurement type %u",
930 			   req->type);
931 		break;
932 	}
933 
934 reject:
935 	if (!is_multicast_ether_addr(wpa_s->rrm.dst_addr) &&
936 	    wpas_rrm_report_elem(buf, req->token,
937 				 MEASUREMENT_REPORT_MODE_REJECT_INCAPABLE,
938 				 req->type, NULL, 0) < 0) {
939 		wpa_printf(MSG_DEBUG, "RRM: Failed to add report element");
940 		return -1;
941 	}
942 
943 	return 0;
944 }
945 
946 
947 static struct wpabuf *
wpas_rrm_process_msr_req_elems(struct wpa_supplicant * wpa_s,const u8 * pos,size_t len)948 wpas_rrm_process_msr_req_elems(struct wpa_supplicant *wpa_s, const u8 *pos,
949 			       size_t len)
950 {
951 	struct wpabuf *buf = NULL;
952 
953 	while (len) {
954 		const struct rrm_measurement_request_element *req;
955 		int res;
956 
957 		if (len < 2) {
958 			wpa_printf(MSG_DEBUG, "RRM: Truncated element");
959 			goto out;
960 		}
961 
962 		req = (const struct rrm_measurement_request_element *) pos;
963 		if (req->eid != WLAN_EID_MEASURE_REQUEST) {
964 			wpa_printf(MSG_DEBUG,
965 				   "RRM: Expected Measurement Request element, but EID is %u",
966 				   req->eid);
967 			printf("len is %d", len);
968 			goto out;
969 		}
970 
971 		if (req->len < 3) {
972 			wpa_printf(MSG_DEBUG, "RRM: Element length too short");
973 			goto out;
974 		}
975 
976 		if (req->len > len - 2) {
977 			wpa_printf(MSG_DEBUG, "RRM: Element length too long");
978 			goto out;
979 		}
980 
981 		res = wpas_rrm_handle_msr_req_element(wpa_s, req, &buf);
982 		if (res < 0)
983 			goto out;
984 
985 		pos += req->len + 2;
986 		len -= req->len + 2;
987 	}
988 
989 	return buf;
990 
991 out:
992 	wpabuf_free(buf);
993 	return NULL;
994 }
995 
996 
wpas_rrm_handle_radio_measurement_request(struct wpa_supplicant * wpa_s,const u8 * src,const u8 * dst,const u8 * frame,size_t len)997 void wpas_rrm_handle_radio_measurement_request(struct wpa_supplicant *wpa_s,
998 					       const u8 *src, const u8 *dst,
999 					       const u8 *frame, size_t len)
1000 {
1001 	struct wpabuf *report;
1002 
1003 	if (!wpa_s->rrm.rrm_used) {
1004 		wpa_printf(MSG_INFO,
1005 			   "RRM: Ignoring radio measurement request: Not RRM network");
1006 		return;
1007 	}
1008 
1009 	if (len < 3) {
1010 		wpa_printf(MSG_INFO,
1011 			   "RRM: Ignoring too short radio measurement request");
1012 		return;
1013 	}
1014 
1015 	wpa_s->rrm.token = *frame;
1016 	os_memcpy(wpa_s->rrm.dst_addr, dst, ETH_ALEN);
1017 
1018 	/* Number of repetitions is not supported */
1019 
1020 	report = wpas_rrm_process_msr_req_elems(wpa_s, frame + 3, len - 3);
1021 	if (!report)
1022 		return;
1023 
1024 	wpas_rrm_send_msr_report(wpa_s, report);
1025 	wpabuf_free(report);
1026 }
1027 
1028 
wpas_rrm_handle_link_measurement_request(struct wpa_supplicant * wpa_s,const u8 * src,const u8 * frame,size_t len,int rssi)1029 void wpas_rrm_handle_link_measurement_request(struct wpa_supplicant *wpa_s,
1030 					      const u8 *src,
1031 					      const u8 *frame, size_t len,
1032 					      int rssi)
1033 {
1034 	struct wpabuf *buf;
1035 	const struct rrm_link_measurement_request *req;
1036 	struct rrm_link_measurement_report report;
1037 
1038 	req = (const struct rrm_link_measurement_request *) frame;
1039 	if (len < sizeof(*req)) {
1040 		wpa_printf(MSG_INFO,
1041 			   "RRM: Link measurement report failed. Request too short");
1042 		return;
1043 	}
1044 
1045 	os_memset(&report, 0, sizeof(report));
1046 	report.dialog_token = req->dialog_token;
1047 	report.tpc.eid = WLAN_EID_TPC_REPORT;
1048 	report.tpc.len = 2;
1049 	/* Note: The driver is expected to update report.tpc.tx_power and
1050 	 * report.tpc.link_margin subfields when sending out this frame.
1051 	 * Similarly, the driver would need to update report.rx_ant_id and
1052 	 * report.tx_ant_id subfields. */
1053 
1054 #ifdef ESP_SUPPLICANT
1055 	esp_get_tx_power(&report.tpc.tx_power);
1056 	/* Minimum RSSI = -96 dbm */
1057 	report.tpc.link_margin = rssi + 96;
1058 #endif
1059 	report.rsni = 255; /* 255 indicates that RSNI is not available */
1060 	report.rcpi = rssi_to_rcpi(rssi);
1061 
1062 	/* action_category + action_code */
1063 	buf = wpabuf_alloc(2 + sizeof(report));
1064 	if (buf == NULL) {
1065 		wpa_printf(MSG_ERROR,
1066 			   "RRM: Link measurement report failed. Buffer allocation failed");
1067 		return;
1068 	}
1069 
1070 	wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
1071 	wpabuf_put_u8(buf, WLAN_RRM_LINK_MEASUREMENT_REPORT);
1072 	wpabuf_put_data(buf, &report, sizeof(report));
1073 	wpa_hexdump_buf(MSG_DEBUG, "RRM: Link measurement report", buf);
1074 
1075 	if (wpa_drv_send_action(wpa_s, 0, 0,
1076 				wpabuf_head(buf), wpabuf_len(buf), 0)) {
1077 		wpa_printf(MSG_ERROR,
1078 			   "RRM: Link measurement report failed. Send action failed");
1079 	}
1080 	wpabuf_free(buf);
1081 }
1082 
1083 
wpas_beacon_rep_scan_process(struct wpa_supplicant * wpa_s,u64 scan_start_tsf)1084 int wpas_beacon_rep_scan_process(struct wpa_supplicant *wpa_s,
1085 				 u64 scan_start_tsf)
1086 {
1087 	size_t i = 0;
1088 	struct wpabuf *buf = NULL;
1089 	struct wpa_bss *bss = NULL;
1090 
1091 	if (!wpa_s->beacon_rep_data.token)
1092 		return 0;
1093 
1094 	if (!wpa_s->current_bss)
1095 		goto out;
1096 
1097 	wpa_printf(MSG_DEBUG, "RRM: TSF  current BSS: " MACSTR,
1098 		   MAC2STR(wpa_s->current_bss->bssid));
1099 
1100 	for (i = 0; i < wpa_s->num_bss; i++) {
1101 		bss = wpa_bss_get_next_bss(wpa_s, bss);
1102 
1103 		if (!bss)
1104 			continue;
1105 
1106 		if (wpa_s->beacon_rep_data.scan_params.channel &&
1107 				bss->channel != wpa_s->beacon_rep_data.scan_params.channel)
1108 			continue;
1109 		/* We flush scan results before issuing scan again */
1110 #ifndef ESP_SUPPLICANT
1111 		/*
1112 		 * Don't report results that were not received during the
1113 		 * current measurement.
1114 		 */
1115 		if (scan_start_tsf <
1116 			   scan_res->res[i]->parent_tsf) {
1117 			struct os_reltime update_time, diff;
1118 
1119 			/* For now, allow 7 ms older results due to some
1120 			 * unknown issue with cfg80211 BSS table updates during
1121 			 * a scan with the current BSS.
1122 			 * TODO: Fix this more properly to avoid having to have
1123 			 * this type of hacks in place. */
1124 			calculate_update_time(&scan_res->fetch_time,
1125 					      scan_res->res[i]->age,
1126 					      &update_time);
1127 			os_reltime_sub(&wpa_s->beacon_rep_scan,
1128 				       &update_time, &diff);
1129 			if (os_reltime_before(&update_time,
1130 					      &wpa_s->beacon_rep_scan) &&
1131 			    (diff.sec || diff.usec >= 8000)) {
1132 				wpa_printf(MSG_ERROR,
1133 					   "RRM: Ignore scan result for " MACSTR
1134 					   " due to old update (age(ms) %u, calculated age %u.%06u seconds)",
1135 					   MAC2STR(scan_res->res[i]->bssid),
1136 					   scan_res->res[i]->age,
1137 					   (unsigned int) diff.sec,
1138 					   (unsigned int) diff.usec);
1139 				continue;
1140 			}
1141 		} else {
1142 			continue;
1143 		}
1144 #endif
1145 		if (wpas_add_beacon_rep(wpa_s, &buf, bss, scan_start_tsf,
1146 					bss->parent_tsf) < 0)
1147 			break;
1148 	}
1149 
1150 	if (!buf && wpas_beacon_rep_no_results(wpa_s, &buf))
1151 		goto out;
1152 
1153 	wpa_hexdump_buf(MSG_DEBUG, "RRM: Radio Measurement report", buf);
1154 
1155 	wpas_rrm_send_msr_report(wpa_s, buf);
1156 	wpabuf_free(buf);
1157 
1158 out:
1159 	wpas_clear_beacon_rep_data(wpa_s);
1160 	return 1;
1161 }
1162 
1163 
wpas_clear_beacon_rep_data(struct wpa_supplicant * wpa_s)1164 void wpas_clear_beacon_rep_data(struct wpa_supplicant *wpa_s)
1165 {
1166 	struct beacon_rep_data *data = &wpa_s->beacon_rep_data;
1167 
1168 	eloop_cancel_timeout(wpas_rrm_scan_timeout, wpa_s, NULL);
1169 	bitfield_free(data->eids);
1170 	os_memset(data, 0, sizeof(*data));
1171 }
1172