1367a1092SKalle Valo /******************************************************************************
2367a1092SKalle Valo 
3367a1092SKalle Valo   Copyright(c) 2003 - 2005 Intel Corporation. All rights reserved.
4367a1092SKalle Valo 
5367a1092SKalle Valo   This program is free software; you can redistribute it and/or modify it
6367a1092SKalle Valo   under the terms of version 2 of the GNU General Public License as
7367a1092SKalle Valo   published by the Free Software Foundation.
8367a1092SKalle Valo 
9367a1092SKalle Valo   This program is distributed in the hope that it will be useful, but WITHOUT
10367a1092SKalle Valo   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11367a1092SKalle Valo   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12367a1092SKalle Valo   more details.
13367a1092SKalle Valo 
14367a1092SKalle Valo   You should have received a copy of the GNU General Public License along with
15367a1092SKalle Valo   this program; if not, write to the Free Software Foundation, Inc., 59
16367a1092SKalle Valo   Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17367a1092SKalle Valo 
18367a1092SKalle Valo   The full GNU General Public License is included in this distribution in the
19367a1092SKalle Valo   file called LICENSE.
20367a1092SKalle Valo 
21367a1092SKalle Valo   Contact Information:
22367a1092SKalle Valo   Intel Linux Wireless <ilw@linux.intel.com>
23367a1092SKalle Valo   Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
24367a1092SKalle Valo 
25367a1092SKalle Valo ******************************************************************************/
26367a1092SKalle Valo #include <linux/compiler.h>
27367a1092SKalle Valo #include <linux/errno.h>
28367a1092SKalle Valo #include <linux/if_arp.h>
29367a1092SKalle Valo #include <linux/in6.h>
30367a1092SKalle Valo #include <linux/in.h>
31367a1092SKalle Valo #include <linux/ip.h>
32367a1092SKalle Valo #include <linux/kernel.h>
33367a1092SKalle Valo #include <linux/module.h>
34367a1092SKalle Valo #include <linux/netdevice.h>
35367a1092SKalle Valo #include <linux/proc_fs.h>
36367a1092SKalle Valo #include <linux/skbuff.h>
37367a1092SKalle Valo #include <linux/slab.h>
38367a1092SKalle Valo #include <linux/tcp.h>
39367a1092SKalle Valo #include <linux/types.h>
40367a1092SKalle Valo #include <linux/wireless.h>
41367a1092SKalle Valo #include <linux/etherdevice.h>
427c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
43367a1092SKalle Valo 
44367a1092SKalle Valo #include "libipw.h"
45367a1092SKalle Valo 
46367a1092SKalle Valo /*
47367a1092SKalle Valo 
48367a1092SKalle Valo 802.11 Data Frame
49367a1092SKalle Valo 
50367a1092SKalle Valo       ,-------------------------------------------------------------------.
51367a1092SKalle Valo Bytes |  2   |  2   |    6    |    6    |    6    |  2   | 0..2312 |   4  |
52367a1092SKalle Valo       |------|------|---------|---------|---------|------|---------|------|
53367a1092SKalle Valo Desc. | ctrl | dura |  DA/RA  |   TA    |    SA   | Sequ |  Frame  |  fcs |
54367a1092SKalle Valo       |      | tion | (BSSID) |         |         | ence |  data   |      |
55367a1092SKalle Valo       `--------------------------------------------------|         |------'
56367a1092SKalle Valo Total: 28 non-data bytes                                 `----.----'
57367a1092SKalle Valo 							      |
58367a1092SKalle Valo        .- 'Frame data' expands, if WEP enabled, to <----------'
59367a1092SKalle Valo        |
60367a1092SKalle Valo        V
61367a1092SKalle Valo       ,-----------------------.
62367a1092SKalle Valo Bytes |  4  |   0-2296  |  4  |
63367a1092SKalle Valo       |-----|-----------|-----|
64367a1092SKalle Valo Desc. | IV  | Encrypted | ICV |
65367a1092SKalle Valo       |     | Packet    |     |
66367a1092SKalle Valo       `-----|           |-----'
67367a1092SKalle Valo 	    `-----.-----'
68367a1092SKalle Valo 		  |
69367a1092SKalle Valo        .- 'Encrypted Packet' expands to
70367a1092SKalle Valo        |
71367a1092SKalle Valo        V
72367a1092SKalle Valo       ,---------------------------------------------------.
73367a1092SKalle Valo Bytes |  1   |  1   |    1    |    3     |  2   |  0-2304 |
74367a1092SKalle Valo       |------|------|---------|----------|------|---------|
75367a1092SKalle Valo Desc. | SNAP | SNAP | Control |Eth Tunnel| Type | IP      |
76367a1092SKalle Valo       | DSAP | SSAP |         |          |      | Packet  |
77367a1092SKalle Valo       | 0xAA | 0xAA |0x03 (UI)|0x00-00-F8|      |         |
78367a1092SKalle Valo       `----------------------------------------------------
79367a1092SKalle Valo Total: 8 non-data bytes
80367a1092SKalle Valo 
81367a1092SKalle Valo 802.3 Ethernet Data Frame
82367a1092SKalle Valo 
83367a1092SKalle Valo       ,-----------------------------------------.
84367a1092SKalle Valo Bytes |   6   |   6   |  2   |  Variable |   4  |
85367a1092SKalle Valo       |-------|-------|------|-----------|------|
86367a1092SKalle Valo Desc. | Dest. | Source| Type | IP Packet |  fcs |
87367a1092SKalle Valo       |  MAC  |  MAC  |      |           |      |
88367a1092SKalle Valo       `-----------------------------------------'
89367a1092SKalle Valo Total: 18 non-data bytes
90367a1092SKalle Valo 
91367a1092SKalle Valo In the event that fragmentation is required, the incoming payload is split into
92367a1092SKalle Valo N parts of size ieee->fts.  The first fragment contains the SNAP header and the
93367a1092SKalle Valo remaining packets are just data.
94367a1092SKalle Valo 
95367a1092SKalle Valo If encryption is enabled, each fragment payload size is reduced by enough space
96367a1092SKalle Valo to add the prefix and postfix (IV and ICV totalling 8 bytes in the case of WEP)
97367a1092SKalle Valo So if you have 1500 bytes of payload with ieee->fts set to 500 without
98367a1092SKalle Valo encryption it will take 3 frames.  With WEP it will take 4 frames as the
99367a1092SKalle Valo payload of each frame is reduced to 492 bytes.
100367a1092SKalle Valo 
101367a1092SKalle Valo * SKB visualization
102367a1092SKalle Valo *
103367a1092SKalle Valo *  ,- skb->data
104367a1092SKalle Valo * |
105367a1092SKalle Valo * |    ETHERNET HEADER        ,-<-- PAYLOAD
106367a1092SKalle Valo * |                           |     14 bytes from skb->data
107367a1092SKalle Valo * |  2 bytes for Type --> ,T. |     (sizeof ethhdr)
108367a1092SKalle Valo * |                       | | |
109367a1092SKalle Valo * |,-Dest.--. ,--Src.---. | | |
110367a1092SKalle Valo * |  6 bytes| | 6 bytes | | | |
111367a1092SKalle Valo * v         | |         | | | |
112367a1092SKalle Valo * 0         | v       1 | v | v           2
113367a1092SKalle Valo * 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
114367a1092SKalle Valo *     ^     | ^         | ^ |
115367a1092SKalle Valo *     |     | |         | | |
116367a1092SKalle Valo *     |     | |         | `T' <---- 2 bytes for Type
117367a1092SKalle Valo *     |     | |         |
118367a1092SKalle Valo *     |     | '---SNAP--' <-------- 6 bytes for SNAP
119367a1092SKalle Valo *     |     |
120367a1092SKalle Valo *     `-IV--' <-------------------- 4 bytes for IV (WEP)
121367a1092SKalle Valo *
122367a1092SKalle Valo *      SNAP HEADER
123367a1092SKalle Valo *
124367a1092SKalle Valo */
125367a1092SKalle Valo 
126367a1092SKalle Valo static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 };
127367a1092SKalle Valo static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 };
128367a1092SKalle Valo 
129367a1092SKalle Valo static int libipw_copy_snap(u8 * data, __be16 h_proto)
130367a1092SKalle Valo {
131367a1092SKalle Valo 	struct libipw_snap_hdr *snap;
132367a1092SKalle Valo 	u8 *oui;
133367a1092SKalle Valo 
134367a1092SKalle Valo 	snap = (struct libipw_snap_hdr *)data;
135367a1092SKalle Valo 	snap->dsap = 0xaa;
136367a1092SKalle Valo 	snap->ssap = 0xaa;
137367a1092SKalle Valo 	snap->ctrl = 0x03;
138367a1092SKalle Valo 
139367a1092SKalle Valo 	if (h_proto == htons(ETH_P_AARP) || h_proto == htons(ETH_P_IPX))
140367a1092SKalle Valo 		oui = P802_1H_OUI;
141367a1092SKalle Valo 	else
142367a1092SKalle Valo 		oui = RFC1042_OUI;
143367a1092SKalle Valo 	snap->oui[0] = oui[0];
144367a1092SKalle Valo 	snap->oui[1] = oui[1];
145367a1092SKalle Valo 	snap->oui[2] = oui[2];
146367a1092SKalle Valo 
147367a1092SKalle Valo 	memcpy(data + SNAP_SIZE, &h_proto, sizeof(u16));
148367a1092SKalle Valo 
149367a1092SKalle Valo 	return SNAP_SIZE + sizeof(u16);
150367a1092SKalle Valo }
151367a1092SKalle Valo 
152367a1092SKalle Valo static int libipw_encrypt_fragment(struct libipw_device *ieee,
153367a1092SKalle Valo 					     struct sk_buff *frag, int hdr_len)
154367a1092SKalle Valo {
155367a1092SKalle Valo 	struct lib80211_crypt_data *crypt =
156367a1092SKalle Valo 		ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx];
157367a1092SKalle Valo 	int res;
158367a1092SKalle Valo 
159367a1092SKalle Valo 	if (crypt == NULL)
160367a1092SKalle Valo 		return -1;
161367a1092SKalle Valo 
162367a1092SKalle Valo 	/* To encrypt, frame format is:
163367a1092SKalle Valo 	 * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) */
164367a1092SKalle Valo 	atomic_inc(&crypt->refcnt);
165367a1092SKalle Valo 	res = 0;
166367a1092SKalle Valo 	if (crypt->ops && crypt->ops->encrypt_mpdu)
167367a1092SKalle Valo 		res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv);
168367a1092SKalle Valo 
169367a1092SKalle Valo 	atomic_dec(&crypt->refcnt);
170367a1092SKalle Valo 	if (res < 0) {
171367a1092SKalle Valo 		printk(KERN_INFO "%s: Encryption failed: len=%d.\n",
172367a1092SKalle Valo 		       ieee->dev->name, frag->len);
173367a1092SKalle Valo 		ieee->ieee_stats.tx_discards++;
174367a1092SKalle Valo 		return -1;
175367a1092SKalle Valo 	}
176367a1092SKalle Valo 
177367a1092SKalle Valo 	return 0;
178367a1092SKalle Valo }
179367a1092SKalle Valo 
180367a1092SKalle Valo void libipw_txb_free(struct libipw_txb *txb)
181367a1092SKalle Valo {
182367a1092SKalle Valo 	int i;
183367a1092SKalle Valo 	if (unlikely(!txb))
184367a1092SKalle Valo 		return;
185367a1092SKalle Valo 	for (i = 0; i < txb->nr_frags; i++)
186367a1092SKalle Valo 		if (txb->fragments[i])
187367a1092SKalle Valo 			dev_kfree_skb_any(txb->fragments[i]);
188367a1092SKalle Valo 	kfree(txb);
189367a1092SKalle Valo }
190367a1092SKalle Valo 
191367a1092SKalle Valo static struct libipw_txb *libipw_alloc_txb(int nr_frags, int txb_size,
192367a1092SKalle Valo 						 int headroom, gfp_t gfp_mask)
193367a1092SKalle Valo {
194367a1092SKalle Valo 	struct libipw_txb *txb;
195367a1092SKalle Valo 	int i;
196367a1092SKalle Valo 	txb = kmalloc(sizeof(struct libipw_txb) + (sizeof(u8 *) * nr_frags),
197367a1092SKalle Valo 		      gfp_mask);
198367a1092SKalle Valo 	if (!txb)
199367a1092SKalle Valo 		return NULL;
200367a1092SKalle Valo 
201367a1092SKalle Valo 	memset(txb, 0, sizeof(struct libipw_txb));
202367a1092SKalle Valo 	txb->nr_frags = nr_frags;
203367a1092SKalle Valo 	txb->frag_size = txb_size;
204367a1092SKalle Valo 
205367a1092SKalle Valo 	for (i = 0; i < nr_frags; i++) {
206367a1092SKalle Valo 		txb->fragments[i] = __dev_alloc_skb(txb_size + headroom,
207367a1092SKalle Valo 						    gfp_mask);
208367a1092SKalle Valo 		if (unlikely(!txb->fragments[i])) {
209367a1092SKalle Valo 			i--;
210367a1092SKalle Valo 			break;
211367a1092SKalle Valo 		}
212367a1092SKalle Valo 		skb_reserve(txb->fragments[i], headroom);
213367a1092SKalle Valo 	}
214367a1092SKalle Valo 	if (unlikely(i != nr_frags)) {
215367a1092SKalle Valo 		while (i >= 0)
216367a1092SKalle Valo 			dev_kfree_skb_any(txb->fragments[i--]);
217367a1092SKalle Valo 		kfree(txb);
218367a1092SKalle Valo 		return NULL;
219367a1092SKalle Valo 	}
220367a1092SKalle Valo 	return txb;
221367a1092SKalle Valo }
222367a1092SKalle Valo 
223367a1092SKalle Valo static int libipw_classify(struct sk_buff *skb)
224367a1092SKalle Valo {
225367a1092SKalle Valo 	struct ethhdr *eth;
226367a1092SKalle Valo 	struct iphdr *ip;
227367a1092SKalle Valo 
228367a1092SKalle Valo 	eth = (struct ethhdr *)skb->data;
229367a1092SKalle Valo 	if (eth->h_proto != htons(ETH_P_IP))
230367a1092SKalle Valo 		return 0;
231367a1092SKalle Valo 
232367a1092SKalle Valo 	ip = ip_hdr(skb);
233367a1092SKalle Valo 	switch (ip->tos & 0xfc) {
234367a1092SKalle Valo 	case 0x20:
235367a1092SKalle Valo 		return 2;
236367a1092SKalle Valo 	case 0x40:
237367a1092SKalle Valo 		return 1;
238367a1092SKalle Valo 	case 0x60:
239367a1092SKalle Valo 		return 3;
240367a1092SKalle Valo 	case 0x80:
241367a1092SKalle Valo 		return 4;
242367a1092SKalle Valo 	case 0xa0:
243367a1092SKalle Valo 		return 5;
244367a1092SKalle Valo 	case 0xc0:
245367a1092SKalle Valo 		return 6;
246367a1092SKalle Valo 	case 0xe0:
247367a1092SKalle Valo 		return 7;
248367a1092SKalle Valo 	default:
249367a1092SKalle Valo 		return 0;
250367a1092SKalle Valo 	}
251367a1092SKalle Valo }
252367a1092SKalle Valo 
253367a1092SKalle Valo /* Incoming skb is converted to a txb which consists of
254367a1092SKalle Valo  * a block of 802.11 fragment packets (stored as skbs) */
255367a1092SKalle Valo netdev_tx_t libipw_xmit(struct sk_buff *skb, struct net_device *dev)
256367a1092SKalle Valo {
257367a1092SKalle Valo 	struct libipw_device *ieee = netdev_priv(dev);
258367a1092SKalle Valo 	struct libipw_txb *txb = NULL;
259367a1092SKalle Valo 	struct libipw_hdr_3addrqos *frag_hdr;
260367a1092SKalle Valo 	int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size,
261367a1092SKalle Valo 	    rts_required;
262367a1092SKalle Valo 	unsigned long flags;
263367a1092SKalle Valo 	int encrypt, host_encrypt, host_encrypt_msdu;
264367a1092SKalle Valo 	__be16 ether_type;
265367a1092SKalle Valo 	int bytes, fc, hdr_len;
266367a1092SKalle Valo 	struct sk_buff *skb_frag;
267367a1092SKalle Valo 	struct libipw_hdr_3addrqos header = {/* Ensure zero initialized */
268367a1092SKalle Valo 		.duration_id = 0,
269367a1092SKalle Valo 		.seq_ctl = 0,
270367a1092SKalle Valo 		.qos_ctl = 0
271367a1092SKalle Valo 	};
272367a1092SKalle Valo 	u8 dest[ETH_ALEN], src[ETH_ALEN];
273367a1092SKalle Valo 	struct lib80211_crypt_data *crypt;
274367a1092SKalle Valo 	int priority = skb->priority;
275367a1092SKalle Valo 	int snapped = 0;
276367a1092SKalle Valo 
277367a1092SKalle Valo 	if (ieee->is_queue_full && (*ieee->is_queue_full) (dev, priority))
278367a1092SKalle Valo 		return NETDEV_TX_BUSY;
279367a1092SKalle Valo 
280367a1092SKalle Valo 	spin_lock_irqsave(&ieee->lock, flags);
281367a1092SKalle Valo 
282367a1092SKalle Valo 	/* If there is no driver handler to take the TXB, dont' bother
283367a1092SKalle Valo 	 * creating it... */
284367a1092SKalle Valo 	if (!ieee->hard_start_xmit) {
285367a1092SKalle Valo 		printk(KERN_WARNING "%s: No xmit handler.\n", ieee->dev->name);
286367a1092SKalle Valo 		goto success;
287367a1092SKalle Valo 	}
288367a1092SKalle Valo 
289367a1092SKalle Valo 	if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) {
290367a1092SKalle Valo 		printk(KERN_WARNING "%s: skb too small (%d).\n",
291367a1092SKalle Valo 		       ieee->dev->name, skb->len);
292367a1092SKalle Valo 		goto success;
293367a1092SKalle Valo 	}
294367a1092SKalle Valo 
295367a1092SKalle Valo 	ether_type = ((struct ethhdr *)skb->data)->h_proto;
296367a1092SKalle Valo 
297367a1092SKalle Valo 	crypt = ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx];
298367a1092SKalle Valo 
299367a1092SKalle Valo 	encrypt = !(ether_type == htons(ETH_P_PAE) && ieee->ieee802_1x) &&
300367a1092SKalle Valo 	    ieee->sec.encrypt;
301367a1092SKalle Valo 
302367a1092SKalle Valo 	host_encrypt = ieee->host_encrypt && encrypt && crypt;
303367a1092SKalle Valo 	host_encrypt_msdu = ieee->host_encrypt_msdu && encrypt && crypt;
304367a1092SKalle Valo 
305367a1092SKalle Valo 	if (!encrypt && ieee->ieee802_1x &&
306367a1092SKalle Valo 	    ieee->drop_unencrypted && ether_type != htons(ETH_P_PAE)) {
307367a1092SKalle Valo 		dev->stats.tx_dropped++;
308367a1092SKalle Valo 		goto success;
309367a1092SKalle Valo 	}
310367a1092SKalle Valo 
311367a1092SKalle Valo 	/* Save source and destination addresses */
312367a1092SKalle Valo 	skb_copy_from_linear_data(skb, dest, ETH_ALEN);
313367a1092SKalle Valo 	skb_copy_from_linear_data_offset(skb, ETH_ALEN, src, ETH_ALEN);
314367a1092SKalle Valo 
315367a1092SKalle Valo 	if (host_encrypt)
316367a1092SKalle Valo 		fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA |
317367a1092SKalle Valo 		    IEEE80211_FCTL_PROTECTED;
318367a1092SKalle Valo 	else
319367a1092SKalle Valo 		fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA;
320367a1092SKalle Valo 
321367a1092SKalle Valo 	if (ieee->iw_mode == IW_MODE_INFRA) {
322367a1092SKalle Valo 		fc |= IEEE80211_FCTL_TODS;
323367a1092SKalle Valo 		/* To DS: Addr1 = BSSID, Addr2 = SA, Addr3 = DA */
324367a1092SKalle Valo 		memcpy(header.addr1, ieee->bssid, ETH_ALEN);
325367a1092SKalle Valo 		memcpy(header.addr2, src, ETH_ALEN);
326367a1092SKalle Valo 		memcpy(header.addr3, dest, ETH_ALEN);
327367a1092SKalle Valo 	} else if (ieee->iw_mode == IW_MODE_ADHOC) {
328367a1092SKalle Valo 		/* not From/To DS: Addr1 = DA, Addr2 = SA, Addr3 = BSSID */
329367a1092SKalle Valo 		memcpy(header.addr1, dest, ETH_ALEN);
330367a1092SKalle Valo 		memcpy(header.addr2, src, ETH_ALEN);
331367a1092SKalle Valo 		memcpy(header.addr3, ieee->bssid, ETH_ALEN);
332367a1092SKalle Valo 	}
333367a1092SKalle Valo 	hdr_len = LIBIPW_3ADDR_LEN;
334367a1092SKalle Valo 
335367a1092SKalle Valo 	if (ieee->is_qos_active && ieee->is_qos_active(dev, skb)) {
336367a1092SKalle Valo 		fc |= IEEE80211_STYPE_QOS_DATA;
337367a1092SKalle Valo 		hdr_len += 2;
338367a1092SKalle Valo 
339367a1092SKalle Valo 		skb->priority = libipw_classify(skb);
340367a1092SKalle Valo 		header.qos_ctl |= cpu_to_le16(skb->priority & LIBIPW_QCTL_TID);
341367a1092SKalle Valo 	}
342367a1092SKalle Valo 	header.frame_ctl = cpu_to_le16(fc);
343367a1092SKalle Valo 
344367a1092SKalle Valo 	/* Advance the SKB to the start of the payload */
345367a1092SKalle Valo 	skb_pull(skb, sizeof(struct ethhdr));
346367a1092SKalle Valo 
347367a1092SKalle Valo 	/* Determine total amount of storage required for TXB packets */
348367a1092SKalle Valo 	bytes = skb->len + SNAP_SIZE + sizeof(u16);
349367a1092SKalle Valo 
350367a1092SKalle Valo 	/* Encrypt msdu first on the whole data packet. */
351367a1092SKalle Valo 	if ((host_encrypt || host_encrypt_msdu) &&
352367a1092SKalle Valo 	    crypt && crypt->ops && crypt->ops->encrypt_msdu) {
353367a1092SKalle Valo 		int res = 0;
354367a1092SKalle Valo 		int len = bytes + hdr_len + crypt->ops->extra_msdu_prefix_len +
355367a1092SKalle Valo 		    crypt->ops->extra_msdu_postfix_len;
356367a1092SKalle Valo 		struct sk_buff *skb_new = dev_alloc_skb(len);
357367a1092SKalle Valo 
358367a1092SKalle Valo 		if (unlikely(!skb_new))
359367a1092SKalle Valo 			goto failed;
360367a1092SKalle Valo 
361367a1092SKalle Valo 		skb_reserve(skb_new, crypt->ops->extra_msdu_prefix_len);
362367a1092SKalle Valo 		memcpy(skb_put(skb_new, hdr_len), &header, hdr_len);
363367a1092SKalle Valo 		snapped = 1;
364367a1092SKalle Valo 		libipw_copy_snap(skb_put(skb_new, SNAP_SIZE + sizeof(u16)),
365367a1092SKalle Valo 				    ether_type);
366367a1092SKalle Valo 		skb_copy_from_linear_data(skb, skb_put(skb_new, skb->len), skb->len);
367367a1092SKalle Valo 		res = crypt->ops->encrypt_msdu(skb_new, hdr_len, crypt->priv);
368367a1092SKalle Valo 		if (res < 0) {
369367a1092SKalle Valo 			LIBIPW_ERROR("msdu encryption failed\n");
370367a1092SKalle Valo 			dev_kfree_skb_any(skb_new);
371367a1092SKalle Valo 			goto failed;
372367a1092SKalle Valo 		}
373367a1092SKalle Valo 		dev_kfree_skb_any(skb);
374367a1092SKalle Valo 		skb = skb_new;
375367a1092SKalle Valo 		bytes += crypt->ops->extra_msdu_prefix_len +
376367a1092SKalle Valo 		    crypt->ops->extra_msdu_postfix_len;
377367a1092SKalle Valo 		skb_pull(skb, hdr_len);
378367a1092SKalle Valo 	}
379367a1092SKalle Valo 
380367a1092SKalle Valo 	if (host_encrypt || ieee->host_open_frag) {
381367a1092SKalle Valo 		/* Determine fragmentation size based on destination (multicast
382367a1092SKalle Valo 		 * and broadcast are not fragmented) */
383367a1092SKalle Valo 		if (is_multicast_ether_addr(dest) ||
384367a1092SKalle Valo 		    is_broadcast_ether_addr(dest))
385367a1092SKalle Valo 			frag_size = MAX_FRAG_THRESHOLD;
386367a1092SKalle Valo 		else
387367a1092SKalle Valo 			frag_size = ieee->fts;
388367a1092SKalle Valo 
389367a1092SKalle Valo 		/* Determine amount of payload per fragment.  Regardless of if
390367a1092SKalle Valo 		 * this stack is providing the full 802.11 header, one will
391367a1092SKalle Valo 		 * eventually be affixed to this fragment -- so we must account
392367a1092SKalle Valo 		 * for it when determining the amount of payload space. */
393367a1092SKalle Valo 		bytes_per_frag = frag_size - hdr_len;
394367a1092SKalle Valo 		if (ieee->config &
395367a1092SKalle Valo 		    (CFG_LIBIPW_COMPUTE_FCS | CFG_LIBIPW_RESERVE_FCS))
396367a1092SKalle Valo 			bytes_per_frag -= LIBIPW_FCS_LEN;
397367a1092SKalle Valo 
398367a1092SKalle Valo 		/* Each fragment may need to have room for encryption
399367a1092SKalle Valo 		 * pre/postfix */
400367a1092SKalle Valo 		if (host_encrypt)
401367a1092SKalle Valo 			bytes_per_frag -= crypt->ops->extra_mpdu_prefix_len +
402367a1092SKalle Valo 			    crypt->ops->extra_mpdu_postfix_len;
403367a1092SKalle Valo 
404367a1092SKalle Valo 		/* Number of fragments is the total
405367a1092SKalle Valo 		 * bytes_per_frag / payload_per_fragment */
406367a1092SKalle Valo 		nr_frags = bytes / bytes_per_frag;
407367a1092SKalle Valo 		bytes_last_frag = bytes % bytes_per_frag;
408367a1092SKalle Valo 		if (bytes_last_frag)
409367a1092SKalle Valo 			nr_frags++;
410367a1092SKalle Valo 		else
411367a1092SKalle Valo 			bytes_last_frag = bytes_per_frag;
412367a1092SKalle Valo 	} else {
413367a1092SKalle Valo 		nr_frags = 1;
414367a1092SKalle Valo 		bytes_per_frag = bytes_last_frag = bytes;
415367a1092SKalle Valo 		frag_size = bytes + hdr_len;
416367a1092SKalle Valo 	}
417367a1092SKalle Valo 
418367a1092SKalle Valo 	rts_required = (frag_size > ieee->rts
419367a1092SKalle Valo 			&& ieee->config & CFG_LIBIPW_RTS);
420367a1092SKalle Valo 	if (rts_required)
421367a1092SKalle Valo 		nr_frags++;
422367a1092SKalle Valo 
423367a1092SKalle Valo 	/* When we allocate the TXB we allocate enough space for the reserve
424367a1092SKalle Valo 	 * and full fragment bytes (bytes_per_frag doesn't include prefix,
425367a1092SKalle Valo 	 * postfix, header, FCS, etc.) */
426367a1092SKalle Valo 	txb = libipw_alloc_txb(nr_frags, frag_size,
427367a1092SKalle Valo 				  ieee->tx_headroom, GFP_ATOMIC);
428367a1092SKalle Valo 	if (unlikely(!txb)) {
429367a1092SKalle Valo 		printk(KERN_WARNING "%s: Could not allocate TXB\n",
430367a1092SKalle Valo 		       ieee->dev->name);
431367a1092SKalle Valo 		goto failed;
432367a1092SKalle Valo 	}
433367a1092SKalle Valo 	txb->encrypted = encrypt;
434367a1092SKalle Valo 	if (host_encrypt)
435367a1092SKalle Valo 		txb->payload_size = frag_size * (nr_frags - 1) +
436367a1092SKalle Valo 		    bytes_last_frag;
437367a1092SKalle Valo 	else
438367a1092SKalle Valo 		txb->payload_size = bytes;
439367a1092SKalle Valo 
440367a1092SKalle Valo 	if (rts_required) {
441367a1092SKalle Valo 		skb_frag = txb->fragments[0];
442367a1092SKalle Valo 		frag_hdr =
443367a1092SKalle Valo 		    (struct libipw_hdr_3addrqos *)skb_put(skb_frag, hdr_len);
444367a1092SKalle Valo 
445367a1092SKalle Valo 		/*
446367a1092SKalle Valo 		 * Set header frame_ctl to the RTS.
447367a1092SKalle Valo 		 */
448367a1092SKalle Valo 		header.frame_ctl =
449367a1092SKalle Valo 		    cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS);
450367a1092SKalle Valo 		memcpy(frag_hdr, &header, hdr_len);
451367a1092SKalle Valo 
452367a1092SKalle Valo 		/*
453367a1092SKalle Valo 		 * Restore header frame_ctl to the original data setting.
454367a1092SKalle Valo 		 */
455367a1092SKalle Valo 		header.frame_ctl = cpu_to_le16(fc);
456367a1092SKalle Valo 
457367a1092SKalle Valo 		if (ieee->config &
458367a1092SKalle Valo 		    (CFG_LIBIPW_COMPUTE_FCS | CFG_LIBIPW_RESERVE_FCS))
459367a1092SKalle Valo 			skb_put(skb_frag, 4);
460367a1092SKalle Valo 
461367a1092SKalle Valo 		txb->rts_included = 1;
462367a1092SKalle Valo 		i = 1;
463367a1092SKalle Valo 	} else
464367a1092SKalle Valo 		i = 0;
465367a1092SKalle Valo 
466367a1092SKalle Valo 	for (; i < nr_frags; i++) {
467367a1092SKalle Valo 		skb_frag = txb->fragments[i];
468367a1092SKalle Valo 
469367a1092SKalle Valo 		if (host_encrypt)
470367a1092SKalle Valo 			skb_reserve(skb_frag,
471367a1092SKalle Valo 				    crypt->ops->extra_mpdu_prefix_len);
472367a1092SKalle Valo 
473367a1092SKalle Valo 		frag_hdr =
474367a1092SKalle Valo 		    (struct libipw_hdr_3addrqos *)skb_put(skb_frag, hdr_len);
475367a1092SKalle Valo 		memcpy(frag_hdr, &header, hdr_len);
476367a1092SKalle Valo 
477367a1092SKalle Valo 		/* If this is not the last fragment, then add the MOREFRAGS
478367a1092SKalle Valo 		 * bit to the frame control */
479367a1092SKalle Valo 		if (i != nr_frags - 1) {
480367a1092SKalle Valo 			frag_hdr->frame_ctl =
481367a1092SKalle Valo 			    cpu_to_le16(fc | IEEE80211_FCTL_MOREFRAGS);
482367a1092SKalle Valo 			bytes = bytes_per_frag;
483367a1092SKalle Valo 		} else {
484367a1092SKalle Valo 			/* The last fragment takes the remaining length */
485367a1092SKalle Valo 			bytes = bytes_last_frag;
486367a1092SKalle Valo 		}
487367a1092SKalle Valo 
488367a1092SKalle Valo 		if (i == 0 && !snapped) {
489367a1092SKalle Valo 			libipw_copy_snap(skb_put
490367a1092SKalle Valo 					    (skb_frag, SNAP_SIZE + sizeof(u16)),
491367a1092SKalle Valo 					    ether_type);
492367a1092SKalle Valo 			bytes -= SNAP_SIZE + sizeof(u16);
493367a1092SKalle Valo 		}
494367a1092SKalle Valo 
495367a1092SKalle Valo 		skb_copy_from_linear_data(skb, skb_put(skb_frag, bytes), bytes);
496367a1092SKalle Valo 
497367a1092SKalle Valo 		/* Advance the SKB... */
498367a1092SKalle Valo 		skb_pull(skb, bytes);
499367a1092SKalle Valo 
500367a1092SKalle Valo 		/* Encryption routine will move the header forward in order
501367a1092SKalle Valo 		 * to insert the IV between the header and the payload */
502367a1092SKalle Valo 		if (host_encrypt)
503367a1092SKalle Valo 			libipw_encrypt_fragment(ieee, skb_frag, hdr_len);
504367a1092SKalle Valo 
505367a1092SKalle Valo 		if (ieee->config &
506367a1092SKalle Valo 		    (CFG_LIBIPW_COMPUTE_FCS | CFG_LIBIPW_RESERVE_FCS))
507367a1092SKalle Valo 			skb_put(skb_frag, 4);
508367a1092SKalle Valo 	}
509367a1092SKalle Valo 
510367a1092SKalle Valo       success:
511367a1092SKalle Valo 	spin_unlock_irqrestore(&ieee->lock, flags);
512367a1092SKalle Valo 
513367a1092SKalle Valo 	dev_kfree_skb_any(skb);
514367a1092SKalle Valo 
515367a1092SKalle Valo 	if (txb) {
516367a1092SKalle Valo 		netdev_tx_t ret = (*ieee->hard_start_xmit)(txb, dev, priority);
517367a1092SKalle Valo 		if (ret == NETDEV_TX_OK) {
518367a1092SKalle Valo 			dev->stats.tx_packets++;
519367a1092SKalle Valo 			dev->stats.tx_bytes += txb->payload_size;
520367a1092SKalle Valo 			return NETDEV_TX_OK;
521367a1092SKalle Valo 		}
522367a1092SKalle Valo 
523367a1092SKalle Valo 		libipw_txb_free(txb);
524367a1092SKalle Valo 	}
525367a1092SKalle Valo 
526367a1092SKalle Valo 	return NETDEV_TX_OK;
527367a1092SKalle Valo 
528367a1092SKalle Valo       failed:
529367a1092SKalle Valo 	spin_unlock_irqrestore(&ieee->lock, flags);
530367a1092SKalle Valo 	netif_stop_queue(dev);
531367a1092SKalle Valo 	dev->stats.tx_errors++;
532367a1092SKalle Valo 	return NETDEV_TX_BUSY;
533367a1092SKalle Valo }
534367a1092SKalle Valo EXPORT_SYMBOL(libipw_xmit);
535367a1092SKalle Valo 
536367a1092SKalle Valo EXPORT_SYMBOL(libipw_txb_free);
537