ieee80211_sta.c
来自「linux 内核源代码」· C语言 代码 · 共 2,351 行 · 第 1/5 页
C
2,351 行
return; } if (sdata->type != IEEE80211_IF_TYPE_IBSS && memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) { printk(KERN_DEBUG "%s: authentication frame received from " "unknown AP (SA=%s BSSID=%s) - " "ignored\n", dev->name, print_mac(mac, mgmt->sa), print_mac(mac, mgmt->bssid)); return; } if (sdata->type != IEEE80211_IF_TYPE_IBSS && memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0) { printk(KERN_DEBUG "%s: authentication frame received from " "unknown BSSID (SA=%s BSSID=%s) - " "ignored\n", dev->name, print_mac(mac, mgmt->sa), print_mac(mac, mgmt->bssid)); return; } auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg); auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction); status_code = le16_to_cpu(mgmt->u.auth.status_code); printk(KERN_DEBUG "%s: RX authentication from %s (alg=%d " "transaction=%d status=%d)\n", dev->name, print_mac(mac, mgmt->sa), auth_alg, auth_transaction, status_code); if (sdata->type == IEEE80211_IF_TYPE_IBSS) { /* IEEE 802.11 standard does not require authentication in IBSS * networks and most implementations do not seem to use it. * However, try to reply to authentication attempts if someone * has actually implemented this. * TODO: Could implement shared key authentication. */ if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1) { printk(KERN_DEBUG "%s: unexpected IBSS authentication " "frame (alg=%d transaction=%d)\n", dev->name, auth_alg, auth_transaction); return; } ieee80211_send_auth(dev, ifsta, 2, NULL, 0, 0); } if (auth_alg != ifsta->auth_alg || auth_transaction != ifsta->auth_transaction) { printk(KERN_DEBUG "%s: unexpected authentication frame " "(alg=%d transaction=%d)\n", dev->name, auth_alg, auth_transaction); return; } if (status_code != WLAN_STATUS_SUCCESS) { printk(KERN_DEBUG "%s: AP denied authentication (auth_alg=%d " "code=%d)\n", dev->name, ifsta->auth_alg, status_code); if (status_code == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG) { u8 algs[3]; const int num_algs = ARRAY_SIZE(algs); int i, pos; algs[0] = algs[1] = algs[2] = 0xff; if (ifsta->auth_algs & IEEE80211_AUTH_ALG_OPEN) algs[0] = WLAN_AUTH_OPEN; if (ifsta->auth_algs & IEEE80211_AUTH_ALG_SHARED_KEY) algs[1] = WLAN_AUTH_SHARED_KEY; if (ifsta->auth_algs & IEEE80211_AUTH_ALG_LEAP) algs[2] = WLAN_AUTH_LEAP; if (ifsta->auth_alg == WLAN_AUTH_OPEN) pos = 0; else if (ifsta->auth_alg == WLAN_AUTH_SHARED_KEY) pos = 1; else pos = 2; for (i = 0; i < num_algs; i++) { pos++; if (pos >= num_algs) pos = 0; if (algs[pos] == ifsta->auth_alg || algs[pos] == 0xff) continue; if (algs[pos] == WLAN_AUTH_SHARED_KEY && !ieee80211_sta_wep_configured(dev)) continue; ifsta->auth_alg = algs[pos]; printk(KERN_DEBUG "%s: set auth_alg=%d for " "next try\n", dev->name, ifsta->auth_alg); break; } } return; } switch (ifsta->auth_alg) { case WLAN_AUTH_OPEN: case WLAN_AUTH_LEAP: ieee80211_auth_completed(dev, ifsta); break; case WLAN_AUTH_SHARED_KEY: if (ifsta->auth_transaction == 4) ieee80211_auth_completed(dev, ifsta); else ieee80211_auth_challenge(dev, ifsta, mgmt, len); break; }}static void ieee80211_rx_mgmt_deauth(struct net_device *dev, struct ieee80211_if_sta *ifsta, struct ieee80211_mgmt *mgmt, size_t len){ u16 reason_code; DECLARE_MAC_BUF(mac); if (len < 24 + 2) { printk(KERN_DEBUG "%s: too short (%zd) deauthentication frame " "received from %s - ignored\n", dev->name, len, print_mac(mac, mgmt->sa)); return; } if (memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) { printk(KERN_DEBUG "%s: deauthentication frame received from " "unknown AP (SA=%s BSSID=%s) - " "ignored\n", dev->name, print_mac(mac, mgmt->sa), print_mac(mac, mgmt->bssid)); return; } reason_code = le16_to_cpu(mgmt->u.deauth.reason_code); printk(KERN_DEBUG "%s: RX deauthentication from %s" " (reason=%d)\n", dev->name, print_mac(mac, mgmt->sa), reason_code); if (ifsta->flags & IEEE80211_STA_AUTHENTICATED) { printk(KERN_DEBUG "%s: deauthenticated\n", dev->name); } if (ifsta->state == IEEE80211_AUTHENTICATE || ifsta->state == IEEE80211_ASSOCIATE || ifsta->state == IEEE80211_ASSOCIATED) { ifsta->state = IEEE80211_AUTHENTICATE; mod_timer(&ifsta->timer, jiffies + IEEE80211_RETRY_AUTH_INTERVAL); } ieee80211_set_disassoc(dev, ifsta, 1); ifsta->flags &= ~IEEE80211_STA_AUTHENTICATED;}static void ieee80211_rx_mgmt_disassoc(struct net_device *dev, struct ieee80211_if_sta *ifsta, struct ieee80211_mgmt *mgmt, size_t len){ u16 reason_code; DECLARE_MAC_BUF(mac); if (len < 24 + 2) { printk(KERN_DEBUG "%s: too short (%zd) disassociation frame " "received from %s - ignored\n", dev->name, len, print_mac(mac, mgmt->sa)); return; } if (memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) { printk(KERN_DEBUG "%s: disassociation frame received from " "unknown AP (SA=%s BSSID=%s) - " "ignored\n", dev->name, print_mac(mac, mgmt->sa), print_mac(mac, mgmt->bssid)); return; } reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); printk(KERN_DEBUG "%s: RX disassociation from %s" " (reason=%d)\n", dev->name, print_mac(mac, mgmt->sa), reason_code); if (ifsta->flags & IEEE80211_STA_ASSOCIATED) printk(KERN_DEBUG "%s: disassociated\n", dev->name); if (ifsta->state == IEEE80211_ASSOCIATED) { ifsta->state = IEEE80211_ASSOCIATE; mod_timer(&ifsta->timer, jiffies + IEEE80211_RETRY_AUTH_INTERVAL); } ieee80211_set_disassoc(dev, ifsta, 0);}static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev, struct ieee80211_if_sta *ifsta, struct ieee80211_mgmt *mgmt, size_t len, int reassoc){ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_hw_mode *mode; struct sta_info *sta; u32 rates; u16 capab_info, status_code, aid; struct ieee802_11_elems elems; u8 *pos; int i, j; DECLARE_MAC_BUF(mac); /* AssocResp and ReassocResp have identical structure, so process both * of them in this function. */ if (ifsta->state != IEEE80211_ASSOCIATE) { printk(KERN_DEBUG "%s: association frame received from " "%s, but not in associate state - ignored\n", dev->name, print_mac(mac, mgmt->sa)); return; } if (len < 24 + 6) { printk(KERN_DEBUG "%s: too short (%zd) association frame " "received from %s - ignored\n", dev->name, len, print_mac(mac, mgmt->sa)); return; } if (memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) { printk(KERN_DEBUG "%s: association frame received from " "unknown AP (SA=%s BSSID=%s) - " "ignored\n", dev->name, print_mac(mac, mgmt->sa), print_mac(mac, mgmt->bssid)); return; } capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info); status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code); aid = le16_to_cpu(mgmt->u.assoc_resp.aid); printk(KERN_DEBUG "%s: RX %sssocResp from %s (capab=0x%x " "status=%d aid=%d)\n", dev->name, reassoc ? "Rea" : "A", print_mac(mac, mgmt->sa), capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14)))); if (status_code != WLAN_STATUS_SUCCESS) { printk(KERN_DEBUG "%s: AP denied association (code=%d)\n", dev->name, status_code); /* if this was a reassociation, ensure we try a "full" * association next time. This works around some broken APs * which do not correctly reject reassociation requests. */ ifsta->flags &= ~IEEE80211_STA_PREV_BSSID_SET; return; } if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14))) printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not " "set\n", dev->name, aid); aid &= ~(BIT(15) | BIT(14)); pos = mgmt->u.assoc_resp.variable; ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); if (!elems.supp_rates) { printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n", dev->name); return; } /* it probably doesn't, but if the frame includes an ERP value then * update our stored copy */ if (elems.erp_info && elems.erp_info_len >= 1) { struct ieee80211_sta_bss *bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel, ifsta->ssid, ifsta->ssid_len); if (bss) { bss->erp_value = elems.erp_info[0]; bss->has_erp_value = 1; ieee80211_rx_bss_put(dev, bss); } } printk(KERN_DEBUG "%s: associated\n", dev->name); ifsta->aid = aid; ifsta->ap_capab = capab_info; kfree(ifsta->assocresp_ies); ifsta->assocresp_ies_len = len - (pos - (u8 *) mgmt); ifsta->assocresp_ies = kmalloc(ifsta->assocresp_ies_len, GFP_KERNEL); if (ifsta->assocresp_ies) memcpy(ifsta->assocresp_ies, pos, ifsta->assocresp_ies_len); ieee80211_set_associated(dev, ifsta, 1); /* Add STA entry for the AP */ sta = sta_info_get(local, ifsta->bssid); if (!sta) { struct ieee80211_sta_bss *bss; sta = sta_info_add(local, dev, ifsta->bssid, GFP_KERNEL); if (!sta) { printk(KERN_DEBUG "%s: failed to add STA entry for the" " AP\n", dev->name); return; } bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel, ifsta->ssid, ifsta->ssid_len); if (bss) { sta->last_rssi = bss->rssi; sta->last_signal = bss->signal; sta->last_noise = bss->noise; ieee80211_rx_bss_put(dev, bss); } } sta->dev = dev; sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_AP; rates = 0; mode = local->oper_hw_mode; for (i = 0; i < elems.supp_rates_len; i++) { int rate = (elems.supp_rates[i] & 0x7f) * 5; for (j = 0; j < mode->num_rates; j++) if (mode->rates[j].rate == rate) rates |= BIT(j); } for (i = 0; i < elems.ext_supp_rates_len; i++) { int rate = (elems.ext_supp_rates[i] & 0x7f) * 5; for (j = 0; j < mode->num_rates; j++) if (mode->rates[j].rate == rate) rates |= BIT(j); } sta->supp_rates = rates; rate_control_rate_init(sta, local); if (elems.wmm_param && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) { sta->flags |= WLAN_STA_WME; ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param, elems.wmm_param_len); } sta_info_put(sta); ieee80211_associated(dev, ifsta);}/* Caller must hold local->sta_bss_lock */static void __ieee80211_rx_bss_hash_add(struct net_device *dev, struct ieee80211_sta_bss *bss){ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); bss->hnext = local->sta_bss_hash[STA_HASH(bss->bssid)]; local->sta_bss_hash[STA_HASH(bss->bssid)] = bss;}/* Caller must hold local->sta_bss_lock */static void __ieee80211_rx_bss_hash_del(struct net_device *dev, struct ieee80211_sta_bss *bss){ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_sta_bss *b, *prev = NULL; b = local->sta_bss_hash[STA_HASH(bss->bssid)]; while (b) { if (b == bss) { if (!prev) local->sta_bss_hash[STA_HASH(bss->bssid)] = bss->hnext; else prev->hnext = bss->hnext; break; } prev = b; b = b->hnext; }}static struct ieee80211_sta_bss *ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid, int channel, u8 *ssid, u8 ssid_len){ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_sta_bss *bss; bss = kzalloc(sizeof(*bss), GFP_ATOMIC); if (!bss) return NULL; atomic_inc(&bss->users); atomic_inc(&bss->users); memcpy(bss->bssid, bssid, ETH_ALEN); bss->channel = channel; if (ssid && ssid_len <= IEEE80211_MAX_SSID_LEN) { memcpy(bss->ssid, ssid, ssid_len); bss->ssid_len = ssid_len; } spin_lock_bh(&local->sta_bss_lock); /* TODO: order by RSSI? */ list_add_tail(&bss->list, &local->sta_bss_list); __ieee80211_rx_bss_hash_add(dev, bss); spin_unlock_bh(&local->sta_bss_lock); return bss;}static struct ieee80211_sta_bss *ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int channel, u8 *ssid, u8 ssid_len){ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_sta_bss *bss; spin_lock_bh(&local->sta_bss_lock); bss = local->sta_bss_hash[STA_HASH(bssid)]; while (bss) { if (!memcmp(bss->bssid, bssid, ETH_ALEN) && bss->channel == channel && bss->ssid_len == ssid_len && (ssid_len == 0 || !memcmp(bss->ssid, ssid, ssid_len))) { atomic_inc(&bss->users); break; } bss = bss->hnext; } spin_unlock_bh(&local->sta_bss_lock); return bss;}static void ieee80211_rx_bss_free(struct ieee80211_sta_bss *bss){ kfree(bss->wpa_ie); kfree(bss->rsn_ie); kfree(bss->wmm_ie); kfree(bss);}static void ieee80211_rx_bss_put(struct net_device *dev, struct ieee80211_sta_bss *bss){ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); if (!atomic_dec_and_test(&bss->users)) return; spin_lock_bh(&local->sta_bss_lock); __ieee80211_rx_bss_hash_del(dev, bss); list_del(&bss->list); spin_unlock_bh(&local->sta_bss_lock); ieee80211_rx_bss_free(bss);}void ieee80211_rx_bss_list_init(struct net_device *dev){ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); spin_lock_init(&local->sta_bss_lock); INIT_LIST_HEAD(&local->sta_bss_list);}void ieee80211_rx_bss_list_deinit(struct net_device *dev){ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_sta_bss *bss, *tmp;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?