/*
 * RTL8188EU monitor interface
 *
 * Copyright (C) 2015 Jakub Sitnicki
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License version 2 as published by the
 * Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 */

#include <linux/ieee80211.h>
#include <linux/netdevice.h>
#include <net/cfg80211.h>

#include <drv_types.h>
#include <rtw_recv.h>
#include <rtw_xmit.h>
#include <mon.h>

/**
 * unprotect_frame() - unset Protected flag and strip off IV and ICV/MIC
 */
static void unprotect_frame(struct sk_buff *skb, int iv_len, int icv_len)
{
	struct ieee80211_hdr *hdr;
	int hdr_len;

	hdr = (struct ieee80211_hdr *)skb->data;
	hdr_len = ieee80211_hdrlen(hdr->frame_control);

	if (skb->len < hdr_len + iv_len + icv_len)
		return;
	if (!ieee80211_has_protected(hdr->frame_control))
		return;

	hdr->frame_control &= ~cpu_to_le16(IEEE80211_FCTL_PROTECTED);

	memmove(skb->data + iv_len, skb->data, hdr_len);
	skb_pull(skb, iv_len);
	skb_trim(skb, skb->len - icv_len);
}

static void mon_recv_decrypted(struct net_device *dev, const u8 *data,
			       int data_len, int iv_len, int icv_len)
{
	struct sk_buff *skb;

	skb = netdev_alloc_skb(dev, data_len);
	if (!skb)
		return;
	skb_put_data(skb, data, data_len);

	/*
	 * Frame data is not encrypted. Strip off protection so
	 * userspace doesn't think that it is.
	 */
	unprotect_frame(skb, iv_len, icv_len);

	skb->ip_summed = CHECKSUM_UNNECESSARY;
	skb->protocol = eth_type_trans(skb, dev);
	netif_rx(skb);
}

static void mon_recv_decrypted_recv(struct net_device *dev, const u8 *data,
				    int data_len)
{
	struct sk_buff *skb;
	struct ieee80211_hdr *hdr;
	int hdr_len;

	skb = netdev_alloc_skb(dev, data_len);
	if (!skb)
		return;
	memcpy(skb_put(skb, data_len), data, data_len);

	/*
	 * Frame data is not encrypted. Strip off protection so
	 * userspace doesn't think that it is.
	 */

	hdr = (struct ieee80211_hdr *)skb->data;
	hdr_len = ieee80211_hdrlen(hdr->frame_control);

	if (ieee80211_has_protected(hdr->frame_control))
		hdr->frame_control &= ~cpu_to_le16(IEEE80211_FCTL_PROTECTED);

	skb->ip_summed = CHECKSUM_UNNECESSARY;
	skb->protocol = eth_type_trans(skb, dev);
	netif_rx(skb);
}

static void mon_recv_encrypted(struct net_device *dev, const u8 *data,
			       int data_len)
{
	if (net_ratelimit())
		netdev_info(dev, "Encrypted packets are not supported");
}

/**
 * rtl88eu_mon_recv_hook() - forward received frame to the monitor interface
 *
 * Assumes that the frame contains an IV and an ICV/MIC, and that
 * encrypt field in frame->attrib have been set accordingly.
 */
void rtl88eu_mon_recv_hook(struct net_device *dev, struct recv_frame *frame)
{
	struct rx_pkt_attrib *attr;
	int data_len;
	u8 *data;

	if (!dev || !frame)
		return;
	if (!netif_running(dev))
		return;

	attr = &frame->attrib;
	data = frame->pkt->data;
	data_len = frame->pkt->len;

	if (attr->bdecrypted)
		mon_recv_decrypted_recv(dev, data, data_len);
	else
		mon_recv_encrypted(dev, data, data_len);
}

/**
 * rtl88eu_mon_xmit_hook() - forward trasmitted frame to the monitor interface
 *
 * Assumes that:
 * - frame header contains an IV and frame->attrib.iv_len is set accordingly,
 * - data is not encrypted and ICV/MIC has not been appended yet.
 */
void rtl88eu_mon_xmit_hook(struct net_device *dev, struct xmit_frame *frame,
			   uint frag_len)
{
	struct pkt_attrib *attr;
	u8 *data;
	int i, offset;

	if (!dev || !frame)
		return;
	if (!netif_running(dev))
		return;

	attr = &frame->attrib;

	offset = TXDESC_SIZE + frame->pkt_offset * PACKET_OFFSET_SZ;
	data = frame->buf_addr + offset;

	for (i = 0; i < attr->nr_frags - 1; i++) {
		mon_recv_decrypted(dev, data, frag_len, attr->iv_len, 0);
		data += frag_len;
		data = (u8 *)round_up((size_t)data, 4);
	}
	/* Last fragment has different length */
	mon_recv_decrypted(dev, data, attr->last_txcmdsz, attr->iv_len, 0);
}

static netdev_tx_t mon_xmit(struct sk_buff *skb, struct net_device *dev)
{
	dev_kfree_skb(skb);
	return NETDEV_TX_OK;
}

static const struct net_device_ops mon_netdev_ops = {
	.ndo_start_xmit		= mon_xmit,
	.ndo_set_mac_address	= eth_mac_addr,
	.ndo_validate_addr	= eth_validate_addr,
};

static void mon_setup(struct net_device *dev)
{
	dev->netdev_ops = &mon_netdev_ops;
	dev->needs_free_netdev = true;
	ether_setup(dev);
	dev->priv_flags |= IFF_NO_QUEUE;
	dev->type = ARPHRD_IEEE80211;
	/*
	 * Use a locally administered address (IEEE 802)
	 * XXX: Copied from mac80211_hwsim driver. Revisit.
	 */
	eth_zero_addr(dev->dev_addr);
	dev->dev_addr[0] = 0x12;
}

struct net_device *rtl88eu_mon_init(void)
{
	struct net_device *dev;
	int err;

	dev = alloc_netdev(0, "mon%d", NET_NAME_UNKNOWN, mon_setup);
	if (!dev)
		goto fail;

	err = register_netdev(dev);
	if (err < 0)
		goto fail_free_dev;

	return dev;

fail_free_dev:
	free_netdev(dev);
fail:
	return NULL;
}

void rtl88eu_mon_deinit(struct net_device *dev)
{
	if (!dev)
		return;

	unregister_netdev(dev);
}
