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

📄 hostap_80211_tx.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 2 页
字号:
		printk(KERN_DEBUG "%s: hostap_mgmt_start_xmit: short skb "		       "(len=%d)\n", dev->name, skb->len);		kfree_skb(skb);		return 0;	}	iface->stats.tx_packets++;	iface->stats.tx_bytes += skb->len;	meta = (struct hostap_skb_tx_data *) skb->cb;	memset(meta, 0, sizeof(*meta));	meta->magic = HOSTAP_SKB_TX_DATA_MAGIC;	meta->iface = iface;	if (skb->len >= IEEE80211_DATA_HDR3_LEN + sizeof(rfc1042_header) + 2) {		hdr = (struct ieee80211_hdr_4addr *) skb->data;		fc = le16_to_cpu(hdr->frame_ctl);		if (WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA &&		    WLAN_FC_GET_STYPE(fc) == IEEE80211_STYPE_DATA) {			u8 *pos = &skb->data[IEEE80211_DATA_HDR3_LEN +					     sizeof(rfc1042_header)];			meta->ethertype = (pos[0] << 8) | pos[1];		}	}	/* Send IEEE 802.11 encapsulated frame using the master radio device */	skb->dev = local->dev;	dev_queue_xmit(skb);	return 0;}/* Called only from software IRQ */static struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb,					  struct ieee80211_crypt_data *crypt){	struct hostap_interface *iface;	local_info_t *local;	struct ieee80211_hdr_4addr *hdr;	u16 fc;	int prefix_len, postfix_len, hdr_len, res;	DECLARE_MAC_BUF(mac);	iface = netdev_priv(skb->dev);	local = iface->local;	if (skb->len < IEEE80211_DATA_HDR3_LEN) {		kfree_skb(skb);		return NULL;	}	if (local->tkip_countermeasures &&	    strcmp(crypt->ops->name, "TKIP") == 0) {		hdr = (struct ieee80211_hdr_4addr *) skb->data;		if (net_ratelimit()) {			printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "			       "TX packet to %s\n",			       local->dev->name, print_mac(mac, hdr->addr1));		}		kfree_skb(skb);		return NULL;	}	skb = skb_unshare(skb, GFP_ATOMIC);	if (skb == NULL)		return NULL;	prefix_len = crypt->ops->extra_mpdu_prefix_len +		crypt->ops->extra_msdu_prefix_len;	postfix_len = crypt->ops->extra_mpdu_postfix_len +		crypt->ops->extra_msdu_postfix_len;	if ((skb_headroom(skb) < prefix_len ||	     skb_tailroom(skb) < postfix_len) &&	    pskb_expand_head(skb, prefix_len, postfix_len, GFP_ATOMIC)) {		kfree_skb(skb);		return NULL;	}	hdr = (struct ieee80211_hdr_4addr *) skb->data; 	fc = le16_to_cpu(hdr->frame_ctl);	hdr_len = hostap_80211_get_hdrlen(fc);	/* Host-based IEEE 802.11 fragmentation for TX is not yet supported, so	 * call both MSDU and MPDU encryption functions from here. */	atomic_inc(&crypt->refcnt);	res = 0;	if (crypt->ops->encrypt_msdu)		res = crypt->ops->encrypt_msdu(skb, hdr_len, crypt->priv);	if (res == 0 && crypt->ops->encrypt_mpdu)		res = crypt->ops->encrypt_mpdu(skb, hdr_len, crypt->priv);	atomic_dec(&crypt->refcnt);	if (res < 0) {		kfree_skb(skb);		return NULL;	}	return skb;}/* hard_start_xmit function for master radio interface wifi#. * AP processing (TX rate control, power save buffering, etc.). * Use hardware TX function to send the frame. */int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev){	struct hostap_interface *iface;	local_info_t *local;	int ret = 1;	u16 fc;	struct hostap_tx_data tx;	ap_tx_ret tx_ret;	struct hostap_skb_tx_data *meta;	int no_encrypt = 0;	struct ieee80211_hdr_4addr *hdr;	iface = netdev_priv(dev);	local = iface->local;	tx.skb = skb;	tx.sta_ptr = NULL;	meta = (struct hostap_skb_tx_data *) skb->cb;	if (meta->magic != HOSTAP_SKB_TX_DATA_MAGIC) {		printk(KERN_DEBUG "%s: invalid skb->cb magic (0x%08x, "		       "expected 0x%08x)\n",		       dev->name, meta->magic, HOSTAP_SKB_TX_DATA_MAGIC);		ret = 0;		iface->stats.tx_dropped++;		goto fail;	}	if (local->host_encrypt) {		/* Set crypt to default algorithm and key; will be replaced in		 * AP code if STA has own alg/key */		tx.crypt = local->crypt[local->tx_keyidx];		tx.host_encrypt = 1;	} else {		tx.crypt = NULL;		tx.host_encrypt = 0;	}	if (skb->len < 24) {		printk(KERN_DEBUG "%s: hostap_master_start_xmit: short skb "		       "(len=%d)\n", dev->name, skb->len);		ret = 0;		iface->stats.tx_dropped++;		goto fail;	}	/* FIX (?):	 * Wi-Fi 802.11b test plan suggests that AP should ignore power save	 * bit in authentication and (re)association frames and assume tha	 * STA remains awake for the response. */	tx_ret = hostap_handle_sta_tx(local, &tx);	skb = tx.skb;	meta = (struct hostap_skb_tx_data *) skb->cb;	hdr = (struct ieee80211_hdr_4addr *) skb->data; 	fc = le16_to_cpu(hdr->frame_ctl);	switch (tx_ret) {	case AP_TX_CONTINUE:		break;	case AP_TX_CONTINUE_NOT_AUTHORIZED:		if (local->ieee_802_1x &&		    WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA &&		    meta->ethertype != ETH_P_PAE &&		    !(meta->flags & HOSTAP_TX_FLAGS_WDS)) {			printk(KERN_DEBUG "%s: dropped frame to unauthorized "			       "port (IEEE 802.1X): ethertype=0x%04x\n",			       dev->name, meta->ethertype);			hostap_dump_tx_80211(dev->name, skb);			ret = 0; /* drop packet */			iface->stats.tx_dropped++;			goto fail;		}		break;	case AP_TX_DROP:		ret = 0; /* drop packet */		iface->stats.tx_dropped++;		goto fail;	case AP_TX_RETRY:		goto fail;	case AP_TX_BUFFERED:		/* do not free skb here, it will be freed when the		 * buffered frame is sent/timed out */		ret = 0;		goto tx_exit;	}	/* Request TX callback if protocol version is 2 in 802.11 header;	 * this version 2 is a special case used between hostapd and kernel	 * driver */	if (((fc & IEEE80211_FCTL_VERS) == BIT(1)) &&	    local->ap && local->ap->tx_callback_idx && meta->tx_cb_idx == 0) {		meta->tx_cb_idx = local->ap->tx_callback_idx;		/* remove special version from the frame header */		fc &= ~IEEE80211_FCTL_VERS;		hdr->frame_ctl = cpu_to_le16(fc);	}	if (WLAN_FC_GET_TYPE(fc) != IEEE80211_FTYPE_DATA) {		no_encrypt = 1;		tx.crypt = NULL;	}	if (local->ieee_802_1x && meta->ethertype == ETH_P_PAE && tx.crypt &&	    !(fc & IEEE80211_FCTL_PROTECTED)) {		no_encrypt = 1;		PDEBUG(DEBUG_EXTRA2, "%s: TX: IEEE 802.1X - passing "		       "unencrypted EAPOL frame\n", dev->name);		tx.crypt = NULL; /* no encryption for IEEE 802.1X frames */	}	if (tx.crypt && (!tx.crypt->ops || !tx.crypt->ops->encrypt_mpdu))		tx.crypt = NULL;	else if ((tx.crypt || local->crypt[local->tx_keyidx]) && !no_encrypt) {		/* Add ISWEP flag both for firmware and host based encryption		 */		fc |= IEEE80211_FCTL_PROTECTED;		hdr->frame_ctl = cpu_to_le16(fc);	} else if (local->drop_unencrypted &&		   WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA &&		   meta->ethertype != ETH_P_PAE) {		if (net_ratelimit()) {			printk(KERN_DEBUG "%s: dropped unencrypted TX data "			       "frame (drop_unencrypted=1)\n", dev->name);		}		iface->stats.tx_dropped++;		ret = 0;		goto fail;	}	if (tx.crypt) {		skb = hostap_tx_encrypt(skb, tx.crypt);		if (skb == NULL) {			printk(KERN_DEBUG "%s: TX - encryption failed\n",			       dev->name);			ret = 0;			goto fail;		}		meta = (struct hostap_skb_tx_data *) skb->cb;		if (meta->magic != HOSTAP_SKB_TX_DATA_MAGIC) {			printk(KERN_DEBUG "%s: invalid skb->cb magic (0x%08x, "			       "expected 0x%08x) after hostap_tx_encrypt\n",			       dev->name, meta->magic,			       HOSTAP_SKB_TX_DATA_MAGIC);			ret = 0;			iface->stats.tx_dropped++;			goto fail;		}	}	if (local->func->tx == NULL || local->func->tx(skb, dev)) {		ret = 0;		iface->stats.tx_dropped++;	} else {		ret = 0;		iface->stats.tx_packets++;		iface->stats.tx_bytes += skb->len;	} fail:	if (!ret && skb)		dev_kfree_skb(skb); tx_exit:	if (tx.sta_ptr)		hostap_handle_sta_release(tx.sta_ptr);	return ret;}EXPORT_SYMBOL(hostap_master_start_xmit);

⌨️ 快捷键说明

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