linux/drivers/staging/rtl8188eu/os_dep/mon.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * RTL8188EU monitor interface
   4 *
   5 * Copyright (C) 2015 Jakub Sitnicki
   6 */
   7
   8#include <linux/ieee80211.h>
   9#include <linux/netdevice.h>
  10#include <net/cfg80211.h>
  11
  12#include <drv_types.h>
  13#include <rtw_recv.h>
  14#include <rtw_xmit.h>
  15#include <mon.h>
  16
  17/**
  18 * unprotect_frame() - unset Protected flag and strip off IV and ICV/MIC
  19 */
  20static void unprotect_frame(struct sk_buff *skb, int iv_len, int icv_len)
  21{
  22        struct ieee80211_hdr *hdr;
  23        int hdr_len;
  24
  25        hdr = (struct ieee80211_hdr *)skb->data;
  26        hdr_len = ieee80211_hdrlen(hdr->frame_control);
  27
  28        if (skb->len < hdr_len + iv_len + icv_len)
  29                return;
  30        if (!ieee80211_has_protected(hdr->frame_control))
  31                return;
  32
  33        hdr->frame_control &= ~cpu_to_le16(IEEE80211_FCTL_PROTECTED);
  34
  35        memmove(skb->data + iv_len, skb->data, hdr_len);
  36        skb_pull(skb, iv_len);
  37        skb_trim(skb, skb->len - icv_len);
  38}
  39
  40static void mon_recv_decrypted(struct net_device *dev, const u8 *data,
  41                               int data_len, int iv_len, int icv_len)
  42{
  43        struct sk_buff *skb;
  44
  45        skb = netdev_alloc_skb(dev, data_len);
  46        if (!skb)
  47                return;
  48        skb_put_data(skb, data, data_len);
  49
  50        /*
  51         * Frame data is not encrypted. Strip off protection so
  52         * userspace doesn't think that it is.
  53         */
  54        unprotect_frame(skb, iv_len, icv_len);
  55
  56        skb->ip_summed = CHECKSUM_UNNECESSARY;
  57        skb->protocol = eth_type_trans(skb, dev);
  58        netif_rx(skb);
  59}
  60
  61static void mon_recv_encrypted(struct net_device *dev, const u8 *data,
  62                               int data_len)
  63{
  64        if (net_ratelimit())
  65                netdev_info(dev, "Encrypted packets are not supported");
  66}
  67
  68/**
  69 * rtl88eu_mon_recv_hook() - forward received frame to the monitor interface
  70 *
  71 * Assumes that the frame contains an IV and an ICV/MIC, and that
  72 * encrypt field in frame->attrib have been set accordingly.
  73 */
  74void rtl88eu_mon_recv_hook(struct net_device *dev, struct recv_frame *frame)
  75{
  76        struct rx_pkt_attrib *attr;
  77        int iv_len, icv_len;
  78        int data_len;
  79        u8 *data;
  80
  81        if (!dev || !frame)
  82                return;
  83        if (!netif_running(dev))
  84                return;
  85
  86        attr = &frame->attrib;
  87        data = frame->pkt->data;
  88        data_len = frame->pkt->len;
  89
  90        /* Broadcast and multicast frames don't have attr->{iv,icv}_len set */
  91        SET_ICE_IV_LEN(iv_len, icv_len, attr->encrypt);
  92
  93        if (attr->bdecrypted)
  94                mon_recv_decrypted(dev, data, data_len, iv_len, icv_len);
  95        else
  96                mon_recv_encrypted(dev, data, data_len);
  97}
  98
  99/**
 100 * rtl88eu_mon_xmit_hook() - forward trasmitted frame to the monitor interface
 101 *
 102 * Assumes that:
 103 * - frame header contains an IV and frame->attrib.iv_len is set accordingly,
 104 * - data is not encrypted and ICV/MIC has not been appended yet.
 105 */
 106void rtl88eu_mon_xmit_hook(struct net_device *dev, struct xmit_frame *frame,
 107                           uint frag_len)
 108{
 109        struct pkt_attrib *attr;
 110        u8 *data;
 111        int i, offset;
 112
 113        if (!dev || !frame)
 114                return;
 115        if (!netif_running(dev))
 116                return;
 117
 118        attr = &frame->attrib;
 119
 120        offset = TXDESC_SIZE + frame->pkt_offset * PACKET_OFFSET_SZ;
 121        data = frame->buf_addr + offset;
 122
 123        for (i = 0; i < attr->nr_frags - 1; i++) {
 124                mon_recv_decrypted(dev, data, frag_len, attr->iv_len, 0);
 125                data += frag_len;
 126                data = (u8 *)round_up((size_t)data, 4);
 127        }
 128        /* Last fragment has different length */
 129        mon_recv_decrypted(dev, data, attr->last_txcmdsz, attr->iv_len, 0);
 130}
 131
 132static netdev_tx_t mon_xmit(struct sk_buff *skb, struct net_device *dev)
 133{
 134        dev_kfree_skb(skb);
 135        return NETDEV_TX_OK;
 136}
 137
 138static const struct net_device_ops mon_netdev_ops = {
 139        .ndo_start_xmit         = mon_xmit,
 140        .ndo_set_mac_address    = eth_mac_addr,
 141        .ndo_validate_addr      = eth_validate_addr,
 142};
 143
 144static void mon_setup(struct net_device *dev)
 145{
 146        dev->netdev_ops = &mon_netdev_ops;
 147        dev->needs_free_netdev = true;
 148        ether_setup(dev);
 149        dev->priv_flags |= IFF_NO_QUEUE;
 150        dev->type = ARPHRD_IEEE80211;
 151        /*
 152         * Use a locally administered address (IEEE 802)
 153         * XXX: Copied from mac80211_hwsim driver. Revisit.
 154         */
 155        eth_zero_addr(dev->dev_addr);
 156        dev->dev_addr[0] = 0x12;
 157}
 158
 159struct net_device *rtl88eu_mon_init(void)
 160{
 161        struct net_device *dev;
 162        int err;
 163
 164        dev = alloc_netdev(0, "mon%d", NET_NAME_UNKNOWN, mon_setup);
 165        if (!dev)
 166                goto fail;
 167
 168        err = register_netdev(dev);
 169        if (err < 0)
 170                goto fail_free_dev;
 171
 172        return dev;
 173
 174fail_free_dev:
 175        free_netdev(dev);
 176fail:
 177        return NULL;
 178}
 179
 180void rtl88eu_mon_deinit(struct net_device *dev)
 181{
 182        if (!dev)
 183                return;
 184
 185        unregister_netdev(dev);
 186}
 187