blob: f505aa127e21cc9e1378e18329a9addfad836c43 [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
James Ketrenos3cdd00c2005-09-21 11:54:43 -0500225/* Incoming skb is converted to a txb which consist of
226 * a block of 802.11 fragment packets (stored as skbs) */
Jeff Garzik0edd5b42005-09-07 00:48:31 -0400227int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
Jeff Garzikb4538722005-05-12 22:48:20 -0400228{
229 struct ieee80211_device *ieee = netdev_priv(dev);
230 struct ieee80211_txb *txb = NULL;
James Ketrenosee34af32005-09-21 11:54:36 -0500231 struct ieee80211_hdr_3addr *frag_hdr;
James Ketrenos3cdd00c2005-09-21 11:54:43 -0500232 int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size,
233 rts_required;
Jeff Garzikb4538722005-05-12 22:48:20 -0400234 unsigned long flags;
235 struct net_device_stats *stats = &ieee->stats;
James Ketrenosf1bf6632005-09-21 11:53:54 -0500236 int ether_type, encrypt, host_encrypt;
Jeff Garzikb4538722005-05-12 22:48:20 -0400237 int bytes, fc, hdr_len;
238 struct sk_buff *skb_frag;
James Ketrenosee34af32005-09-21 11:54:36 -0500239 struct ieee80211_hdr_3addr header = { /* Ensure zero initialized */
Jeff Garzikb4538722005-05-12 22:48:20 -0400240 .duration_id = 0,
241 .seq_ctl = 0
242 };
243 u8 dest[ETH_ALEN], src[ETH_ALEN];
244
Jeff Garzik0edd5b42005-09-07 00:48:31 -0400245 struct ieee80211_crypt_data *crypt;
Jeff Garzikb4538722005-05-12 22:48:20 -0400246
247 spin_lock_irqsave(&ieee->lock, flags);
248
249 /* If there is no driver handler to take the TXB, dont' bother
250 * creating it... */
251 if (!ieee->hard_start_xmit) {
Jeff Garzik0edd5b42005-09-07 00:48:31 -0400252 printk(KERN_WARNING "%s: No xmit handler.\n", ieee->dev->name);
Jeff Garzikb4538722005-05-12 22:48:20 -0400253 goto success;
254 }
255
256 if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) {
257 printk(KERN_WARNING "%s: skb too small (%d).\n",
258 ieee->dev->name, skb->len);
259 goto success;
260 }
261
262 ether_type = ntohs(((struct ethhdr *)skb->data)->h_proto);
263
264 crypt = ieee->crypt[ieee->tx_keyidx];
265
266 encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) &&
James Ketrenosf1bf6632005-09-21 11:53:54 -0500267 ieee->sec.encrypt;
268 host_encrypt = ieee->host_encrypt && encrypt;
Jeff Garzikb4538722005-05-12 22:48:20 -0400269
270 if (!encrypt && ieee->ieee802_1x &&
271 ieee->drop_unencrypted && ether_type != ETH_P_PAE) {
272 stats->tx_dropped++;
273 goto success;
274 }
275
Jeff Garzikb4538722005-05-12 22:48:20 -0400276 /* Save source and destination addresses */
James Ketrenos18294d82005-09-13 17:40:29 -0500277 memcpy(dest, skb->data, ETH_ALEN);
278 memcpy(src, skb->data + ETH_ALEN, ETH_ALEN);
Jeff Garzikb4538722005-05-12 22:48:20 -0400279
280 /* Advance the SKB to the start of the payload */
281 skb_pull(skb, sizeof(struct ethhdr));
282
283 /* Determine total amount of storage required for TXB packets */
284 bytes = skb->len + SNAP_SIZE + sizeof(u16);
285
James Ketrenosf1bf6632005-09-21 11:53:54 -0500286 if (host_encrypt)
Jeff Garzikb4538722005-05-12 22:48:20 -0400287 fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA |
Jeff Garzik0edd5b42005-09-07 00:48:31 -0400288 IEEE80211_FCTL_PROTECTED;
Jeff Garzikb4538722005-05-12 22:48:20 -0400289 else
290 fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA;
291
292 if (ieee->iw_mode == IW_MODE_INFRA) {
293 fc |= IEEE80211_FCTL_TODS;
294 /* To DS: Addr1 = BSSID, Addr2 = SA,
295 Addr3 = DA */
James Ketrenos18294d82005-09-13 17:40:29 -0500296 memcpy(header.addr1, ieee->bssid, ETH_ALEN);
297 memcpy(header.addr2, src, ETH_ALEN);
298 memcpy(header.addr3, dest, ETH_ALEN);
Jeff Garzikb4538722005-05-12 22:48:20 -0400299 } else if (ieee->iw_mode == IW_MODE_ADHOC) {
300 /* not From/To DS: Addr1 = DA, Addr2 = SA,
301 Addr3 = BSSID */
James Ketrenos18294d82005-09-13 17:40:29 -0500302 memcpy(header.addr1, dest, ETH_ALEN);
303 memcpy(header.addr2, src, ETH_ALEN);
304 memcpy(header.addr3, ieee->bssid, ETH_ALEN);
Jeff Garzikb4538722005-05-12 22:48:20 -0400305 }
306 header.frame_ctl = cpu_to_le16(fc);
307 hdr_len = IEEE80211_3ADDR_LEN;
308
309 /* Determine fragmentation size based on destination (multicast
310 * and broadcast are not fragmented) */
Jeff Garzik0edd5b42005-09-07 00:48:31 -0400311 if (is_multicast_ether_addr(dest) || is_broadcast_ether_addr(dest))
Jeff Garzikb4538722005-05-12 22:48:20 -0400312 frag_size = MAX_FRAG_THRESHOLD;
313 else
314 frag_size = ieee->fts;
315
316 /* Determine amount of payload per fragment. Regardless of if
317 * this stack is providing the full 802.11 header, one will
318 * eventually be affixed to this fragment -- so we must account for
319 * it when determining the amount of payload space. */
320 bytes_per_frag = frag_size - IEEE80211_3ADDR_LEN;
321 if (ieee->config &
322 (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
323 bytes_per_frag -= IEEE80211_FCS_LEN;
324
325 /* Each fragment may need to have room for encryptiong pre/postfix */
James Ketrenosf1bf6632005-09-21 11:53:54 -0500326 if (host_encrypt)
Jeff Garzikb4538722005-05-12 22:48:20 -0400327 bytes_per_frag -= crypt->ops->extra_prefix_len +
Jeff Garzik0edd5b42005-09-07 00:48:31 -0400328 crypt->ops->extra_postfix_len;
Jeff Garzikb4538722005-05-12 22:48:20 -0400329
330 /* Number of fragments is the total bytes_per_frag /
331 * payload_per_fragment */
332 nr_frags = bytes / bytes_per_frag;
333 bytes_last_frag = bytes % bytes_per_frag;
334 if (bytes_last_frag)
335 nr_frags++;
336 else
337 bytes_last_frag = bytes_per_frag;
338
James Ketrenos3cdd00c2005-09-21 11:54:43 -0500339 rts_required = (frag_size > ieee->rts
340 && ieee->config & CFG_IEEE80211_RTS);
341 if (rts_required)
342 nr_frags++;
343 else
344 bytes_last_frag = bytes_per_frag;
345
Jeff Garzikb4538722005-05-12 22:48:20 -0400346 /* When we allocate the TXB we allocate enough space for the reserve
347 * and full fragment bytes (bytes_per_frag doesn't include prefix,
348 * postfix, header, FCS, etc.) */
349 txb = ieee80211_alloc_txb(nr_frags, frag_size, GFP_ATOMIC);
350 if (unlikely(!txb)) {
351 printk(KERN_WARNING "%s: Could not allocate TXB\n",
352 ieee->dev->name);
353 goto failed;
354 }
355 txb->encrypted = encrypt;
356 txb->payload_size = bytes;
357
James Ketrenos3cdd00c2005-09-21 11:54:43 -0500358 if (rts_required) {
359 skb_frag = txb->fragments[0];
360 frag_hdr =
361 (struct ieee80211_hdr_3addr *)skb_put(skb_frag, hdr_len);
362
363 /*
364 * Set header frame_ctl to the RTS.
365 */
366 header.frame_ctl =
367 cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS);
368 memcpy(frag_hdr, &header, hdr_len);
369
370 /*
371 * Restore header frame_ctl to the original data setting.
372 */
373 header.frame_ctl = cpu_to_le16(fc);
374
375 if (ieee->config &
376 (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
377 skb_put(skb_frag, 4);
378
379 txb->rts_included = 1;
380 i = 1;
381 } else
382 i = 0;
383
384 for (; i < nr_frags; i++) {
Jeff Garzikb4538722005-05-12 22:48:20 -0400385 skb_frag = txb->fragments[i];
386
James Ketrenosf1bf6632005-09-21 11:53:54 -0500387 if (host_encrypt)
Jeff Garzikb4538722005-05-12 22:48:20 -0400388 skb_reserve(skb_frag, crypt->ops->extra_prefix_len);
389
James Ketrenosee34af32005-09-21 11:54:36 -0500390 frag_hdr =
391 (struct ieee80211_hdr_3addr *)skb_put(skb_frag, hdr_len);
Jeff Garzikb4538722005-05-12 22:48:20 -0400392 memcpy(frag_hdr, &header, hdr_len);
393
394 /* If this is not the last fragment, then add the MOREFRAGS
395 * bit to the frame control */
396 if (i != nr_frags - 1) {
Jeff Garzik0edd5b42005-09-07 00:48:31 -0400397 frag_hdr->frame_ctl =
398 cpu_to_le16(fc | IEEE80211_FCTL_MOREFRAGS);
Jeff Garzikb4538722005-05-12 22:48:20 -0400399 bytes = bytes_per_frag;
400 } else {
401 /* The last fragment takes the remaining length */
402 bytes = bytes_last_frag;
403 }
404
Jeff Garzik0edd5b42005-09-07 00:48:31 -0400405 /* Put a SNAP header on the first fragment */
Jeff Garzikb4538722005-05-12 22:48:20 -0400406 if (i == 0) {
Jeff Garzik0edd5b42005-09-07 00:48:31 -0400407 ieee80211_put_snap(skb_put
408 (skb_frag, SNAP_SIZE + sizeof(u16)),
409 ether_type);
Jeff Garzikb4538722005-05-12 22:48:20 -0400410 bytes -= SNAP_SIZE + sizeof(u16);
411 }
412
413 memcpy(skb_put(skb_frag, bytes), skb->data, bytes);
414
415 /* Advance the SKB... */
416 skb_pull(skb, bytes);
417
418 /* Encryption routine will move the header forward in order
419 * to insert the IV between the header and the payload */
James Ketrenosf1bf6632005-09-21 11:53:54 -0500420 if (host_encrypt)
Jeff Garzikb4538722005-05-12 22:48:20 -0400421 ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len);
James Ketrenosf1bf6632005-09-21 11:53:54 -0500422
423 /* ipw2200/2915 Hardware encryption doesn't support TKIP MIC */
424 if (!ieee->host_encrypt && encrypt &&
425 (ieee->sec.level == SEC_LEVEL_2) &&
426 crypt && crypt->ops && crypt->ops->encrypt_msdu) {
427 int res = 0;
428 res = crypt->ops->encrypt_msdu(skb_frag, hdr_len,
429 crypt->priv);
430 if (res < 0) {
431 IEEE80211_ERROR("TKIP MIC encryption failed\n");
432 goto failed;
433 }
434 }
435
Jeff Garzikb4538722005-05-12 22:48:20 -0400436 if (ieee->config &
437 (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
438 skb_put(skb_frag, 4);
439 }
440
Jeff Garzik0edd5b42005-09-07 00:48:31 -0400441 success:
Jeff Garzikb4538722005-05-12 22:48:20 -0400442 spin_unlock_irqrestore(&ieee->lock, flags);
443
444 dev_kfree_skb_any(skb);
445
446 if (txb) {
Jeff Garzik0edd5b42005-09-07 00:48:31 -0400447 if ((*ieee->hard_start_xmit) (txb, dev) == 0) {
Jeff Garzikb4538722005-05-12 22:48:20 -0400448 stats->tx_packets++;
449 stats->tx_bytes += txb->payload_size;
450 return 0;
451 }
452 ieee80211_txb_free(txb);
453 }
454
455 return 0;
456
Jeff Garzik0edd5b42005-09-07 00:48:31 -0400457 failed:
Jeff Garzikb4538722005-05-12 22:48:20 -0400458 spin_unlock_irqrestore(&ieee->lock, flags);
459 netif_stop_queue(dev);
460 stats->tx_errors++;
461 return 1;
Jeff Garzikb4538722005-05-12 22:48:20 -0400462}
463
James Ketrenos3f552bb2005-09-21 11:54:47 -0500464/* Incoming 802.11 strucure is converted to a TXB
465 * a block of 802.11 fragment packets (stored as skbs) */
466int ieee80211_tx_frame(struct ieee80211_device *ieee,
467 struct ieee80211_hdr *frame, int len)
468{
469 struct ieee80211_txb *txb = NULL;
470 unsigned long flags;
471 struct net_device_stats *stats = &ieee->stats;
472 struct sk_buff *skb_frag;
473
474 spin_lock_irqsave(&ieee->lock, flags);
475
476 /* If there is no driver handler to take the TXB, dont' bother
477 * creating it... */
478 if (!ieee->hard_start_xmit) {
479 printk(KERN_WARNING "%s: No xmit handler.\n", ieee->dev->name);
480 goto success;
481 }
482
483 if (unlikely(len < 24)) {
484 printk(KERN_WARNING "%s: skb too small (%d).\n",
485 ieee->dev->name, len);
486 goto success;
487 }
488
489 /* When we allocate the TXB we allocate enough space for the reserve
490 * and full fragment bytes (bytes_per_frag doesn't include prefix,
491 * postfix, header, FCS, etc.) */
492 txb = ieee80211_alloc_txb(1, len, GFP_ATOMIC);
493 if (unlikely(!txb)) {
494 printk(KERN_WARNING "%s: Could not allocate TXB\n",
495 ieee->dev->name);
496 goto failed;
497 }
498 txb->encrypted = 0;
499 txb->payload_size = len;
500
501 skb_frag = txb->fragments[0];
502
503 memcpy(skb_put(skb_frag, len), frame, len);
504
505 if (ieee->config &
506 (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
507 skb_put(skb_frag, 4);
508
509 success:
510 spin_unlock_irqrestore(&ieee->lock, flags);
511
512 if (txb) {
513 if ((*ieee->hard_start_xmit) (txb, ieee->dev) == 0) {
514 stats->tx_packets++;
515 stats->tx_bytes += txb->payload_size;
516 return 0;
517 }
518 ieee80211_txb_free(txb);
519 }
520 return 0;
521
522 failed:
523 spin_unlock_irqrestore(&ieee->lock, flags);
524 stats->tx_errors++;
525 return 1;
526}
527
528EXPORT_SYMBOL(ieee80211_tx_frame);
Jeff Garzikb4538722005-05-12 22:48:20 -0400529EXPORT_SYMBOL(ieee80211_txb_free);