@@ -1835,6 +1835,7 @@ enum beacon_report_mode {
#define WLAN_BEACON_REQUEST_SUBELEM_DETAIL 2 /* Reporting Detail */
#define WLAN_BEACON_REQUEST_SUBELEM_REQUEST 10
#define WLAN_BEACON_REQUEST_SUBELEM_AP_CHANNEL 51 /* AP Channel Report */
+#define WLAN_BEACON_REQUEST_SUBELEM_LAST_INDICATION 164
#define WLAN_BEACON_REQUEST_SUBELEM_VENDOR 221
/*
@@ -1886,12 +1887,16 @@ struct rrm_measurement_beacon_report {
/* IEEE Std 802.11-2016, Table 9-112 - Beacon report Subelement IDs */
#define WLAN_BEACON_REPORT_SUBELEM_FRAME_BODY 1
#define WLAN_BEACON_REPORT_SUBELEM_FRAME_BODY_FRAGMENT_ID 2
+#define WLAN_BEACON_REPORT_SUBELEM_LAST_INDICATION 164
#define WLAN_BEACON_REPORT_SUBELEM_VENDOR 221
/* IEEE P802.11 - Beacon Report fragmentation */
#define REPORTED_FRAME_BODY_SUBELEM_LEN 4
#define REPORTED_FRAME_BODY_MORE_FRAGMENTS BIT(7)
+/* IEEE P802.11 - Enhancement to Beacon Report */
+#define BEACON_REPORT_LAST_INDICATION_SUBELEM_LEN 3
+
/* IEEE Std 802.11ad-2012 - Multi-band element */
struct multi_band_ie {
u8 eid; /* WLAN_EID_MULTI_BAND */
@@ -392,6 +392,45 @@ static void wpas_rrm_send_msr_report_mpdu(struct wpa_supplicant *wpa_s,
}
+static int wpas_rrm_beacon_rep_update_last_frame(const u8 *pos, size_t len)
+{
+ struct rrm_measurement_report_element *msr_rep;
+ const u8 *end = pos + len;
+ const u8 *msr_rep_end;
+
+ while (end - pos >= (int)sizeof(*msr_rep)) {
+ msr_rep = (void *)pos;
+ msr_rep_end = pos + msr_rep->len + 2;
+
+ if (msr_rep->eid != WLAN_EID_MEASURE_REPORT) {
+ /* should not happen. This indicates a bug */
+ wpa_printf(MSG_ERROR,
+ "RRM: non measurement report element in measurement report frame");
+ return -1;
+ }
+
+ if (msr_rep->type == MEASURE_TYPE_BEACON) {
+ struct rrm_measurement_beacon_report *rep =
+ (void *)msr_rep->variable;
+ u8 *subelem = rep->variable;
+
+ while (subelem + 2 < msr_rep_end &&
+ subelem[0] !=
+ WLAN_BEACON_REPORT_SUBELEM_LAST_INDICATION)
+ subelem += 2 + subelem[1];
+
+ if (subelem +
+ BEACON_REPORT_LAST_INDICATION_SUBELEM_LEN <= end)
+ subelem[2] = 1;
+ }
+
+ pos += pos[1] + 2;
+ }
+
+ return 0;
+}
+
+
static void wpas_rrm_send_msr_report(struct wpa_supplicant *wpa_s,
struct wpabuf *buf)
{
@@ -403,6 +442,9 @@ static void wpas_rrm_send_msr_report(struct wpa_supplicant *wpa_s,
while (len) {
int send_len = (len > MPDU_REPORT_LEN) ? next - pos : len;
+ if (send_len == len)
+ wpas_rrm_beacon_rep_update_last_frame(pos, len);
+
if (send_len == len ||
(send_len + next[1] + 2) > MPDU_REPORT_LEN) {
wpas_rrm_send_msr_report_mpdu(wpa_s, pos, send_len);
@@ -796,12 +838,14 @@ static int wpas_add_beacon_rep_elem(struct beacon_rep_data *data,
{
int ret;
u8 *buf, *pos;
+ u32 subelems_len = REPORTED_FRAME_BODY_SUBELEM_LEN +
+ (data->last_indication ?
+ BEACON_REPORT_LAST_INDICATION_SUBELEM_LEN : 0);
/* Maximum element length: beacon report element + reported frame body
* subelement + all IEs of the reported beacon + reported frame body
* fragment ID subelement */
- buf = os_malloc(sizeof(*rep) + 14 + *ie_len +
- REPORTED_FRAME_BODY_SUBELEM_LEN);
+ buf = os_malloc(sizeof(*rep) + 14 + *ie_len + subelems_len);
if (!buf)
return -1;
@@ -832,11 +876,20 @@ static int wpas_add_beacon_rep_elem(struct beacon_rep_data *data,
else
pos[3] &= ~REPORTED_FRAME_BODY_MORE_FRAGMENTS;
+ pos += REPORTED_FRAME_BODY_SUBELEM_LEN;
+
+ if (data->last_indication) {
+ pos[0] = WLAN_BEACON_REPORT_SUBELEM_LAST_INDICATION;
+ pos[1] = 1;
+
+ /* this field will be updated later if this is the last frame */
+ pos[2] = 0;
+ }
+
ret = wpas_rrm_report_elem(wpa_buf, data->token,
MEASUREMENT_REPORT_MODE_ACCEPT,
MEASURE_TYPE_BEACON, buf,
- ret + sizeof(*rep) +
- REPORTED_FRAME_BODY_SUBELEM_LEN);
+ ret + sizeof(*rep) + subelems_len);
out:
os_free(buf);
return ret;
@@ -1051,6 +1104,16 @@ static int wpas_rm_handle_beacon_req_subelem(struct wpa_supplicant *wpa_s,
case WLAN_BEACON_REQUEST_SUBELEM_AP_CHANNEL:
/* Skip - it will be processed when freqs are added */
break;
+ case WLAN_BEACON_REQUEST_SUBELEM_LAST_INDICATION:
+ if (slen != 1) {
+ wpa_printf(MSG_DEBUG,
+ "Invalid request subelement length: %u",
+ slen);
+ return -1;
+ }
+
+ data->last_indication = subelem[0];
+ break;
default:
wpa_printf(MSG_DEBUG,
"Beacon request: Unknown subelement id %u", sid);
@@ -461,6 +461,7 @@ struct beacon_rep_data {
u8 bssid[ETH_ALEN];
enum beacon_report_detail report_detail;
struct bitfield *eids;
+ int last_indication;
};