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; }
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; }