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

📄 rx.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		break;	case (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS):		/* RA TA DA SA */		memcpy(dst, hdr->addr3, ETH_ALEN);		memcpy(src, hdr->addr4, ETH_ALEN);		if (unlikely(sdata->type != IEEE80211_IF_TYPE_WDS)) {			if (net_ratelimit())				printk(KERN_DEBUG "%s: dropped FromDS&ToDS "				       "frame (RA=%s TA=%s DA=%s SA=%s)\n",				       rx->dev->name,				       print_mac(mac, hdr->addr1),				       print_mac(mac2, hdr->addr2),				       print_mac(mac3, hdr->addr3),				       print_mac(mac4, hdr->addr4));			return TXRX_DROP;		}		break;	case IEEE80211_FCTL_FROMDS:		/* DA BSSID SA */		memcpy(dst, hdr->addr1, ETH_ALEN);		memcpy(src, hdr->addr3, ETH_ALEN);		if (sdata->type != IEEE80211_IF_TYPE_STA ||		    (is_multicast_ether_addr(dst) &&		     !compare_ether_addr(src, dev->dev_addr)))			return TXRX_DROP;		break;	case 0:		/* DA SA BSSID */		memcpy(dst, hdr->addr1, ETH_ALEN);		memcpy(src, hdr->addr2, ETH_ALEN);		if (sdata->type != IEEE80211_IF_TYPE_IBSS) {			if (net_ratelimit()) {				printk(KERN_DEBUG "%s: dropped IBSS frame "				       "(DA=%s SA=%s BSSID=%s)\n",				       dev->name,				       print_mac(mac, hdr->addr1),				       print_mac(mac2, hdr->addr2),				       print_mac(mac3, hdr->addr3));			}			return TXRX_DROP;		}		break;	}	payload = skb->data + hdrlen;	if (unlikely(skb->len - hdrlen < 8)) {		if (net_ratelimit()) {			printk(KERN_DEBUG "%s: RX too short data frame "			       "payload\n", dev->name);		}		return TXRX_DROP;	}	ethertype = (payload[6] << 8) | payload[7];	if (likely((compare_ether_addr(payload, rfc1042_header) == 0 &&		    ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||		   compare_ether_addr(payload, bridge_tunnel_header) == 0)) {		/* remove RFC1042 or Bridge-Tunnel encapsulation and		 * replace EtherType */		skb_pull(skb, hdrlen + 6);		memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN);		memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN);	} else {		struct ethhdr *ehdr;		__be16 len;		skb_pull(skb, hdrlen);		len = htons(skb->len);		ehdr = (struct ethhdr *) skb_push(skb, sizeof(struct ethhdr));		memcpy(ehdr->h_dest, dst, ETH_ALEN);		memcpy(ehdr->h_source, src, ETH_ALEN);		ehdr->h_proto = len;	}	skb->dev = dev;	skb2 = NULL;	dev->stats.rx_packets++;	dev->stats.rx_bytes += skb->len;	if (local->bridge_packets && (sdata->type == IEEE80211_IF_TYPE_AP	    || sdata->type == IEEE80211_IF_TYPE_VLAN) &&	    (rx->flags & IEEE80211_TXRXD_RXRA_MATCH)) {		if (is_multicast_ether_addr(skb->data)) {			/* send multicast frames both to higher layers in			 * local net stack and back to the wireless media */			skb2 = skb_copy(skb, GFP_ATOMIC);			if (!skb2 && net_ratelimit())				printk(KERN_DEBUG "%s: failed to clone "				       "multicast frame\n", dev->name);		} else {			struct sta_info *dsta;			dsta = sta_info_get(local, skb->data);			if (dsta && !dsta->dev) {				if (net_ratelimit())					printk(KERN_DEBUG "Station with null "					       "dev structure!\n");			} else if (dsta && dsta->dev == dev) {				/* Destination station is associated to this				 * AP, so send the frame directly to it and				 * do not pass the frame to local net stack.				 */				skb2 = skb;				skb = NULL;			}			if (dsta)				sta_info_put(dsta);		}	}	if (skb) {		/* deliver to local stack */		skb->protocol = eth_type_trans(skb, dev);		memset(skb->cb, 0, sizeof(skb->cb));		netif_rx(skb);	}	if (skb2) {		/* send to wireless media */		skb2->protocol = __constant_htons(ETH_P_802_3);		skb_set_network_header(skb2, 0);		skb_set_mac_header(skb2, 0);		dev_queue_xmit(skb2);	}	return TXRX_QUEUED;}static ieee80211_txrx_resultieee80211_rx_h_mgmt(struct ieee80211_txrx_data *rx){	struct ieee80211_sub_if_data *sdata;	if (!(rx->flags & IEEE80211_TXRXD_RXRA_MATCH))		return TXRX_DROP;	sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev);	if ((sdata->type == IEEE80211_IF_TYPE_STA ||	     sdata->type == IEEE80211_IF_TYPE_IBSS) &&	    !(sdata->flags & IEEE80211_SDATA_USERSPACE_MLME))		ieee80211_sta_rx_mgmt(rx->dev, rx->skb, rx->u.rx.status);	else		return TXRX_DROP;	return TXRX_QUEUED;}static inline ieee80211_txrx_result __ieee80211_invoke_rx_handlers(				struct ieee80211_local *local,				ieee80211_rx_handler *handlers,				struct ieee80211_txrx_data *rx,				struct sta_info *sta){	ieee80211_rx_handler *handler;	ieee80211_txrx_result res = TXRX_DROP;	for (handler = handlers; *handler != NULL; handler++) {		res = (*handler)(rx);		switch (res) {		case TXRX_CONTINUE:			continue;		case TXRX_DROP:			I802_DEBUG_INC(local->rx_handlers_drop);			if (sta)				sta->rx_dropped++;			break;		case TXRX_QUEUED:			I802_DEBUG_INC(local->rx_handlers_queued);			break;		}		break;	}	if (res == TXRX_DROP)		dev_kfree_skb(rx->skb);	return res;}static inline void ieee80211_invoke_rx_handlers(struct ieee80211_local *local,						ieee80211_rx_handler *handlers,						struct ieee80211_txrx_data *rx,						struct sta_info *sta){	if (__ieee80211_invoke_rx_handlers(local, handlers, rx, sta) ==	    TXRX_CONTINUE)		dev_kfree_skb(rx->skb);}static void ieee80211_rx_michael_mic_report(struct net_device *dev,					    struct ieee80211_hdr *hdr,					    struct sta_info *sta,					    struct ieee80211_txrx_data *rx){	int keyidx, hdrlen;	DECLARE_MAC_BUF(mac);	DECLARE_MAC_BUF(mac2);	hdrlen = ieee80211_get_hdrlen_from_skb(rx->skb);	if (rx->skb->len >= hdrlen + 4)		keyidx = rx->skb->data[hdrlen + 3] >> 6;	else		keyidx = -1;	if (net_ratelimit())		printk(KERN_DEBUG "%s: TKIP hwaccel reported Michael MIC "		       "failure from %s to %s keyidx=%d\n",		       dev->name, print_mac(mac, hdr->addr2),		       print_mac(mac2, hdr->addr1), keyidx);	if (!sta) {		/*		 * Some hardware seem to generate incorrect Michael MIC		 * reports; ignore them to avoid triggering countermeasures.		 */		if (net_ratelimit())			printk(KERN_DEBUG "%s: ignored spurious Michael MIC "			       "error for unknown address %s\n",			       dev->name, print_mac(mac, hdr->addr2));		goto ignore;	}	if (!(rx->fc & IEEE80211_FCTL_PROTECTED)) {		if (net_ratelimit())			printk(KERN_DEBUG "%s: ignored spurious Michael MIC "			       "error for a frame with no PROTECTED flag (src "			       "%s)\n", dev->name, print_mac(mac, hdr->addr2));		goto ignore;	}	if (rx->sdata->type == IEEE80211_IF_TYPE_AP && keyidx) {		/*		 * APs with pairwise keys should never receive Michael MIC		 * errors for non-zero keyidx because these are reserved for		 * group keys and only the AP is sending real multicast		 * frames in the BSS.		 */		if (net_ratelimit())			printk(KERN_DEBUG "%s: ignored Michael MIC error for "			       "a frame with non-zero keyidx (%d)"			       " (src %s)\n", dev->name, keyidx,			       print_mac(mac, hdr->addr2));		goto ignore;	}	if ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA &&	    ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT ||	     (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_AUTH)) {		if (net_ratelimit())			printk(KERN_DEBUG "%s: ignored spurious Michael MIC "			       "error for a frame that cannot be encrypted "			       "(fc=0x%04x) (src %s)\n",			       dev->name, rx->fc, print_mac(mac, hdr->addr2));		goto ignore;	}	mac80211_ev_michael_mic_failure(rx->dev, keyidx, hdr); ignore:	dev_kfree_skb(rx->skb);	rx->skb = NULL;}ieee80211_rx_handler ieee80211_rx_handlers[] ={	ieee80211_rx_h_if_stats,	ieee80211_rx_h_passive_scan,	ieee80211_rx_h_check,	ieee80211_rx_h_decrypt,	ieee80211_rx_h_sta_process,	ieee80211_rx_h_defragment,	ieee80211_rx_h_ps_poll,	ieee80211_rx_h_michael_mic_verify,	/* this must be after decryption - so header is counted in MPDU mic	 * must be before pae and data, so QOS_DATA format frames	 * are not passed to user space by these functions	 */	ieee80211_rx_h_remove_qos_control,	ieee80211_rx_h_802_1x_pae,	ieee80211_rx_h_drop_unencrypted,	ieee80211_rx_h_data,	ieee80211_rx_h_mgmt,	NULL};/* main receive path */static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,				u8 *bssid, struct ieee80211_txrx_data *rx,				struct ieee80211_hdr *hdr){	int multicast = is_multicast_ether_addr(hdr->addr1);	switch (sdata->type) {	case IEEE80211_IF_TYPE_STA:		if (!bssid)			return 0;		if (!ieee80211_bssid_match(bssid, sdata->u.sta.bssid)) {			if (!(rx->flags & IEEE80211_TXRXD_RXIN_SCAN))				return 0;			rx->flags &= ~IEEE80211_TXRXD_RXRA_MATCH;		} else if (!multicast &&			   compare_ether_addr(sdata->dev->dev_addr,					      hdr->addr1) != 0) {			if (!(sdata->dev->flags & IFF_PROMISC))				return 0;			rx->flags &= ~IEEE80211_TXRXD_RXRA_MATCH;		}		break;	case IEEE80211_IF_TYPE_IBSS:		if (!bssid)			return 0;		if (!ieee80211_bssid_match(bssid, sdata->u.sta.bssid)) {			if (!(rx->flags & IEEE80211_TXRXD_RXIN_SCAN))				return 0;			rx->flags &= ~IEEE80211_TXRXD_RXRA_MATCH;		} else if (!multicast &&			   compare_ether_addr(sdata->dev->dev_addr,					      hdr->addr1) != 0) {			if (!(sdata->dev->flags & IFF_PROMISC))				return 0;			rx->flags &= ~IEEE80211_TXRXD_RXRA_MATCH;		} else if (!rx->sta)			rx->sta = ieee80211_ibss_add_sta(sdata->dev, rx->skb,							 bssid, hdr->addr2);		break;	case IEEE80211_IF_TYPE_VLAN:	case IEEE80211_IF_TYPE_AP:		if (!bssid) {			if (compare_ether_addr(sdata->dev->dev_addr,					       hdr->addr1))				return 0;		} else if (!ieee80211_bssid_match(bssid,					sdata->dev->dev_addr)) {			if (!(rx->flags & IEEE80211_TXRXD_RXIN_SCAN))				return 0;			rx->flags &= ~IEEE80211_TXRXD_RXRA_MATCH;		}		if (sdata->dev == sdata->local->mdev &&		    !(rx->flags & IEEE80211_TXRXD_RXIN_SCAN))			/* do not receive anything via			 * master device when not scanning */			return 0;		break;	case IEEE80211_IF_TYPE_WDS:		if (bssid ||		    (rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA)			return 0;		if (compare_ether_addr(sdata->u.wds.remote_addr, hdr->addr2))			return 0;		break;	case IEEE80211_IF_TYPE_MNTR:		/* take everything */		break;	case IEEE80211_IF_TYPE_INVALID:		/* should never get here */		WARN_ON(1);		break;	}	return 1;}/* * This is the receive path handler. It is called by a low level driver when an * 802.11 MPDU is received from the hardware. */void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,		    struct ieee80211_rx_status *status){	struct ieee80211_local *local = hw_to_local(hw);	struct ieee80211_sub_if_data *sdata;	struct sta_info *sta;	struct ieee80211_hdr *hdr;	struct ieee80211_txrx_data rx;	u16 type;	int prepres;	struct ieee80211_sub_if_data *prev = NULL;	struct sk_buff *skb_new;	u8 *bssid;	/*	 * key references and virtual interfaces are protected using RCU	 * and this requires that we are in a read-side RCU section during	 * receive processing	 */	rcu_read_lock();	/*	 * Frames with failed FCS/PLCP checksum are not returned,	 * all other frames are returned without radiotap header	 * if it was previously present.	 * Also, frames with less than 16 bytes are dropped.	 */	skb = ieee80211_rx_monitor(local, skb, status);	if (!skb) {		rcu_read_unlock();		return;	}	hdr = (struct ieee80211_hdr *) skb->data;	memset(&rx, 0, sizeof(rx));	rx.skb = skb;	rx.local = local;	rx.u.rx.status = status;	rx.fc = le16_to_cpu(hdr->frame_control);	type = rx.fc & IEEE80211_FCTL_FTYPE;	if (type == IEEE80211_FTYPE_DATA || type == IEEE80211_FTYPE_MGMT)		local->dot11ReceivedFragmentCount++;	sta = rx.sta = sta_info_get(local, hdr->addr2);	if (sta) {		rx.dev = rx.sta->dev;		rx.sdata = IEEE80211_DEV_TO_SUB_IF(rx.dev);	}	if ((status->flag & RX_FLAG_MMIC_ERROR)) {		ieee80211_rx_michael_mic_report(local->mdev, hdr, sta, &rx);		goto end;	}	if (unlikely(local->sta_scanning))		rx.flags |= IEEE80211_TXRXD_RXIN_SCAN;	if (__ieee80211_invoke_rx_handlers(local, local->rx_pre_handlers, &rx,					   sta) != TXRX_CONTINUE)		goto end;	skb = rx.skb;	if (sta && !(sta->flags & (WLAN_STA_WDS | WLAN_STA_ASSOC_AP)) &&	    !atomic_read(&local->iff_promiscs) &&	    !is_multicast_ether_addr(hdr->addr1)) {		rx.flags |= IEEE80211_TXRXD_RXRA_MATCH;		ieee80211_invoke_rx_handlers(local, local->rx_handlers, &rx,					     rx.sta);		sta_info_put(sta);		rcu_read_unlock();		return;	}	bssid = ieee80211_get_bssid(hdr, skb->len);	list_for_each_entry_rcu(sdata, &local->interfaces, list) {		if (!netif_running(sdata->dev))			continue;		if (sdata->type == IEEE80211_IF_TYPE_MNTR)			continue;		rx.flags |= IEEE80211_TXRXD_RXRA_MATCH;		prepres = prepare_for_handlers(sdata, bssid, &rx, hdr);		/* prepare_for_handlers can change sta */		sta = rx.sta;		if (!prepres)			continue;		/*		 * frame is destined for this interface, but if it's not		 * also for the previous one we handle that after the		 * loop to avoid copying the SKB once too much		 */		if (!prev) {			prev = sdata;			continue;		}		/*		 * frame was destined for the previous interface		 * so invoke RX handlers for it		 */		skb_new = skb_copy(skb, GFP_ATOMIC);		if (!skb_new) {			if (net_ratelimit())				printk(KERN_DEBUG "%s: failed to copy "				       "multicast frame for %s",				       wiphy_name(local->hw.wiphy),				       prev->dev->name);			continue;		}		rx.skb = skb_new;		rx.dev = prev->dev;		rx.sdata = prev;		ieee80211_invoke_rx_handlers(local, local->rx_handlers,					     &rx, sta);		prev = sdata;	}	if (prev) {		rx.skb = skb;		rx.dev = prev->dev;		rx.sdata = prev;		ieee80211_invoke_rx_handlers(local, local->rx_handlers,					     &rx, sta);	} else		dev_kfree_skb(skb); end:	rcu_read_unlock();	if (sta)		sta_info_put(sta);}EXPORT_SYMBOL(__ieee80211_rx);/* This is a version of the rx handler that can be called from hard irq * context. Post the skb on the queue and schedule the tasklet */void ieee80211_rx_irqsafe(struct ieee80211_hw *hw, struct sk_buff *skb,			  struct ieee80211_rx_status *status){	struct ieee80211_local *local = hw_to_local(hw);	BUILD_BUG_ON(sizeof(struct ieee80211_rx_status) > sizeof(skb->cb));	skb->dev = local->mdev;	/* copy status into skb->cb for use by tasklet */	memcpy(skb->cb, status, sizeof(*status));	skb->pkt_type = IEEE80211_RX_MSG;	skb_queue_tail(&local->skb_queue, skb);	tasklet_schedule(&local->tasklet);}EXPORT_SYMBOL(ieee80211_rx_irqsafe);

⌨️ 快捷键说明

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