blob: 29770cfefc3d7041c8d1ec157c949242a23a389e [file] [log] [blame]
Jeff Garzikb4538722005-05-12 22:48:20 -04001/******************************************************************************
2
3 Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved.
4
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of version 2 of the GNU General Public License as
7 published by the Free Software Foundation.
8
9 This program is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 more details.
13
14 You should have received a copy of the GNU General Public License along with
15 this program; if not, write to the Free Software Foundation, Inc., 59
16 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
18 The full GNU General Public License is included in this distribution in the
19 file called LICENSE.
20
21 Contact Information:
22 James P. Ketrenos <ipw2100-admin@linux.intel.com>
23 Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
24
25******************************************************************************/
26#include <linux/compiler.h>
27#include <linux/config.h>
28#include <linux/errno.h>
29#include <linux/if_arp.h>
30#include <linux/in6.h>
31#include <linux/in.h>
32#include <linux/ip.h>
33#include <linux/kernel.h>
34#include <linux/module.h>
35#include <linux/netdevice.h>
Jeff Garzikb4538722005-05-12 22:48:20 -040036#include <linux/proc_fs.h>
37#include <linux/skbuff.h>
38#include <linux/slab.h>
39#include <linux/tcp.h>
40#include <linux/types.h>
41#include <linux/version.h>
42#include <linux/wireless.h>
43#include <linux/etherdevice.h>
44#include <asm/uaccess.h>
45
46#include <net/ieee80211.h>
47
Jeff Garzikb4538722005-05-12 22:48:20 -040048/*
49
Jeff Garzikb4538722005-05-12 22:48:20 -040050802.11 Data Frame
51
52 ,-------------------------------------------------------------------.
53Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 |
54 |------|------|---------|---------|---------|------|---------|------|
55Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | Frame | fcs |
56 | | tion | (BSSID) | | | ence | data | |
57 `--------------------------------------------------| |------'
58Total: 28 non-data bytes `----.----'
59 |
60 .- 'Frame data' expands to <---------------------------'
61 |
62 V
63 ,---------------------------------------------------.
64Bytes | 1 | 1 | 1 | 3 | 2 | 0-2304 |
65 |------|------|---------|----------|------|---------|
66Desc. | SNAP | SNAP | Control |Eth Tunnel| Type | IP |
67 | DSAP | SSAP | | | | Packet |
68 | 0xAA | 0xAA |0x03 (UI)|0x00-00-F8| | |
69 `-----------------------------------------| |
70Total: 8 non-data bytes `----.----'
71 |
72 .- 'IP Packet' expands, if WEP enabled, to <--'
73 |
74 V
75 ,-----------------------.
76Bytes | 4 | 0-2296 | 4 |
77 |-----|-----------|-----|
78Desc. | IV | Encrypted | ICV |
79 | | IP Packet | |
80 `-----------------------'
81Total: 8 non-data bytes
82
Jeff Garzikb4538722005-05-12 22:48:20 -040083802.3 Ethernet Data Frame
84
85 ,-----------------------------------------.
86Bytes | 6 | 6 | 2 | Variable | 4 |
87 |-------|-------|------|-----------|------|
88Desc. | Dest. | Source| Type | IP Packet | fcs |
89 | MAC | MAC | | | |
90 `-----------------------------------------'
91Total: 18 non-data bytes
92
93In the event that fragmentation is required, the incoming payload is split into
94N parts of size ieee->fts. The first fragment contains the SNAP header and the
95remaining packets are just data.
96
97If encryption is enabled, each fragment payload size is reduced by enough space
98to add the prefix and postfix (IV and ICV totalling 8 bytes in the case of WEP)
99So if you have 1500 bytes of payload with ieee->fts set to 500 without
100encryption it will take 3 frames. With WEP it will take 4 frames as the
101payload of each frame is reduced to 492 bytes.
102
103* SKB visualization
104*
105* ,- skb->data
106* |
107* | ETHERNET HEADER ,-<-- PAYLOAD
108* | | 14 bytes from skb->data
109* | 2 bytes for Type --> ,T. | (sizeof ethhdr)
110* | | | |
111* |,-Dest.--. ,--Src.---. | | |
112* | 6 bytes| | 6 bytes | | | |
113* v | | | | | |
114* 0 | v 1 | v | v 2
115* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
116* ^ | ^ | ^ |
117* | | | | | |
118* | | | | `T' <---- 2 bytes for Type
119* | | | |
120* | | '---SNAP--' <-------- 6 bytes for SNAP
121* | |
122* `-IV--' <-------------------- 4 bytes for IV (WEP)
123*
124* SNAP HEADER
125*
126*/
127
128static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 };
129static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 };
130
Jeff Garzik0edd5b42005-09-07 00:48:31 -0400131static inline int ieee80211_put_snap(u8 * data, u16 h_proto)
Jeff Garzikb4538722005-05-12 22:48:20 -0400132{
133 struct ieee80211_snap_hdr *snap;
134 u8 *oui;
135
136 snap = (struct ieee80211_snap_hdr *)data;
137 snap->dsap = 0xaa;
138 snap->ssap = 0xaa;
139 snap->ctrl = 0x03;
140
141 if (h_proto == 0x8137 || h_proto == 0x80f3)
142 oui = P802_1H_OUI;
143 else
144 oui = RFC1042_OUI;
145 snap->oui[0] = oui[0];
146 snap->oui[1] = oui[1];
147 snap->oui[2] = oui[2];
148
Jeff Garzik0edd5b42005-09-07 00:48:31 -0400149 *(u16 *) (data + SNAP_SIZE) = htons(h_proto);
Jeff Garzikb4538722005-05-12 22:48:20 -0400150
151 return SNAP_SIZE + sizeof(u16);
152}
153
Jeff Garzik0edd5b42005-09-07 00:48:31 -0400154static inline int ieee80211_encrypt_fragment(struct ieee80211_device *ieee,
155 struct sk_buff *frag, int hdr_len)
Jeff Garzikb4538722005-05-12 22:48:20 -0400156{
Jeff Garzik0edd5b42005-09-07 00:48:31 -0400157 struct ieee80211_crypt_data *crypt = ieee->crypt[ieee->tx_keyidx];
Jeff Garzikb4538722005-05-12 22:48:20 -0400158 int res;
159
Jeff Garzikb4538722005-05-12 22:48:20 -0400160 /* To encrypt, frame format is:
161 * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) */
162
163 // PR: FIXME: Copied from hostap. Check fragmentation/MSDU/MPDU encryption.
164 /* Host-based IEEE 802.11 fragmentation for TX is not yet supported, so
165 * call both MSDU and MPDU encryption functions from here. */
166 atomic_inc(&crypt->refcnt);
167 res = 0;
168 if (crypt->ops->encrypt_msdu)
169 res = crypt->ops->encrypt_msdu(frag, hdr_len, crypt->priv);
170 if (res == 0 && crypt->ops->encrypt_mpdu)
171 res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv);
172
173 atomic_dec(&crypt->refcnt);
174 if (res < 0) {
175 printk(KERN_INFO "%s: Encryption failed: len=%d.\n",
176 ieee->dev->name, frag->len);
177 ieee->ieee_stats.tx_discards++;
178 return -1;
179 }
180
181 return 0;
182}
183
Jeff Garzik0edd5b42005-09-07 00:48:31 -0400184void ieee80211_txb_free(struct ieee80211_txb *txb)
185{
Jeff Garzikb4538722005-05-12 22:48:20 -0400186 int i;
187 if (unlikely(!txb))
188 return;
189 for (i = 0; i < txb->nr_frags; i++)
190 if (txb->fragments[i])
191 dev_kfree_skb_any(txb->fragments[i]);
192 kfree(txb);
193}
194
Adrian Bunke1572492005-05-06 23:32:39 +0200195static struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size,
196 int gfp_mask)
Jeff Garzikb4538722005-05-12 22:48:20 -0400197{
198 struct ieee80211_txb *txb;
199 int i;
Jeff Garzik0edd5b42005-09-07 00:48:31 -0400200 txb = kmalloc(sizeof(struct ieee80211_txb) + (sizeof(u8 *) * nr_frags),
201 gfp_mask);
Jeff Garzikb4538722005-05-12 22:48:20 -0400202 if (!txb)
203 return NULL;
204
Adrian Bunk0a989b22005-04-11 16:52:15 -0700205 memset(txb, 0, sizeof(struct ieee80211_txb));
Jeff Garzikb4538722005-05-12 22:48:20 -0400206 txb->nr_frags = nr_frags;
207 txb->frag_size = txb_size;
208
209 for (i = 0; i < nr_frags; i++) {
210 txb->fragments[i] = dev_alloc_skb(txb_size);
211 if (unlikely(!txb->fragments[i])) {
212 i--;
213 break;
214 }
215 }
216 if (unlikely(i != nr_frags)) {
217 while (i >= 0)
218 dev_kfree_skb_any(txb->fragments[i--]);
219 kfree(txb);
220 return NULL;
221 }
222 return txb;
223}
224
225/* SKBs are added to the ieee->tx_queue. */
Jeff Garzik0edd5b42005-09-07 00:48:31 -0400226int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
Jeff Garzikb4538722005-05-12 22:48:20 -0400227{
228 struct ieee80211_device *ieee = netdev_priv(dev);
229 struct ieee80211_txb *txb = NULL;
James Ketrenosee34af32005-09-21 11:54:36 -0500230 struct ieee80211_hdr_3addr *frag_hdr;
Jeff Garzikb4538722005-05-12 22:48:20 -0400231 int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size;
232 unsigned long flags;
233 struct net_device_stats *stats = &ieee->stats;
James Ketrenosf1bf6632005-09-21 11:53:54 -0500234 int ether_type, encrypt, host_encrypt;
Jeff Garzikb4538722005-05-12 22:48:20 -0400235 int bytes, fc, hdr_len;
236 struct sk_buff *skb_frag;
James Ketrenosee34af32005-09-21 11:54:36 -0500237 struct ieee80211_hdr_3addr header = { /* Ensure zero initialized */
Jeff Garzikb4538722005-05-12 22:48:20 -0400238 .duration_id = 0,
239 .seq_ctl = 0
240 };
241 u8 dest[ETH_ALEN], src[ETH_ALEN];
242
Jeff Garzik0edd5b42005-09-07 00:48:31 -0400243 struct ieee80211_crypt_data *crypt;
Jeff Garzikb4538722005-05-12 22:48:20 -0400244
245 spin_lock_irqsave(&ieee->lock, flags);
246
247 /* If there is no driver handler to take the TXB, dont' bother
248 * creating it... */
249 if (!ieee->hard_start_xmit) {
Jeff Garzik0edd5b42005-09-07 00:48:31 -0400250 printk(KERN_WARNING "%s: No xmit handler.\n", ieee->dev->name);
Jeff Garzikb4538722005-05-12 22:48:20 -0400251 goto success;
252 }
253
254 if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) {
255 printk(KERN_WARNING "%s: skb too small (%d).\n",
256 ieee->dev->name, skb->len);
257 goto success;
258 }
259
260 ether_type = ntohs(((struct ethhdr *)skb->data)->h_proto);
261
262 crypt = ieee->crypt[ieee->tx_keyidx];
263
264 encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) &&
James Ketrenosf1bf6632005-09-21 11:53:54 -0500265 ieee->sec.encrypt;
266 host_encrypt = ieee->host_encrypt && encrypt;
Jeff Garzikb4538722005-05-12 22:48:20 -0400267
268 if (!encrypt && ieee->ieee802_1x &&
269 ieee->drop_unencrypted && ether_type != ETH_P_PAE) {
270 stats->tx_dropped++;
271 goto success;
272 }
273
Jeff Garzikb4538722005-05-12 22:48:20 -0400274 /* Save source and destination addresses */
James Ketrenos18294d82005-09-13 17:40:29 -0500275 memcpy(dest, skb->data, ETH_ALEN);
276 memcpy(src, skb->data + ETH_ALEN, ETH_ALEN);
Jeff Garzikb4538722005-05-12 22:48:20 -0400277
278 /* Advance the SKB to the start of the payload */
279 skb_pull(skb, sizeof(struct ethhdr));
280
281 /* Determine total amount of storage required for TXB packets */
282 bytes = skb->len + SNAP_SIZE + sizeof(u16);
283
James Ketrenosf1bf6632005-09-21 11:53:54 -0500284 if (host_encrypt)
Jeff Garzikb4538722005-05-12 22:48:20 -0400285 fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA |
Jeff Garzik0edd5b42005-09-07 00:48:31 -0400286 IEEE80211_FCTL_PROTECTED;
Jeff Garzikb4538722005-05-12 22:48:20 -0400287 else
288 fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA;
289
290 if (ieee->iw_mode == IW_MODE_INFRA) {
291 fc |= IEEE80211_FCTL_TODS;
292 /* To DS: Addr1 = BSSID, Addr2 = SA,
293 Addr3 = DA */
James Ketrenos18294d82005-09-13 17:40:29 -0500294 memcpy(header.addr1, ieee->bssid, ETH_ALEN);
295 memcpy(header.addr2, src, ETH_ALEN);
296 memcpy(header.addr3, dest, ETH_ALEN);
Jeff Garzikb4538722005-05-12 22:48:20 -0400297 } else if (ieee->iw_mode == IW_MODE_ADHOC) {
298 /* not From/To DS: Addr1 = DA, Addr2 = SA,
299 Addr3 = BSSID */
James Ketrenos18294d82005-09-13 17:40:29 -0500300 memcpy(header.addr1, dest, ETH_ALEN);
301 memcpy(header.addr2, src, ETH_ALEN);
302 memcpy(header.addr3, ieee->bssid, ETH_ALEN);
Jeff Garzikb4538722005-05-12 22:48:20 -0400303 }
304 header.frame_ctl = cpu_to_le16(fc);
305 hdr_len = IEEE80211_3ADDR_LEN;
306
307 /* Determine fragmentation size based on destination (multicast
308 * and broadcast are not fragmented) */
Jeff Garzik0edd5b42005-09-07 00:48:31 -0400309 if (is_multicast_ether_addr(dest) || is_broadcast_ether_addr(dest))
Jeff Garzikb4538722005-05-12 22:48:20 -0400310 frag_size = MAX_FRAG_THRESHOLD;
311 else
312 frag_size = ieee->fts;
313
314 /* Determine amount of payload per fragment. Regardless of if
315 * this stack is providing the full 802.11 header, one will
316 * eventually be affixed to this fragment -- so we must account for
317 * it when determining the amount of payload space. */
318 bytes_per_frag = frag_size - IEEE80211_3ADDR_LEN;
319 if (ieee->config &
320 (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
321 bytes_per_frag -= IEEE80211_FCS_LEN;
322
323 /* Each fragment may need to have room for encryptiong pre/postfix */
James Ketrenosf1bf6632005-09-21 11:53:54 -0500324 if (host_encrypt)
Jeff Garzikb4538722005-05-12 22:48:20 -0400325 bytes_per_frag -= crypt->ops->extra_prefix_len +
Jeff Garzik0edd5b42005-09-07 00:48:31 -0400326 crypt->ops->extra_postfix_len;
Jeff Garzikb4538722005-05-12 22:48:20 -0400327
328 /* Number of fragments is the total bytes_per_frag /
329 * payload_per_fragment */
330 nr_frags = bytes / bytes_per_frag;
331 bytes_last_frag = bytes % bytes_per_frag;
332 if (bytes_last_frag)
333 nr_frags++;
334 else
335 bytes_last_frag = bytes_per_frag;
336
337 /* When we allocate the TXB we allocate enough space for the reserve
338 * and full fragment bytes (bytes_per_frag doesn't include prefix,
339 * postfix, header, FCS, etc.) */
340 txb = ieee80211_alloc_txb(nr_frags, frag_size, GFP_ATOMIC);
341 if (unlikely(!txb)) {
342 printk(KERN_WARNING "%s: Could not allocate TXB\n",
343 ieee->dev->name);
344 goto failed;
345 }
346 txb->encrypted = encrypt;
347 txb->payload_size = bytes;
348
349 for (i = 0; i < nr_frags; i++) {
350 skb_frag = txb->fragments[i];
351
James Ketrenosf1bf6632005-09-21 11:53:54 -0500352 if (host_encrypt)
Jeff Garzikb4538722005-05-12 22:48:20 -0400353 skb_reserve(skb_frag, crypt->ops->extra_prefix_len);
354
James Ketrenosee34af32005-09-21 11:54:36 -0500355 frag_hdr =
356 (struct ieee80211_hdr_3addr *)skb_put(skb_frag, hdr_len);
Jeff Garzikb4538722005-05-12 22:48:20 -0400357 memcpy(frag_hdr, &header, hdr_len);
358
359 /* If this is not the last fragment, then add the MOREFRAGS
360 * bit to the frame control */
361 if (i != nr_frags - 1) {
Jeff Garzik0edd5b42005-09-07 00:48:31 -0400362 frag_hdr->frame_ctl =
363 cpu_to_le16(fc | IEEE80211_FCTL_MOREFRAGS);
Jeff Garzikb4538722005-05-12 22:48:20 -0400364 bytes = bytes_per_frag;
365 } else {
366 /* The last fragment takes the remaining length */
367 bytes = bytes_last_frag;
368 }
369
Jeff Garzik0edd5b42005-09-07 00:48:31 -0400370 /* Put a SNAP header on the first fragment */
Jeff Garzikb4538722005-05-12 22:48:20 -0400371 if (i == 0) {
Jeff Garzik0edd5b42005-09-07 00:48:31 -0400372 ieee80211_put_snap(skb_put
373 (skb_frag, SNAP_SIZE + sizeof(u16)),
374 ether_type);
Jeff Garzikb4538722005-05-12 22:48:20 -0400375 bytes -= SNAP_SIZE + sizeof(u16);
376 }
377
378 memcpy(skb_put(skb_frag, bytes), skb->data, bytes);
379
380 /* Advance the SKB... */
381 skb_pull(skb, bytes);
382
383 /* Encryption routine will move the header forward in order
384 * to insert the IV between the header and the payload */
James Ketrenosf1bf6632005-09-21 11:53:54 -0500385 if (host_encrypt)
Jeff Garzikb4538722005-05-12 22:48:20 -0400386 ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len);
James Ketrenosf1bf6632005-09-21 11:53:54 -0500387
388 /* ipw2200/2915 Hardware encryption doesn't support TKIP MIC */
389 if (!ieee->host_encrypt && encrypt &&
390 (ieee->sec.level == SEC_LEVEL_2) &&
391 crypt && crypt->ops && crypt->ops->encrypt_msdu) {
392 int res = 0;
393 res = crypt->ops->encrypt_msdu(skb_frag, hdr_len,
394 crypt->priv);
395 if (res < 0) {
396 IEEE80211_ERROR("TKIP MIC encryption failed\n");
397 goto failed;
398 }
399 }
400
Jeff Garzikb4538722005-05-12 22:48:20 -0400401 if (ieee->config &
402 (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
403 skb_put(skb_frag, 4);
404 }
405
Jeff Garzik0edd5b42005-09-07 00:48:31 -0400406 success:
Jeff Garzikb4538722005-05-12 22:48:20 -0400407 spin_unlock_irqrestore(&ieee->lock, flags);
408
409 dev_kfree_skb_any(skb);
410
411 if (txb) {
Jeff Garzik0edd5b42005-09-07 00:48:31 -0400412 if ((*ieee->hard_start_xmit) (txb, dev) == 0) {
Jeff Garzikb4538722005-05-12 22:48:20 -0400413 stats->tx_packets++;
414 stats->tx_bytes += txb->payload_size;
415 return 0;
416 }
417 ieee80211_txb_free(txb);
418 }
419
420 return 0;
421
Jeff Garzik0edd5b42005-09-07 00:48:31 -0400422 failed:
Jeff Garzikb4538722005-05-12 22:48:20 -0400423 spin_unlock_irqrestore(&ieee->lock, flags);
424 netif_stop_queue(dev);
425 stats->tx_errors++;
426 return 1;
427
428}
429
430EXPORT_SYMBOL(ieee80211_txb_free);