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

📄 hostap_80211_rx.c

📁 IEEE 802.11a/b/g linux2.4/2.6 驱动程序源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
#include <linux/etherdevice.h>#include "hostap_80211.h"#include "hostap.h"void hostap_dump_rx_80211(const char *name, struct sk_buff *skb,			  struct hostap_80211_rx_status *rx_stats){	struct hostap_ieee80211_hdr *hdr;	u16 fc;	hdr = (struct hostap_ieee80211_hdr *) skb->data;	printk(KERN_DEBUG "%s: RX signal=%d noise=%d rate=%d len=%d "	       "jiffies=%ld\n",	       name, rx_stats->signal, rx_stats->noise, rx_stats->rate,	       skb->len, jiffies);	if (skb->len < 2)		return;	fc = le16_to_cpu(hdr->frame_control);	printk(KERN_DEBUG "   FC=0x%04x (type=%d:%d)%s%s",	       fc, WLAN_FC_GET_TYPE(fc), WLAN_FC_GET_STYPE(fc),	       fc & WLAN_FC_TODS ? " [ToDS]" : "",	       fc & WLAN_FC_FROMDS ? " [FromDS]" : "");	if (skb->len < IEEE80211_DATA_HDR3_LEN) {		printk("\n");		return;	}	printk(" dur=0x%04x seq=0x%04x\n", le16_to_cpu(hdr->duration_id),	       le16_to_cpu(hdr->seq_ctrl));	printk(KERN_DEBUG "   A1=" MACSTR " A2=" MACSTR " A3=" MACSTR,	       MAC2STR(hdr->addr1), MAC2STR(hdr->addr2), MAC2STR(hdr->addr3));	if (skb->len >= 30)		printk(" A4=" MACSTR, MAC2STR(hdr->addr4));	printk("\n");}/* Send RX frame to netif with 802.11 (and possible prism) header. * Called from hardware or software IRQ context. */int prism2_rx_80211(struct net_device *dev, struct sk_buff *skb,		    struct hostap_80211_rx_status *rx_stats, int type){	struct hostap_interface *iface = dev->priv;	local_info_t *local = iface->local;	int hdrlen, phdrlen, head_need, tail_need;	u16 fc;	int prism_header, ret;	struct hostap_ieee80211_hdr *hdr;	dev->last_rx = jiffies;	if (dev->type == ARPHRD_IEEE80211_PRISM) {		if (local->monitor_type == PRISM2_MONITOR_PRISM) {			prism_header = 1;			phdrlen = sizeof(struct linux_wlan_ng_prism_hdr);		} else { /* local->monitor_type == PRISM2_MONITOR_CAPHDR */			prism_header = 2;			phdrlen = sizeof(struct linux_wlan_ng_cap_hdr);		}	} else {		prism_header = 0;		phdrlen = 0;	}	hdr = (struct hostap_ieee80211_hdr *) skb->data;	fc = le16_to_cpu(hdr->frame_control);	if (type == PRISM2_RX_MGMT && (fc & WLAN_FC_PVER)) {		printk(KERN_DEBUG "%s: dropped management frame with header "		       "version %d\n", dev->name, fc & WLAN_FC_PVER);		dev_kfree_skb_any(skb);		return 0;	}	hdrlen = hostap_80211_get_hdrlen(fc);	/* check if there is enough room for extra data; if not, expand skb	 * buffer to be large enough for the changes */	head_need = phdrlen;	tail_need = 0;#ifdef PRISM2_ADD_BOGUS_CRC	tail_need += 4;#endif /* PRISM2_ADD_BOGUS_CRC */	head_need -= skb_headroom(skb);	tail_need -= skb_tailroom(skb);	if (head_need > 0 || tail_need > 0) {		if (pskb_expand_head(skb, head_need > 0 ? head_need : 0,				     tail_need > 0 ? tail_need : 0,				     GFP_ATOMIC)) {			printk(KERN_DEBUG "%s: prism2_rx_80211 failed to "			       "reallocate skb buffer\n", dev->name);			dev_kfree_skb_any(skb);			return 0;		}	}	/* We now have an skb with enough head and tail room, so just insert	 * the extra data */#ifdef PRISM2_ADD_BOGUS_CRC	memset(skb_put(skb, 4), 0xff, 4); /* Prism2 strips CRC */#endif /* PRISM2_ADD_BOGUS_CRC */	if (prism_header == 1) {		struct linux_wlan_ng_prism_hdr *hdr;		hdr = (struct linux_wlan_ng_prism_hdr *)			skb_push(skb, phdrlen);		memset(hdr, 0, phdrlen);		hdr->msgcode = LWNG_CAP_DID_BASE;		hdr->msglen = sizeof(*hdr);		memcpy(hdr->devname, dev->name, sizeof(hdr->devname));#define LWNG_SETVAL(f,i,s,l,d) \hdr->f.did = LWNG_CAP_DID_BASE | (i << 12); \hdr->f.status = s; hdr->f.len = l; hdr->f.data = d		LWNG_SETVAL(hosttime, 1, 0, 4, jiffies);		LWNG_SETVAL(mactime, 2, 0, 4, rx_stats->mac_time);		LWNG_SETVAL(channel, 3, 1 /* no value */, 4, 0);		LWNG_SETVAL(rssi, 4, 1 /* no value */, 4, 0);		LWNG_SETVAL(sq, 5, 1 /* no value */, 4, 0);		LWNG_SETVAL(signal, 6, 0, 4, rx_stats->signal);		LWNG_SETVAL(noise, 7, 0, 4, rx_stats->noise);		LWNG_SETVAL(rate, 8, 0, 4, rx_stats->rate / 5);		LWNG_SETVAL(istx, 9, 0, 4, 0);		LWNG_SETVAL(frmlen, 10, 0, 4, skb->len - phdrlen);#undef LWNG_SETVAL	} else if (prism_header == 2) {		struct linux_wlan_ng_cap_hdr *hdr;		hdr = (struct linux_wlan_ng_cap_hdr *)			skb_push(skb, phdrlen);		memset(hdr, 0, phdrlen);		hdr->version    = htonl(LWNG_CAPHDR_VERSION);		hdr->length     = htonl(phdrlen);		hdr->mactime    = __cpu_to_be64(rx_stats->mac_time);		hdr->hosttime   = __cpu_to_be64(jiffies);		hdr->phytype    = htonl(4); /* dss_dot11_b */		hdr->channel    = htonl(local->channel);		hdr->datarate   = htonl(rx_stats->rate);		hdr->antenna    = htonl(0); /* unknown */		hdr->priority   = htonl(0); /* unknown */		hdr->ssi_type   = htonl(3); /* raw */		hdr->ssi_signal = htonl(rx_stats->signal);		hdr->ssi_noise  = htonl(rx_stats->noise);		hdr->preamble   = htonl(0); /* unknown */		hdr->encoding   = htonl(1); /* cck */	}	ret = skb->len - phdrlen;	skb->dev = dev;	skb->mac.raw = skb->data;	skb_pull(skb, hdrlen);	if (prism_header)		skb_pull(skb, phdrlen);	skb->pkt_type = PACKET_OTHERHOST;	skb->protocol = __constant_htons(ETH_P_802_2);	memset(skb->cb, 0, sizeof(skb->cb));	netif_rx(skb);	return ret;}/* Called only as a tasklet (software IRQ) */static void monitor_rx(struct net_device *dev, struct sk_buff *skb,		       struct hostap_80211_rx_status *rx_stats){	struct net_device_stats *stats;	int len;	len = prism2_rx_80211(dev, skb, rx_stats, PRISM2_RX_MONITOR);	stats = hostap_get_stats(dev);	stats->rx_packets++;	stats->rx_bytes += len;}/* Called only as a tasklet (software IRQ) */static struct prism2_frag_entry *prism2_frag_cache_find(local_info_t *local, unsigned int seq,		       unsigned int frag, u8 *src, u8 *dst){	struct prism2_frag_entry *entry;	int i;	for (i = 0; i < PRISM2_FRAG_CACHE_LEN; i++) {		entry = &local->frag_cache[i];		if (entry->skb != NULL &&		    time_after(jiffies, entry->first_frag_time + 2 * HZ)) {			printk(KERN_DEBUG "%s: expiring fragment cache entry "			       "seq=%u last_frag=%u\n",			       local->dev->name, entry->seq, entry->last_frag);			dev_kfree_skb(entry->skb);			entry->skb = NULL;		}		if (entry->skb != NULL && entry->seq == seq &&		    (entry->last_frag + 1 == frag || frag == -1) &&		    memcmp(entry->src_addr, src, ETH_ALEN) == 0 &&		    memcmp(entry->dst_addr, dst, ETH_ALEN) == 0)			return entry;	}	return NULL;}/* Called only as a tasklet (software IRQ) */static struct sk_buff *prism2_frag_cache_get(local_info_t *local, struct hostap_ieee80211_hdr *hdr){	struct sk_buff *skb = NULL;	u16 sc;	unsigned int frag, seq;	struct prism2_frag_entry *entry;	sc = le16_to_cpu(hdr->seq_ctrl);	frag = WLAN_GET_SEQ_FRAG(sc);	seq = WLAN_GET_SEQ_SEQ(sc);	if (frag == 0) {		/* Reserve enough space to fit maximum frame length */		skb = dev_alloc_skb(local->dev->mtu +				    sizeof(struct hostap_ieee80211_hdr) +				    8 /* LLC */ +				    2 /* alignment */ +				    8 /* WEP */ + ETH_ALEN /* WDS */);		if (skb == NULL)			return NULL;		entry = &local->frag_cache[local->frag_next_idx];		local->frag_next_idx++;		if (local->frag_next_idx >= PRISM2_FRAG_CACHE_LEN)			local->frag_next_idx = 0;		if (entry->skb != NULL)			dev_kfree_skb(entry->skb);		entry->first_frag_time = jiffies;		entry->seq = seq;		entry->last_frag = frag;		entry->skb = skb;		memcpy(entry->src_addr, hdr->addr2, ETH_ALEN);		memcpy(entry->dst_addr, hdr->addr1, ETH_ALEN);	} else {		/* received a fragment of a frame for which the head fragment		 * should have already been received */		entry = prism2_frag_cache_find(local, seq, frag, hdr->addr2,					       hdr->addr1);		if (entry != NULL) {			entry->last_frag = frag;			skb = entry->skb;		}	}	return skb;}/* Called only as a tasklet (software IRQ) */static int prism2_frag_cache_invalidate(local_info_t *local,					struct hostap_ieee80211_hdr *hdr){	u16 sc;	unsigned int seq;	struct prism2_frag_entry *entry;	sc = le16_to_cpu(hdr->seq_ctrl);	seq = WLAN_GET_SEQ_SEQ(sc);	entry = prism2_frag_cache_find(local, seq, -1, hdr->addr2, hdr->addr1);	if (entry == NULL) {		printk(KERN_DEBUG "%s: could not invalidate fragment cache "		       "entry (seq=%u)\n",		       local->dev->name, seq);		return -1;	}	entry->skb = NULL;	return 0;}static struct hostap_bss_info *__hostap_get_bss(local_info_t *local, u8 *bssid,						u8 *ssid, size_t ssid_len){	struct list_head *ptr;	struct hostap_bss_info *bss;	list_for_each(ptr, &local->bss_list) {		bss = list_entry(ptr, struct hostap_bss_info, list);		if (memcmp(bss->bssid, bssid, ETH_ALEN) == 0 &&		    (ssid == NULL ||		     (ssid_len == bss->ssid_len &&		      memcmp(ssid, bss->ssid, ssid_len) == 0))) {			list_move(&bss->list, &local->bss_list);			return bss;		}	}	return NULL;}static struct hostap_bss_info *__hostap_add_bss(local_info_t *local, u8 *bssid,						u8 *ssid, size_t ssid_len){	struct hostap_bss_info *bss;	if (local->num_bss_info >= HOSTAP_MAX_BSS_COUNT) {		bss = list_entry(local->bss_list.prev,				 struct hostap_bss_info, list);		list_del(&bss->list);		local->num_bss_info--;	} else {		bss = (struct hostap_bss_info *)			kmalloc(sizeof(*bss), GFP_ATOMIC);		if (bss == NULL)			return NULL;	}	memset(bss, 0, sizeof(*bss));	memcpy(bss->bssid, bssid, ETH_ALEN);	memcpy(bss->ssid, ssid, ssid_len);	bss->ssid_len = ssid_len;	local->num_bss_info++;	list_add(&bss->list, &local->bss_list);	return bss;}static void __hostap_expire_bss(local_info_t *local){	struct hostap_bss_info *bss;	while (local->num_bss_info > 0) {		bss = list_entry(local->bss_list.prev,				 struct hostap_bss_info, list);		if (!time_after(jiffies, bss->last_update + 60 * HZ))			break;		list_del(&bss->list);		local->num_bss_info--;		kfree(bss);	}}/* Both IEEE 802.11 Beacon and Probe Response frames have similar structure, so * the same routine can be used to parse both of them. */static void hostap_rx_sta_beacon(local_info_t *local, struct sk_buff *skb,				 int stype){	struct hostap_ieee80211_mgmt *mgmt;	int left, chan = 0;

⌨️ 快捷键说明

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