📄 mlme.c
字号:
int count; u8 *pos; if (wmm_param_len < 8 || wmm_param[5] /* version */ != 1) return; count = wmm_param[6] & 0x0f; if (count == wpa_s->mlme.wmm_last_param_set) return; wpa_s->mlme.wmm_last_param_set = count; pos = wmm_param + 8; left = wmm_param_len - 8;#if 0 /* FIX */ wmm_acm = 0; for (; left >= 4; left -= 4, pos += 4) { int aci = (pos[0] >> 5) & 0x03; int acm = (pos[0] >> 4) & 0x01; int queue; switch (aci) { case 1: queue = IEEE80211_TX_QUEUE_DATA3; if (acm) wmm_acm |= BIT(1) | BIT(2); break; case 2: queue = IEEE80211_TX_QUEUE_DATA1; if (acm) wmm_acm |= BIT(4) | BIT(5); break; case 3: queue = IEEE80211_TX_QUEUE_DATA0; if (acm) wmm_acm |= BIT(6) | BIT(7); break; case 0: default: queue = IEEE80211_TX_QUEUE_DATA2; if (acm) wpa_s->mlme.wmm_acm |= BIT(0) | BIT(3); break; } params.aifs = pos[0] & 0x0f; params.cw_max = ecw2cw((pos[1] & 0xf0) >> 4); params.cw_min = ecw2cw(pos[1] & 0x0f); /* TXOP is in units of 32 usec; burst_time in 0.1 ms */ params.burst_time = (pos[2] | (pos[3] << 8)) * 32 / 100; wpa_printf(MSG_DEBUG, "MLME: WMM queue=%d aci=%d acm=%d " "aifs=%d cWmin=%d cWmax=%d burst=%d", queue, aci, acm, params.aifs, params.cw_min, params.cw_max, params.burst_time); /* TODO: handle ACM (block TX, fallback to next lowest allowed * AC for now) */ if (local->hw->conf_tx(local->mdev, queue, ¶ms)) { wpa_printf(MSG_DEBUG, "MLME: failed to set TX queue " "parameters for queue %d", queue); } }#endif}static void ieee80211_set_associated(struct wpa_supplicant *wpa_s, int assoc){ if (wpa_s->mlme.associated == assoc) return; wpa_s->mlme.associated = assoc; if (assoc) { union wpa_event_data data; os_memset(&data, 0, sizeof(data)); wpa_s->mlme.prev_bssid_set = 1; os_memcpy(wpa_s->mlme.prev_bssid, wpa_s->bssid, ETH_ALEN); data.assoc_info.req_ies = wpa_s->mlme.assocreq_ies; data.assoc_info.req_ies_len = wpa_s->mlme.assocreq_ies_len; data.assoc_info.resp_ies = wpa_s->mlme.assocresp_ies; data.assoc_info.resp_ies_len = wpa_s->mlme.assocresp_ies_len; wpa_supplicant_event(wpa_s, EVENT_ASSOC, &data); } else { wpa_supplicant_event(wpa_s, EVENT_DISASSOC, NULL); } os_get_time(&wpa_s->mlme.last_probe);}static void ieee80211_sta_tx(struct wpa_supplicant *wpa_s, const u8 *buf, size_t len){ wpa_drv_send_mlme(wpa_s, buf, len);}static void ieee80211_send_auth(struct wpa_supplicant *wpa_s, int transaction, u8 *extra, size_t extra_len, int encrypt){ u8 *buf; size_t len; struct ieee80211_mgmt *mgmt; buf = os_malloc(sizeof(*mgmt) + 6 + extra_len); if (buf == NULL) { wpa_printf(MSG_DEBUG, "MLME: failed to allocate buffer for " "auth frame"); return; } mgmt = (struct ieee80211_mgmt *) buf; len = 24 + 6; os_memset(mgmt, 0, 24 + 6); mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_AUTH); if (encrypt) mgmt->frame_control |= host_to_le16(WLAN_FC_ISWEP); os_memcpy(mgmt->da, wpa_s->bssid, ETH_ALEN); os_memcpy(mgmt->sa, wpa_s->own_addr, ETH_ALEN); os_memcpy(mgmt->bssid, wpa_s->bssid, ETH_ALEN); mgmt->u.auth.auth_alg = host_to_le16(wpa_s->mlme.auth_alg); mgmt->u.auth.auth_transaction = host_to_le16(transaction); wpa_s->mlme.auth_transaction = transaction + 1; mgmt->u.auth.status_code = host_to_le16(0); if (extra) { os_memcpy(buf + len, extra, extra_len); len += extra_len; } ieee80211_sta_tx(wpa_s, buf, len); os_free(buf);}static void ieee80211_reschedule_timer(struct wpa_supplicant *wpa_s, int ms){ eloop_cancel_timeout(ieee80211_sta_timer, wpa_s, NULL); eloop_register_timeout(ms / 1000, 1000 * (ms % 1000), ieee80211_sta_timer, wpa_s, NULL);}static void ieee80211_authenticate(struct wpa_supplicant *wpa_s){ wpa_s->mlme.auth_tries++; if (wpa_s->mlme.auth_tries > IEEE80211_AUTH_MAX_TRIES) { wpa_printf(MSG_DEBUG, "MLME: authentication with AP " MACSTR " timed out", MAC2STR(wpa_s->bssid)); return; } wpa_s->mlme.state = IEEE80211_AUTHENTICATE; wpa_printf(MSG_DEBUG, "MLME: authenticate with AP " MACSTR, MAC2STR(wpa_s->bssid)); ieee80211_send_auth(wpa_s, 1, NULL, 0, 0); ieee80211_reschedule_timer(wpa_s, IEEE80211_AUTH_TIMEOUT);}static void ieee80211_send_assoc(struct wpa_supplicant *wpa_s){ struct ieee80211_mgmt *mgmt; u8 *pos, *ies, *buf; int i, len; u16 capab; struct ieee80211_sta_bss *bss; int wmm = 0; size_t blen; if (wpa_s->mlme.curr_rates == NULL) { wpa_printf(MSG_DEBUG, "MLME: curr_rates not set for assoc"); return; } buf = os_malloc(sizeof(*mgmt) + 200 + wpa_s->mlme.extra_ie_len + wpa_s->mlme.ssid_len); if (buf == NULL) { wpa_printf(MSG_DEBUG, "MLME: failed to allocate buffer for " "assoc frame"); return; } blen = 0; capab = wpa_s->mlme.capab; if (wpa_s->mlme.phymode == WPA_MODE_IEEE80211G) { capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME | WLAN_CAPABILITY_SHORT_PREAMBLE; } bss = ieee80211_bss_get(wpa_s, wpa_s->bssid); if (bss) { if (bss->capability & WLAN_CAPABILITY_PRIVACY) capab |= WLAN_CAPABILITY_PRIVACY; if (bss->wmm_ie) { wmm = 1; } } mgmt = (struct ieee80211_mgmt *) buf; blen += 24; os_memset(mgmt, 0, 24); os_memcpy(mgmt->da, wpa_s->bssid, ETH_ALEN); os_memcpy(mgmt->sa, wpa_s->own_addr, ETH_ALEN); os_memcpy(mgmt->bssid, wpa_s->bssid, ETH_ALEN); if (wpa_s->mlme.prev_bssid_set) { blen += 10; mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_REASSOC_REQ); mgmt->u.reassoc_req.capab_info = host_to_le16(capab); mgmt->u.reassoc_req.listen_interval = host_to_le16(1); os_memcpy(mgmt->u.reassoc_req.current_ap, wpa_s->mlme.prev_bssid, ETH_ALEN); } else { blen += 4; mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_ASSOC_REQ); mgmt->u.assoc_req.capab_info = host_to_le16(capab); mgmt->u.assoc_req.listen_interval = host_to_le16(1); } /* SSID */ ies = pos = buf + blen; blen += 2 + wpa_s->mlme.ssid_len; *pos++ = WLAN_EID_SSID; *pos++ = wpa_s->mlme.ssid_len; os_memcpy(pos, wpa_s->mlme.ssid, wpa_s->mlme.ssid_len); len = wpa_s->mlme.num_curr_rates; if (len > 8) len = 8; pos = buf + blen; blen += len + 2; *pos++ = WLAN_EID_SUPP_RATES; *pos++ = len; for (i = 0; i < len; i++) { int rate = wpa_s->mlme.curr_rates[i].rate; *pos++ = (u8) (rate / 5); } if (wpa_s->mlme.num_curr_rates > len) { pos = buf + blen; blen += wpa_s->mlme.num_curr_rates - len + 2; *pos++ = WLAN_EID_EXT_SUPP_RATES; *pos++ = wpa_s->mlme.num_curr_rates - len; for (i = len; i < wpa_s->mlme.num_curr_rates; i++) { int rate = wpa_s->mlme.curr_rates[i].rate; *pos++ = (u8) (rate / 5); } } if (wpa_s->mlme.extra_ie) { pos = buf + blen; blen += wpa_s->mlme.extra_ie_len; os_memcpy(pos, wpa_s->mlme.extra_ie, wpa_s->mlme.extra_ie_len); } if (wmm && wpa_s->mlme.wmm_enabled) { pos = buf + blen; blen += 9; *pos++ = WLAN_EID_VENDOR_SPECIFIC; *pos++ = 7; /* len */ *pos++ = 0x00; /* Microsoft OUI 00:50:F2 */ *pos++ = 0x50; *pos++ = 0xf2; *pos++ = 2; /* WME */ *pos++ = 0; /* WME info */ *pos++ = 1; /* WME ver */ *pos++ = 0; } os_free(wpa_s->mlme.assocreq_ies); wpa_s->mlme.assocreq_ies_len = (buf + blen) - ies; wpa_s->mlme.assocreq_ies = os_malloc(wpa_s->mlme.assocreq_ies_len); if (wpa_s->mlme.assocreq_ies) { os_memcpy(wpa_s->mlme.assocreq_ies, ies, wpa_s->mlme.assocreq_ies_len); } ieee80211_sta_tx(wpa_s, buf, blen); os_free(buf);}static void ieee80211_send_deauth(struct wpa_supplicant *wpa_s, u16 reason){ u8 *buf; size_t len; struct ieee80211_mgmt *mgmt; buf = os_zalloc(sizeof(*mgmt)); if (buf == NULL) { wpa_printf(MSG_DEBUG, "MLME: failed to allocate buffer for " "deauth frame"); return; } mgmt = (struct ieee80211_mgmt *) buf; len = 24; os_memcpy(mgmt->da, wpa_s->bssid, ETH_ALEN); os_memcpy(mgmt->sa, wpa_s->own_addr, ETH_ALEN); os_memcpy(mgmt->bssid, wpa_s->bssid, ETH_ALEN); mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_DEAUTH); len += 2; mgmt->u.deauth.reason_code = host_to_le16(reason); ieee80211_sta_tx(wpa_s, buf, len); os_free(buf);}static void ieee80211_send_disassoc(struct wpa_supplicant *wpa_s, u16 reason){ u8 *buf; size_t len; struct ieee80211_mgmt *mgmt; buf = os_zalloc(sizeof(*mgmt)); if (buf == NULL) { wpa_printf(MSG_DEBUG, "MLME: failed to allocate buffer for " "disassoc frame"); return; } mgmt = (struct ieee80211_mgmt *) buf; len = 24; os_memcpy(mgmt->da, wpa_s->bssid, ETH_ALEN); os_memcpy(mgmt->sa, wpa_s->own_addr, ETH_ALEN); os_memcpy(mgmt->bssid, wpa_s->bssid, ETH_ALEN); mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_DISASSOC); len += 2; mgmt->u.disassoc.reason_code = host_to_le16(reason); ieee80211_sta_tx(wpa_s, buf, len); os_free(buf);}static int ieee80211_privacy_mismatch(struct wpa_supplicant *wpa_s){ struct ieee80211_sta_bss *bss; int res = 0; if (wpa_s->mlme.mixed_cell || wpa_s->mlme.key_mgmt != KEY_MGMT_NONE) return 0; bss = ieee80211_bss_get(wpa_s, wpa_s->bssid); if (bss == NULL) return 0; if (ieee80211_sta_wep_configured(wpa_s) != !!(bss->capability & WLAN_CAPABILITY_PRIVACY)) res = 1; return res;}static void ieee80211_associate(struct wpa_supplicant *wpa_s){ wpa_s->mlme.assoc_tries++; if (wpa_s->mlme.assoc_tries > IEEE80211_ASSOC_MAX_TRIES) { wpa_printf(MSG_DEBUG, "MLME: association with AP " MACSTR " timed out", MAC2STR(wpa_s->bssid)); return; } wpa_s->mlme.state = IEEE80211_ASSOCIATE; wpa_printf(MSG_DEBUG, "MLME: associate with AP " MACSTR, MAC2STR(wpa_s->bssid)); if (ieee80211_privacy_mismatch(wpa_s)) { wpa_printf(MSG_DEBUG, "MLME: mismatch in privacy " "configuration and mixed-cell disabled - abort " "association"); return; } ieee80211_send_assoc(wpa_s); ieee80211_reschedule_timer(wpa_s, IEEE80211_ASSOC_TIMEOUT);}static void ieee80211_associated(struct wpa_supplicant *wpa_s){ int disassoc; /* TODO: start monitoring current AP signal quality and number of * missed beacons. Scan other channels every now and then and search * for better APs. */ /* TODO: remove expired BSSes */ wpa_s->mlme.state = IEEE80211_ASSOCIATED;#if 0 /* FIX */ sta = sta_info_get(local, wpa_s->bssid); if (sta == NULL) { wpa_printf(MSG_DEBUG "MLME: No STA entry for own AP " MACSTR, MAC2STR(wpa_s->bssid)); disassoc = 1; } else { disassoc = 0; if (time_after(jiffies, sta->last_rx + IEEE80211_MONITORING_INTERVAL)) { if (wpa_s->mlme.probereq_poll) { wpa_printf(MSG_DEBUG "MLME: No ProbeResp from " "current AP " MACSTR " - assume " "out of range", MAC2STR(wpa_s->bssid)); disassoc = 1; } else { ieee80211_send_probe_req( wpa_s->bssid, wpa_s->mlme.scan_ssid, wpa_s->mlme.scan_ssid_len); wpa_s->mlme.probereq_poll = 1; } } else { wpa_s->mlme.probereq_poll = 0; if (time_after(jiffies, wpa_s->mlme.last_probe + IEEE80211_PROBE_INTERVAL)) { wpa_s->mlme.last_probe = jiffies; ieee80211_send_probe_req(wpa_s->bssid, wpa_s->mlme.ssid, wpa_s->mlme.ssid_len); } } sta_info_release(local, sta); }#else disassoc = 0;#endif if (disassoc) { wpa_supplicant_event(wpa_s, EVENT_DISASSOC, NULL); ieee80211_reschedule_timer(wpa_s, IEEE80211_MONITORING_INTERVAL + 30000); } else { ieee80211_reschedule_timer(wpa_s, IEEE80211_MONITORING_INTERVAL); }}static void ieee80211_send_probe_req(struct wpa_supplicant *wpa_s, const u8 *dst, const u8 *ssid, size_t ssid_len){ u8 *buf; size_t len; struct ieee80211_mgmt *mgmt; u8 *pos, *supp_rates; u8 *esupp_rates = NULL; int i; buf = os_malloc(sizeof(*mgmt) + 200); if (buf == NULL) { wpa_printf(MSG_DEBUG, "MLME: failed to allocate buffer for " "probe request"); return; } mgmt = (struct ieee80211_mgmt *) buf; len = 24; os_memset(mgmt, 0, 24); mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_PROBE_REQ); os_memcpy(mgmt->sa, wpa_s->own_addr, ETH_ALEN); if (dst) { os_memcpy(mgmt->da, dst, ETH_ALEN); os_memcpy(mgmt->bssid, dst, ETH_ALEN); } else { os_memset(mgmt->da, 0xff, ETH_ALEN); os_memset(mgmt->bssid, 0xff, ETH_ALEN); } pos = buf + len; len += 2 + ssid_len; *pos++ = WLAN_EID_SSID; *pos++ = ssid_len; os_memcpy(pos, ssid, ssid_len); supp_rates = buf + len; len += 2; supp_rates[0] = WLAN_EID_SUPP_RATES; supp_rates[1] = 0; for (i = 0; i < wpa_s->mlme.num_curr_rates; i++) { struct wpa_rate_data *rate = &wpa_s->mlme.curr_rates[i]; if (!(rate->flags & WPA_RATE_SUPPORTED)) continue; if (esupp_rates) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -