|
@@ -371,6 +371,25 @@ static int ieee802_11_parse_vendor_specific(struct hostapd_data *hapd,
|
|
|
}
|
|
|
|
|
|
|
|
|
+#ifdef CONFIG_IEEE80211W
|
|
|
+static u8 * hostapd_eid_assoc_comeback_time(struct hostapd_data *hapd,
|
|
|
+ struct sta_info *sta, u8 *eid)
|
|
|
+{
|
|
|
+ u8 *pos = eid;
|
|
|
+ u32 timeout;
|
|
|
+
|
|
|
+ *pos++ = WLAN_EID_ASSOC_COMEBACK_TIME;
|
|
|
+ *pos++ = 4;
|
|
|
+ timeout = (hapd->conf->assoc_ping_attempts - sta->ping_count + 1) *
|
|
|
+ hapd->conf->assoc_ping_timeout;
|
|
|
+ WPA_PUT_LE32(pos, timeout);
|
|
|
+ pos += 4;
|
|
|
+
|
|
|
+ return pos;
|
|
|
+}
|
|
|
+#endif /* CONFIG_IEEE80211W */
|
|
|
+
|
|
|
+
|
|
|
ParseRes ieee802_11_parse_elems(struct hostapd_data *hapd, u8 *start,
|
|
|
size_t len,
|
|
|
struct ieee802_11_elems *elems,
|
|
@@ -514,12 +533,10 @@ void ieee802_11_print_ssid(char *buf, const u8 *ssid, u8 len)
|
|
|
void ieee802_11_send_deauth(struct hostapd_data *hapd, u8 *addr, u16 reason)
|
|
|
{
|
|
|
struct ieee80211_mgmt mgmt;
|
|
|
- char buf[30];
|
|
|
|
|
|
hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
|
|
|
HOSTAPD_LEVEL_DEBUG,
|
|
|
"deauthenticate - reason %d", reason);
|
|
|
- os_snprintf(buf, sizeof(buf), "SEND-DEAUTHENTICATE %d", reason);
|
|
|
os_memset(&mgmt, 0, sizeof(mgmt));
|
|
|
mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
|
|
|
WLAN_FC_STYPE_DEAUTH);
|
|
@@ -1160,6 +1177,21 @@ static void handle_assoc(struct hostapd_data *hapd,
|
|
|
if (resp != WLAN_STATUS_SUCCESS)
|
|
|
goto fail;
|
|
|
#ifdef CONFIG_IEEE80211W
|
|
|
+ if ((sta->flags & WLAN_STA_MFP) && !sta->ping_timed_out) {
|
|
|
+ /*
|
|
|
+ * STA has already been associated with MFP and ping
|
|
|
+ * timeout has not been reached. Reject the
|
|
|
+ * association attempt temporarily and start ping, if
|
|
|
+ * one is not pending.
|
|
|
+ */
|
|
|
+
|
|
|
+ if (sta->ping_count == 0)
|
|
|
+ ap_sta_start_ping(hapd, sta);
|
|
|
+
|
|
|
+ resp = WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY;
|
|
|
+ goto fail;
|
|
|
+ }
|
|
|
+
|
|
|
if (wpa_auth_uses_mfp(sta->wpa_sm))
|
|
|
sta->flags |= WLAN_STA_MFP;
|
|
|
else
|
|
@@ -1352,6 +1384,11 @@ static void handle_assoc(struct hostapd_data *hapd,
|
|
|
}
|
|
|
#endif /* CONFIG_IEEE80211R */
|
|
|
|
|
|
+#ifdef CONFIG_IEEE80211W
|
|
|
+ if (resp == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY)
|
|
|
+ p = hostapd_eid_assoc_comeback_time(hapd, sta, p);
|
|
|
+#endif /* CONFIG_IEEE80211W */
|
|
|
+
|
|
|
send_len += p - reply->u.assoc_resp.variable;
|
|
|
|
|
|
/* Request TX callback */
|
|
@@ -1553,6 +1590,56 @@ static void handle_beacon(struct hostapd_data *hapd,
|
|
|
}
|
|
|
|
|
|
|
|
|
+#ifdef CONFIG_IEEE80211W
|
|
|
+static void hostapd_ping_action(struct hostapd_data *hapd,
|
|
|
+ struct ieee80211_mgmt *mgmt, size_t len)
|
|
|
+{
|
|
|
+ struct sta_info *sta;
|
|
|
+ u8 *end;
|
|
|
+ int i;
|
|
|
+
|
|
|
+ end = mgmt->u.action.u.ping_resp.trans_id + WLAN_PING_TRANS_ID_LEN;
|
|
|
+ if (((u8 *) mgmt) + len < end) {
|
|
|
+ wpa_printf(MSG_DEBUG, "IEEE 802.11: Too short Ping Action "
|
|
|
+ "frame (len=%lu)", (unsigned long) len);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (mgmt->u.action.u.ping_resp.action != WLAN_PING_RESPONSE) {
|
|
|
+ wpa_printf(MSG_DEBUG, "IEEE 802.11: Unexpected Ping Action %d",
|
|
|
+ mgmt->u.action.u.ping_resp.action);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* MLME-PING.confirm */
|
|
|
+
|
|
|
+ sta = ap_get_sta(hapd, mgmt->sa);
|
|
|
+ if (sta == NULL || sta->ping_trans_id == NULL) {
|
|
|
+ wpa_printf(MSG_DEBUG, "IEEE 802.11: No matching STA with "
|
|
|
+ "pending ping request found");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (i = 0; i < sta->ping_count; i++) {
|
|
|
+ if (os_memcmp(sta->ping_trans_id + i * WLAN_PING_TRANS_ID_LEN,
|
|
|
+ mgmt->u.action.u.ping_resp.trans_id,
|
|
|
+ WLAN_PING_TRANS_ID_LEN) == 0)
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (i >= sta->ping_count) {
|
|
|
+ wpa_printf(MSG_DEBUG, "IEEE 802.11: No matching ping "
|
|
|
+ "transaction identifier found");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
|
|
+ HOSTAPD_LEVEL_DEBUG, "Reply to pending ping received");
|
|
|
+ ap_sta_stop_ping(hapd, sta);
|
|
|
+}
|
|
|
+#endif /* CONFIG_IEEE80211W */
|
|
|
+
|
|
|
+
|
|
|
static void handle_action(struct hostapd_data *hapd,
|
|
|
struct ieee80211_mgmt *mgmt, size_t len)
|
|
|
{
|
|
@@ -1588,6 +1675,11 @@ static void handle_action(struct hostapd_data *hapd,
|
|
|
case WME_ACTION_CATEGORY:
|
|
|
hostapd_wme_action(hapd, mgmt, len);
|
|
|
return;
|
|
|
+#ifdef CONFIG_IEEE80211W
|
|
|
+ case WLAN_ACTION_PING:
|
|
|
+ hostapd_ping_action(hapd, mgmt, len);
|
|
|
+ return;
|
|
|
+#endif /* CONFIG_IEEE80211W */
|
|
|
}
|
|
|
|
|
|
hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
|
|
@@ -1811,6 +1903,10 @@ static void handle_assoc_cb(struct hostapd_data *hapd,
|
|
|
ht_cap = &sta->ht_capabilities;
|
|
|
#endif /* CONFIG_IEEE80211N */
|
|
|
|
|
|
+#ifdef CONFIG_IEEE80211W
|
|
|
+ sta->ping_timed_out = 0;
|
|
|
+#endif /* CONFIG_IEEE80211W */
|
|
|
+
|
|
|
if (hostapd_sta_add(hapd->conf->iface, hapd, sta->addr, sta->aid,
|
|
|
sta->capability, sta->supported_rates,
|
|
|
sta->supported_rates_len, 0, sta->listen_interval,
|
|
@@ -1881,6 +1977,9 @@ void ieee802_11_mgmt_cb(struct hostapd_data *hapd, u8 *buf, size_t len,
|
|
|
case WLAN_FC_STYPE_DEAUTH:
|
|
|
/* ignore */
|
|
|
break;
|
|
|
+ case WLAN_FC_STYPE_ACTION:
|
|
|
+ wpa_printf(MSG_DEBUG, "mgmt::action cb");
|
|
|
+ break;
|
|
|
default:
|
|
|
printf("unknown mgmt cb frame subtype %d\n", stype);
|
|
|
break;
|