📄 mlme.c
字号:
static void ieee80211_bss_info(struct wpa_supplicant *wpa_s, struct ieee80211_mgmt *mgmt, size_t len, struct ieee80211_rx_status *rx_status, int beacon){ struct ieee802_11_elems elems; size_t baselen; int channel, invalid = 0, clen; struct ieee80211_sta_bss *bss; u64 timestamp; u8 *pos; if (!beacon && os_memcmp(mgmt->da, wpa_s->own_addr, ETH_ALEN)) return; /* ignore ProbeResp to foreign address */#if 0 wpa_printf(MSG_MSGDUMP, "MLME: RX %s from " MACSTR " to " MACSTR, beacon ? "Beacon" : "Probe Response", MAC2STR(mgmt->sa), MAC2STR(mgmt->da));#endif baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt; if (baselen > len) return; pos = mgmt->u.beacon.timestamp; timestamp = ((u64) pos[7] << 56) | ((u64) pos[6] << 48) | ((u64) pos[5] << 40) | ((u64) pos[4] << 32) | ((u64) pos[3] << 24) | ((u64) pos[2] << 16) | ((u64) pos[1] << 8) | ((u64) pos[0]);#if 0 /* FIX */ if (local->conf.mode == IW_MODE_ADHOC && beacon && os_memcmp(mgmt->bssid, local->bssid, ETH_ALEN) == 0) {#ifdef IEEE80211_IBSS_DEBUG static unsigned long last_tsf_debug = 0; u64 tsf; if (local->hw->get_tsf) tsf = local->hw->get_tsf(local->mdev); else tsf = -1LLU; if (time_after(jiffies, last_tsf_debug + 5 * HZ)) { wpa_printf(MSG_DEBUG, "RX beacon SA=" MACSTR " BSSID=" MACSTR " TSF=0x%llx BCN=0x%llx diff=%lld " "@%ld", MAC2STR(mgmt->sa), MAC2STR(mgmt->bssid), tsf, timestamp, tsf - timestamp, jiffies); last_tsf_debug = jiffies; }#endif /* IEEE80211_IBSS_DEBUG */ }#endif if (ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems) == ParseFailed) invalid = 1;#if 0 /* FIX */ if (local->conf.mode == IW_MODE_ADHOC && elems.supp_rates && os_memcmp(mgmt->bssid, local->bssid, ETH_ALEN) == 0 && (sta = sta_info_get(local, mgmt->sa))) { struct ieee80211_rate *rates; size_t num_rates; u32 supp_rates, prev_rates; int i, j, oper_mode; rates = local->curr_rates; num_rates = local->num_curr_rates; oper_mode = wpa_s->mlme.sta_scanning ? local->scan_oper_phymode : local->conf.phymode; for (i = 0; i < local->hw->num_modes; i++) { struct ieee80211_hw_modes *mode = &local->hw->modes[i]; if (oper_mode == mode->mode) { rates = mode->rates; num_rates = mode->num_rates; break; } } supp_rates = 0; for (i = 0; i < elems.supp_rates_len + elems.ext_supp_rates_len; i++) { u8 rate = 0; int own_rate; if (i < elems.supp_rates_len) rate = elems.supp_rates[i]; else if (elems.ext_supp_rates) rate = elems.ext_supp_rates [i - elems.supp_rates_len]; own_rate = 5 * (rate & 0x7f); if (oper_mode == MODE_ATHEROS_TURBO) own_rate *= 2; for (j = 0; j < num_rates; j++) if (rates[j].rate == own_rate) supp_rates |= BIT(j); } prev_rates = sta->supp_rates; sta->supp_rates &= supp_rates; if (sta->supp_rates == 0) { /* No matching rates - this should not really happen. * Make sure that at least one rate is marked * supported to avoid issues with TX rate ctrl. */ sta->supp_rates = wpa_s->mlme.supp_rates_bits; } if (sta->supp_rates != prev_rates) { wpa_printf(MSG_DEBUG, "MLME: updated supp_rates set " "for " MACSTR " based on beacon info " "(0x%x & 0x%x -> 0x%x)", MAC2STR(sta->addr), prev_rates, supp_rates, sta->supp_rates); } sta_info_release(local, sta); }#endif if (elems.ssid == NULL) return; if (elems.ds_params && elems.ds_params_len == 1) channel = elems.ds_params[0]; else channel = rx_status->channel; bss = ieee80211_bss_get(wpa_s, mgmt->bssid); if (bss == NULL) { bss = ieee80211_bss_add(wpa_s, mgmt->bssid); if (bss == NULL) return; } else {#if 0 /* TODO: order by RSSI? */ spin_lock_bh(&local->sta_bss_lock); list_move_tail(&bss->list, &local->sta_bss_list); spin_unlock_bh(&local->sta_bss_lock);#endif } if (bss->probe_resp && beacon) { /* Do not allow beacon to override data from Probe Response. */ return; } bss->beacon_int = le_to_host16(mgmt->u.beacon.beacon_int); bss->capability = le_to_host16(mgmt->u.beacon.capab_info); if (elems.ssid && elems.ssid_len <= MAX_SSID_LEN) { os_memcpy(bss->ssid, elems.ssid, elems.ssid_len); bss->ssid_len = elems.ssid_len; } bss->supp_rates_len = 0; if (elems.supp_rates) { clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len; if (clen > elems.supp_rates_len) clen = elems.supp_rates_len; os_memcpy(&bss->supp_rates[bss->supp_rates_len], elems.supp_rates, clen); bss->supp_rates_len += clen; } if (elems.ext_supp_rates) { clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len; if (clen > elems.ext_supp_rates_len) clen = elems.ext_supp_rates_len; os_memcpy(&bss->supp_rates[bss->supp_rates_len], elems.ext_supp_rates, clen); bss->supp_rates_len += clen; } if (elems.wpa && (bss->wpa_ie == NULL || bss->wpa_ie_len != elems.wpa_len || os_memcmp(bss->wpa_ie, elems.wpa, elems.wpa_len))) { os_free(bss->wpa_ie); bss->wpa_ie = os_malloc(elems.wpa_len + 2); if (bss->wpa_ie) { os_memcpy(bss->wpa_ie, elems.wpa - 2, elems.wpa_len + 2); bss->wpa_ie_len = elems.wpa_len + 2; } else bss->wpa_ie_len = 0; } else if (!elems.wpa && bss->wpa_ie) { os_free(bss->wpa_ie); bss->wpa_ie = NULL; bss->wpa_ie_len = 0; } if (elems.rsn && (bss->rsn_ie == NULL || bss->rsn_ie_len != elems.rsn_len || os_memcmp(bss->rsn_ie, elems.rsn, elems.rsn_len))) { os_free(bss->rsn_ie); bss->rsn_ie = os_malloc(elems.rsn_len + 2); if (bss->rsn_ie) { os_memcpy(bss->rsn_ie, elems.rsn - 2, elems.rsn_len + 2); bss->rsn_ie_len = elems.rsn_len + 2; } else bss->rsn_ie_len = 0; } else if (!elems.rsn && bss->rsn_ie) { os_free(bss->rsn_ie); bss->rsn_ie = NULL; bss->rsn_ie_len = 0; } if (elems.wmm_param && (bss->wmm_ie == NULL || bss->wmm_ie_len != elems.wmm_param_len || os_memcmp(bss->wmm_ie, elems.wmm_param, elems.wmm_param_len))) { os_free(bss->wmm_ie); bss->wmm_ie = os_malloc(elems.wmm_param_len + 2); if (bss->wmm_ie) { os_memcpy(bss->wmm_ie, elems.wmm_param - 2, elems.wmm_param_len + 2); bss->wmm_ie_len = elems.wmm_param_len + 2; } else bss->wmm_ie_len = 0; } else if (!elems.wmm_param && bss->wmm_ie) { os_free(bss->wmm_ie); bss->wmm_ie = NULL; bss->wmm_ie_len = 0; } bss->hw_mode = wpa_s->mlme.phymode; bss->channel = channel; bss->freq = wpa_s->mlme.freq; if (channel != wpa_s->mlme.channel && (wpa_s->mlme.phymode == WPA_MODE_IEEE80211G || wpa_s->mlme.phymode == WPA_MODE_IEEE80211B) && channel >= 1 && channel <= 14) { static const int freq_list[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 2457, 2462, 2467, 2472, 2484 }; /* IEEE 802.11g/b mode can receive packets from neighboring * channels, so map the channel into frequency. */ bss->freq = freq_list[channel - 1]; } bss->timestamp = timestamp; os_get_time(&bss->last_update); bss->rssi = rx_status->ssi; if (!beacon) bss->probe_resp++;}static void ieee80211_rx_mgmt_probe_resp(struct wpa_supplicant *wpa_s, struct ieee80211_mgmt *mgmt, size_t len, struct ieee80211_rx_status *rx_status){ ieee80211_bss_info(wpa_s, mgmt, len, rx_status, 0);}static void ieee80211_rx_mgmt_beacon(struct wpa_supplicant *wpa_s, struct ieee80211_mgmt *mgmt, size_t len, struct ieee80211_rx_status *rx_status){ int use_protection; size_t baselen; struct ieee802_11_elems elems; ieee80211_bss_info(wpa_s, mgmt, len, rx_status, 1); if (!wpa_s->mlme.associated || os_memcmp(wpa_s->bssid, mgmt->bssid, ETH_ALEN) != 0) return; /* Process beacon from the current BSS */ baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt; if (baselen > len) return; if (ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems) == ParseFailed) return; use_protection = 0; if (elems.erp_info && elems.erp_info_len >= 1) { use_protection = (elems.erp_info[0] & ERP_INFO_USE_PROTECTION) != 0; } if (use_protection != !!wpa_s->mlme.use_protection) { wpa_printf(MSG_DEBUG, "MLME: CTS protection %s (BSSID=" MACSTR ")", use_protection ? "enabled" : "disabled", MAC2STR(wpa_s->bssid)); wpa_s->mlme.use_protection = use_protection ? 1 : 0; wpa_s->mlme.cts_protect_erp_frames = use_protection; } if (elems.wmm_param && wpa_s->mlme.wmm_enabled) { ieee80211_sta_wmm_params(wpa_s, elems.wmm_param, elems.wmm_param_len); }}static void ieee80211_rx_mgmt_probe_req(struct wpa_supplicant *wpa_s, struct ieee80211_mgmt *mgmt, size_t len, struct ieee80211_rx_status *rx_status){ int tx_last_beacon, adhoc;#if 0 /* FIX */ struct ieee80211_mgmt *resp;#endif u8 *pos, *end; struct wpa_ssid *ssid = wpa_s->current_ssid; adhoc = ssid && ssid->mode == 1; if (!adhoc || wpa_s->mlme.state != IEEE80211_IBSS_JOINED || len < 24 + 2 || wpa_s->mlme.probe_resp == NULL) return;#if 0 /* FIX */ if (local->hw->tx_last_beacon) tx_last_beacon = local->hw->tx_last_beacon(local->mdev); else#endif tx_last_beacon = 1;#ifdef IEEE80211_IBSS_DEBUG wpa_printf(MSG_DEBUG, "MLME: RX ProbeReq SA=" MACSTR " DA=" MACSTR " BSSID=" MACSTR " (tx_last_beacon=%d)", MAC2STR(mgmt->sa), MAC2STR(mgmt->da), MAC2STR(mgmt->bssid), tx_last_beacon);#endif /* IEEE80211_IBSS_DEBUG */ if (!tx_last_beacon) return; if (os_memcmp(mgmt->bssid, wpa_s->bssid, ETH_ALEN) != 0 && os_memcmp(mgmt->bssid, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) != 0) return; end = ((u8 *) mgmt) + len; pos = mgmt->u.probe_req.variable; if (pos[0] != WLAN_EID_SSID || pos + 2 + pos[1] > end) { wpa_printf(MSG_DEBUG, "MLME: Invalid SSID IE in ProbeReq from " MACSTR, MAC2STR(mgmt->sa)); return; } if (pos[1] != 0 && (pos[1] != wpa_s->mlme.ssid_len || os_memcmp(pos + 2, wpa_s->mlme.ssid, wpa_s->mlme.ssid_len) != 0)) { /* Ignore ProbeReq for foreign SSID */ return; }#if 0 /* FIX */ /* Reply with ProbeResp */ skb = skb_copy(wpa_s->mlme.probe_resp, GFP_ATOMIC); if (skb == NULL) return; resp = (struct ieee80211_mgmt *) skb->data; os_memcpy(resp->da, mgmt->sa, ETH_ALEN);#ifdef IEEE80211_IBSS_DEBUG wpa_printf(MSG_DEBUG, "MLME: Sending ProbeResp to " MACSTR, MAC2STR(resp->da));#endif /* IEEE80211_IBSS_DEBUG */ ieee80211_sta_tx(wpa_s, skb, 0, 1);#endif}static void ieee80211_sta_rx_mgmt(struct wpa_supplicant *wpa_s, const u8 *buf, size_t len, struct ieee80211_rx_status *rx_status){ struct ieee80211_mgmt *mgmt; u16 fc; if (len < 24) return; mgmt = (struct ieee80211_mgmt *) buf; fc = le_to_host16(mgmt->frame_control); switch (WLAN_FC_GET_STYPE(fc)) { case WLAN_FC_STYPE_PROBE_REQ: ieee80211_rx_mgmt_probe_req(wpa_s, mgmt, len, rx_status); break; case WLAN_FC_STYPE_PROBE_RESP: ieee80211_rx_mgmt_probe_resp(wpa_s, mgmt, len, rx_status); break; case WLAN_FC_STYPE_BEACON: ieee80211_rx_mgmt_beacon(wpa_s, mgmt, len, rx_status); break; case WLAN_FC_STYPE_AUTH: ieee80211_rx_mgmt_auth(wpa_s, mgmt, len, rx_status); break; case WLAN_FC_STYPE_ASSOC_RESP: ieee80211_rx_mgmt_assoc_resp(wpa_s, mgmt, len, rx_status, 0); break; case WLAN_FC_STYPE_REASSOC_RESP: ieee80211_rx_mgmt_assoc_resp(wpa_s, mgmt, len, rx_status, 1); break; case WLAN_FC_STYPE_DEAUTH: ieee80211_rx_mgmt_deauth(wpa_s, mgmt, len, rx_status); break; case WLAN_FC_STYPE_DISASSOC: ieee80211_rx_mgmt_disassoc(wpa_s, mgmt, len, rx_status); break; default: wpa_printf(MSG_DEBUG, "MLME: received unknown management " "frame - stype=%d", WLAN_FC_GET_STYPE(fc)); break; }}static void ieee80211_sta_rx_scan(struct wpa_supplicant *wpa_s, const u8 *buf, size_t len, struct ieee80211_rx_status *rx_status){ struct ieee80211_mgmt *mgmt; u16 fc; if (len < 24) return; mgmt = (struct ieee80211_mgmt *) buf; fc = le_to_host16(mgmt->frame_control); if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT) { if (WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_RESP) { ieee80211_rx_mgmt_probe_resp(wpa_s, mgmt, len, rx_status); } else if (WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON) { ieee80211_rx_mgmt_beacon(wpa_s, mgmt, len, rx_status); } }}static int ieee80211_sta_active_ibss(struct wpa_supplicant *wpa_s){ int active = 0;#if 0 /* FIX */ list_for_each(ptr, &local->sta_list) { sta = list_entry(ptr, struct sta_info, list); if (sta->dev == dev && time_after(sta->last_rx + IEEE80211_IBSS_MERGE_INTERVAL, jiffies)) { active++; break; } }#endif return active;}static void ieee80211_sta_expire(struct wpa_supplicant *wpa_s){#if 0 /* FIX */ list_for_each_safe(ptr, n, &local->sta_list) { sta = list_entry(ptr, struct sta_info, list); if (time_after(jiffies, sta->last_rx + IEEE80211_IBSS_INACTIVITY_LIMIT)) { wpa_printf(MSG_DEBUG, "MLME: expiring inactive STA " MACSTR, MAC2STR(sta->addr)); sta_info_free(local, sta, 1); } }#endif}static void ieee80211_sta_merge_ibss(struct wpa_supplicant *wpa_s){ ieee80211_reschedule_timer(wpa_s, IEEE80211_IBSS_MERGE_INTERVAL); ieee80211_sta_expire(wpa_s); if (ieee80211_sta_active_ibss(wpa_s)) return; wpa_printf(MSG_DEBUG, "MLME: No active IBSS STAs - trying to scan for " "other IBSS networks with same SSID (merge)"); ieee80211_sta_req_scan(wpa_s, wpa_s->mlme.ssid, wpa_s->mlme.ssid_len);}static void ieee80211_sta_timer(void *eloop_ctx, void *timeout_ctx){ struct wpa_supplicant *wpa_s = eloop_ctx;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -