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

📄 ieee80211_tx.c

📁 Source for the 802.11 (wireless) network stack for Linux
💻 C
📖 第 1 页 / 共 2 页
字号:
		fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA |		    IEEE80211_FCTL_PROTECTED;	else		fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA;	if (ieee->iw_mode == IW_MODE_INFRA) {		fc |= IEEE80211_FCTL_TODS;		/* To DS: Addr1 = BSSID, Addr2 = SA, Addr3 = DA */		memcpy(header.addr1, ieee->bssid, ETH_ALEN);		memcpy(header.addr2, src, ETH_ALEN);		memcpy(header.addr3, dest, ETH_ALEN);	} else if (ieee->iw_mode == IW_MODE_ADHOC) {		/* not From/To DS: Addr1 = DA, Addr2 = SA, Addr3 = BSSID */		memcpy(header.addr1, dest, ETH_ALEN);		memcpy(header.addr2, src, ETH_ALEN);		memcpy(header.addr3, ieee->bssid, ETH_ALEN);	}	header.frame_ctl = cpu_to_le16(fc);	hdr_len = IEEE80211_3ADDR_LEN;	/* Encrypt msdu first on the whole data packet. */	if ((host_encrypt || host_encrypt_msdu) &&	    crypt && crypt->ops && crypt->ops->encrypt_msdu) {		int res = 0;		int len = bytes + hdr_len + crypt->ops->extra_msdu_prefix_len +		    crypt->ops->extra_msdu_postfix_len;		struct sk_buff *skb_new = dev_alloc_skb(len);		if (unlikely(!skb_new))			goto failed;		skb_reserve(skb_new, crypt->ops->extra_msdu_prefix_len);		memcpy(skb_put(skb_new, hdr_len), &header, hdr_len);		snapped = 1;		ieee80211_copy_snap(skb_put(skb_new, SNAP_SIZE + sizeof(u16)),				    ether_type);		memcpy(skb_put(skb_new, skb->len), skb->data, skb->len);		res = crypt->ops->encrypt_msdu(skb_new, hdr_len, crypt->priv);		if (res < 0) {			IEEE80211_ERROR("msdu encryption failed\n");			dev_kfree_skb_any(skb_new);			goto failed;		}		dev_kfree_skb_any(skb);		skb = skb_new;		bytes += crypt->ops->extra_msdu_prefix_len +		    crypt->ops->extra_msdu_postfix_len;		skb_pull(skb, hdr_len);	}	if (host_encrypt || ieee->host_open_frag) {		/* Determine fragmentation size based on destination (multicast		 * and broadcast are not fragmented) */		if (is_multicast_ether_addr(dest) ||		    ieee80211_is_broadcast_ether_addr(dest))			frag_size = MAX_FRAG_THRESHOLD;		else			frag_size = ieee->fts;		/* Determine amount of payload per fragment.  Regardless of if		 * this stack is providing the full 802.11 header, one will		 * eventually be affixed to this fragment -- so we must account		 * for it when determining the amount of payload space. */		bytes_per_frag = frag_size - IEEE80211_3ADDR_LEN;		if (ieee->config &		    (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))			bytes_per_frag -= IEEE80211_FCS_LEN;		/* Each fragment may need to have room for encryptiong		 * pre/postfix */		if (host_encrypt)			bytes_per_frag -= crypt->ops->extra_mpdu_prefix_len +			    crypt->ops->extra_mpdu_postfix_len;		/* Number of fragments is the total		 * bytes_per_frag / payload_per_fragment */		nr_frags = bytes / bytes_per_frag;		bytes_last_frag = bytes % bytes_per_frag;		if (bytes_last_frag)			nr_frags++;		else			bytes_last_frag = bytes_per_frag;	} else {		nr_frags = 1;		bytes_per_frag = bytes_last_frag = bytes;		frag_size = bytes + IEEE80211_3ADDR_LEN;	}	rts_required = (frag_size > ieee->rts			&& ieee->config & CFG_IEEE80211_RTS);	if (rts_required)		nr_frags++;	/* When we allocate the TXB we allocate enough space for the reserve	 * and full fragment bytes (bytes_per_frag doesn't include prefix,	 * postfix, header, FCS, etc.) */	txb = ieee80211_alloc_txb(nr_frags, frag_size, GFP_ATOMIC);	if (unlikely(!txb)) {		printk(KERN_WARNING "%s: Could not allocate TXB\n",		       ieee->dev->name);		goto failed;	}	txb->encrypted = encrypt;	if (host_encrypt)		txb->payload_size = frag_size * (nr_frags - 1) +		    bytes_last_frag;	else		txb->payload_size = bytes;	if (rts_required) {		skb_frag = txb->fragments[0];		frag_hdr =		    (struct ieee80211_hdr_3addr *)skb_put(skb_frag, hdr_len);		/*		 * Set header frame_ctl to the RTS.		 */		header.frame_ctl =		    cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS);		memcpy(frag_hdr, &header, hdr_len);		/*		 * Restore header frame_ctl to the original data setting.		 */		header.frame_ctl = cpu_to_le16(fc);		if (ieee->config &		    (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))			skb_put(skb_frag, 4);		txb->rts_included = 1;		i = 1;	} else		i = 0;	for (; i < nr_frags; i++) {		skb_frag = txb->fragments[i];		if (host_encrypt || host_build_iv)			skb_reserve(skb_frag,				    crypt->ops->extra_mpdu_prefix_len);		frag_hdr =		    (struct ieee80211_hdr_3addr *)skb_put(skb_frag, hdr_len);		memcpy(frag_hdr, &header, hdr_len);		/* If this is not the last fragment, then add the MOREFRAGS		 * bit to the frame control */		if (i != nr_frags - 1) {			frag_hdr->frame_ctl =			    cpu_to_le16(fc | IEEE80211_FCTL_MOREFRAGS);			bytes = bytes_per_frag;		} else {			/* The last fragment takes the remaining length */			bytes = bytes_last_frag;		}		if (i == 0 && !snapped) {			ieee80211_copy_snap(skb_put					    (skb_frag, SNAP_SIZE + sizeof(u16)),					    ether_type);			bytes -= SNAP_SIZE + sizeof(u16);		}		memcpy(skb_put(skb_frag, bytes), skb->data, bytes);		/* Advance the SKB... */		skb_pull(skb, bytes);		/* Encryption routine will move the header forward in order		 * to insert the IV between the header and the payload */		if (host_encrypt)			ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len);		else if (host_build_iv) {			struct ieee80211_crypt_data *crypt;			crypt = ieee->crypt[ieee->tx_keyidx];			atomic_inc(&crypt->refcnt);			if (crypt->ops->build_iv)				crypt->ops->build_iv(skb_frag, hdr_len,						     crypt->priv);			atomic_dec(&crypt->refcnt);		}		if (ieee->config &		    (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))			skb_put(skb_frag, 4);	}      success:	spin_unlock_irqrestore(&ieee->lock, flags);	dev_kfree_skb_any(skb);	if (txb) {		int ret = (*ieee->hard_start_xmit) (txb, dev, priority);		if (ret == 0) {			stats->tx_packets++;			stats->tx_bytes += txb->payload_size;			return 0;		}		if (ret == NETDEV_TX_BUSY) {			printk(KERN_ERR "%s: NETDEV_TX_BUSY returned; "			       "driver should report queue full via "			       "ieee_device->is_queue_full.\n",			       ieee->dev->name);		}		ieee80211_txb_free(txb);	}	return 0;      failed:	spin_unlock_irqrestore(&ieee->lock, flags);	netif_stop_queue(dev);	stats->tx_errors++;	return 1;}/* Incoming 802.11 strucure is converted to a TXB * a block of 802.11 fragment packets (stored as skbs) */int ieee80211_tx_frame(struct ieee80211_device *ieee,		       struct ieee80211_hdr *frame, int len){	struct ieee80211_txb *txb = NULL;	unsigned long flags;	struct net_device_stats *stats = &ieee->stats;	struct sk_buff *skb_frag;	int priority = -1;	spin_lock_irqsave(&ieee->lock, flags);	/* If there is no driver handler to take the TXB, dont' bother	 * creating it... */	if (!ieee->hard_start_xmit) {		printk(KERN_WARNING "%s: No xmit handler.\n", ieee->dev->name);		goto success;	}	if (unlikely(len < 24)) {		printk(KERN_WARNING "%s: skb too small (%d).\n",		       ieee->dev->name, len);		goto success;	}	/* When we allocate the TXB we allocate enough space for the reserve	 * and full fragment bytes (bytes_per_frag doesn't include prefix,	 * postfix, header, FCS, etc.) */	txb = ieee80211_alloc_txb(1, len, GFP_ATOMIC);	if (unlikely(!txb)) {		printk(KERN_WARNING "%s: Could not allocate TXB\n",		       ieee->dev->name);		goto failed;	}	txb->encrypted = 0;	txb->payload_size = len;	skb_frag = txb->fragments[0];	memcpy(skb_put(skb_frag, len), frame, len);	if (ieee->config &	    (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))		skb_put(skb_frag, 4);      success:	spin_unlock_irqrestore(&ieee->lock, flags);	if (txb) {		if ((*ieee->hard_start_xmit) (txb, ieee->dev, priority) == 0) {			stats->tx_packets++;			stats->tx_bytes += txb->payload_size;			return 0;		}		ieee80211_txb_free(txb);	}	return 0;      failed:	spin_unlock_irqrestore(&ieee->lock, flags);	stats->tx_errors++;	return 1;}EXPORT_SYMBOL(ieee80211_tx_frame);EXPORT_SYMBOL(ieee80211_txb_free);

⌨️ 快捷键说明

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