aboutsummaryrefslogtreecommitdiff
path: root/contrib/wpa/src/ap/wnm_ap.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/wpa/src/ap/wnm_ap.c')
-rw-r--r--contrib/wpa/src/ap/wnm_ap.c83
1 files changed, 69 insertions, 14 deletions
diff --git a/contrib/wpa/src/ap/wnm_ap.c b/contrib/wpa/src/ap/wnm_ap.c
index 27c69d34a7ca..d32967e6cef6 100644
--- a/contrib/wpa/src/ap/wnm_ap.c
+++ b/contrib/wpa/src/ap/wnm_ap.c
@@ -54,6 +54,7 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd,
size_t len;
size_t gtk_elem_len = 0;
size_t igtk_elem_len = 0;
+ size_t bigtk_elem_len = 0;
struct wnm_sleep_element wnmsleep_ie;
u8 *wnmtfs_ie, *oci_ie;
u8 wnmsleep_ie_len, oci_ie_len;
@@ -102,6 +103,15 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd,
os_free(wnmtfs_ie);
return -1;
}
+#ifdef CONFIG_TESTING_OPTIONS
+ if (hapd->conf->oci_freq_override_wnm_sleep) {
+ wpa_printf(MSG_INFO,
+ "TEST: Override OCI frequency %d -> %u MHz",
+ ci.frequency,
+ hapd->conf->oci_freq_override_wnm_sleep);
+ ci.frequency = hapd->conf->oci_freq_override_wnm_sleep;
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
oci_ie_len = OCV_OCI_EXTENDED_LEN;
oci_ie = os_zalloc(oci_ie_len);
@@ -122,8 +132,10 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd,
#define MAX_GTK_SUBELEM_LEN 45
#define MAX_IGTK_SUBELEM_LEN 26
+#define MAX_BIGTK_SUBELEM_LEN 26
mgmt = os_zalloc(sizeof(*mgmt) + wnmsleep_ie_len +
MAX_GTK_SUBELEM_LEN + MAX_IGTK_SUBELEM_LEN +
+ MAX_BIGTK_SUBELEM_LEN +
oci_ie_len);
if (mgmt == NULL) {
wpa_printf(MSG_DEBUG, "MLME: Failed to allocate buffer for "
@@ -150,7 +162,6 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd,
pos += gtk_elem_len;
wpa_printf(MSG_DEBUG, "Pass 4, gtk_len = %d",
(int) gtk_elem_len);
-#ifdef CONFIG_IEEE80211W
res = wpa_wnmsleep_igtk_subelem(sta->wpa_sm, pos);
if (res < 0)
goto fail;
@@ -158,11 +169,21 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd,
pos += igtk_elem_len;
wpa_printf(MSG_DEBUG, "Pass 4 igtk_len = %d",
(int) igtk_elem_len);
-#endif /* CONFIG_IEEE80211W */
+ if (hapd->conf->beacon_prot &&
+ (hapd->iface->drv_flags &
+ WPA_DRIVER_FLAGS_BEACON_PROTECTION)) {
+ res = wpa_wnmsleep_bigtk_subelem(sta->wpa_sm, pos);
+ if (res < 0)
+ goto fail;
+ bigtk_elem_len = res;
+ pos += bigtk_elem_len;
+ wpa_printf(MSG_DEBUG, "Pass 4 bigtk_len = %d",
+ (int) bigtk_elem_len);
+ }
WPA_PUT_LE16((u8 *)
&mgmt->u.action.u.wnm_sleep_resp.keydata_len,
- gtk_elem_len + igtk_elem_len);
+ gtk_elem_len + igtk_elem_len + bigtk_elem_len);
}
os_memcpy(pos, &wnmsleep_ie, wnmsleep_ie_len);
/* copy TFS IE here */
@@ -178,7 +199,8 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd,
#endif /* CONFIG_OCV */
len = 1 + sizeof(mgmt->u.action.u.wnm_sleep_resp) + gtk_elem_len +
- igtk_elem_len + wnmsleep_ie_len + wnmtfs_ie_len + oci_ie_len;
+ igtk_elem_len + bigtk_elem_len +
+ wnmsleep_ie_len + wnmtfs_ie_len + oci_ie_len;
/* In driver, response frame should be forced to sent when STA is in
* PS mode */
@@ -191,8 +213,8 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd,
/* when entering wnmsleep
* 1. pause the node in driver
- * 2. mark the node so that AP won't update GTK/IGTK during
- * WNM Sleep
+ * 2. mark the node so that AP won't update GTK/IGTK/BIGTK
+ * during WNM Sleep
*/
if (wnmsleep_ie.status == WNM_STATUS_SLEEP_ACCEPT &&
wnmsleep_ie.action_type == WNM_SLEEP_MODE_ENTER) {
@@ -203,7 +225,7 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd,
}
/* when exiting wnmsleep
* 1. unmark the node
- * 2. start GTK/IGTK update if MFP is not used
+ * 2. start GTK/IGTK/BIGTK update if MFP is not used
* 3. unpause the node in driver
*/
if ((wnmsleep_ie.status == WNM_STATUS_SLEEP_ACCEPT ||
@@ -223,6 +245,7 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd,
#undef MAX_GTK_SUBELEM_LEN
#undef MAX_IGTK_SUBELEM_LEN
+#undef MAX_BIGTK_SUBELEM_LEN
fail:
os_free(wnmtfs_ie);
os_free(oci_ie);
@@ -305,8 +328,9 @@ static void ieee802_11_rx_wnmsleep_req(struct hostapd_data *hapd,
if (ocv_verify_tx_params(oci_ie, oci_ie_len, &ci,
channel_width_to_int(ci.chanwidth),
- ci.seg1_idx) != 0) {
- wpa_msg(hapd, MSG_WARNING, "WNM: %s", ocv_errorstr);
+ ci.seg1_idx) != OCI_SUCCESS) {
+ wpa_msg(hapd, MSG_WARNING, "WNM: OCV failed: %s",
+ ocv_errorstr);
return;
}
}
@@ -510,6 +534,31 @@ static void ieee802_11_rx_bss_trans_mgmt_resp(struct hostapd_data *hapd,
}
+static void wnm_beacon_protection_failure(struct hostapd_data *hapd,
+ const u8 *addr)
+{
+ struct sta_info *sta;
+
+ if (!hapd->conf->beacon_prot ||
+ !(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_BEACON_PROTECTION))
+ return;
+
+ sta = ap_get_sta(hapd, addr);
+ if (!sta || !(sta->flags & WLAN_STA_AUTHORIZED)) {
+ wpa_printf(MSG_DEBUG, "Station " MACSTR
+ " not found for received WNM-Notification Request",
+ MAC2STR(addr));
+ return;
+ }
+
+ hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
+ HOSTAPD_LEVEL_INFO,
+ "Beacon protection failure reported");
+ wpa_msg(hapd->msg_ctx, MSG_INFO, WPA_EVENT_UNPROT_BEACON "reporter="
+ MACSTR, MAC2STR(addr));
+}
+
+
static void ieee802_11_rx_wnm_notification_req(struct hostapd_data *hapd,
const u8 *addr, const u8 *buf,
size_t len)
@@ -528,8 +577,14 @@ static void ieee802_11_rx_wnm_notification_req(struct hostapd_data *hapd,
MAC2STR(addr), dialog_token, type);
wpa_hexdump(MSG_MSGDUMP, "WNM: Notification Request subelements",
buf, len);
- if (type == WLAN_EID_VENDOR_SPECIFIC)
+ switch (type) {
+ case WNM_NOTIF_TYPE_BEACON_PROTECTION_FAILURE:
+ wnm_beacon_protection_failure(hapd, addr);
+ break;
+ case WNM_NOTIF_TYPE_VENDOR_SPECIFIC:
mbo_ap_wnm_notification_req(hapd, addr, buf, len);
+ break;
+ }
}
@@ -643,7 +698,7 @@ int wnm_send_disassoc_imminent(struct hostapd_data *hapd,
wpa_printf(MSG_DEBUG, "WNM: Send BSS Transition Management Request frame to indicate imminent disassociation (disassoc_timer=%d) to "
MACSTR, disassoc_timer, MAC2STR(sta->addr));
- if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) {
+ if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0, NULL, 0, 0) < 0) {
wpa_printf(MSG_DEBUG, "Failed to send BSS Transition "
"Management Request frame");
return -1;
@@ -716,7 +771,7 @@ int wnm_send_ess_disassoc_imminent(struct hostapd_data *hapd,
os_memcpy(pos, url, url_len);
pos += url_len;
- if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) {
+ if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0, NULL, 0, 0) < 0) {
wpa_printf(MSG_DEBUG, "Failed to send BSS Transition "
"Management Request frame");
return -1;
@@ -792,7 +847,7 @@ int wnm_send_bss_tm_req(struct hostapd_data *hapd, struct sta_info *sta,
mbo_len);
}
- if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) {
+ if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0, NULL, 0, 0) < 0) {
wpa_printf(MSG_DEBUG,
"Failed to send BSS Transition Management Request frame");
os_free(buf);
@@ -836,7 +891,7 @@ int wnm_send_coloc_intf_req(struct hostapd_data *hapd, struct sta_info *sta,
wpa_printf(MSG_DEBUG, "WNM: Sending Collocated Interference Request to "
MACSTR " (dialog_token=%u auto_report=%u timeout=%u)",
MAC2STR(sta->addr), dialog_token, auto_report, timeout);
- if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) {
+ if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0, NULL, 0, 0) < 0) {
wpa_printf(MSG_DEBUG,
"WNM: Failed to send Collocated Interference Request frame");
return -1;