aboutsummaryrefslogtreecommitdiffstats
path: root/net/ieee80211/ieee80211_tx.c
diff options
context:
space:
mode:
authorJeff Garzik <jgarzik@pobox.com>2005-05-12 22:48:20 -0400
committerJeff Garzik <jgarzik@pobox.com>2005-05-12 22:48:20 -0400
commitb453872c35cfcbdbf5a794737817f7d4e7b1b579 (patch)
tree6639da0b12e3f071b57f388c97d28e451f8f3cd3 /net/ieee80211/ieee80211_tx.c
parentfff9cfd99c0f88645c3f50d7476d6c8cef99f140 (diff)
[NET] ieee80211 subsystem
Contributors: Host AP contributors James Ketrenos <jketreno@linux.intel.com> Francois Romieu <romieu@fr.zoreil.com> Adrian Bunk <bunk@stusta.de> Matthew Galgoci <mgalgoci@parcelfarce.linux.th eplanet.co.uk>
Diffstat (limited to 'net/ieee80211/ieee80211_tx.c')
-rw-r--r--net/ieee80211/ieee80211_tx.c448
1 files changed, 448 insertions, 0 deletions
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c
new file mode 100644
index 000000000000..d70e6b82715e
--- /dev/null
+++ b/net/ieee80211/ieee80211_tx.c
@@ -0,0 +1,448 @@
1/******************************************************************************
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>
36#include <linux/pci.h>
37#include <linux/proc_fs.h>
38#include <linux/skbuff.h>
39#include <linux/slab.h>
40#include <linux/tcp.h>
41#include <linux/types.h>
42#include <linux/version.h>
43#include <linux/wireless.h>
44#include <linux/etherdevice.h>
45#include <asm/uaccess.h>
46
47#include <net/ieee80211.h>
48
49
50/*
51
52
53802.11 Data Frame
54
55 ,-------------------------------------------------------------------.
56Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 |
57 |------|------|---------|---------|---------|------|---------|------|
58Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | Frame | fcs |
59 | | tion | (BSSID) | | | ence | data | |
60 `--------------------------------------------------| |------'
61Total: 28 non-data bytes `----.----'
62 |
63 .- 'Frame data' expands to <---------------------------'
64 |
65 V
66 ,---------------------------------------------------.
67Bytes | 1 | 1 | 1 | 3 | 2 | 0-2304 |
68 |------|------|---------|----------|------|---------|
69Desc. | SNAP | SNAP | Control |Eth Tunnel| Type | IP |
70 | DSAP | SSAP | | | | Packet |
71 | 0xAA | 0xAA |0x03 (UI)|0x00-00-F8| | |
72 `-----------------------------------------| |
73Total: 8 non-data bytes `----.----'
74 |
75 .- 'IP Packet' expands, if WEP enabled, to <--'
76 |
77 V
78 ,-----------------------.
79Bytes | 4 | 0-2296 | 4 |
80 |-----|-----------|-----|
81Desc. | IV | Encrypted | ICV |
82 | | IP Packet | |
83 `-----------------------'
84Total: 8 non-data bytes
85
86
87802.3 Ethernet Data Frame
88
89 ,-----------------------------------------.
90Bytes | 6 | 6 | 2 | Variable | 4 |
91 |-------|-------|------|-----------|------|
92Desc. | Dest. | Source| Type | IP Packet | fcs |
93 | MAC | MAC | | | |
94 `-----------------------------------------'
95Total: 18 non-data bytes
96
97In the event that fragmentation is required, the incoming payload is split into
98N parts of size ieee->fts. The first fragment contains the SNAP header and the
99remaining packets are just data.
100
101If encryption is enabled, each fragment payload size is reduced by enough space
102to add the prefix and postfix (IV and ICV totalling 8 bytes in the case of WEP)
103So if you have 1500 bytes of payload with ieee->fts set to 500 without
104encryption it will take 3 frames. With WEP it will take 4 frames as the
105payload of each frame is reduced to 492 bytes.
106
107* SKB visualization
108*
109* ,- skb->data
110* |
111* | ETHERNET HEADER ,-<-- PAYLOAD
112* | | 14 bytes from skb->data
113* | 2 bytes for Type --> ,T. | (sizeof ethhdr)
114* | | | |
115* |,-Dest.--. ,--Src.---. | | |
116* | 6 bytes| | 6 bytes | | | |
117* v | | | | | |
118* 0 | v 1 | v | v 2
119* 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
120* ^ | ^ | ^ |
121* | | | | | |
122* | | | | `T' <---- 2 bytes for Type
123* | | | |
124* | | '---SNAP--' <-------- 6 bytes for SNAP
125* | |
126* `-IV--' <-------------------- 4 bytes for IV (WEP)
127*
128* SNAP HEADER
129*
130*/
131
132static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 };
133static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 };
134
135static inline int ieee80211_put_snap(u8 *data, u16 h_proto)
136{
137 struct ieee80211_snap_hdr *snap;
138 u8 *oui;
139
140 snap = (struct ieee80211_snap_hdr *)data;
141 snap->dsap = 0xaa;
142 snap->ssap = 0xaa;
143 snap->ctrl = 0x03;
144
145 if (h_proto == 0x8137 || h_proto == 0x80f3)
146 oui = P802_1H_OUI;
147 else
148 oui = RFC1042_OUI;
149 snap->oui[0] = oui[0];
150 snap->oui[1] = oui[1];
151 snap->oui[2] = oui[2];
152
153 *(u16 *)(data + SNAP_SIZE) = htons(h_proto);
154
155 return SNAP_SIZE + sizeof(u16);
156}
157
158static inline int ieee80211_encrypt_fragment(
159 struct ieee80211_device *ieee,
160 struct sk_buff *frag,
161 int hdr_len)
162{
163 struct ieee80211_crypt_data* crypt = ieee->crypt[ieee->tx_keyidx];
164 int res;
165
166#ifdef CONFIG_IEEE80211_CRYPT_TKIP
167 struct ieee80211_hdr *header;
168
169 if (ieee->tkip_countermeasures &&
170 crypt && crypt->ops && strcmp(crypt->ops->name, "TKIP") == 0) {
171 header = (struct ieee80211_hdr *) frag->data;
172 if (net_ratelimit()) {
173 printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
174 "TX packet to " MAC_FMT "\n",
175 ieee->dev->name, MAC_ARG(header->addr1));
176 }
177 return -1;
178 }
179#endif
180 /* To encrypt, frame format is:
181 * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) */
182
183 // PR: FIXME: Copied from hostap. Check fragmentation/MSDU/MPDU encryption.
184 /* Host-based IEEE 802.11 fragmentation for TX is not yet supported, so
185 * call both MSDU and MPDU encryption functions from here. */
186 atomic_inc(&crypt->refcnt);
187 res = 0;
188 if (crypt->ops->encrypt_msdu)
189 res = crypt->ops->encrypt_msdu(frag, hdr_len, crypt->priv);
190 if (res == 0 && crypt->ops->encrypt_mpdu)
191 res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv);
192
193 atomic_dec(&crypt->refcnt);
194 if (res < 0) {
195 printk(KERN_INFO "%s: Encryption failed: len=%d.\n",
196 ieee->dev->name, frag->len);
197 ieee->ieee_stats.tx_discards++;
198 return -1;
199 }
200
201 return 0;
202}
203
204
205void ieee80211_txb_free(struct ieee80211_txb *txb) {
206 int i;
207 if (unlikely(!txb))
208 return;
209 for (i = 0; i < txb->nr_frags; i++)
210 if (txb->fragments[i])
211 dev_kfree_skb_any(txb->fragments[i]);
212 kfree(txb);
213}
214
215struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size,
216 int gfp_mask)
217{
218 struct ieee80211_txb *txb;
219 int i;
220 txb = kmalloc(
221 sizeof(struct ieee80211_txb) + (sizeof(u8*) * nr_frags),
222 gfp_mask);
223 if (!txb)
224 return NULL;
225
226 memset(txb, sizeof(struct ieee80211_txb), 0);
227 txb->nr_frags = nr_frags;
228 txb->frag_size = txb_size;
229
230 for (i = 0; i < nr_frags; i++) {
231 txb->fragments[i] = dev_alloc_skb(txb_size);
232 if (unlikely(!txb->fragments[i])) {
233 i--;
234 break;
235 }
236 }
237 if (unlikely(i != nr_frags)) {
238 while (i >= 0)
239 dev_kfree_skb_any(txb->fragments[i--]);
240 kfree(txb);
241 return NULL;
242 }
243 return txb;
244}
245
246/* SKBs are added to the ieee->tx_queue. */
247int ieee80211_xmit(struct sk_buff *skb,
248 struct net_device *dev)
249{
250 struct ieee80211_device *ieee = netdev_priv(dev);
251 struct ieee80211_txb *txb = NULL;
252 struct ieee80211_hdr *frag_hdr;
253 int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size;
254 unsigned long flags;
255 struct net_device_stats *stats = &ieee->stats;
256 int ether_type, encrypt;
257 int bytes, fc, hdr_len;
258 struct sk_buff *skb_frag;
259 struct ieee80211_hdr header = { /* Ensure zero initialized */
260 .duration_id = 0,
261 .seq_ctl = 0
262 };
263 u8 dest[ETH_ALEN], src[ETH_ALEN];
264
265 struct ieee80211_crypt_data* crypt;
266
267 spin_lock_irqsave(&ieee->lock, flags);
268
269 /* If there is no driver handler to take the TXB, dont' bother
270 * creating it... */
271 if (!ieee->hard_start_xmit) {
272 printk(KERN_WARNING "%s: No xmit handler.\n",
273 ieee->dev->name);
274 goto success;
275 }
276
277 if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) {
278 printk(KERN_WARNING "%s: skb too small (%d).\n",
279 ieee->dev->name, skb->len);
280 goto success;
281 }
282
283 ether_type = ntohs(((struct ethhdr *)skb->data)->h_proto);
284
285 crypt = ieee->crypt[ieee->tx_keyidx];
286
287 encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) &&
288 ieee->host_encrypt && crypt && crypt->ops;
289
290 if (!encrypt && ieee->ieee802_1x &&
291 ieee->drop_unencrypted && ether_type != ETH_P_PAE) {
292 stats->tx_dropped++;
293 goto success;
294 }
295
296#ifdef CONFIG_IEEE80211_DEBUG
297 if (crypt && !encrypt && ether_type == ETH_P_PAE) {
298 struct eapol *eap = (struct eapol *)(skb->data +
299 sizeof(struct ethhdr) - SNAP_SIZE - sizeof(u16));
300 IEEE80211_DEBUG_EAP("TX: IEEE 802.11 EAPOL frame: %s\n",
301 eap_get_type(eap->type));
302 }
303#endif
304
305 /* Save source and destination addresses */
306 memcpy(&dest, skb->data, ETH_ALEN);
307 memcpy(&src, skb->data+ETH_ALEN, ETH_ALEN);
308
309 /* Advance the SKB to the start of the payload */
310 skb_pull(skb, sizeof(struct ethhdr));
311
312 /* Determine total amount of storage required for TXB packets */
313 bytes = skb->len + SNAP_SIZE + sizeof(u16);
314
315 if (encrypt)
316 fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA |
317 IEEE80211_FCTL_WEP;
318 else
319 fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA;
320
321 if (ieee->iw_mode == IW_MODE_INFRA) {
322 fc |= IEEE80211_FCTL_TODS;
323 /* To DS: Addr1 = BSSID, Addr2 = SA,
324 Addr3 = DA */
325 memcpy(&header.addr1, ieee->bssid, ETH_ALEN);
326 memcpy(&header.addr2, &src, ETH_ALEN);
327 memcpy(&header.addr3, &dest, ETH_ALEN);
328 } else if (ieee->iw_mode == IW_MODE_ADHOC) {
329 /* not From/To DS: Addr1 = DA, Addr2 = SA,
330 Addr3 = BSSID */
331 memcpy(&header.addr1, dest, ETH_ALEN);
332 memcpy(&header.addr2, src, ETH_ALEN);
333 memcpy(&header.addr3, ieee->bssid, ETH_ALEN);
334 }
335 header.frame_ctl = cpu_to_le16(fc);
336 hdr_len = IEEE80211_3ADDR_LEN;
337
338 /* Determine fragmentation size based on destination (multicast
339 * and broadcast are not fragmented) */
340 if (is_multicast_ether_addr(dest) ||
341 is_broadcast_ether_addr(dest))
342 frag_size = MAX_FRAG_THRESHOLD;
343 else
344 frag_size = ieee->fts;
345
346 /* Determine amount of payload per fragment. Regardless of if
347 * this stack is providing the full 802.11 header, one will
348 * eventually be affixed to this fragment -- so we must account for
349 * it when determining the amount of payload space. */
350 bytes_per_frag = frag_size - IEEE80211_3ADDR_LEN;
351 if (ieee->config &
352 (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
353 bytes_per_frag -= IEEE80211_FCS_LEN;
354
355 /* Each fragment may need to have room for encryptiong pre/postfix */
356 if (encrypt)
357 bytes_per_frag -= crypt->ops->extra_prefix_len +
358 crypt->ops->extra_postfix_len;
359
360 /* Number of fragments is the total bytes_per_frag /
361 * payload_per_fragment */
362 nr_frags = bytes / bytes_per_frag;
363 bytes_last_frag = bytes % bytes_per_frag;
364 if (bytes_last_frag)
365 nr_frags++;
366 else
367 bytes_last_frag = bytes_per_frag;
368
369 /* When we allocate the TXB we allocate enough space for the reserve
370 * and full fragment bytes (bytes_per_frag doesn't include prefix,
371 * postfix, header, FCS, etc.) */
372 txb = ieee80211_alloc_txb(nr_frags, frag_size, GFP_ATOMIC);
373 if (unlikely(!txb)) {
374 printk(KERN_WARNING "%s: Could not allocate TXB\n",
375 ieee->dev->name);
376 goto failed;
377 }
378 txb->encrypted = encrypt;
379 txb->payload_size = bytes;
380
381 for (i = 0; i < nr_frags; i++) {
382 skb_frag = txb->fragments[i];
383
384 if (encrypt)
385 skb_reserve(skb_frag, crypt->ops->extra_prefix_len);
386
387 frag_hdr = (struct ieee80211_hdr *)skb_put(skb_frag, hdr_len);
388 memcpy(frag_hdr, &header, hdr_len);
389
390 /* If this is not the last fragment, then add the MOREFRAGS
391 * bit to the frame control */
392 if (i != nr_frags - 1) {
393 frag_hdr->frame_ctl = cpu_to_le16(
394 fc | IEEE80211_FCTL_MOREFRAGS);
395 bytes = bytes_per_frag;
396 } else {
397 /* The last fragment takes the remaining length */
398 bytes = bytes_last_frag;
399 }
400
401 /* Put a SNAP header on the first fragment */
402 if (i == 0) {
403 ieee80211_put_snap(
404 skb_put(skb_frag, SNAP_SIZE + sizeof(u16)),
405 ether_type);
406 bytes -= SNAP_SIZE + sizeof(u16);
407 }
408
409 memcpy(skb_put(skb_frag, bytes), skb->data, bytes);
410
411 /* Advance the SKB... */
412 skb_pull(skb, bytes);
413
414 /* Encryption routine will move the header forward in order
415 * to insert the IV between the header and the payload */
416 if (encrypt)
417 ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len);
418 if (ieee->config &
419 (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
420 skb_put(skb_frag, 4);
421 }
422
423
424 success:
425 spin_unlock_irqrestore(&ieee->lock, flags);
426
427 dev_kfree_skb_any(skb);
428
429 if (txb) {
430 if ((*ieee->hard_start_xmit)(txb, dev) == 0) {
431 stats->tx_packets++;
432 stats->tx_bytes += txb->payload_size;
433 return 0;
434 }
435 ieee80211_txb_free(txb);
436 }
437
438 return 0;
439
440 failed:
441 spin_unlock_irqrestore(&ieee->lock, flags);
442 netif_stop_queue(dev);
443 stats->tx_errors++;
444 return 1;
445
446}
447
448EXPORT_SYMBOL(ieee80211_txb_free);