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