[PATCH 05/15] wpa_supplicant: Limit RRM response size to MMPDU size

Andrei Otcheretianski andrei.otcheretianski at intel.com
Wed Dec 28 05:06:37 PST 2016


From: Avraham Stern <avraham.stern at intel.com>

The length of a Measurement Report frame should be limited by the
maximum allowed MMPDU size (IEEE802.11 - 2012, section 8.5.2.3).
Enforce this size limit, and in case the report elements are longer
than the allowed size, split them between several MPDUs.

Signed-off-by: Avraham Stern <avraham.stern at intel.com>
---
 wpa_supplicant/rrm.c              | 75 ++++++++++++++++++++++++++-------------
 wpa_supplicant/wpa_supplicant_i.h |  3 ++
 2 files changed, 54 insertions(+), 24 deletions(-)

diff --git a/wpa_supplicant/rrm.c b/wpa_supplicant/rrm.c
index e284543..3ffde24 100644
--- a/wpa_supplicant/rrm.c
+++ b/wpa_supplicant/rrm.c
@@ -410,12 +410,59 @@ out:
 }
 
 
+static void wpas_rrm_send_msr_report_mpdu(struct wpa_supplicant *wpa_s,
+					  const u8 *data, size_t len)
+{
+	struct wpabuf *report = wpabuf_alloc(len + 3);
+
+	if (!report)
+		return;
+
+	wpabuf_put_u8(report, WLAN_ACTION_RADIO_MEASUREMENT);
+	wpabuf_put_u8(report, WLAN_RRM_RADIO_MEASUREMENT_REPORT);
+	wpabuf_put_u8(report, wpa_s->rrm.token);
+
+	wpabuf_put_data(report, data, len);
+
+	if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
+				wpa_s->own_addr, wpa_s->bssid,
+				wpabuf_head(report), wpabuf_len(report), 0)) {
+		wpa_printf(MSG_ERROR,
+			   "RRM: Radio measurement report failed. Send action failed");
+	}
+
+	wpabuf_free(report);
+}
+
+static void wpas_rrm_send_msr_report(struct wpa_supplicant *wpa_s,
+				     struct wpabuf *buf)
+{
+	int len = wpabuf_len(buf);
+	const u8 *pos = wpabuf_head_u8(buf), *next = pos;
+
+#define MPDU_REPORT_LEN (int)(IEEE80211_MAX_MMPDU_SIZE - IEEE80211_HDRLEN - 3)
+
+	while (len) {
+		int send_len = (len > MPDU_REPORT_LEN) ? next - 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);
+			len -= send_len;
+			pos = next;
+		}
+
+		next += next[1] + 2;
+	}
+#undef MPDU_REPORT_LEN
+}
+
+
 void wpas_rrm_handle_radio_measurement_request(struct wpa_supplicant *wpa_s,
 					       const u8 *src,
 					       const u8 *frame, size_t len)
 {
-	struct wpabuf *buf, *report;
-	u8 token;
+	struct wpabuf *report;
 
 	if (wpa_s->wpa_state != WPA_COMPLETED) {
 		wpa_printf(MSG_INFO,
@@ -435,35 +482,15 @@ void wpas_rrm_handle_radio_measurement_request(struct wpa_supplicant *wpa_s,
 		return;
 	}
 
-	token = *frame;
+	wpa_s->rrm.token = *frame;
 
 	/* Num of repetitions is not supported */
 
 	report = wpas_rrm_process_msr_req_elems(wpa_s, frame + 3, len - 3);
-
 	if (!report)
 		return;
 
-	buf = wpabuf_alloc(3 + wpabuf_len(report));
-	if (!buf) {
-		wpabuf_free(report);
-		return;
-	}
-
-	wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
-	wpabuf_put_u8(buf, WLAN_RRM_RADIO_MEASUREMENT_REPORT);
-	wpabuf_put_u8(buf, token);
-
-	wpabuf_put_buf(buf, report);
-	wpabuf_free(report);
-
-	if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, src,
-				wpa_s->own_addr, wpa_s->bssid,
-				wpabuf_head(buf), wpabuf_len(buf), 0)) {
-		wpa_printf(MSG_ERROR,
-			   "RRM: Radio measurement report failed: Sending Action frame failed");
-	}
-	wpabuf_free(buf);
+	wpas_rrm_send_msr_report(wpa_s, report);
 	wpabuf_free(report);
 }
 
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index f03d51a..b182dda 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -424,6 +424,9 @@ struct rrm_data {
 
 	/* next_neighbor_rep_token - Next request's dialog token */
 	u8 next_neighbor_rep_token;
+
+	/* token - Dialog token of the current radio measurement */
+	u8 token;
 };
 
 enum wpa_supplicant_test_failure {
-- 
1.9.1




More information about the Hostap mailing list