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

📄 ieee80211_sta.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	struct ieee80211_mgmt *mgmt;	skb = dev_alloc_skb(local->hw.extra_tx_headroom +			    sizeof(*mgmt) + 6 + extra_len);	if (!skb) {		printk(KERN_DEBUG "%s: failed to allocate buffer for auth "		       "frame\n", dev->name);		return;	}	skb_reserve(skb, local->hw.extra_tx_headroom);	mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24 + 6);	memset(mgmt, 0, 24 + 6);	mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,					   IEEE80211_STYPE_AUTH);	if (encrypt)		mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);	memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);	memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);	memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);	mgmt->u.auth.auth_alg = cpu_to_le16(ifsta->auth_alg);	mgmt->u.auth.auth_transaction = cpu_to_le16(transaction);	ifsta->auth_transaction = transaction + 1;	mgmt->u.auth.status_code = cpu_to_le16(0);	if (extra)		memcpy(skb_put(skb, extra_len), extra, extra_len);	ieee80211_sta_tx(dev, skb, encrypt);}static void ieee80211_authenticate(struct net_device *dev,				   struct ieee80211_if_sta *ifsta){	DECLARE_MAC_BUF(mac);	ifsta->auth_tries++;	if (ifsta->auth_tries > IEEE80211_AUTH_MAX_TRIES) {		printk(KERN_DEBUG "%s: authentication with AP %s"		       " timed out\n",		       dev->name, print_mac(mac, ifsta->bssid));		ifsta->state = IEEE80211_DISABLED;		return;	}	ifsta->state = IEEE80211_AUTHENTICATE;	printk(KERN_DEBUG "%s: authenticate with AP %s\n",	       dev->name, print_mac(mac, ifsta->bssid));	ieee80211_send_auth(dev, ifsta, 1, NULL, 0, 0);	mod_timer(&ifsta->timer, jiffies + IEEE80211_AUTH_TIMEOUT);}static void ieee80211_send_assoc(struct net_device *dev,				 struct ieee80211_if_sta *ifsta){	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);	struct ieee80211_hw_mode *mode;	struct sk_buff *skb;	struct ieee80211_mgmt *mgmt;	u8 *pos, *ies;	int i, len;	u16 capab;	struct ieee80211_sta_bss *bss;	int wmm = 0;	skb = dev_alloc_skb(local->hw.extra_tx_headroom +			    sizeof(*mgmt) + 200 + ifsta->extra_ie_len +			    ifsta->ssid_len);	if (!skb) {		printk(KERN_DEBUG "%s: failed to allocate buffer for assoc "		       "frame\n", dev->name);		return;	}	skb_reserve(skb, local->hw.extra_tx_headroom);	mode = local->oper_hw_mode;	capab = ifsta->capab;	if (mode->mode == MODE_IEEE80211G) {		capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME |			WLAN_CAPABILITY_SHORT_PREAMBLE;	}	bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel,				   ifsta->ssid, ifsta->ssid_len);	if (bss) {		if (bss->capability & WLAN_CAPABILITY_PRIVACY)			capab |= WLAN_CAPABILITY_PRIVACY;		if (bss->wmm_ie) {			wmm = 1;		}		ieee80211_rx_bss_put(dev, bss);	}	mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);	memset(mgmt, 0, 24);	memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);	memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);	memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);	if (ifsta->flags & IEEE80211_STA_PREV_BSSID_SET) {		skb_put(skb, 10);		mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,						   IEEE80211_STYPE_REASSOC_REQ);		mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab);		mgmt->u.reassoc_req.listen_interval = cpu_to_le16(1);		memcpy(mgmt->u.reassoc_req.current_ap, ifsta->prev_bssid,		       ETH_ALEN);	} else {		skb_put(skb, 4);		mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,						   IEEE80211_STYPE_ASSOC_REQ);		mgmt->u.assoc_req.capab_info = cpu_to_le16(capab);		mgmt->u.assoc_req.listen_interval = cpu_to_le16(1);	}	/* SSID */	ies = pos = skb_put(skb, 2 + ifsta->ssid_len);	*pos++ = WLAN_EID_SSID;	*pos++ = ifsta->ssid_len;	memcpy(pos, ifsta->ssid, ifsta->ssid_len);	len = mode->num_rates;	if (len > 8)		len = 8;	pos = skb_put(skb, len + 2);	*pos++ = WLAN_EID_SUPP_RATES;	*pos++ = len;	for (i = 0; i < len; i++) {		int rate = mode->rates[i].rate;		*pos++ = (u8) (rate / 5);	}	if (mode->num_rates > len) {		pos = skb_put(skb, mode->num_rates - len + 2);		*pos++ = WLAN_EID_EXT_SUPP_RATES;		*pos++ = mode->num_rates - len;		for (i = len; i < mode->num_rates; i++) {			int rate = mode->rates[i].rate;			*pos++ = (u8) (rate / 5);		}	}	if (ifsta->extra_ie) {		pos = skb_put(skb, ifsta->extra_ie_len);		memcpy(pos, ifsta->extra_ie, ifsta->extra_ie_len);	}	if (wmm && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) {		pos = skb_put(skb, 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;	}	kfree(ifsta->assocreq_ies);	ifsta->assocreq_ies_len = (skb->data + skb->len) - ies;	ifsta->assocreq_ies = kmalloc(ifsta->assocreq_ies_len, GFP_KERNEL);	if (ifsta->assocreq_ies)		memcpy(ifsta->assocreq_ies, ies, ifsta->assocreq_ies_len);	ieee80211_sta_tx(dev, skb, 0);}static void ieee80211_send_deauth(struct net_device *dev,				  struct ieee80211_if_sta *ifsta, u16 reason){	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);	struct sk_buff *skb;	struct ieee80211_mgmt *mgmt;	skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt));	if (!skb) {		printk(KERN_DEBUG "%s: failed to allocate buffer for deauth "		       "frame\n", dev->name);		return;	}	skb_reserve(skb, local->hw.extra_tx_headroom);	mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);	memset(mgmt, 0, 24);	memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);	memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);	memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);	mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,					   IEEE80211_STYPE_DEAUTH);	skb_put(skb, 2);	mgmt->u.deauth.reason_code = cpu_to_le16(reason);	ieee80211_sta_tx(dev, skb, 0);}static void ieee80211_send_disassoc(struct net_device *dev,				    struct ieee80211_if_sta *ifsta, u16 reason){	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);	struct sk_buff *skb;	struct ieee80211_mgmt *mgmt;	skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt));	if (!skb) {		printk(KERN_DEBUG "%s: failed to allocate buffer for disassoc "		       "frame\n", dev->name);		return;	}	skb_reserve(skb, local->hw.extra_tx_headroom);	mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);	memset(mgmt, 0, 24);	memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);	memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);	memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);	mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,					   IEEE80211_STYPE_DISASSOC);	skb_put(skb, 2);	mgmt->u.disassoc.reason_code = cpu_to_le16(reason);	ieee80211_sta_tx(dev, skb, 0);}static int ieee80211_privacy_mismatch(struct net_device *dev,				      struct ieee80211_if_sta *ifsta){	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);	struct ieee80211_sta_bss *bss;	int bss_privacy;	int wep_privacy;	int privacy_invoked;	if (!ifsta || (ifsta->flags & IEEE80211_STA_MIXED_CELL))		return 0;	bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel,				   ifsta->ssid, ifsta->ssid_len);	if (!bss)		return 0;	bss_privacy = !!(bss->capability & WLAN_CAPABILITY_PRIVACY);	wep_privacy = !!ieee80211_sta_wep_configured(dev);	privacy_invoked = !!(ifsta->flags & IEEE80211_STA_PRIVACY_INVOKED);	ieee80211_rx_bss_put(dev, bss);	if ((bss_privacy == wep_privacy) || (bss_privacy == privacy_invoked))		return 0;	return 1;}static void ieee80211_associate(struct net_device *dev,				struct ieee80211_if_sta *ifsta){	DECLARE_MAC_BUF(mac);	ifsta->assoc_tries++;	if (ifsta->assoc_tries > IEEE80211_ASSOC_MAX_TRIES) {		printk(KERN_DEBUG "%s: association with AP %s"		       " timed out\n",		       dev->name, print_mac(mac, ifsta->bssid));		ifsta->state = IEEE80211_DISABLED;		return;	}	ifsta->state = IEEE80211_ASSOCIATE;	printk(KERN_DEBUG "%s: associate with AP %s\n",	       dev->name, print_mac(mac, ifsta->bssid));	if (ieee80211_privacy_mismatch(dev, ifsta)) {		printk(KERN_DEBUG "%s: mismatch in privacy configuration and "		       "mixed-cell disabled - abort association\n", dev->name);		ifsta->state = IEEE80211_DISABLED;		return;	}	ieee80211_send_assoc(dev, ifsta);	mod_timer(&ifsta->timer, jiffies + IEEE80211_ASSOC_TIMEOUT);}static void ieee80211_associated(struct net_device *dev,				 struct ieee80211_if_sta *ifsta){	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);	struct sta_info *sta;	int disassoc;	DECLARE_MAC_BUF(mac);	/* 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 */	ifsta->state = IEEE80211_ASSOCIATED;	sta = sta_info_get(local, ifsta->bssid);	if (!sta) {		printk(KERN_DEBUG "%s: No STA entry for own AP %s\n",		       dev->name, print_mac(mac, ifsta->bssid));		disassoc = 1;	} else {		disassoc = 0;		if (time_after(jiffies,			       sta->last_rx + IEEE80211_MONITORING_INTERVAL)) {			if (ifsta->flags & IEEE80211_STA_PROBEREQ_POLL) {				printk(KERN_DEBUG "%s: No ProbeResp from "				       "current AP %s - assume out of "				       "range\n",				       dev->name, print_mac(mac, ifsta->bssid));				disassoc = 1;				sta_info_free(sta);			} else				ieee80211_send_probe_req(dev, ifsta->bssid,							 local->scan_ssid,							 local->scan_ssid_len);			ifsta->flags ^= IEEE80211_STA_PROBEREQ_POLL;		} else {			ifsta->flags &= ~IEEE80211_STA_PROBEREQ_POLL;			if (time_after(jiffies, ifsta->last_probe +				       IEEE80211_PROBE_INTERVAL)) {				ifsta->last_probe = jiffies;				ieee80211_send_probe_req(dev, ifsta->bssid,							 ifsta->ssid,							 ifsta->ssid_len);			}		}		sta_info_put(sta);	}	if (disassoc) {		ifsta->state = IEEE80211_DISABLED;		ieee80211_set_associated(dev, ifsta, 0);	} else {		mod_timer(&ifsta->timer, jiffies +				      IEEE80211_MONITORING_INTERVAL);	}}static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst,				     u8 *ssid, size_t ssid_len){	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);	struct ieee80211_hw_mode *mode;	struct sk_buff *skb;	struct ieee80211_mgmt *mgmt;	u8 *pos, *supp_rates, *esupp_rates = NULL;	int i;	skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200);	if (!skb) {		printk(KERN_DEBUG "%s: failed to allocate buffer for probe "		       "request\n", dev->name);		return;	}	skb_reserve(skb, local->hw.extra_tx_headroom);	mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);	memset(mgmt, 0, 24);	mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,					   IEEE80211_STYPE_PROBE_REQ);	memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);	if (dst) {		memcpy(mgmt->da, dst, ETH_ALEN);		memcpy(mgmt->bssid, dst, ETH_ALEN);	} else {		memset(mgmt->da, 0xff, ETH_ALEN);		memset(mgmt->bssid, 0xff, ETH_ALEN);	}	pos = skb_put(skb, 2 + ssid_len);	*pos++ = WLAN_EID_SSID;	*pos++ = ssid_len;	memcpy(pos, ssid, ssid_len);	supp_rates = skb_put(skb, 2);	supp_rates[0] = WLAN_EID_SUPP_RATES;	supp_rates[1] = 0;	mode = local->oper_hw_mode;	for (i = 0; i < mode->num_rates; i++) {		struct ieee80211_rate *rate = &mode->rates[i];		if (!(rate->flags & IEEE80211_RATE_SUPPORTED))			continue;		if (esupp_rates) {			pos = skb_put(skb, 1);			esupp_rates[1]++;		} else if (supp_rates[1] == 8) {			esupp_rates = skb_put(skb, 3);			esupp_rates[0] = WLAN_EID_EXT_SUPP_RATES;			esupp_rates[1] = 1;			pos = &esupp_rates[2];		} else {			pos = skb_put(skb, 1);			supp_rates[1]++;		}		*pos = rate->rate / 5;	}	ieee80211_sta_tx(dev, skb, 0);}static int ieee80211_sta_wep_configured(struct net_device *dev){	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);	if (!sdata || !sdata->default_key ||	    sdata->default_key->conf.alg != ALG_WEP)		return 0;	return 1;}static void ieee80211_auth_completed(struct net_device *dev,				     struct ieee80211_if_sta *ifsta){	printk(KERN_DEBUG "%s: authenticated\n", dev->name);	ifsta->flags |= IEEE80211_STA_AUTHENTICATED;	ieee80211_associate(dev, ifsta);}static void ieee80211_auth_challenge(struct net_device *dev,				     struct ieee80211_if_sta *ifsta,				     struct ieee80211_mgmt *mgmt,				     size_t len){	u8 *pos;	struct ieee802_11_elems elems;	printk(KERN_DEBUG "%s: replying to auth challenge\n", dev->name);	pos = mgmt->u.auth.variable;	ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);	if (!elems.challenge) {		printk(KERN_DEBUG "%s: no challenge IE in shared key auth "		       "frame\n", dev->name);		return;	}	ieee80211_send_auth(dev, ifsta, 3, elems.challenge - 2,			    elems.challenge_len + 2, 1);}static void ieee80211_rx_mgmt_auth(struct net_device *dev,				   struct ieee80211_if_sta *ifsta,				   struct ieee80211_mgmt *mgmt,				   size_t len){	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);	u16 auth_alg, auth_transaction, status_code;	DECLARE_MAC_BUF(mac);	if (ifsta->state != IEEE80211_AUTHENTICATE &&	    sdata->type != IEEE80211_IF_TYPE_IBSS) {		printk(KERN_DEBUG "%s: authentication frame received from "		       "%s, but not in authenticate state - ignored\n",		       dev->name, print_mac(mac, mgmt->sa));		return;	}	if (len < 24 + 6) {		printk(KERN_DEBUG "%s: too short (%zd) authentication frame "		       "received from %s - ignored\n",		       dev->name, len, print_mac(mac, mgmt->sa));

⌨️ 快捷键说明

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