• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
unprotect_frame(struct sk_buff * skb,int iv_len,int icv_len)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 
mon_recv_decrypted(struct net_device * dev,const u8 * data,int data_len,int iv_len,int icv_len)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 
mon_recv_encrypted(struct net_device * dev,const u8 * data,int data_len)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  */
rtl88eu_mon_recv_hook(struct net_device * dev,struct recv_frame * frame)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->rx_data;
96 	data_len = frame->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  */
rtl88eu_mon_xmit_hook(struct net_device * dev,struct xmit_frame * frame,uint frag_len)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 
mon_xmit(struct sk_buff * skb,struct net_device * dev)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_change_mtu		= eth_change_mtu,
149 	.ndo_set_mac_address	= eth_mac_addr,
150 	.ndo_validate_addr	= eth_validate_addr,
151 };
152 
mon_setup(struct net_device * dev)153 static void mon_setup(struct net_device *dev)
154 {
155 	dev->netdev_ops = &mon_netdev_ops;
156 	dev->destructor = free_netdev;
157 	ether_setup(dev);
158 	dev->tx_queue_len = 0;
159 	dev->type = ARPHRD_IEEE80211;
160 	/*
161 	 * Use a locally administered address (IEEE 802)
162 	 * XXX: Copied from mac80211_hwsim driver. Revisit.
163 	 */
164 	eth_zero_addr(dev->dev_addr);
165 	dev->dev_addr[0] = 0x12;
166 }
167 
rtl88eu_mon_init(void)168 struct net_device *rtl88eu_mon_init(void)
169 {
170 	struct net_device *dev;
171 	int err;
172 
173 	dev = alloc_netdev(0, "mon%d", NET_NAME_UNKNOWN, mon_setup);
174 	if (!dev)
175 		goto fail;
176 
177 	err = register_netdev(dev);
178 	if (err < 0)
179 		goto fail_free_dev;
180 
181 	return dev;
182 
183 fail_free_dev:
184 	free_netdev(dev);
185 fail:
186 	return NULL;
187 }
188 
rtl88eu_mon_deinit(struct net_device * dev)189 void rtl88eu_mon_deinit(struct net_device *dev)
190 {
191 	if (!dev)
192 		return;
193 
194 	unregister_netdev(dev);
195 }
196