📄 mlme.c
字号:
switch (wpa_s->mlme.state) { case IEEE80211_DISABLED: break; case IEEE80211_AUTHENTICATE: ieee80211_authenticate(wpa_s); break; case IEEE80211_ASSOCIATE: ieee80211_associate(wpa_s); break; case IEEE80211_ASSOCIATED: ieee80211_associated(wpa_s); break; case IEEE80211_IBSS_SEARCH: ieee80211_sta_find_ibss(wpa_s); break; case IEEE80211_IBSS_JOINED: ieee80211_sta_merge_ibss(wpa_s); break; default: wpa_printf(MSG_DEBUG, "ieee80211_sta_timer: Unknown state %d", wpa_s->mlme.state); break; } if (ieee80211_privacy_mismatch(wpa_s)) { wpa_printf(MSG_DEBUG, "MLME: privacy configuration mismatch " "and mixed-cell disabled - disassociate"); ieee80211_send_disassoc(wpa_s, WLAN_REASON_UNSPECIFIED); ieee80211_set_associated(wpa_s, 0); }}static void ieee80211_sta_new_auth(struct wpa_supplicant *wpa_s){ struct wpa_ssid *ssid = wpa_s->current_ssid; if (ssid && ssid->mode != 0) return;#if 0 /* FIX */ if (local->hw->reset_tsf) { /* Reset own TSF to allow time synchronization work. */ local->hw->reset_tsf(local->mdev); }#endif wpa_s->mlme.wmm_last_param_set = -1; /* allow any WMM update */ if (wpa_s->mlme.auth_algs & IEEE80211_AUTH_ALG_OPEN) wpa_s->mlme.auth_alg = WLAN_AUTH_OPEN; else if (wpa_s->mlme.auth_algs & IEEE80211_AUTH_ALG_SHARED_KEY) wpa_s->mlme.auth_alg = WLAN_AUTH_SHARED_KEY; else if (wpa_s->mlme.auth_algs & IEEE80211_AUTH_ALG_LEAP) wpa_s->mlme.auth_alg = WLAN_AUTH_LEAP; else wpa_s->mlme.auth_alg = WLAN_AUTH_OPEN; wpa_printf(MSG_DEBUG, "MLME: Initial auth_alg=%d", wpa_s->mlme.auth_alg); wpa_s->mlme.auth_transaction = -1; wpa_s->mlme.auth_tries = wpa_s->mlme.assoc_tries = 0; ieee80211_authenticate(wpa_s);}static int ieee80211_ibss_allowed(struct wpa_supplicant *wpa_s){#if 0 /* FIX */ int m, c; for (m = 0; m < local->hw->num_modes; m++) { struct ieee80211_hw_modes *mode = &local->hw->modes[m]; if (mode->mode != local->conf.phymode) continue; for (c = 0; c < mode->num_channels; c++) { struct ieee80211_channel *chan = &mode->channels[c]; if (chan->flag & IEEE80211_CHAN_W_SCAN && chan->chan == local->conf.channel) { if (chan->flag & IEEE80211_CHAN_W_IBSS) return 1; break; } } }#endif return 0;}static int ieee80211_sta_join_ibss(struct wpa_supplicant *wpa_s, struct ieee80211_sta_bss *bss){ int res = 0, rates, done = 0; struct ieee80211_mgmt *mgmt;#if 0 /* FIX */ struct ieee80211_tx_control control; struct ieee80211_rate *rate; struct rate_control_extra extra;#endif u8 *pos, *buf; size_t len; /* Remove possible STA entries from other IBSS networks. */#if 0 /* FIX */ sta_info_flush(local, NULL); if (local->hw->reset_tsf) { /* Reset own TSF to allow time synchronization work. */ local->hw->reset_tsf(local->mdev); }#endif os_memcpy(wpa_s->bssid, bss->bssid, ETH_ALEN);#if 0 /* FIX */ local->conf.beacon_int = bss->beacon_int >= 10 ? bss->beacon_int : 10; sdata->drop_unencrypted = bss->capability & host_to_le16(WLAN_CAPABILITY_PRIVACY) ? 1 : 0;#endif#if 0 /* FIX */ os_memset(&rq, 0, sizeof(rq)); rq.m = bss->freq * 100000; rq.e = 1; res = ieee80211_ioctl_siwfreq(wpa_s, NULL, &rq, NULL);#endif if (!ieee80211_ibss_allowed(wpa_s)) {#if 0 /* FIX */ wpa_printf(MSG_DEBUG, "MLME: IBSS not allowed on channel %d " "(%d MHz)", local->conf.channel, local->conf.freq);#endif return -1; } /* Set beacon template based on scan results */ buf = os_malloc(400); len = 0; do { if (buf == NULL) break; mgmt = (struct ieee80211_mgmt *) buf; len += 24 + sizeof(mgmt->u.beacon); os_memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon)); mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_BEACON); os_memset(mgmt->da, 0xff, ETH_ALEN); os_memcpy(mgmt->sa, wpa_s->own_addr, ETH_ALEN); os_memcpy(mgmt->bssid, wpa_s->bssid, ETH_ALEN);#if 0 /* FIX */ mgmt->u.beacon.beacon_int = host_to_le16(local->conf.beacon_int);#endif mgmt->u.beacon.capab_info = host_to_le16(bss->capability); pos = buf + len; len += 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); rates = bss->supp_rates_len; if (rates > 8) rates = 8; pos = buf + len; len += 2 + rates; *pos++ = WLAN_EID_SUPP_RATES; *pos++ = rates; os_memcpy(pos, bss->supp_rates, rates); pos = buf + len; len += 2 + 1; *pos++ = WLAN_EID_DS_PARAMS; *pos++ = 1; *pos++ = bss->channel; pos = buf + len; len += 2 + 2; *pos++ = WLAN_EID_IBSS_PARAMS; *pos++ = 2; /* FIX: set ATIM window based on scan results */ *pos++ = 0; *pos++ = 0; if (bss->supp_rates_len > 8) { rates = bss->supp_rates_len - 8; pos = buf + len; len += 2 + rates; *pos++ = WLAN_EID_EXT_SUPP_RATES; *pos++ = rates; os_memcpy(pos, &bss->supp_rates[8], rates); }#if 0 /* FIX */ os_memset(&control, 0, sizeof(control)); control.pkt_type = PKT_PROBE_RESP; os_memset(&extra, 0, sizeof(extra)); extra.endidx = local->num_curr_rates; rate = rate_control_get_rate(wpa_s, skb, &extra); if (rate == NULL) { wpa_printf(MSG_DEBUG, "MLME: Failed to determine TX " "rate for IBSS beacon"); break; } control.tx_rate = (wpa_s->mlme.short_preamble && (rate->flags & IEEE80211_RATE_PREAMBLE2)) ? rate->val2 : rate->val; control.antenna_sel = local->conf.antenna_sel; control.power_level = local->conf.power_level; control.no_ack = 1; control.retry_limit = 1; control.rts_cts_duration = 0;#endif#if 0 /* FIX */ wpa_s->mlme.probe_resp = skb_copy(skb, GFP_ATOMIC); if (wpa_s->mlme.probe_resp) { mgmt = (struct ieee80211_mgmt *) wpa_s->mlme.probe_resp->data; mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_PROBE_RESP); } else { wpa_printf(MSG_DEBUG, "MLME: Could not allocate " "ProbeResp template for IBSS"); } if (local->hw->beacon_update && local->hw->beacon_update(wpa_s, skb, &control) == 0) { wpa_printf(MSG_DEBUG, "MLME: Configured IBSS beacon " "template based on scan results"); skb = NULL; } rates = 0; for (i = 0; i < bss->supp_rates_len; i++) { int rate = (bss->supp_rates[i] & 0x7f) * 5; if (local->conf.phymode == MODE_ATHEROS_TURBO) rate *= 2; for (j = 0; j < local->num_curr_rates; j++) if (local->curr_rates[j].rate == rate) rates |= BIT(j); } wpa_s->mlme.supp_rates_bits = rates;#endif done = 1; } while (0); os_free(buf); if (!done) { wpa_printf(MSG_DEBUG, "MLME: Failed to configure IBSS beacon " "template"); } wpa_s->mlme.state = IEEE80211_IBSS_JOINED; ieee80211_reschedule_timer(wpa_s, IEEE80211_IBSS_MERGE_INTERVAL); return res;}#if 0 /* FIX */static int ieee80211_sta_create_ibss(struct wpa_supplicant *wpa_s){ struct ieee80211_sta_bss *bss; u8 bssid[ETH_ALEN], *pos; int i;#if 0 /* Easier testing, use fixed BSSID. */ os_memset(bssid, 0xfe, ETH_ALEN);#else /* Generate random, not broadcast, locally administered BSSID. Mix in * own MAC address to make sure that devices that do not have proper * random number generator get different BSSID. */ os_get_random(bssid, ETH_ALEN); for (i = 0; i < ETH_ALEN; i++) bssid[i] ^= wpa_s->own_addr[i]; bssid[0] &= ~0x01; bssid[0] |= 0x02;#endif wpa_printf(MSG_DEBUG, "MLME: Creating new IBSS network, BSSID " MACSTR "", MAC2STR(bssid)); bss = ieee80211_bss_add(wpa_s, bssid); if (bss == NULL) return -ENOMEM;#if 0 /* FIX */ if (local->conf.beacon_int == 0) local->conf.beacon_int = 100; bss->beacon_int = local->conf.beacon_int; bss->hw_mode = local->conf.phymode; bss->channel = local->conf.channel; bss->freq = local->conf.freq;#endif os_get_time(&bss->last_update); bss->capability = host_to_le16(WLAN_CAPABILITY_IBSS);#if 0 /* FIX */ if (sdata->default_key) { bss->capability |= host_to_le16(WLAN_CAPABILITY_PRIVACY); } else sdata->drop_unencrypted = 0; bss->supp_rates_len = local->num_curr_rates;#endif pos = bss->supp_rates;#if 0 /* FIX */ for (i = 0; i < local->num_curr_rates; i++) { int rate = local->curr_rates[i].rate; if (local->conf.phymode == MODE_ATHEROS_TURBO) rate /= 2; *pos++ = (u8) (rate / 5); }#endif return ieee80211_sta_join_ibss(wpa_s, bss);}#endifstatic int ieee80211_sta_find_ibss(struct wpa_supplicant *wpa_s){ struct ieee80211_sta_bss *bss; int found = 0; u8 bssid[ETH_ALEN]; int active_ibss; struct os_time now; if (wpa_s->mlme.ssid_len == 0) return -EINVAL; active_ibss = ieee80211_sta_active_ibss(wpa_s);#ifdef IEEE80211_IBSS_DEBUG wpa_printf(MSG_DEBUG, "MLME: sta_find_ibss (active_ibss=%d)", active_ibss);#endif /* IEEE80211_IBSS_DEBUG */ for (bss = wpa_s->mlme.sta_bss_list; bss; bss = bss->next) { if (wpa_s->mlme.ssid_len != bss->ssid_len || os_memcmp(wpa_s->mlme.ssid, bss->ssid, bss->ssid_len) != 0 || !(bss->capability & WLAN_CAPABILITY_IBSS)) continue;#ifdef IEEE80211_IBSS_DEBUG wpa_printf(MSG_DEBUG, " bssid=" MACSTR " found", MAC2STR(bss->bssid));#endif /* IEEE80211_IBSS_DEBUG */ os_memcpy(bssid, bss->bssid, ETH_ALEN); found = 1; if (active_ibss || os_memcmp(bssid, wpa_s->bssid, ETH_ALEN) != 0) break; }#ifdef IEEE80211_IBSS_DEBUG wpa_printf(MSG_DEBUG, " sta_find_ibss: selected " MACSTR " current " MACSTR, MAC2STR(bssid), MAC2STR(wpa_s->bssid));#endif /* IEEE80211_IBSS_DEBUG */ if (found && os_memcmp(wpa_s->bssid, bssid, ETH_ALEN) != 0 && (bss = ieee80211_bss_get(wpa_s, bssid))) { wpa_printf(MSG_DEBUG, "MLME: Selected IBSS BSSID " MACSTR " based on configured SSID", MAC2STR(bssid)); return ieee80211_sta_join_ibss(wpa_s, bss); }#ifdef IEEE80211_IBSS_DEBUG wpa_printf(MSG_DEBUG, " did not try to join ibss");#endif /* IEEE80211_IBSS_DEBUG */ /* Selected IBSS not found in current scan results - try to scan */ os_get_time(&now);#if 0 /* FIX */ if (wpa_s->mlme.state == IEEE80211_IBSS_JOINED && !ieee80211_sta_active_ibss(wpa_s)) { ieee80211_reschedule_timer(wpa_s, IEEE80211_IBSS_MERGE_INTERVAL); } else if (time_after(jiffies, wpa_s->mlme.last_scan_completed + IEEE80211_SCAN_INTERVAL)) { wpa_printf(MSG_DEBUG, "MLME: Trigger new scan to find an IBSS " "to join"); return ieee80211_sta_req_scan(wpa_s->mlme.ssid, wpa_s->mlme.ssid_len); } else if (wpa_s->mlme.state != IEEE80211_IBSS_JOINED) { int interval = IEEE80211_SCAN_INTERVAL; if (time_after(jiffies, wpa_s->mlme.ibss_join_req + IEEE80211_IBSS_JOIN_TIMEOUT)) { if (wpa_s->mlme.create_ibss && ieee80211_ibss_allowed(wpa_s)) return ieee80211_sta_create_ibss(wpa_s); if (wpa_s->mlme.create_ibss) { wpa_printf(MSG_DEBUG, "MLME: IBSS not allowed " "on the configured channel %d " "(%d MHz)", local->conf.channel, local->conf.freq); } /* No IBSS found - decrease scan interval and continue * scanning. */ interval = IEEE80211_SCAN_INTERVAL_SLOW; } wpa_s->mlme.state = IEEE80211_IBSS_SEARCH; ieee80211_reschedule_timer(wpa_s, interval); return 0; }#endif return 0;}int ieee80211_sta_get_ssid(struct wpa_supplicant *wpa_s, u8 *ssid, size_t *len){ os_memcpy(ssid, wpa_s->mlme.ssid, wpa_s->mlme.ssid_len); *len = wpa_s->mlme.ssid_len; return 0;}int ieee80211_sta_associate(struct wpa_supplicant *wpa_s, struct wpa_driver_associate_params *params){ struct ieee80211_sta_bss *bss; wpa_s->mlme.bssid_set = 0; wpa_s->mlme.freq = params->freq; if (params->bssid) { os_memcpy(wpa_s->bssid, params->bssid, ETH_ALEN); if (os_memcmp(params->bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN)) wpa_s->mlme.bssid_set = 1; bss = ieee80211_bss_get(wpa_s, wpa_s->bssid); if (bss) { wpa_s->mlme.phymode = bss->hw_mode; wpa_s->mlme.channel = bss->channel; wpa_s->mlme.freq = bss->freq; } }#if 0 /* FIX */ /* TODO: This should always be done for IBSS, even if IEEE80211_QOS is * not defined. */ if (local->hw->conf_tx) { struct ieee80211_tx_queue_params qparam; int i; os_memset(&qparam, 0, sizeof(qparam)); /* TODO: are these ok defaults for all hw_modes? */ qparam.aifs = 2; qparam.cw_min = local->conf.phymode == MODE_IEEE80211B ? 31 : 15; qparam.cw_max = 1023; qparam.burst_time = 0; for (i = IEEE80211_TX_QUEUE_DATA0; i < NUM_TX_DATA_QUEUES; i++) { local->hw->conf_tx(wpa_s, i + IEEE80211_TX_QUEUE_DATA0, &qparam); } /* IBSS uses different parameters for Beacon sending */ qparam.cw_min++; qparam.cw_min *= 2; qparam.cw_min--; local->hw->conf_tx(wpa_s, IEEE80211_TX_QUEUE_BEACON, &qparam); }#endif if (wpa_s->mlme.ssid_len != params->ssid_len || os_memcmp(wpa_s->mlme.ssid, params->ssid, params->ssid_len) != 0) wpa_s->mlme.prev_bssid_set = 0; os_memcpy(wpa_s->mlme.ssid, params->ssid, params->ssid_len); os_memset(wpa_s->mlme.ssid + params->ssid_len, 0, MAX_SSID_LEN - params->ssid_len); wpa_s->mlme.ssid_len = params->ssid_len; wpa_s->mlme.ssid_set = 1; os_free(wpa_s->mlme.extra_ie); if (params->wpa_ie == NULL || params->wpa_ie_len == 0) { wpa_s->mlme.extra_ie = NULL; wpa_s->mlme.extra_ie_len = 0; return 0; } wpa_s->mlme.extra_ie = os_malloc(params->wpa_ie_len); if (wpa_s->mlme.extra_ie == NULL) { wpa_s->mlme.extra_ie_len = 0; return -1; } os_memcpy(wpa_s->mlme.extra_ie, params->wpa_ie, params->wpa_ie_len); wpa_s->mlme.extra_ie_len = params->wpa_ie_len;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -