📄 ieee802_11.c
字号:
#endif /* CONFIG_IEEE80211W */ else if (res == WPA_INVALID_MDIE) resp = WLAN_STATUS_INVALID_MDIE; else if (res != WPA_IE_OK) resp = WLAN_STATUS_INVALID_IE; if (resp != WLAN_STATUS_SUCCESS) goto fail;#ifdef CONFIG_IEEE80211W if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out && sta->sa_query_count > 0) ap_check_sa_query_timeout(hapd, sta); if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out && (!reassoc || sta->auth_alg != WLAN_AUTH_FT)) { /* * STA has already been associated with MFP and SA * Query timeout has not been reached. Reject the * association attempt temporarily and start SA Query, * if one is not pending. */ if (sta->sa_query_count == 0) ap_sta_start_sa_query(hapd, sta); resp = WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY; goto fail; } if (wpa_auth_uses_mfp(sta->wpa_sm)) sta->flags |= WLAN_STA_MFP; else sta->flags &= ~WLAN_STA_MFP;#endif /* CONFIG_IEEE80211W */#ifdef CONFIG_IEEE80211R if (sta->auth_alg == WLAN_AUTH_FT) { if (!reassoc) { wpa_printf(MSG_DEBUG, "FT: " MACSTR " tried " "to use association (not " "re-association) with FT auth_alg", MAC2STR(sta->addr)); resp = WLAN_STATUS_UNSPECIFIED_FAILURE; goto fail; } resp = wpa_ft_validate_reassoc(sta->wpa_sm, pos, left); if (resp != WLAN_STATUS_SUCCESS) goto fail; }#endif /* CONFIG_IEEE80211R */#ifdef CONFIG_IEEE80211N if ((sta->flags & WLAN_STA_HT) && wpa_auth_get_pairwise(sta->wpa_sm) == WPA_CIPHER_TKIP) { wpa_printf(MSG_DEBUG, "HT: " MACSTR " tried to " "use TKIP with HT association", MAC2STR(sta->addr)); resp = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; goto fail; }#endif /* CONFIG_IEEE80211N */ } else wpa_auth_sta_no_wpa(sta->wpa_sm); if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G) sta->flags |= WLAN_STA_NONERP; for (i = 0; i < sta->supported_rates_len; i++) { if ((sta->supported_rates[i] & 0x7f) > 22) { sta->flags &= ~WLAN_STA_NONERP; break; } } if (sta->flags & WLAN_STA_NONERP && !sta->nonerp_set) { sta->nonerp_set = 1; hapd->iface->num_sta_non_erp++; if (hapd->iface->num_sta_non_erp == 1) ieee802_11_set_beacons(hapd->iface); } if (!(sta->capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) && !sta->no_short_slot_time_set) { sta->no_short_slot_time_set = 1; hapd->iface->num_sta_no_short_slot_time++; if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G && hapd->iface->num_sta_no_short_slot_time == 1) ieee802_11_set_beacons(hapd->iface); } if (sta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) sta->flags |= WLAN_STA_SHORT_PREAMBLE; else sta->flags &= ~WLAN_STA_SHORT_PREAMBLE; if (!(sta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) && !sta->no_short_preamble_set) { sta->no_short_preamble_set = 1; hapd->iface->num_sta_no_short_preamble++; if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G && hapd->iface->num_sta_no_short_preamble == 1) ieee802_11_set_beacons(hapd->iface); }#ifdef CONFIG_IEEE80211N if (sta->flags & WLAN_STA_HT) { u16 ht_capab = le_to_host16( sta->ht_capabilities.data.capabilities_info); wpa_printf(MSG_DEBUG, "HT: STA " MACSTR " HT Capabilities " "Info: 0x%04x", MAC2STR(sta->addr), ht_capab); if ((ht_capab & HT_CAP_INFO_GREEN_FIELD) == 0) { if (!sta->no_ht_gf_set) { sta->no_ht_gf_set = 1; hapd->iface->num_sta_ht_no_gf++; } wpa_printf(MSG_DEBUG, "%s STA " MACSTR " - no " "greenfield, num of non-gf stations %d", __func__, MAC2STR(sta->addr), hapd->iface->num_sta_ht_no_gf); } if ((ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) == 0) { if (!sta->ht_20mhz_set) { sta->ht_20mhz_set = 1; hapd->iface->num_sta_ht_20mhz++; } wpa_printf(MSG_DEBUG, "%s STA " MACSTR " - 20 MHz HT, " "num of 20MHz HT STAs %d", __func__, MAC2STR(sta->addr), hapd->iface->num_sta_ht_20mhz); } } else { if (!sta->no_ht_set) { sta->no_ht_set = 1; hapd->iface->num_sta_no_ht++; } if (hapd->iconf->ieee80211n) { wpa_printf(MSG_DEBUG, "%s STA " MACSTR " - no HT, num of non-HT stations %d", __func__, MAC2STR(sta->addr), hapd->iface->num_sta_no_ht); } } if (hostapd_ht_operation_update(hapd->iface) > 0) ieee802_11_set_beacons(hapd->iface);#endif /* CONFIG_IEEE80211N */ /* get a unique AID */ if (sta->aid > 0) { wpa_printf(MSG_DEBUG, " old AID %d", sta->aid); } else { for (sta->aid = 1; sta->aid <= MAX_AID_TABLE_SIZE; sta->aid++) if (hapd->sta_aid[sta->aid - 1] == NULL) break; if (sta->aid > MAX_AID_TABLE_SIZE) { sta->aid = 0; resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; wpa_printf(MSG_ERROR, " no room for more AIDs"); goto fail; } else { hapd->sta_aid[sta->aid - 1] = sta; wpa_printf(MSG_DEBUG, " new AID %d", sta->aid); } } hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_DEBUG, "association OK (aid %d)", sta->aid); /* Station will be marked associated, after it acknowledges AssocResp */#ifdef CONFIG_IEEE80211W if ((sta->flags & WLAN_STA_MFP) && sta->sa_query_timed_out) { wpa_printf(MSG_DEBUG, "Allowing %sassociation after timed out " "SA Query procedure", reassoc ? "re" : ""); /* TODO: Send a protected Disassociate frame to the STA using * the old key and Reason Code "Previous Authentication no * longer valid". Make sure this is only sent protected since * unprotected frame would be received by the STA that is now * trying to associate. */ }#endif /* CONFIG_IEEE80211W */ if (reassoc) { os_memcpy(sta->previous_ap, mgmt->u.reassoc_req.current_ap, ETH_ALEN); } if (sta->last_assoc_req) os_free(sta->last_assoc_req); sta->last_assoc_req = os_malloc(len); if (sta->last_assoc_req) os_memcpy(sta->last_assoc_req, mgmt, len); /* Make sure that the previously registered inactivity timer will not * remove the STA immediately. */ sta->timeout_next = STA_NULLFUNC; fail: os_memset(buf, 0, sizeof(buf)); reply = (struct ieee80211_mgmt *) buf; reply->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, (send_deauth ? WLAN_FC_STYPE_DEAUTH : (reassoc ? WLAN_FC_STYPE_REASSOC_RESP : WLAN_FC_STYPE_ASSOC_RESP))); os_memcpy(reply->da, mgmt->sa, ETH_ALEN); os_memcpy(reply->sa, hapd->own_addr, ETH_ALEN); os_memcpy(reply->bssid, mgmt->bssid, ETH_ALEN); send_len = IEEE80211_HDRLEN; if (send_deauth) { send_len += sizeof(reply->u.deauth); reply->u.deauth.reason_code = host_to_le16(resp); } else { u8 *p; send_len += sizeof(reply->u.assoc_resp); reply->u.assoc_resp.capab_info = host_to_le16(hostapd_own_capab_info(hapd, sta, 0)); reply->u.assoc_resp.status_code = host_to_le16(resp); reply->u.assoc_resp.aid = host_to_le16((sta ? sta->aid : 0) | BIT(14) | BIT(15)); /* Supported rates */ p = hostapd_eid_supp_rates(hapd, reply->u.assoc_resp.variable); /* Extended supported rates */ p = hostapd_eid_ext_supp_rates(hapd, p); if (sta->flags & WLAN_STA_WME) p = hostapd_eid_wme(hapd, p); p = hostapd_eid_ht_capabilities_info(hapd, p); p = hostapd_eid_ht_operation(hapd, p);#ifdef CONFIG_IEEE80211R if (resp == WLAN_STATUS_SUCCESS) { /* IEEE 802.11r: Mobility Domain Information, Fast BSS * Transition Information, RSN */ p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, p, buf + sizeof(buf) - p, sta->auth_alg); }#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; } if (hostapd_send_mgmt_frame(hapd, reply, send_len, 0) < 0) perror("handle_assoc: send");}static void handle_disassoc(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt, size_t len){ struct sta_info *sta; if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.disassoc)) { printf("handle_disassoc - too short payload (len=%lu)\n", (unsigned long) len); return; } wpa_printf(MSG_DEBUG, "disassocation: STA=" MACSTR " reason_code=%d", MAC2STR(mgmt->sa), le_to_host16(mgmt->u.disassoc.reason_code)); sta = ap_get_sta(hapd, mgmt->sa); if (sta == NULL) { printf("Station " MACSTR " trying to disassociate, but it " "is not associated.\n", MAC2STR(mgmt->sa)); return; } sta->flags &= ~WLAN_STA_ASSOC; wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC); hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_INFO, "disassociated"); sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST; ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); /* Stop Accounting and IEEE 802.1X sessions, but leave the STA * authenticated. */ accounting_sta_stop(hapd, sta); ieee802_1x_free_station(sta); hostapd_sta_remove(hapd, sta->addr); if (sta->timeout_next == STA_NULLFUNC || sta->timeout_next == STA_DISASSOC) { sta->timeout_next = STA_DEAUTH; eloop_cancel_timeout(ap_handle_timer, hapd, sta); eloop_register_timeout(AP_DEAUTH_DELAY, 0, ap_handle_timer, hapd, sta); } mlme_disassociate_indication( hapd, sta, le_to_host16(mgmt->u.disassoc.reason_code));}static void handle_deauth(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt, size_t len){ struct sta_info *sta; if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.deauth)) { printf("handle_deauth - too short payload (len=%lu)\n", (unsigned long) len); return; } wpa_printf(MSG_DEBUG, "deauthentication: STA=" MACSTR " reason_code=%d", MAC2STR(mgmt->sa), le_to_host16(mgmt->u.deauth.reason_code)); sta = ap_get_sta(hapd, mgmt->sa); if (sta == NULL) { printf("Station " MACSTR " trying to deauthenticate, but it " "is not authenticated.\n", MAC2STR(mgmt->sa)); return; } sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH); hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_DEBUG, "deauthenticated"); mlme_deauthenticate_indication( hapd, sta, le_to_host16(mgmt->u.deauth.reason_code)); sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST; ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); ap_free_sta(hapd, sta);}static void handle_beacon(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt, size_t len, struct hostapd_frame_info *fi){ struct ieee802_11_elems elems; if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.beacon)) { printf("handle_beacon - too short payload (len=%lu)\n", (unsigned long) len); return; } (void) ieee802_11_parse_elems(mgmt->u.beacon.variable, len - (IEEE80211_HDRLEN + sizeof(mgmt->u.beacon)), &elems, 0); ap_list_process_beacon(hapd->iface, mgmt, &elems, fi);}#ifdef CONFIG_IEEE80211W/* MLME-SAQuery.request */void ieee802_11_send_sa_query_req(struct hostapd_data *hapd, const u8 *addr, const u8 *trans_id){ struct ieee80211_mgmt mgmt; u8 *end; os_memset(&mgmt, 0, sizeof(mgmt)); mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_ACTION); os_memcpy(mgmt.da, addr, ETH_ALEN); os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN); os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN); mgmt.u.action.category = WLAN_ACTION_SA_QUERY; mgmt.u.action.u.sa_query_req.action = WLAN_SA_QUERY_REQUEST; os_memcpy(mgmt.u.action.u.sa_query_req.trans_id, trans_id, WLAN_SA_QUERY_TR_ID_LEN); end = mgmt.u.action.u.sa_query_req.trans_id + WLAN_SA_QUERY_TR_ID_LEN; if (hostapd_send_mgmt_frame(hapd, &mgmt, end - (u8 *) &mgmt, 0) < 0) perror("ieee802_11_send_sa_query_req: send");}static void hostapd_sa_query_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.sa_query_resp.trans_id + WLAN_SA_QUERY_TR_ID_LEN; if (((u8 *) mgmt) + len < end) { wpa_printf(MSG_DEBUG, "IEEE 802.11: Too short SA Query Action " "frame (len=%lu)", (unsigned long) len); return; } if (mgmt->u.action.u.sa_query_resp.action != WLAN_SA_QUERY_RESPONSE) { wpa_printf(MSG_DEBUG, "IEEE 802.11: Unexpected SA Query " "Action %d", mgmt->u.action.u.sa_query_resp.action); return; } /* MLME-SAQuery.confirm */ sta = ap_get_sta(hapd, mgmt->sa); if (sta == NULL || sta->sa_query_trans_id == NULL) { wpa_printf(MSG_DEBUG, "IEEE 802.11: No matching STA with " "pending SA Query request found"); return; } for (i = 0; i < sta->sa_query_count; i++) { if (os_memcmp(sta->sa_query_trans_id + i * WLAN_SA_QUERY_TR_ID_LEN, mgmt->u.action.u.sa_query_resp.trans_id, WLAN_SA_QUERY_TR_ID_LEN) == 0) break; } if (i >= sta->sa_query_count) { wpa_printf(MSG_DEBUG, "IEEE 802.11: No matching SA Query " "transaction identifier found"); return; } hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_DEBUG, "Reply to pending SA Query received"); ap_sta_stop_sa_query(hapd, sta);}#endif /* CONFIG_IEEE80211W */static void handle_action(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt, size_t len){ 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; } switch (mgmt->u.action.category) {#ifdef CONFIG_IEEE80211R case WLAN_ACTION_FT: { struct sta_info *sta; sta = ap_get_sta(hapd, mgmt->sa);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -