Ejemplo n.º 1
0
static int wlan_rx_wapi_process(const unsigned char vif_id,
				unsigned char *pData, unsigned short len)
{
	struct ieee80211_hdr_3addr *addr;
	int decryp_data_len = 0;
	struct sk_buff *skb;
	u8 snap_header[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
	wlan_vif_t *vif;
	struct net_device *ndev;

	vif = &(g_wlan.netif[vif_id]);
	ndev = vif->ndev;
	if ((NULL == pData) || (0 == len) || (NULL == ndev)) {
		printkd("[%s][%d][err]\n", __func__, (int)vif_id);
		return ERROR;
	}
	addr = (struct ieee80211_hdr_3addr *)pData;
	skb = dev_alloc_skb(len + NET_IP_ALIGN);
	if (NULL == skb)
		return ERROR;
	skb_reserve(skb, NET_IP_ALIGN);

	decryp_data_len =
	    wlan_rx_wapi_decryption(vif, (unsigned char *)addr, 24, (len - 24),
				    (skb->data + 12));
	if (decryp_data_len == 0) {
		dev_kfree_skb(skb);
		return ERROR;
	}
	if (memcmp((skb->data + 12), snap_header, sizeof(snap_header)) == 0) {
		skb_reserve(skb, 6);
		memcpy(skb->data, addr->addr1, 6);
		memcpy(skb->data + 6, addr->addr2, 6);
		skb_put(skb, (decryp_data_len + 6));
	} else {
		/* copy eth header */
		memcpy(skb->data, addr->addr3, 6);
		memcpy(skb->data + 6, addr->addr2, 6);
		skb_put(skb, (decryp_data_len + 12));
	}
	skb->dev = ndev;
	skb->protocol = eth_type_trans(skb, ndev);
	ndev->stats.rx_packets++;
	printkp("rx_skb:%d\n", (int)(ndev->stats.rx_packets));
	ndev->stats.rx_bytes += skb->len;
	if (in_interrupt())
		netif_rx(skb);
	else
		netif_rx_ni(skb);
	return OK;
}
Ejemplo n.º 2
0
static int sprdwl_rx_handler(struct napi_struct *napi, int budget)
{
	struct sprdwl_priv *priv = container_of(napi, struct sprdwl_priv, napi);
	struct sblock blk;
	struct sk_buff *skb;
	int ret, work_done;
	u16 decryp_data_len = 0;
	struct wlan_sblock_recv_data *data;
	uint32_t length = 0;
#ifdef CONFIG_SPRDWL_FW_ZEROCOPY
	u8 offset = 0;
#endif
	for (work_done = 0; work_done < budget; work_done++) {
		ret = sblock_receive(WLAN_CP_ID, WLAN_SBLOCK_CH, &blk, 0);
		if (ret) {
			dev_dbg(&priv->ndev->dev, "no more sblock to read\n");
			break;
		}
#ifdef CONFIG_SPRDWL_FW_ZEROCOPY
		offset = *(u8 *)blk.addr;
		length = blk.length - 2 - offset;
#else
		length = blk.length;
#endif
		/*16 bytes align */
		skb = dev_alloc_skb(length + NET_IP_ALIGN);
		if (!skb) {
			dev_err(&priv->ndev->dev,
				"Failed to allocate skbuff!\n");
			priv->ndev->stats.rx_dropped++;
			goto rx_failed;
		}
#ifdef CONFIG_SPRDWL_FW_ZEROCOPY
		data = (struct wlan_sblock_recv_data *)(blk.addr + 2 + offset);
#else
		data = (struct wlan_sblock_recv_data *)blk.addr;
#endif

		if (data->is_encrypted == 1) {
			if (priv->connect_status == SPRDWL_CONNECTED &&
			    priv->cipher_type == SPRDWL_CIPHER_WAPI &&
			    priv->key_len[GROUP][priv->key_index[GROUP]] != 0 &&
			    priv->
			    key_len[PAIRWISE][priv->key_index[PAIRWISE]] != 0) {
				u8 snap_header[6] = { 0xaa, 0xaa, 0x03,
					0x00, 0x00, 0x00
				};
				skb_reserve(skb, NET_IP_ALIGN);
				decryp_data_len = wlan_rx_wapi_decryption(priv,
						   (u8 *)&data->u2.encrypt,
						   data->u1.encrypt.header_len,
						   (length -
						   sizeof(data->is_encrypted) -
						   sizeof(data->u1) -
						   data->u1.encrypt.header_len),
						   (skb->data + 12));
				if (decryp_data_len == 0) {
					dev_err(&priv->ndev->dev,
						"Failed to decrypt WAPI data!\n");
					priv->ndev->stats.rx_dropped++;
					dev_kfree_skb(skb);
					goto rx_failed;
				}
				if (memcmp((skb->data + 12), snap_header,
					   sizeof(snap_header)) == 0) {
					skb_reserve(skb, 6);
					/* copy the eth address from eth header,
					 * but not copy eth type
					 */
					memcpy(skb->data,
					       data->u2.encrypt.
					       mac_header.addr1, 6);
					memcpy(skb->data + 6,
					       data->u2.encrypt.
					       mac_header.addr2, 6);
					skb_put(skb, (decryp_data_len + 6));
				} else {
					/* copy eth header */
					memcpy(skb->data,
					       data->u2.encrypt.
					       mac_header.addr3, 6);
					memcpy(skb->data + 6,
					       data->u2.encrypt.
					       mac_header.addr2, 6);
					skb_put(skb, (decryp_data_len + 12));
				}
			} else {
				dev_err(&priv->ndev->dev,
					"wrong encryption data!\n");
				priv->ndev->stats.rx_dropped++;
				dev_kfree_skb(skb);
				goto rx_failed;
			}
		} else if (data->is_encrypted == 0) {
			skb_reserve(skb, NET_IP_ALIGN);
			/* dec the first encrypt byte */
			memcpy(skb->data, (u8 *)&data->u2,
			       (length - sizeof(data->is_encrypted) -
				sizeof(data->u1)));
			skb_put(skb,
				(length - sizeof(data->is_encrypted) -
				 sizeof(data->u1)));
		} else {
			dev_err(&priv->ndev->dev,
				"wrong data fromat recieved!\n");
			priv->ndev->stats.rx_dropped++;
			dev_kfree_skb(skb);
			goto rx_failed;
		}

#ifdef DUMP_RECEIVE_PACKET
		print_hex_dump(KERN_DEBUG, "receive packet: ",
			       DUMP_PREFIX_OFFSET, 16, 1, skb->data, skb->len,
			       0);
#endif
		skb->dev = priv->ndev;
		skb->protocol = eth_type_trans(skb, priv->ndev);
		/* CHECKSUM_UNNECESSARY not supported by our hardware */
		/* skb->ip_summed = CHECKSUM_UNNECESSARY; */

		priv->ndev->stats.rx_packets++;
		priv->ndev->stats.rx_bytes += skb->len;

		napi_gro_receive(napi, skb);

rx_failed:
		ret = sblock_release(WLAN_CP_ID, WLAN_SBLOCK_CH, &blk);
		if (ret)
			dev_err(&priv->ndev->dev,
				"Failed to release sblock (%d)!\n", ret);
	}
	if (work_done < budget)
		napi_complete(napi);

	return work_done;
}