static void hostapd_action_rx(struct hostapd_data *hapd, struct rx_action *action) { struct sta_info *sta; wpa_printf(MSG_DEBUG, "RX_ACTION cat %d action plen %d", action->category, (int) action->len); sta = ap_get_sta(hapd, action->sa); if (sta == NULL) { wpa_printf(MSG_DEBUG, "%s: station not found", __func__); return; } #ifdef CONFIG_IEEE80211R if (action->category == WLAN_ACTION_FT) { wpa_printf(MSG_DEBUG, "%s: FT_ACTION length %d", __func__, (int) action->len); wpa_ft_action_rx(sta->wpa_sm, action->data, action->len); } #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_IEEE80211W if (action->category == WLAN_ACTION_SA_QUERY && action->len >= 4) { wpa_printf(MSG_DEBUG, "%s: SA_QUERY_ACTION length %d", __func__, (int) action->len); ieee802_11_sa_query_action(hapd, action->sa, *(action->data + 1), action->data + 2); } #endif /* CONFIG_IEEE80211W */ }
static void hostapd_action_rx(struct hostapd_data *hapd, struct rx_mgmt *drv_mgmt) { struct ieee80211_mgmt *mgmt; struct sta_info *sta; size_t plen __maybe_unused; u16 fc; if (drv_mgmt->frame_len < 24 + 1) return; plen = drv_mgmt->frame_len - 24 - 1; mgmt = (struct ieee80211_mgmt *) drv_mgmt->frame; fc = le_to_host16(mgmt->frame_control); if (WLAN_FC_GET_STYPE(fc) != WLAN_FC_STYPE_ACTION) return; /* handled by the driver */ wpa_printf(MSG_DEBUG, "RX_ACTION cat %d action plen %d", mgmt->u.action.category, (int) plen); sta = ap_get_sta(hapd, mgmt->sa); if (sta == NULL) { wpa_printf(MSG_DEBUG, "%s: station not found", __func__); return; } #ifdef CONFIG_IEEE80211R if (mgmt->u.action.category == WLAN_ACTION_FT) { const u8 *payload = drv_mgmt->frame + 24 + 1; wpa_ft_action_rx(sta->wpa_sm, payload, plen); } #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_IEEE80211W if (mgmt->u.action.category == WLAN_ACTION_SA_QUERY && plen >= 4) { ieee802_11_sa_query_action( hapd, mgmt->sa, mgmt->u.action.u.sa_query_resp.action, mgmt->u.action.u.sa_query_resp.trans_id); } #endif /* CONFIG_IEEE80211W */ #ifdef CONFIG_WNM if (mgmt->u.action.category == WLAN_ACTION_WNM) { ieee802_11_rx_wnm_action_ap(hapd, mgmt, drv_mgmt->frame_len); } #endif /* CONFIG_WNM */ #ifdef CONFIG_FST if (mgmt->u.action.category == WLAN_ACTION_FST && hapd->iface->fst) { fst_rx_action(hapd->iface->fst, mgmt, drv_mgmt->frame_len); return; } #endif /* CONFIG_FST */ }
static void hostapd_action_rx(struct hostapd_data *hapd, struct rx_action *action) { struct sta_info *sta; sta = ap_get_sta(hapd, action->sa); if (sta == NULL) { wpa_printf(MSG_DEBUG, "%s: station not found", __func__); return; } #ifdef CONFIG_IEEE80211R if (action->category == WLAN_ACTION_FT) { wpa_printf(MSG_DEBUG, "%s: FT_ACTION length %d", __func__, action->len); wpa_ft_action_rx(sta->wpa_sm, action->data, action->len); } #endif /* CONFIG_IEEE80211R */ }
static void hostapd_action_rx(struct hostapd_data *hapd, struct rx_mgmt *drv_mgmt) { struct ieee80211_mgmt *mgmt; struct sta_info *sta; size_t plen __maybe_unused; u16 fc; u8 *action __maybe_unused; if (drv_mgmt->frame_len < IEEE80211_HDRLEN + 2 + 1) return; plen = drv_mgmt->frame_len - IEEE80211_HDRLEN; mgmt = (struct ieee80211_mgmt *) drv_mgmt->frame; fc = le_to_host16(mgmt->frame_control); if (WLAN_FC_GET_STYPE(fc) != WLAN_FC_STYPE_ACTION) return; /* handled by the driver */ action = (u8 *) &mgmt->u.action.u; wpa_printf(MSG_DEBUG, "RX_ACTION category %u action %u sa " MACSTR " da " MACSTR " plen %d", mgmt->u.action.category, *action, MAC2STR(mgmt->sa), MAC2STR(mgmt->da), (int) plen); sta = ap_get_sta(hapd, mgmt->sa); if (sta == NULL) { wpa_printf(MSG_DEBUG, "%s: station not found", __func__); return; } #ifdef CONFIG_IEEE80211R_AP if (mgmt->u.action.category == WLAN_ACTION_FT) { wpa_ft_action_rx(sta->wpa_sm, (u8 *) &mgmt->u.action, plen); return; } #endif /* CONFIG_IEEE80211R_AP */ #ifdef CONFIG_IEEE80211W if (mgmt->u.action.category == WLAN_ACTION_SA_QUERY) { ieee802_11_sa_query_action(hapd, mgmt, drv_mgmt->frame_len); return; } #endif /* CONFIG_IEEE80211W */ #ifdef CONFIG_WNM_AP if (mgmt->u.action.category == WLAN_ACTION_WNM) { ieee802_11_rx_wnm_action_ap(hapd, mgmt, drv_mgmt->frame_len); return; } #endif /* CONFIG_WNM_AP */ #ifdef CONFIG_FST if (mgmt->u.action.category == WLAN_ACTION_FST && hapd->iface->fst) { fst_rx_action(hapd->iface->fst, mgmt, drv_mgmt->frame_len); return; } #endif /* CONFIG_FST */ #ifdef CONFIG_DPP if (plen >= 2 + 4 && mgmt->u.action.u.vs_public_action.action == WLAN_PA_VENDOR_SPECIFIC && WPA_GET_BE24(mgmt->u.action.u.vs_public_action.oui) == OUI_WFA && mgmt->u.action.u.vs_public_action.variable[0] == DPP_OUI_TYPE) { const u8 *pos, *end; pos = mgmt->u.action.u.vs_public_action.oui; end = drv_mgmt->frame + drv_mgmt->frame_len; hostapd_dpp_rx_action(hapd, mgmt->sa, pos, end - pos, drv_mgmt->freq); return; } #endif /* CONFIG_DPP */ }
static void handle_action(struct hostapd_data *hapd, const struct ieee80211_mgmt *mgmt, size_t len) { struct sta_info *sta; if (len < IEEE80211_HDRLEN + 1) { hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_DEBUG, "handle_action - too short payload (len=%lu)", (unsigned long) len); return; } sta = ap_get_sta(hapd, mgmt->sa); #ifdef CONFIG_IEEE80211W if (sta && (sta->flags & WLAN_STA_MFP) && !(mgmt->frame_control & host_to_le16(WLAN_FC_ISWEP) && robust_action_frame(mgmt->u.action.category))) { hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_DEBUG, "Dropped unprotected Robust Action frame from " "an MFP STA"); return; } #endif /* CONFIG_IEEE80211W */ switch (mgmt->u.action.category) { #ifdef CONFIG_IEEE80211R case WLAN_ACTION_FT: { if (sta == NULL || !(sta->flags & WLAN_STA_ASSOC)) { wpa_printf(MSG_DEBUG, "IEEE 802.11: Ignored FT Action " "frame from unassociated STA " MACSTR, MAC2STR(mgmt->sa)); return; } if (wpa_ft_action_rx(sta->wpa_sm, (u8 *) &mgmt->u.action, len - IEEE80211_HDRLEN)) break; return; } #endif /* CONFIG_IEEE80211R */ case WLAN_ACTION_WMM: hostapd_wmm_action(hapd, mgmt, len); return; #ifdef CONFIG_IEEE80211W case WLAN_ACTION_SA_QUERY: hostapd_sa_query_action(hapd, mgmt, len); return; #endif /* CONFIG_IEEE80211W */ case WLAN_ACTION_PUBLIC: if (hapd->public_action_cb) { hapd->public_action_cb(hapd->public_action_cb_ctx, (u8 *) mgmt, len, hapd->iface->freq); return; } break; } hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_DEBUG, "handle_action - unknown action category %d or invalid " "frame", mgmt->u.action.category); if (!(mgmt->da[0] & 0x01) && !(mgmt->u.action.category & 0x80) && !(mgmt->sa[0] & 0x01)) { struct ieee80211_mgmt *resp; /* * IEEE 802.11-REVma/D9.0 - 7.3.1.11 * Return the Action frame to the source without change * except that MSB of the Category set to 1. */ wpa_printf(MSG_DEBUG, "IEEE 802.11: Return unknown Action " "frame back to sender"); resp = os_malloc(len); if (resp == NULL) return; os_memcpy(resp, mgmt, len); os_memcpy(resp->da, resp->sa, ETH_ALEN); os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN); os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN); resp->u.action.category |= 0x80; hapd->drv.send_mgmt_frame(hapd, resp, len); os_free(resp); } }