blob: 8d87897d7eb7ef218d483a90bb64606cdc557e91 [file] [log] [blame]
Jeff Garzikb4538722005-05-12 22:48:20 -04001/******************************************************************************
2
James Ketrenosebeaddc2005-09-21 11:58:43 -05003 Copyright(c) 2003 - 2005 Intel Corporation. All rights reserved.
Jeff Garzikb4538722005-05-12 22:48:20 -04004
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
James Ketrenos1264fc02005-09-21 11:54:53 -0500131static inline int ieee80211_copy_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) */
Jeff Garzikb4538722005-05-12 22:48:20 -0400162 atomic_inc(&crypt->refcnt);
163 res = 0;
James Ketrenos1264fc02005-09-21 11:54:53 -0500164 if (crypt->ops->encrypt_mpdu)
Jeff Garzikb4538722005-05-12 22:48:20 -0400165 res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv);
166
167 atomic_dec(&crypt->refcnt);
168 if (res < 0) {
169 printk(KERN_INFO "%s: Encryption failed: len=%d.\n",
170 ieee->dev->name, frag->len);
171 ieee->ieee_stats.tx_discards++;
172 return -1;
173 }
174
175 return 0;
176}
177
Jeff Garzik0edd5b42005-09-07 00:48:31 -0400178void ieee80211_txb_free(struct ieee80211_txb *txb)
179{
Jeff Garzikb4538722005-05-12 22:48:20 -0400180 int i;
181 if (unlikely(!txb))
182 return;
183 for (i = 0; i < txb->nr_frags; i++)
184 if (txb->fragments[i])
185 dev_kfree_skb_any(txb->fragments[i]);
186 kfree(txb);
187}
188
Adrian Bunke1572492005-05-06 23:32:39 +0200189static struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size,
190 int gfp_mask)
Jeff Garzikb4538722005-05-12 22:48:20 -0400191{
192 struct ieee80211_txb *txb;
193 int i;
Jeff Garzik0edd5b42005-09-07 00:48:31 -0400194 txb = kmalloc(sizeof(struct ieee80211_txb) + (sizeof(u8 *) * nr_frags),
195 gfp_mask);
Jeff Garzikb4538722005-05-12 22:48:20 -0400196 if (!txb)
197 return NULL;
198
Adrian Bunk0a989b22005-04-11 16:52:15 -0700199 memset(txb, 0, sizeof(struct ieee80211_txb));
Jeff Garzikb4538722005-05-12 22:48:20 -0400200 txb->nr_frags = nr_frags;
201 txb->frag_size = txb_size;
202
203 for (i = 0; i < nr_frags; i++) {
204 txb->fragments[i] = dev_alloc_skb(txb_size);
205 if (unlikely(!txb->fragments[i])) {
206 i--;
207 break;
208 }
209 }
210 if (unlikely(i != nr_frags)) {
211 while (i >= 0)
212 dev_kfree_skb_any(txb->fragments[i--]);
213 kfree(txb);
214 return NULL;
215 }
216 return txb;
217}
218
James Ketrenos1264fc02005-09-21 11:54:53 -0500219/* Incoming skb is converted to a txb which consists of
James Ketrenos3cdd00c2005-09-21 11:54:43 -0500220 * a block of 802.11 fragment packets (stored as skbs) */
Jeff Garzik0edd5b42005-09-07 00:48:31 -0400221int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
Jeff Garzikb4538722005-05-12 22:48:20 -0400222{
223 struct ieee80211_device *ieee = netdev_priv(dev);
224 struct ieee80211_txb *txb = NULL;
James Ketrenosee34af32005-09-21 11:54:36 -0500225 struct ieee80211_hdr_3addr *frag_hdr;
James Ketrenos3cdd00c2005-09-21 11:54:43 -0500226 int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size,
227 rts_required;
Jeff Garzikb4538722005-05-12 22:48:20 -0400228 unsigned long flags;
229 struct net_device_stats *stats = &ieee->stats;
James Ketrenos31b59ea2005-09-21 11:58:49 -0500230 int ether_type, encrypt, host_encrypt, host_encrypt_msdu, host_build_iv;
Jeff Garzikb4538722005-05-12 22:48:20 -0400231 int bytes, fc, hdr_len;
232 struct sk_buff *skb_frag;
James Ketrenosee34af32005-09-21 11:54:36 -0500233 struct ieee80211_hdr_3addr header = { /* Ensure zero initialized */
Jeff Garzikb4538722005-05-12 22:48:20 -0400234 .duration_id = 0,
235 .seq_ctl = 0
236 };
237 u8 dest[ETH_ALEN], src[ETH_ALEN];
Jeff Garzik0edd5b42005-09-07 00:48:31 -0400238 struct ieee80211_crypt_data *crypt;
James Ketrenos2c0aa2a2005-09-21 11:56:27 -0500239 int priority = skb->priority;
James Ketrenos1264fc02005-09-21 11:54:53 -0500240 int snapped = 0;
Jeff Garzikb4538722005-05-12 22:48:20 -0400241
James Ketrenos2c0aa2a2005-09-21 11:56:27 -0500242 if (ieee->is_queue_full && (*ieee->is_queue_full) (dev, priority))
243 return NETDEV_TX_BUSY;
244
Jeff Garzikb4538722005-05-12 22:48:20 -0400245 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;
James Ketrenos31b59ea2005-09-21 11:58:49 -0500266
James Ketrenosf1bf6632005-09-21 11:53:54 -0500267 host_encrypt = ieee->host_encrypt && encrypt;
James Ketrenos1264fc02005-09-21 11:54:53 -0500268 host_encrypt_msdu = ieee->host_encrypt_msdu && encrypt;
James Ketrenos31b59ea2005-09-21 11:58:49 -0500269 host_build_iv = ieee->host_build_iv && encrypt;
Jeff Garzikb4538722005-05-12 22:48:20 -0400270
271 if (!encrypt && ieee->ieee802_1x &&
272 ieee->drop_unencrypted && ether_type != ETH_P_PAE) {
273 stats->tx_dropped++;
274 goto success;
275 }
276
Jeff Garzikb4538722005-05-12 22:48:20 -0400277 /* Save source and destination addresses */
James Ketrenos18294d82005-09-13 17:40:29 -0500278 memcpy(dest, skb->data, ETH_ALEN);
279 memcpy(src, skb->data + ETH_ALEN, ETH_ALEN);
Jeff Garzikb4538722005-05-12 22:48:20 -0400280
281 /* Advance the SKB to the start of the payload */
282 skb_pull(skb, sizeof(struct ethhdr));
283
284 /* Determine total amount of storage required for TXB packets */
285 bytes = skb->len + SNAP_SIZE + sizeof(u16);
286
James Ketrenosf1bf6632005-09-21 11:53:54 -0500287 if (host_encrypt)
Jeff Garzikb4538722005-05-12 22:48:20 -0400288 fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA |
Jeff Garzik0edd5b42005-09-07 00:48:31 -0400289 IEEE80211_FCTL_PROTECTED;
Jeff Garzikb4538722005-05-12 22:48:20 -0400290 else
291 fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA;
292
293 if (ieee->iw_mode == IW_MODE_INFRA) {
294 fc |= IEEE80211_FCTL_TODS;
James Ketrenos1264fc02005-09-21 11:54:53 -0500295 /* To DS: Addr1 = BSSID, Addr2 = SA, 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) {
James Ketrenos1264fc02005-09-21 11:54:53 -0500300 /* not From/To DS: Addr1 = DA, Addr2 = SA, Addr3 = BSSID */
James Ketrenos18294d82005-09-13 17:40:29 -0500301 memcpy(header.addr1, dest, ETH_ALEN);
302 memcpy(header.addr2, src, ETH_ALEN);
303 memcpy(header.addr3, ieee->bssid, ETH_ALEN);
Jeff Garzikb4538722005-05-12 22:48:20 -0400304 }
305 header.frame_ctl = cpu_to_le16(fc);
306 hdr_len = IEEE80211_3ADDR_LEN;
307
James Ketrenos1264fc02005-09-21 11:54:53 -0500308 /* Encrypt msdu first on the whole data packet. */
309 if ((host_encrypt || host_encrypt_msdu) &&
310 crypt && crypt->ops && crypt->ops->encrypt_msdu) {
311 int res = 0;
312 int len = bytes + hdr_len + crypt->ops->extra_msdu_prefix_len +
313 crypt->ops->extra_msdu_postfix_len;
314 struct sk_buff *skb_new = dev_alloc_skb(len);
James Ketrenos31b59ea2005-09-21 11:58:49 -0500315
James Ketrenos1264fc02005-09-21 11:54:53 -0500316 if (unlikely(!skb_new))
317 goto failed;
James Ketrenos31b59ea2005-09-21 11:58:49 -0500318
James Ketrenos1264fc02005-09-21 11:54:53 -0500319 skb_reserve(skb_new, crypt->ops->extra_msdu_prefix_len);
320 memcpy(skb_put(skb_new, hdr_len), &header, hdr_len);
321 snapped = 1;
322 ieee80211_copy_snap(skb_put(skb_new, SNAP_SIZE + sizeof(u16)),
323 ether_type);
324 memcpy(skb_put(skb_new, skb->len), skb->data, skb->len);
325 res = crypt->ops->encrypt_msdu(skb_new, hdr_len, crypt->priv);
326 if (res < 0) {
327 IEEE80211_ERROR("msdu encryption failed\n");
328 dev_kfree_skb_any(skb_new);
329 goto failed;
330 }
331 dev_kfree_skb_any(skb);
332 skb = skb_new;
333 bytes += crypt->ops->extra_msdu_prefix_len +
334 crypt->ops->extra_msdu_postfix_len;
335 skb_pull(skb, hdr_len);
336 }
Jeff Garzikb4538722005-05-12 22:48:20 -0400337
James Ketrenos1264fc02005-09-21 11:54:53 -0500338 if (host_encrypt || ieee->host_open_frag) {
339 /* Determine fragmentation size based on destination (multicast
340 * and broadcast are not fragmented) */
341 if (is_multicast_ether_addr(dest))
342 frag_size = MAX_FRAG_THRESHOLD;
343 else
344 frag_size = ieee->fts;
Jeff Garzikb4538722005-05-12 22:48:20 -0400345
James Ketrenos1264fc02005-09-21 11:54:53 -0500346 /* 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
349 * for 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;
Jeff Garzikb4538722005-05-12 22:48:20 -0400354
James Ketrenos1264fc02005-09-21 11:54:53 -0500355 /* Each fragment may need to have room for encryptiong
356 * pre/postfix */
357 if (host_encrypt)
358 bytes_per_frag -= crypt->ops->extra_mpdu_prefix_len +
359 crypt->ops->extra_mpdu_postfix_len;
360
361 /* Number of fragments is the total
362 * bytes_per_frag / payload_per_fragment */
363 nr_frags = bytes / bytes_per_frag;
364 bytes_last_frag = bytes % bytes_per_frag;
365 if (bytes_last_frag)
366 nr_frags++;
367 else
368 bytes_last_frag = bytes_per_frag;
369 } else {
370 nr_frags = 1;
371 bytes_per_frag = bytes_last_frag = bytes;
372 frag_size = bytes + IEEE80211_3ADDR_LEN;
373 }
Jeff Garzikb4538722005-05-12 22:48:20 -0400374
James Ketrenos3cdd00c2005-09-21 11:54:43 -0500375 rts_required = (frag_size > ieee->rts
376 && ieee->config & CFG_IEEE80211_RTS);
377 if (rts_required)
378 nr_frags++;
James Ketrenos3cdd00c2005-09-21 11:54:43 -0500379
Jeff Garzikb4538722005-05-12 22:48:20 -0400380 /* When we allocate the TXB we allocate enough space for the reserve
381 * and full fragment bytes (bytes_per_frag doesn't include prefix,
382 * postfix, header, FCS, etc.) */
383 txb = ieee80211_alloc_txb(nr_frags, frag_size, GFP_ATOMIC);
384 if (unlikely(!txb)) {
385 printk(KERN_WARNING "%s: Could not allocate TXB\n",
386 ieee->dev->name);
387 goto failed;
388 }
389 txb->encrypted = encrypt;
James Ketrenos1264fc02005-09-21 11:54:53 -0500390 if (host_encrypt)
391 txb->payload_size = frag_size * (nr_frags - 1) +
392 bytes_last_frag;
393 else
394 txb->payload_size = bytes;
Jeff Garzikb4538722005-05-12 22:48:20 -0400395
James Ketrenos3cdd00c2005-09-21 11:54:43 -0500396 if (rts_required) {
397 skb_frag = txb->fragments[0];
398 frag_hdr =
399 (struct ieee80211_hdr_3addr *)skb_put(skb_frag, hdr_len);
400
401 /*
402 * Set header frame_ctl to the RTS.
403 */
404 header.frame_ctl =
405 cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS);
406 memcpy(frag_hdr, &header, hdr_len);
407
408 /*
409 * Restore header frame_ctl to the original data setting.
410 */
411 header.frame_ctl = cpu_to_le16(fc);
412
413 if (ieee->config &
414 (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
415 skb_put(skb_frag, 4);
416
417 txb->rts_included = 1;
418 i = 1;
419 } else
420 i = 0;
421
422 for (; i < nr_frags; i++) {
Jeff Garzikb4538722005-05-12 22:48:20 -0400423 skb_frag = txb->fragments[i];
424
James Ketrenos31b59ea2005-09-21 11:58:49 -0500425 if (host_encrypt || host_build_iv)
James Ketrenos1264fc02005-09-21 11:54:53 -0500426 skb_reserve(skb_frag,
427 crypt->ops->extra_mpdu_prefix_len);
Jeff Garzikb4538722005-05-12 22:48:20 -0400428
James Ketrenosee34af32005-09-21 11:54:36 -0500429 frag_hdr =
430 (struct ieee80211_hdr_3addr *)skb_put(skb_frag, hdr_len);
Jeff Garzikb4538722005-05-12 22:48:20 -0400431 memcpy(frag_hdr, &header, hdr_len);
432
433 /* If this is not the last fragment, then add the MOREFRAGS
434 * bit to the frame control */
435 if (i != nr_frags - 1) {
Jeff Garzik0edd5b42005-09-07 00:48:31 -0400436 frag_hdr->frame_ctl =
437 cpu_to_le16(fc | IEEE80211_FCTL_MOREFRAGS);
Jeff Garzikb4538722005-05-12 22:48:20 -0400438 bytes = bytes_per_frag;
439 } else {
440 /* The last fragment takes the remaining length */
441 bytes = bytes_last_frag;
442 }
443
James Ketrenos1264fc02005-09-21 11:54:53 -0500444 if (i == 0 && !snapped) {
445 ieee80211_copy_snap(skb_put
446 (skb_frag, SNAP_SIZE + sizeof(u16)),
447 ether_type);
Jeff Garzikb4538722005-05-12 22:48:20 -0400448 bytes -= SNAP_SIZE + sizeof(u16);
449 }
450
451 memcpy(skb_put(skb_frag, bytes), skb->data, bytes);
452
453 /* Advance the SKB... */
454 skb_pull(skb, bytes);
455
456 /* Encryption routine will move the header forward in order
457 * to insert the IV between the header and the payload */
James Ketrenosf1bf6632005-09-21 11:53:54 -0500458 if (host_encrypt)
Jeff Garzikb4538722005-05-12 22:48:20 -0400459 ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len);
James Ketrenos31b59ea2005-09-21 11:58:49 -0500460 else if (host_build_iv) {
461 struct ieee80211_crypt_data *crypt;
462
463 crypt = ieee->crypt[ieee->tx_keyidx];
464 atomic_inc(&crypt->refcnt);
465 if (crypt->ops->build_iv)
466 crypt->ops->build_iv(skb_frag, hdr_len,
467 crypt->priv);
468 atomic_dec(&crypt->refcnt);
469 }
James Ketrenosf1bf6632005-09-21 11:53:54 -0500470
Jeff Garzikb4538722005-05-12 22:48:20 -0400471 if (ieee->config &
472 (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
473 skb_put(skb_frag, 4);
474 }
475
Jeff Garzik0edd5b42005-09-07 00:48:31 -0400476 success:
Jeff Garzikb4538722005-05-12 22:48:20 -0400477 spin_unlock_irqrestore(&ieee->lock, flags);
478
479 dev_kfree_skb_any(skb);
480
481 if (txb) {
James Ketrenos9e8571a2005-09-21 11:56:33 -0500482 int ret = (*ieee->hard_start_xmit) (txb, dev, priority);
James Ketrenos1264fc02005-09-21 11:54:53 -0500483 if (ret == 0) {
Jeff Garzikb4538722005-05-12 22:48:20 -0400484 stats->tx_packets++;
485 stats->tx_bytes += txb->payload_size;
486 return 0;
487 }
James Ketrenos2c0aa2a2005-09-21 11:56:27 -0500488
489 if (ret == NETDEV_TX_BUSY) {
490 printk(KERN_ERR "%s: NETDEV_TX_BUSY returned; "
491 "driver should report queue full via "
492 "ieee_device->is_queue_full.\n",
493 ieee->dev->name);
494 }
495
Jeff Garzikb4538722005-05-12 22:48:20 -0400496 ieee80211_txb_free(txb);
497 }
498
499 return 0;
500
Jeff Garzik0edd5b42005-09-07 00:48:31 -0400501 failed:
Jeff Garzikb4538722005-05-12 22:48:20 -0400502 spin_unlock_irqrestore(&ieee->lock, flags);
503 netif_stop_queue(dev);
504 stats->tx_errors++;
505 return 1;
Jeff Garzikb4538722005-05-12 22:48:20 -0400506}
507
James Ketrenos3f552bb2005-09-21 11:54:47 -0500508/* Incoming 802.11 strucure is converted to a TXB
509 * a block of 802.11 fragment packets (stored as skbs) */
510int ieee80211_tx_frame(struct ieee80211_device *ieee,
511 struct ieee80211_hdr *frame, int len)
512{
513 struct ieee80211_txb *txb = NULL;
514 unsigned long flags;
515 struct net_device_stats *stats = &ieee->stats;
516 struct sk_buff *skb_frag;
James Ketrenos9e8571a2005-09-21 11:56:33 -0500517 int priority = -1;
James Ketrenos3f552bb2005-09-21 11:54:47 -0500518
519 spin_lock_irqsave(&ieee->lock, flags);
520
521 /* If there is no driver handler to take the TXB, dont' bother
522 * creating it... */
523 if (!ieee->hard_start_xmit) {
524 printk(KERN_WARNING "%s: No xmit handler.\n", ieee->dev->name);
525 goto success;
526 }
527
528 if (unlikely(len < 24)) {
529 printk(KERN_WARNING "%s: skb too small (%d).\n",
530 ieee->dev->name, len);
531 goto success;
532 }
533
534 /* When we allocate the TXB we allocate enough space for the reserve
535 * and full fragment bytes (bytes_per_frag doesn't include prefix,
536 * postfix, header, FCS, etc.) */
537 txb = ieee80211_alloc_txb(1, len, GFP_ATOMIC);
538 if (unlikely(!txb)) {
539 printk(KERN_WARNING "%s: Could not allocate TXB\n",
540 ieee->dev->name);
541 goto failed;
542 }
543 txb->encrypted = 0;
544 txb->payload_size = len;
545
546 skb_frag = txb->fragments[0];
547
548 memcpy(skb_put(skb_frag, len), frame, len);
549
550 if (ieee->config &
551 (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
552 skb_put(skb_frag, 4);
553
554 success:
555 spin_unlock_irqrestore(&ieee->lock, flags);
556
557 if (txb) {
James Ketrenos9e8571a2005-09-21 11:56:33 -0500558 if ((*ieee->hard_start_xmit) (txb, ieee->dev, priority) == 0) {
James Ketrenos3f552bb2005-09-21 11:54:47 -0500559 stats->tx_packets++;
560 stats->tx_bytes += txb->payload_size;
561 return 0;
562 }
563 ieee80211_txb_free(txb);
564 }
565 return 0;
566
567 failed:
568 spin_unlock_irqrestore(&ieee->lock, flags);
569 stats->tx_errors++;
570 return 1;
571}
572
573EXPORT_SYMBOL(ieee80211_tx_frame);
Jeff Garzikb4538722005-05-12 22:48:20 -0400574EXPORT_SYMBOL(ieee80211_txb_free);