Browse Source

nl80211: Fix protected Action frame reporting for AP mode

Action frame RX report through EVENT_RX_ACTION did not indicate whether
the frame was protected or not even though that information is available
in mlme_event_mgmt(). hostapd_rx_action() has a workaround for setting
the protected flag for SA Query frames, but that did not apply for other
frames, like FT Action. This broke FT-over-DS when PMF is enabled with
newer kernel versions (i.e., the ones that do not use monitor interface
for receiving management frames).

Signed-hostap: Jouni Malinen <j@w1.fi>
Jouni Malinen 11 years ago
parent
commit
2d2ecf51aa
3 changed files with 20 additions and 1 deletions
  1. 3 1
      src/ap/drv_callbacks.c
  2. 12 0
      src/drivers/driver.h
  3. 5 0
      src/drivers/driver_nl80211.c

+ 3 - 1
src/ap/drv_callbacks.c

@@ -696,7 +696,9 @@ static void hostapd_rx_action(struct hostapd_data *hapd,
 	hdr = (struct ieee80211_hdr *) buf;
 	hdr->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
 					  WLAN_FC_STYPE_ACTION);
-	if (rx_action->category == WLAN_ACTION_SA_QUERY) {
+	if (rx_action->protected == 1)
+		hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP);
+	else if (rx_action->category == WLAN_ACTION_SA_QUERY) {
 		/*
 		 * Assume frame was protected; it would have been dropped if
 		 * not.

+ 12 - 0
src/drivers/driver.h

@@ -3804,6 +3804,18 @@ union wpa_event_data {
 		 * freq - Frequency (in MHz) on which the frame was received
 		 */
 		int freq;
+
+		/**
+		 * ssi_signal - Signal strength in dBm (or 0 if not available)
+		 */
+		int ssi_signal;
+
+		/**
+		 * protected - Whether frame was protected (PMF)
+		 *
+		 * 0 = unknown, 1 = yes, -1 = not
+		 */
+		int protected;
 	} rx_action;
 
 	/**

+ 5 - 0
src/drivers/driver_nl80211.c

@@ -1627,6 +1627,11 @@ static void mlme_event_mgmt(struct wpa_driver_nl80211_data *drv,
 		event.rx_action.category = mgmt->u.action.category;
 		event.rx_action.data = &mgmt->u.action.category + 1;
 		event.rx_action.len = frame + len - event.rx_action.data;
+		event.rx_action.ssi_signal = ssi_signal;
+		if (host_to_le16(WLAN_FC_ISWEP) & mgmt->frame_control)
+			event.rx_action.protected = 1;
+		else
+			event.rx_action.protected = -1;
 		wpa_supplicant_event(drv->ctx, EVENT_RX_ACTION, &event);
 	} else {
 		event.rx_mgmt.frame = frame;