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

📄 rx.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	case ALG_TKIP:		result = ieee80211_crypto_tkip_decrypt(rx);		break;	case ALG_CCMP:		result = ieee80211_crypto_ccmp_decrypt(rx);		break;	}	/* either the frame has been decrypted or will be dropped */	rx->u.rx.status->flag |= RX_FLAG_DECRYPTED;	return result;}static void ap_sta_ps_start(struct net_device *dev, struct sta_info *sta){	struct ieee80211_sub_if_data *sdata;	DECLARE_MAC_BUF(mac);	sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);	if (sdata->bss)		atomic_inc(&sdata->bss->num_sta_ps);	sta->flags |= WLAN_STA_PS;	sta->pspoll = 0;#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG	printk(KERN_DEBUG "%s: STA %s aid %d enters power save mode\n",	       dev->name, print_mac(mac, sta->addr), sta->aid);#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */}static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta){	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);	struct sk_buff *skb;	int sent = 0;	struct ieee80211_sub_if_data *sdata;	struct ieee80211_tx_packet_data *pkt_data;	DECLARE_MAC_BUF(mac);	sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);	if (sdata->bss)		atomic_dec(&sdata->bss->num_sta_ps);	sta->flags &= ~(WLAN_STA_PS | WLAN_STA_TIM);	sta->pspoll = 0;	if (!skb_queue_empty(&sta->ps_tx_buf)) {		if (local->ops->set_tim)			local->ops->set_tim(local_to_hw(local), sta->aid, 0);		if (sdata->bss)			bss_tim_clear(local, sdata->bss, sta->aid);	}#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG	printk(KERN_DEBUG "%s: STA %s aid %d exits power save mode\n",	       dev->name, print_mac(mac, sta->addr), sta->aid);#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */	/* Send all buffered frames to the station */	while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) {		pkt_data = (struct ieee80211_tx_packet_data *) skb->cb;		sent++;		pkt_data->flags |= IEEE80211_TXPD_REQUEUE;		dev_queue_xmit(skb);	}	while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) {		pkt_data = (struct ieee80211_tx_packet_data *) skb->cb;		local->total_ps_buffered--;		sent++;#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG		printk(KERN_DEBUG "%s: STA %s aid %d send PS frame "		       "since STA not sleeping anymore\n", dev->name,		       print_mac(mac, sta->addr), sta->aid);#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */		pkt_data->flags |= IEEE80211_TXPD_REQUEUE;		dev_queue_xmit(skb);	}	return sent;}static ieee80211_txrx_resultieee80211_rx_h_sta_process(struct ieee80211_txrx_data *rx){	struct sta_info *sta = rx->sta;	struct net_device *dev = rx->dev;	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;	if (!sta)		return TXRX_CONTINUE;	/* Update last_rx only for IBSS packets which are for the current	 * BSSID to avoid keeping the current IBSS network alive in cases where	 * other STAs are using different BSSID. */	if (rx->sdata->type == IEEE80211_IF_TYPE_IBSS) {		u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len);		if (compare_ether_addr(bssid, rx->sdata->u.sta.bssid) == 0)			sta->last_rx = jiffies;	} else	if (!is_multicast_ether_addr(hdr->addr1) ||	    rx->sdata->type == IEEE80211_IF_TYPE_STA) {		/* Update last_rx only for unicast frames in order to prevent		 * the Probe Request frames (the only broadcast frames from a		 * STA in infrastructure mode) from keeping a connection alive.		 */		sta->last_rx = jiffies;	}	if (!(rx->flags & IEEE80211_TXRXD_RXRA_MATCH))		return TXRX_CONTINUE;	sta->rx_fragments++;	sta->rx_bytes += rx->skb->len;	sta->last_rssi = rx->u.rx.status->ssi;	sta->last_signal = rx->u.rx.status->signal;	sta->last_noise = rx->u.rx.status->noise;	if (!(rx->fc & IEEE80211_FCTL_MOREFRAGS)) {		/* Change STA power saving mode only in the end of a frame		 * exchange sequence */		if ((sta->flags & WLAN_STA_PS) && !(rx->fc & IEEE80211_FCTL_PM))			rx->u.rx.sent_ps_buffered += ap_sta_ps_end(dev, sta);		else if (!(sta->flags & WLAN_STA_PS) &&			 (rx->fc & IEEE80211_FCTL_PM))			ap_sta_ps_start(dev, sta);	}	/* Drop data::nullfunc frames silently, since they are used only to	 * control station power saving mode. */	if ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA &&	    (rx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_NULLFUNC) {		I802_DEBUG_INC(rx->local->rx_handlers_drop_nullfunc);		/* Update counter and free packet here to avoid counting this		 * as a dropped packed. */		sta->rx_packets++;		dev_kfree_skb(rx->skb);		return TXRX_QUEUED;	}	return TXRX_CONTINUE;} /* ieee80211_rx_h_sta_process */static inline struct ieee80211_fragment_entry *ieee80211_reassemble_add(struct ieee80211_sub_if_data *sdata,			 unsigned int frag, unsigned int seq, int rx_queue,			 struct sk_buff **skb){	struct ieee80211_fragment_entry *entry;	int idx;	idx = sdata->fragment_next;	entry = &sdata->fragments[sdata->fragment_next++];	if (sdata->fragment_next >= IEEE80211_FRAGMENT_MAX)		sdata->fragment_next = 0;	if (!skb_queue_empty(&entry->skb_list)) {#ifdef CONFIG_MAC80211_DEBUG		struct ieee80211_hdr *hdr =			(struct ieee80211_hdr *) entry->skb_list.next->data;		DECLARE_MAC_BUF(mac);		DECLARE_MAC_BUF(mac2);		printk(KERN_DEBUG "%s: RX reassembly removed oldest "		       "fragment entry (idx=%d age=%lu seq=%d last_frag=%d "		       "addr1=%s addr2=%s\n",		       sdata->dev->name, idx,		       jiffies - entry->first_frag_time, entry->seq,		       entry->last_frag, print_mac(mac, hdr->addr1),		       print_mac(mac2, hdr->addr2));#endif /* CONFIG_MAC80211_DEBUG */		__skb_queue_purge(&entry->skb_list);	}	__skb_queue_tail(&entry->skb_list, *skb); /* no need for locking */	*skb = NULL;	entry->first_frag_time = jiffies;	entry->seq = seq;	entry->rx_queue = rx_queue;	entry->last_frag = frag;	entry->ccmp = 0;	entry->extra_len = 0;	return entry;}static inline struct ieee80211_fragment_entry *ieee80211_reassemble_find(struct ieee80211_sub_if_data *sdata,			  u16 fc, unsigned int frag, unsigned int seq,			  int rx_queue, struct ieee80211_hdr *hdr){	struct ieee80211_fragment_entry *entry;	int i, idx;	idx = sdata->fragment_next;	for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) {		struct ieee80211_hdr *f_hdr;		u16 f_fc;		idx--;		if (idx < 0)			idx = IEEE80211_FRAGMENT_MAX - 1;		entry = &sdata->fragments[idx];		if (skb_queue_empty(&entry->skb_list) || entry->seq != seq ||		    entry->rx_queue != rx_queue ||		    entry->last_frag + 1 != frag)			continue;		f_hdr = (struct ieee80211_hdr *) entry->skb_list.next->data;		f_fc = le16_to_cpu(f_hdr->frame_control);		if ((fc & IEEE80211_FCTL_FTYPE) != (f_fc & IEEE80211_FCTL_FTYPE) ||		    compare_ether_addr(hdr->addr1, f_hdr->addr1) != 0 ||		    compare_ether_addr(hdr->addr2, f_hdr->addr2) != 0)			continue;		if (entry->first_frag_time + 2 * HZ < jiffies) {			__skb_queue_purge(&entry->skb_list);			continue;		}		return entry;	}	return NULL;}static ieee80211_txrx_resultieee80211_rx_h_defragment(struct ieee80211_txrx_data *rx){	struct ieee80211_hdr *hdr;	u16 sc;	unsigned int frag, seq;	struct ieee80211_fragment_entry *entry;	struct sk_buff *skb;	DECLARE_MAC_BUF(mac);	hdr = (struct ieee80211_hdr *) rx->skb->data;	sc = le16_to_cpu(hdr->seq_ctrl);	frag = sc & IEEE80211_SCTL_FRAG;	if (likely((!(rx->fc & IEEE80211_FCTL_MOREFRAGS) && frag == 0) ||		   (rx->skb)->len < 24 ||		   is_multicast_ether_addr(hdr->addr1))) {		/* not fragmented */		goto out;	}	I802_DEBUG_INC(rx->local->rx_handlers_fragments);	seq = (sc & IEEE80211_SCTL_SEQ) >> 4;	if (frag == 0) {		/* This is the first fragment of a new frame. */		entry = ieee80211_reassemble_add(rx->sdata, frag, seq,						 rx->u.rx.queue, &(rx->skb));		if (rx->key && rx->key->conf.alg == ALG_CCMP &&		    (rx->fc & IEEE80211_FCTL_PROTECTED)) {			/* Store CCMP PN so that we can verify that the next			 * fragment has a sequential PN value. */			entry->ccmp = 1;			memcpy(entry->last_pn,			       rx->key->u.ccmp.rx_pn[rx->u.rx.queue],			       CCMP_PN_LEN);		}		return TXRX_QUEUED;	}	/* This is a fragment for a frame that should already be pending in	 * fragment cache. Add this fragment to the end of the pending entry.	 */	entry = ieee80211_reassemble_find(rx->sdata, rx->fc, frag, seq,					  rx->u.rx.queue, hdr);	if (!entry) {		I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag);		return TXRX_DROP;	}	/* Verify that MPDUs within one MSDU have sequential PN values.	 * (IEEE 802.11i, 8.3.3.4.5) */	if (entry->ccmp) {		int i;		u8 pn[CCMP_PN_LEN], *rpn;		if (!rx->key || rx->key->conf.alg != ALG_CCMP)			return TXRX_DROP;		memcpy(pn, entry->last_pn, CCMP_PN_LEN);		for (i = CCMP_PN_LEN - 1; i >= 0; i--) {			pn[i]++;			if (pn[i])				break;		}		rpn = rx->key->u.ccmp.rx_pn[rx->u.rx.queue];		if (memcmp(pn, rpn, CCMP_PN_LEN) != 0) {			if (net_ratelimit())				printk(KERN_DEBUG "%s: defrag: CCMP PN not "				       "sequential A2=%s"				       " PN=%02x%02x%02x%02x%02x%02x "				       "(expected %02x%02x%02x%02x%02x%02x)\n",				       rx->dev->name, print_mac(mac, hdr->addr2),				       rpn[0], rpn[1], rpn[2], rpn[3], rpn[4],				       rpn[5], pn[0], pn[1], pn[2], pn[3],				       pn[4], pn[5]);			return TXRX_DROP;		}		memcpy(entry->last_pn, pn, CCMP_PN_LEN);	}	skb_pull(rx->skb, ieee80211_get_hdrlen(rx->fc));	__skb_queue_tail(&entry->skb_list, rx->skb);	entry->last_frag = frag;	entry->extra_len += rx->skb->len;	if (rx->fc & IEEE80211_FCTL_MOREFRAGS) {		rx->skb = NULL;		return TXRX_QUEUED;	}	rx->skb = __skb_dequeue(&entry->skb_list);	if (skb_tailroom(rx->skb) < entry->extra_len) {		I802_DEBUG_INC(rx->local->rx_expand_skb_head2);		if (unlikely(pskb_expand_head(rx->skb, 0, entry->extra_len,					      GFP_ATOMIC))) {			I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag);			__skb_queue_purge(&entry->skb_list);			return TXRX_DROP;		}	}	while ((skb = __skb_dequeue(&entry->skb_list))) {		memcpy(skb_put(rx->skb, skb->len), skb->data, skb->len);		dev_kfree_skb(skb);	}	/* Complete frame has been reassembled - process it now */	rx->flags |= IEEE80211_TXRXD_FRAGMENTED; out:	if (rx->sta)		rx->sta->rx_packets++;	if (is_multicast_ether_addr(hdr->addr1))		rx->local->dot11MulticastReceivedFrameCount++;	else		ieee80211_led_rx(rx->local);	return TXRX_CONTINUE;}static ieee80211_txrx_resultieee80211_rx_h_ps_poll(struct ieee80211_txrx_data *rx){	struct sk_buff *skb;	int no_pending_pkts;	DECLARE_MAC_BUF(mac);	if (likely(!rx->sta ||		   (rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_CTL ||		   (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_PSPOLL ||		   !(rx->flags & IEEE80211_TXRXD_RXRA_MATCH)))		return TXRX_CONTINUE;	skb = skb_dequeue(&rx->sta->tx_filtered);	if (!skb) {		skb = skb_dequeue(&rx->sta->ps_tx_buf);		if (skb)			rx->local->total_ps_buffered--;	}	no_pending_pkts = skb_queue_empty(&rx->sta->tx_filtered) &&		skb_queue_empty(&rx->sta->ps_tx_buf);	if (skb) {		struct ieee80211_hdr *hdr =			(struct ieee80211_hdr *) skb->data;		/* tell TX path to send one frame even though the STA may		 * still remain is PS mode after this frame exchange */		rx->sta->pspoll = 1;#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG		printk(KERN_DEBUG "STA %s aid %d: PS Poll (entries after %d)\n",		       print_mac(mac, rx->sta->addr), rx->sta->aid,		       skb_queue_len(&rx->sta->ps_tx_buf));#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */		/* Use MoreData flag to indicate whether there are more		 * buffered frames for this STA */		if (no_pending_pkts) {			hdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_MOREDATA);			rx->sta->flags &= ~WLAN_STA_TIM;		} else			hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);		dev_queue_xmit(skb);		if (no_pending_pkts) {			if (rx->local->ops->set_tim)				rx->local->ops->set_tim(local_to_hw(rx->local),						       rx->sta->aid, 0);			if (rx->sdata->bss)				bss_tim_clear(rx->local, rx->sdata->bss, rx->sta->aid);		}#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG	} else if (!rx->u.rx.sent_ps_buffered) {		printk(KERN_DEBUG "%s: STA %s sent PS Poll even "		       "though there is no buffered frames for it\n",		       rx->dev->name, print_mac(mac, rx->sta->addr));#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */	}	/* Free PS Poll skb here instead of returning TXRX_DROP that would	 * count as an dropped frame. */	dev_kfree_skb(rx->skb);	return TXRX_QUEUED;}static ieee80211_txrx_resultieee80211_rx_h_remove_qos_control(struct ieee80211_txrx_data *rx){	u16 fc = rx->fc;	u8 *data = rx->skb->data;	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) data;	if (!WLAN_FC_IS_QOS_DATA(fc))		return TXRX_CONTINUE;	/* remove the qos control field, update frame type and meta-data */	memmove(data + 2, data, ieee80211_get_hdrlen(fc) - 2);	hdr = (struct ieee80211_hdr *) skb_pull(rx->skb, 2);	/* change frame type to non QOS */	rx->fc = fc &= ~IEEE80211_STYPE_QOS_DATA;	hdr->frame_control = cpu_to_le16(fc);	return TXRX_CONTINUE;}static ieee80211_txrx_resultieee80211_rx_h_802_1x_pae(struct ieee80211_txrx_data *rx){	if (rx->sdata->eapol && ieee80211_is_eapol(rx->skb) &&	    rx->sdata->type != IEEE80211_IF_TYPE_STA &&	    (rx->flags & IEEE80211_TXRXD_RXRA_MATCH))		return TXRX_CONTINUE;	if (unlikely(rx->sdata->ieee802_1x &&		     (rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA &&		     (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_NULLFUNC &&		     (!rx->sta || !(rx->sta->flags & WLAN_STA_AUTHORIZED)) &&		     !ieee80211_is_eapol(rx->skb))) {#ifdef CONFIG_MAC80211_DEBUG		struct ieee80211_hdr *hdr =			(struct ieee80211_hdr *) rx->skb->data;		DECLARE_MAC_BUF(mac);		printk(KERN_DEBUG "%s: dropped frame from %s"		       " (unauthorized port)\n", rx->dev->name,		       print_mac(mac, hdr->addr2));#endif /* CONFIG_MAC80211_DEBUG */		return TXRX_DROP;	}	return TXRX_CONTINUE;}static ieee80211_txrx_resultieee80211_rx_h_drop_unencrypted(struct ieee80211_txrx_data *rx){	/*	 * Pass through unencrypted frames if the hardware has	 * decrypted them already.	 */	if (rx->u.rx.status->flag & RX_FLAG_DECRYPTED)		return TXRX_CONTINUE;	/* Drop unencrypted frames if key is set. */	if (unlikely(!(rx->fc & IEEE80211_FCTL_PROTECTED) &&		     (rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA &&		     (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_NULLFUNC &&		     (rx->key || rx->sdata->drop_unencrypted) &&		     (rx->sdata->eapol == 0 || !ieee80211_is_eapol(rx->skb)))) {		if (net_ratelimit())			printk(KERN_DEBUG "%s: RX non-WEP frame, but expected "			       "encryption\n", rx->dev->name);		return TXRX_DROP;	}	return TXRX_CONTINUE;}static ieee80211_txrx_resultieee80211_rx_h_data(struct ieee80211_txrx_data *rx){	struct net_device *dev = rx->dev;	struct ieee80211_local *local = rx->local;	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;	u16 fc, hdrlen, ethertype;	u8 *payload;	u8 dst[ETH_ALEN];	u8 src[ETH_ALEN];	struct sk_buff *skb = rx->skb, *skb2;	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);	DECLARE_MAC_BUF(mac);	DECLARE_MAC_BUF(mac2);	DECLARE_MAC_BUF(mac3);	DECLARE_MAC_BUF(mac4);	fc = rx->fc;	if (unlikely((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA))		return TXRX_CONTINUE;	if (unlikely(!WLAN_FC_DATA_PRESENT(fc)))		return TXRX_DROP;	hdrlen = ieee80211_get_hdrlen(fc);	/* convert IEEE 802.11 header + possible LLC headers into Ethernet	 * header	 * IEEE 802.11 address fields:	 * ToDS FromDS Addr1 Addr2 Addr3 Addr4	 *   0     0   DA    SA    BSSID n/a	 *   0     1   DA    BSSID SA    n/a	 *   1     0   BSSID SA    DA    n/a	 *   1     1   RA    TA    DA    SA	 */	switch (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) {	case IEEE80211_FCTL_TODS:		/* BSSID SA DA */		memcpy(dst, hdr->addr3, ETH_ALEN);		memcpy(src, hdr->addr2, ETH_ALEN);		if (unlikely(sdata->type != IEEE80211_IF_TYPE_AP &&			     sdata->type != IEEE80211_IF_TYPE_VLAN)) {			if (net_ratelimit())				printk(KERN_DEBUG "%s: dropped ToDS frame "				       "(BSSID=%s SA=%s DA=%s)\n",				       dev->name,				       print_mac(mac, hdr->addr1),				       print_mac(mac2, hdr->addr2),				       print_mac(mac3, hdr->addr3));			return TXRX_DROP;		}

⌨️ 快捷键说明

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