⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ieee80211_sta.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	list_for_each_entry_safe(bss, tmp, &local->sta_bss_list, list)		ieee80211_rx_bss_put(dev, bss);}static void ieee80211_rx_bss_info(struct net_device *dev,				  struct ieee80211_mgmt *mgmt,				  size_t len,				  struct ieee80211_rx_status *rx_status,				  int beacon){	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);	struct ieee802_11_elems elems;	size_t baselen;	int channel, clen;	struct ieee80211_sta_bss *bss;	struct sta_info *sta;	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);	u64 timestamp;	DECLARE_MAC_BUF(mac);	DECLARE_MAC_BUF(mac2);	if (!beacon && memcmp(mgmt->da, dev->dev_addr, ETH_ALEN))		return; /* ignore ProbeResp to foreign address */#if 0	printk(KERN_DEBUG "%s: RX %s from %s to %s\n",	       dev->name, beacon ? "Beacon" : "Probe Response",	       print_mac(mac, mgmt->sa), print_mac(mac2, mgmt->da));#endif	baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt;	if (baselen > len)		return;	timestamp = le64_to_cpu(mgmt->u.beacon.timestamp);	if (sdata->type == IEEE80211_IF_TYPE_IBSS && beacon &&	    memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0) {#ifdef CONFIG_MAC80211_IBSS_DEBUG		static unsigned long last_tsf_debug = 0;		u64 tsf;		if (local->ops->get_tsf)			tsf = local->ops->get_tsf(local_to_hw(local));		else			tsf = -1LLU;		if (time_after(jiffies, last_tsf_debug + 5 * HZ)) {			printk(KERN_DEBUG "RX beacon SA=%s BSSID="			       "%s TSF=0x%llx BCN=0x%llx diff=%lld "			       "@%lu\n",			       print_mac(mac, mgmt->sa), print_mac(mac2, mgmt->bssid),			       (unsigned long long)tsf,			       (unsigned long long)timestamp,			       (unsigned long long)(tsf - timestamp),			       jiffies);			last_tsf_debug = jiffies;		}#endif /* CONFIG_MAC80211_IBSS_DEBUG */	}	ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems);	if (sdata->type == IEEE80211_IF_TYPE_IBSS && elems.supp_rates &&	    memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0 &&	    (sta = sta_info_get(local, mgmt->sa))) {		struct ieee80211_hw_mode *mode;		struct ieee80211_rate *rates;		size_t num_rates;		u32 supp_rates, prev_rates;		int i, j;		mode = local->sta_scanning ?		       local->scan_hw_mode : local->oper_hw_mode;		rates = mode->rates;		num_rates = mode->num_rates;		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);			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 = sdata->u.sta.supp_rates_bits;		}		if (sta->supp_rates != prev_rates) {			printk(KERN_DEBUG "%s: updated supp_rates set for "			       "%s based on beacon info (0x%x & 0x%x -> "			       "0x%x)\n",			       dev->name, print_mac(mac, sta->addr), prev_rates,			       supp_rates, sta->supp_rates);		}		sta_info_put(sta);	}	if (!elems.ssid)		return;	if (elems.ds_params && elems.ds_params_len == 1)		channel = elems.ds_params[0];	else		channel = rx_status->channel;	bss = ieee80211_rx_bss_get(dev, mgmt->bssid, channel,				   elems.ssid, elems.ssid_len);	if (!bss) {		bss = ieee80211_rx_bss_add(dev, mgmt->bssid, channel,					   elems.ssid, elems.ssid_len);		if (!bss)			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. */		ieee80211_rx_bss_put(dev, bss);		return;	}	/* save the ERP value so that it is available at association time */	if (elems.erp_info && elems.erp_info_len >= 1) {		bss->erp_value = elems.erp_info[0];		bss->has_erp_value = 1;	}	bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int);	bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info);	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;		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;		memcpy(&bss->supp_rates[bss->supp_rates_len],		       elems.ext_supp_rates, clen);		bss->supp_rates_len += clen;	}	if (elems.wpa &&	    (!bss->wpa_ie || bss->wpa_ie_len != elems.wpa_len ||	     memcmp(bss->wpa_ie, elems.wpa, elems.wpa_len))) {		kfree(bss->wpa_ie);		bss->wpa_ie = kmalloc(elems.wpa_len + 2, GFP_ATOMIC);		if (bss->wpa_ie) {			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) {		kfree(bss->wpa_ie);		bss->wpa_ie = NULL;		bss->wpa_ie_len = 0;	}	if (elems.rsn &&	    (!bss->rsn_ie || bss->rsn_ie_len != elems.rsn_len ||	     memcmp(bss->rsn_ie, elems.rsn, elems.rsn_len))) {		kfree(bss->rsn_ie);		bss->rsn_ie = kmalloc(elems.rsn_len + 2, GFP_ATOMIC);		if (bss->rsn_ie) {			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) {		kfree(bss->rsn_ie);		bss->rsn_ie = NULL;		bss->rsn_ie_len = 0;	}	if (elems.wmm_param &&	    (!bss->wmm_ie || bss->wmm_ie_len != elems.wmm_param_len ||	     memcmp(bss->wmm_ie, elems.wmm_param, elems.wmm_param_len))) {		kfree(bss->wmm_ie);		bss->wmm_ie = kmalloc(elems.wmm_param_len + 2, GFP_ATOMIC);		if (bss->wmm_ie) {			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) {		kfree(bss->wmm_ie);		bss->wmm_ie = NULL;		bss->wmm_ie_len = 0;	}	bss->hw_mode = rx_status->phymode;	bss->freq = rx_status->freq;	if (channel != rx_status->channel &&	    (bss->hw_mode == MODE_IEEE80211G ||	     bss->hw_mode == 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;	bss->last_update = jiffies;	bss->rssi = rx_status->ssi;	bss->signal = rx_status->signal;	bss->noise = rx_status->noise;	if (!beacon)		bss->probe_resp++;	ieee80211_rx_bss_put(dev, bss);}static void ieee80211_rx_mgmt_probe_resp(struct net_device *dev,					 struct ieee80211_mgmt *mgmt,					 size_t len,					 struct ieee80211_rx_status *rx_status){	ieee80211_rx_bss_info(dev, mgmt, len, rx_status, 0);}static void ieee80211_rx_mgmt_beacon(struct net_device *dev,				     struct ieee80211_mgmt *mgmt,				     size_t len,				     struct ieee80211_rx_status *rx_status){	struct ieee80211_sub_if_data *sdata;	struct ieee80211_if_sta *ifsta;	size_t baselen;	struct ieee802_11_elems elems;	ieee80211_rx_bss_info(dev, mgmt, len, rx_status, 1);	sdata = IEEE80211_DEV_TO_SUB_IF(dev);	if (sdata->type != IEEE80211_IF_TYPE_STA)		return;	ifsta = &sdata->u.sta;	if (!(ifsta->flags & IEEE80211_STA_ASSOCIATED) ||	    memcmp(ifsta->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;	ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems);	if (elems.erp_info && elems.erp_info_len >= 1)		ieee80211_handle_erp_ie(dev, elems.erp_info[0]);	if (elems.wmm_param && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) {		ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param,					 elems.wmm_param_len);	}}static void ieee80211_rx_mgmt_probe_req(struct net_device *dev,					struct ieee80211_if_sta *ifsta,					struct ieee80211_mgmt *mgmt,					size_t len,					struct ieee80211_rx_status *rx_status){	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);	int tx_last_beacon;	struct sk_buff *skb;	struct ieee80211_mgmt *resp;	u8 *pos, *end;	DECLARE_MAC_BUF(mac);#ifdef CONFIG_MAC80211_IBSS_DEBUG	DECLARE_MAC_BUF(mac2);	DECLARE_MAC_BUF(mac3);#endif	if (sdata->type != IEEE80211_IF_TYPE_IBSS ||	    ifsta->state != IEEE80211_IBSS_JOINED ||	    len < 24 + 2 || !ifsta->probe_resp)		return;	if (local->ops->tx_last_beacon)		tx_last_beacon = local->ops->tx_last_beacon(local_to_hw(local));	else		tx_last_beacon = 1;#ifdef CONFIG_MAC80211_IBSS_DEBUG	printk(KERN_DEBUG "%s: RX ProbeReq SA=%s DA=%s BSSID="	       "%s (tx_last_beacon=%d)\n",	       dev->name, print_mac(mac, mgmt->sa), print_mac(mac2, mgmt->da),	       print_mac(mac3, mgmt->bssid), tx_last_beacon);#endif /* CONFIG_MAC80211_IBSS_DEBUG */	if (!tx_last_beacon)		return;	if (memcmp(mgmt->bssid, ifsta->bssid, ETH_ALEN) != 0 &&	    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) {		if (net_ratelimit()) {			printk(KERN_DEBUG "%s: Invalid SSID IE in ProbeReq "			       "from %s\n",			       dev->name, print_mac(mac, mgmt->sa));		}		return;	}	if (pos[1] != 0 &&	    (pos[1] != ifsta->ssid_len ||	     memcmp(pos + 2, ifsta->ssid, ifsta->ssid_len) != 0)) {		/* Ignore ProbeReq for foreign SSID */		return;	}	/* Reply with ProbeResp */	skb = skb_copy(ifsta->probe_resp, GFP_KERNEL);	if (!skb)		return;	resp = (struct ieee80211_mgmt *) skb->data;	memcpy(resp->da, mgmt->sa, ETH_ALEN);#ifdef CONFIG_MAC80211_IBSS_DEBUG	printk(KERN_DEBUG "%s: Sending ProbeResp to %s\n",	       dev->name, print_mac(mac, resp->da));#endif /* CONFIG_MAC80211_IBSS_DEBUG */	ieee80211_sta_tx(dev, skb, 0);}void ieee80211_sta_rx_mgmt(struct net_device *dev, struct sk_buff *skb,			   struct ieee80211_rx_status *rx_status){	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);	struct ieee80211_sub_if_data *sdata;	struct ieee80211_if_sta *ifsta;	struct ieee80211_mgmt *mgmt;	u16 fc;	if (skb->len < 24)		goto fail;	sdata = IEEE80211_DEV_TO_SUB_IF(dev);	ifsta = &sdata->u.sta;	mgmt = (struct ieee80211_mgmt *) skb->data;	fc = le16_to_cpu(mgmt->frame_control);	switch (fc & IEEE80211_FCTL_STYPE) {	case IEEE80211_STYPE_PROBE_REQ:	case IEEE80211_STYPE_PROBE_RESP:	case IEEE80211_STYPE_BEACON:		memcpy(skb->cb, rx_status, sizeof(*rx_status));	case IEEE80211_STYPE_AUTH:	case IEEE80211_STYPE_ASSOC_RESP:	case IEEE80211_STYPE_REASSOC_RESP:	case IEEE80211_STYPE_DEAUTH:	case IEEE80211_STYPE_DISASSOC:		skb_queue_tail(&ifsta->skb_queue, skb);		queue_work(local->hw.workqueue, &ifsta->work);		return;	default:		printk(KERN_DEBUG "%s: received unknown management frame - "		       "stype=%d\n", dev->name,		       (fc & IEEE80211_FCTL_STYPE) >> 4);		break;	} fail:	kfree_skb(skb);}static void ieee80211_sta_rx_queued_mgmt(struct net_device *dev,					 struct sk_buff *skb){	struct ieee80211_rx_status *rx_status;	struct ieee80211_sub_if_data *sdata;	struct ieee80211_if_sta *ifsta;	struct ieee80211_mgmt *mgmt;	u16 fc;	sdata = IEEE80211_DEV_TO_SUB_IF(dev);	ifsta = &sdata->u.sta;	rx_status = (struct ieee80211_rx_status *) skb->cb;	mgmt = (struct ieee80211_mgmt *) skb->data;	fc = le16_to_cpu(mgmt->frame_control);	switch (fc & IEEE80211_FCTL_STYPE) {	case IEEE80211_STYPE_PROBE_REQ:		ieee80211_rx_mgmt_probe_req(dev, ifsta, mgmt, skb->len,					    rx_status);		break;	case IEEE80211_STYPE_PROBE_RESP:		ieee80211_rx_mgmt_probe_resp(dev, mgmt, skb->len, rx_status);		break;	case IEEE80211_STYPE_BEACON:		ieee80211_rx_mgmt_beacon(dev, mgmt, skb->len, rx_status);		break;	case IEEE80211_STYPE_AUTH:		ieee80211_rx_mgmt_auth(dev, ifsta, mgmt, skb->len);		break;	case IEEE80211_STYPE_ASSOC_RESP:		ieee80211_rx_mgmt_assoc_resp(dev, ifsta, mgmt, skb->len, 0);		break;	case IEEE80211_STYPE_REASSOC_RESP:		ieee80211_rx_mgmt_assoc_resp(dev, ifsta, mgmt, skb->len, 1);		break;	case IEEE80211_STYPE_DEAUTH:		ieee80211_rx_mgmt_deauth(dev, ifsta, mgmt, skb->len);		break;	case IEEE80211_STYPE_DISASSOC:		ieee80211_rx_mgmt_disassoc(dev, ifsta, mgmt, skb->len);		break;	}	kfree_skb(skb);}void ieee80211_sta_rx_scan(struct net_device *dev, struct sk_buff *skb,			   struct ieee80211_rx_status *rx_status){	struct ieee80211_mgmt *mgmt;	u16 fc;	if (skb->len < 24) {		dev_kfree_skb(skb);		return;	}	mgmt = (struct ieee80211_mgmt *) skb->data;	fc = le16_to_cpu(mgmt->frame_control);	if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -