diff options
Diffstat (limited to 'contrib/wpa/src/ap/wnm_ap.c')
-rw-r--r-- | contrib/wpa/src/ap/wnm_ap.c | 83 |
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; |