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 + -
显示快捷键?