100b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman/* src/p80211/p80211conv.c
200b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*
300b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* Ether/802.11 conversions and packet buffer routines
400b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*
500b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* Copyright (C) 1999 AbsoluteValue Systems, Inc.  All Rights Reserved.
600b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* --------------------------------------------------------------------
700b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*
800b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* linux-wlan
900b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*
1000b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*   The contents of this file are subject to the Mozilla Public
1100b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*   License Version 1.1 (the "License"); you may not use this file
1200b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*   except in compliance with the License. You may obtain a copy of
1300b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*   the License at http://www.mozilla.org/MPL/
1400b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*
1500b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*   Software distributed under the License is distributed on an "AS
1600b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*   IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
1700b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*   implied. See the License for the specific language governing
1800b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*   rights and limitations under the License.
1900b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*
2000b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*   Alternatively, the contents of this file may be used under the
2100b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*   terms of the GNU Public License version 2 (the "GPL"), in which
2200b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*   case the provisions of the GPL are applicable instead of the
2300b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*   above.  If you wish to allow the use of your version of this file
2400b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*   only under the terms of the GPL and not to allow others to use
2500b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*   your version of this file under the MPL, indicate your decision
2600b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*   by deleting the provisions above and replace them with the notice
2700b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*   and other provisions required by the GPL.  If you do not delete
2800b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*   the provisions above, a recipient may use your version of this
2900b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*   file under either the MPL or the GPL.
3000b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*
3100b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* --------------------------------------------------------------------
3200b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*
3300b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* Inquiries regarding the linux-wlan Open Source project can be
3400b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* made directly to:
3500b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*
3600b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* AbsoluteValue Systems Inc.
3700b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* info@linux-wlan.com
3800b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* http://www.linux-wlan.com
3900b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*
4000b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* --------------------------------------------------------------------
4100b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*
4200b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* Portions of the development of this software were funded by
4300b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* Intersil Corporation as part of PRISM(R) chipset product development.
4400b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*
4500b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* --------------------------------------------------------------------
4600b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*
4700b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* This file defines the functions that perform Ethernet to/from
4800b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* 802.11 frame conversions.
4900b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*
5000b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* --------------------------------------------------------------------
5182eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff*
5282eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff*================================================================ */
5300b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
5400b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman#include <linux/module.h>
5500b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman#include <linux/kernel.h>
5600b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman#include <linux/sched.h>
5700b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman#include <linux/types.h>
5800b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman#include <linux/skbuff.h>
5900b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman#include <linux/slab.h>
6000b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman#include <linux/wireless.h>
6100b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman#include <linux/netdevice.h>
6200b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman#include <linux/etherdevice.h>
6300b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman#include <linux/if_ether.h>
64ae26230bf93d37de73febdd1990090dcbd489b38Moritz Muehlenhoff#include <linux/byteorder/generic.h>
6500b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
6600b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman#include <asm/byteorder.h>
6700b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
6800b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman#include "p80211types.h"
6900b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman#include "p80211hdr.h"
7000b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman#include "p80211conv.h"
7100b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman#include "p80211mgmt.h"
7200b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman#include "p80211msg.h"
7300b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman#include "p80211netdev.h"
7400b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman#include "p80211ioctl.h"
7500b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman#include "p80211req.h"
7600b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
7782eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoffstatic u8 oui_rfc1042[] = { 0x00, 0x00, 0x00 };
7882eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoffstatic u8 oui_8021h[] = { 0x00, 0x00, 0xf8 };
7900b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
8000b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman/*----------------------------------------------------------------
8100b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* p80211pb_ether_to_80211
8200b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*
8300b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* Uses the contents of the ether frame and the etherconv setting
8400b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* to build the elements of the 802.11 frame.
8500b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*
8600b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* We don't actually set
8700b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* up the frame header here.  That's the MAC's job.  We're only handling
8800b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* conversion of DIXII or 802.3+LLC frames to something that works
8900b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* with 802.11.
9000b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*
9100b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* Note -- 802.11 header is NOT part of the skb.  Likewise, the 802.11
9200b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*         FCS is also not present and will need to be added elsewhere.
9300b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*
9400b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* Arguments:
9500b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*	ethconv		Conversion type to perform
9600b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*	skb		skbuff containing the ether frame
9700b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*       p80211_hdr      802.11 header
9800b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*
9900b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* Returns:
10000b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*	0 on success, non-zero otherwise
10100b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*
10200b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* Call context:
10300b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*	May be called in interrupt or non-interrupt context
10400b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman----------------------------------------------------------------*/
105297f06cea635ea4552541a11e7fb7014425110c6Mithlesh Thukralint skb_ether_to_p80211(wlandevice_t *wlandev, u32 ethconv,
10693df38e593d949de83a6447d016cc4b07d392f47Edgardo Hames			struct sk_buff *skb, union p80211_hdr *p80211_hdr,
10751e4896adad00a066fad65649405c1c9fa108157Edgardo Hames			struct p80211_metawep *p80211_wep)
10800b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman{
10900b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
11082eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	u16 fc;
11182eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	u16 proto;
11251e4896adad00a066fad65649405c1c9fa108157Edgardo Hames	struct wlan_ethhdr e_hdr;
11351e4896adad00a066fad65649405c1c9fa108157Edgardo Hames	struct wlan_llc *e_llc;
11451e4896adad00a066fad65649405c1c9fa108157Edgardo Hames	struct wlan_snap *e_snap;
11500b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	int foo;
11600b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
11700b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	memcpy(&e_hdr, skb->data, sizeof(e_hdr));
11800b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
11900b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	if (skb->len <= 0) {
120a7cf7bae3297f16bb4a2f00310377fec06d0ecd6Moritz Muehlenhoff		pr_debug("zero-length skb!\n");
12100b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		return 1;
12200b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	}
12300b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
12482eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	if (ethconv == WLAN_ETHCONV_ENCAP) {	/* simplest case */
12582eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff		pr_debug("ENCAP len: %d\n", skb->len);
12600b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		/* here, we don't care what kind of ether frm. Just stick it */
12700b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		/*  in the 80211 payload */
12800b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		/* which is to say, leave the skb alone. */
12900b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	} else {
13000b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		/* step 1: classify ether frame, DIX or 802.3? */
13100b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		proto = ntohs(e_hdr.type);
13282eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff		if (proto <= 1500) {
13382eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff			pr_debug("802.3 len: %d\n", skb->len);
13482eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff			/* codes <= 1500 reserved for 802.3 lengths */
13500b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman			/* it's 802.3, pass ether payload unchanged,  */
13600b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
13700b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman			/* trim off ethernet header */
13800b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman			skb_pull(skb, WLAN_ETHHDR_LEN);
13900b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
14000b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman			/*   leave off any PAD octets.  */
14100b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman			skb_trim(skb, proto);
14200b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		} else {
14382eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff			pr_debug("DIXII len: %d\n", skb->len);
14400b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman			/* it's DIXII, time for some conversion */
14500b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
14600b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman			/* trim off ethernet header */
14700b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman			skb_pull(skb, WLAN_ETHHDR_LEN);
14800b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
14900b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman			/* tack on SNAP */
15082eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff			e_snap =
1514eb28f7197a2cbaf7a9be778d429a5fb9bb6172eJohan Meiring			    (struct wlan_snap *) skb_push(skb,
1524eb28f7197a2cbaf7a9be778d429a5fb9bb6172eJohan Meiring				sizeof(struct wlan_snap));
15300b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman			e_snap->type = htons(proto);
15482eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff			if (ethconv == WLAN_ETHCONV_8021h
15582eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff			    && p80211_stt_findproto(proto)) {
15682eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff				memcpy(e_snap->oui, oui_8021h,
15782eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff				       WLAN_IEEE_OUI_LEN);
15800b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman			} else {
15982eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff				memcpy(e_snap->oui, oui_rfc1042,
16082eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff				       WLAN_IEEE_OUI_LEN);
16100b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman			}
16200b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
16300b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman			/* tack on llc */
16482eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff			e_llc =
1654eb28f7197a2cbaf7a9be778d429a5fb9bb6172eJohan Meiring			    (struct wlan_llc *) skb_push(skb,
1664eb28f7197a2cbaf7a9be778d429a5fb9bb6172eJohan Meiring				sizeof(struct wlan_llc));
16700b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman			e_llc->dsap = 0xAA;	/* SNAP, see IEEE 802 */
16800b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman			e_llc->ssap = 0xAA;
16900b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman			e_llc->ctl = 0x03;
17000b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
17100b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		}
17200b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	}
17300b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
17400b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	/* Set up the 802.11 header */
17500b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	/* It's a data frame */
17682eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	fc = cpu_to_le16(WLAN_SET_FC_FTYPE(WLAN_FTYPE_DATA) |
17782eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff			 WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_DATAONLY));
17800b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
17982eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	switch (wlandev->macmode) {
18000b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	case WLAN_MACMODE_IBSS_STA:
18128b17a4bdf148b7591c004efd10a8850d52849ecMoritz Muehlenhoff		memcpy(p80211_hdr->a3.a1, &e_hdr.daddr, ETH_ALEN);
18228b17a4bdf148b7591c004efd10a8850d52849ecMoritz Muehlenhoff		memcpy(p80211_hdr->a3.a2, wlandev->netdev->dev_addr, ETH_ALEN);
18328b17a4bdf148b7591c004efd10a8850d52849ecMoritz Muehlenhoff		memcpy(p80211_hdr->a3.a3, wlandev->bssid, ETH_ALEN);
18400b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		break;
18500b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	case WLAN_MACMODE_ESS_STA:
186ae26230bf93d37de73febdd1990090dcbd489b38Moritz Muehlenhoff		fc |= cpu_to_le16(WLAN_SET_FC_TODS(1));
18728b17a4bdf148b7591c004efd10a8850d52849ecMoritz Muehlenhoff		memcpy(p80211_hdr->a3.a1, wlandev->bssid, ETH_ALEN);
18828b17a4bdf148b7591c004efd10a8850d52849ecMoritz Muehlenhoff		memcpy(p80211_hdr->a3.a2, wlandev->netdev->dev_addr, ETH_ALEN);
18928b17a4bdf148b7591c004efd10a8850d52849ecMoritz Muehlenhoff		memcpy(p80211_hdr->a3.a3, &e_hdr.daddr, ETH_ALEN);
19000b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		break;
19100b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	case WLAN_MACMODE_ESS_AP:
192ae26230bf93d37de73febdd1990090dcbd489b38Moritz Muehlenhoff		fc |= cpu_to_le16(WLAN_SET_FC_FROMDS(1));
19328b17a4bdf148b7591c004efd10a8850d52849ecMoritz Muehlenhoff		memcpy(p80211_hdr->a3.a1, &e_hdr.daddr, ETH_ALEN);
19428b17a4bdf148b7591c004efd10a8850d52849ecMoritz Muehlenhoff		memcpy(p80211_hdr->a3.a2, wlandev->bssid, ETH_ALEN);
19528b17a4bdf148b7591c004efd10a8850d52849ecMoritz Muehlenhoff		memcpy(p80211_hdr->a3.a3, &e_hdr.saddr, ETH_ALEN);
19600b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		break;
19700b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	default:
19882eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff		printk(KERN_ERR
19982eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff		       "Error: Converting eth to wlan in unknown mode.\n");
20000b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		return 1;
20100b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		break;
20200b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	}
20300b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
20400b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	p80211_wep->data = NULL;
20500b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
20682eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	if ((wlandev->hostwep & HOSTWEP_PRIVACYINVOKED)
20782eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	    && (wlandev->hostwep & HOSTWEP_ENCRYPT)) {
20882eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff		/* XXXX need to pick keynum other than default? */
20900b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
21000b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		p80211_wep->data = kmalloc(skb->len, GFP_ATOMIC);
2115dd8acc8fd6b0476a2dc49bc6de4712d22c368c0Svenne Krap		foo = wep_encrypt(wlandev, skb->data, p80211_wep->data,
212b02957d58a27525499ab10d272d3b44682a7ae50Greg Kroah-Hartman				  skb->len,
2135813b6243cf02b89c6e6a6a8debc10477e5ce3a8Ruslan Pisarev				  (wlandev->hostwep & HOSTWEP_DEFAULTKEY_MASK),
2143f4b4e779714ae2dd55757617a8033ab338fa7f0Andrew Elwell				  p80211_wep->iv, p80211_wep->icv);
2155dd8acc8fd6b0476a2dc49bc6de4712d22c368c0Svenne Krap		if (foo) {
21682eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff			printk(KERN_WARNING
21782eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff			       "Host en-WEP failed, dropping frame (%d).\n",
21882eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff			       foo);
21900b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman			return 2;
22000b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		}
221ae26230bf93d37de73febdd1990090dcbd489b38Moritz Muehlenhoff		fc |= cpu_to_le16(WLAN_SET_FC_ISWEP(1));
22200b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	}
22300b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
22482eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	/*      skb->nh.raw = skb->data; */
22500b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
22600b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	p80211_hdr->a3.fc = fc;
22700b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	p80211_hdr->a3.dur = 0;
22800b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	p80211_hdr->a3.seq = 0;
22900b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
23000b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	return 0;
23100b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman}
23200b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
23300b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman/* jkriegl: from orinoco, modified */
234297f06cea635ea4552541a11e7fb7014425110c6Mithlesh Thukralstatic void orinoco_spy_gather(wlandevice_t *wlandev, char *mac,
23551e4896adad00a066fad65649405c1c9fa108157Edgardo Hames			       struct p80211_rxmeta *rxmeta)
23600b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman{
23782eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	int i;
23800b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
23982eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	/* Gather wireless spy statistics: for each packet, compare the
24082eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	 * source address with out list, and if match, get the stats... */
24100b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
24282eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	for (i = 0; i < wlandev->spy_number; i++) {
24300b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
24482eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff		if (!memcmp(wlandev->spy_address[i], mac, ETH_ALEN)) {
24500b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman			memcpy(wlandev->spy_address[i], mac, ETH_ALEN);
24682eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff			wlandev->spy_stat[i].level = rxmeta->signal;
24782eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff			wlandev->spy_stat[i].noise = rxmeta->noise;
24882eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff			wlandev->spy_stat[i].qual =
24982eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff			    (rxmeta->signal >
25082eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff			     rxmeta->noise) ? (rxmeta->signal -
25182eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff					       rxmeta->noise) : 0;
25282eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff			wlandev->spy_stat[i].updated = 0x7;
25382eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff		}
25482eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	}
25500b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman}
25600b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
25700b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman/*----------------------------------------------------------------
25800b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* p80211pb_80211_to_ether
25900b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*
26000b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* Uses the contents of a received 802.11 frame and the etherconv
26100b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* setting to build an ether frame.
26200b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*
26300b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* This function extracts the src and dest address from the 802.11
26400b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* frame to use in the construction of the eth frame.
26500b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*
26600b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* Arguments:
26700b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*	ethconv		Conversion type to perform
26800b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*	skb		Packet buffer containing the 802.11 frame
26900b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*
27000b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* Returns:
27100b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*	0 on success, non-zero otherwise
27200b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*
27300b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* Call context:
27400b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*	May be called in interrupt or non-interrupt context
27500b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman----------------------------------------------------------------*/
276297f06cea635ea4552541a11e7fb7014425110c6Mithlesh Thukralint skb_p80211_to_ether(wlandevice_t *wlandev, u32 ethconv,
27782eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff			struct sk_buff *skb)
27800b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman{
27982eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	netdevice_t *netdev = wlandev->netdev;
28082eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	u16 fc;
28182eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	unsigned int payload_length;
28282eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	unsigned int payload_offset;
28382eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	u8 daddr[WLAN_ETHADDR_LEN];
28482eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	u8 saddr[WLAN_ETHADDR_LEN];
28593df38e593d949de83a6447d016cc4b07d392f47Edgardo Hames	union p80211_hdr *w_hdr;
28651e4896adad00a066fad65649405c1c9fa108157Edgardo Hames	struct wlan_ethhdr *e_hdr;
28751e4896adad00a066fad65649405c1c9fa108157Edgardo Hames	struct wlan_llc *e_llc;
28851e4896adad00a066fad65649405c1c9fa108157Edgardo Hames	struct wlan_snap *e_snap;
28900b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
29000b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	int foo;
29100b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
29200b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	payload_length = skb->len - WLAN_HDR_A3_LEN - WLAN_CRC_LEN;
29300b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	payload_offset = WLAN_HDR_A3_LEN;
29400b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
29593df38e593d949de83a6447d016cc4b07d392f47Edgardo Hames	w_hdr = (union p80211_hdr *) skb->data;
29600b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
29782eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	/* setup some vars for convenience */
298ae26230bf93d37de73febdd1990090dcbd489b38Moritz Muehlenhoff	fc = le16_to_cpu(w_hdr->a3.fc);
29982eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	if ((WLAN_GET_FC_TODS(fc) == 0) && (WLAN_GET_FC_FROMDS(fc) == 0)) {
30000b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		memcpy(daddr, w_hdr->a3.a1, WLAN_ETHADDR_LEN);
30100b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		memcpy(saddr, w_hdr->a3.a2, WLAN_ETHADDR_LEN);
3024eb28f7197a2cbaf7a9be778d429a5fb9bb6172eJohan Meiring	} else if ((WLAN_GET_FC_TODS(fc) == 0)
3034eb28f7197a2cbaf7a9be778d429a5fb9bb6172eJohan Meiring			&& (WLAN_GET_FC_FROMDS(fc) == 1)) {
30400b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		memcpy(daddr, w_hdr->a3.a1, WLAN_ETHADDR_LEN);
30500b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		memcpy(saddr, w_hdr->a3.a3, WLAN_ETHADDR_LEN);
3064eb28f7197a2cbaf7a9be778d429a5fb9bb6172eJohan Meiring	} else if ((WLAN_GET_FC_TODS(fc) == 1)
3074eb28f7197a2cbaf7a9be778d429a5fb9bb6172eJohan Meiring			&& (WLAN_GET_FC_FROMDS(fc) == 0)) {
30800b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		memcpy(daddr, w_hdr->a3.a3, WLAN_ETHADDR_LEN);
30900b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		memcpy(saddr, w_hdr->a3.a2, WLAN_ETHADDR_LEN);
31000b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	} else {
31100b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		payload_offset = WLAN_HDR_A4_LEN;
3121f9e9ce1f99e89ee180a3994c44bdff43ebeb139Roel Kluin		if (payload_length < WLAN_HDR_A4_LEN - WLAN_HDR_A3_LEN) {
313edbd606c4671fcd439164c8d63e896044d706156Moritz Muehlenhoff			printk(KERN_ERR "A4 frame too short!\n");
31400b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman			return 1;
31500b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		}
3161f9e9ce1f99e89ee180a3994c44bdff43ebeb139Roel Kluin		payload_length -= (WLAN_HDR_A4_LEN - WLAN_HDR_A3_LEN);
31700b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		memcpy(daddr, w_hdr->a4.a3, WLAN_ETHADDR_LEN);
31800b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		memcpy(saddr, w_hdr->a4.a4, WLAN_ETHADDR_LEN);
31900b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	}
32000b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
32100b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	/* perform de-wep if necessary.. */
32282eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	if ((wlandev->hostwep & HOSTWEP_PRIVACYINVOKED) && WLAN_GET_FC_ISWEP(fc)
32382eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	    && (wlandev->hostwep & HOSTWEP_DECRYPT)) {
32400b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		if (payload_length <= 8) {
325edbd606c4671fcd439164c8d63e896044d706156Moritz Muehlenhoff			printk(KERN_ERR "WEP frame too short (%u).\n",
32682eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff			       skb->len);
32700b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman			return 1;
32800b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		}
3295dd8acc8fd6b0476a2dc49bc6de4712d22c368c0Svenne Krap		foo = wep_decrypt(wlandev, skb->data + payload_offset + 4,
33000b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman				       payload_length - 8, -1,
33100b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman				       skb->data + payload_offset,
33282eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff				       skb->data + payload_offset +
3333f4b4e779714ae2dd55757617a8033ab338fa7f0Andrew Elwell				       payload_length - 4);
3345dd8acc8fd6b0476a2dc49bc6de4712d22c368c0Svenne Krap		if (foo) {
33500b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman			/* de-wep failed, drop skb. */
33675f49e07520d036c2a0903694fdc0bcfb5523b76Mithlesh Thukral			pr_debug("Host de-WEP failed, dropping frame (%d).\n",
33775f49e07520d036c2a0903694fdc0bcfb5523b76Mithlesh Thukral				 foo);
33800b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman			wlandev->rx.decrypt_err++;
33900b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman			return 2;
34000b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		}
34100b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
34200b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		/* subtract the IV+ICV length off the payload */
34300b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		payload_length -= 8;
34400b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		/* chop off the IV */
34500b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		skb_pull(skb, 4);
34600b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		/* chop off the ICV. */
34700b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		skb_trim(skb, skb->len - 4);
34800b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
34900b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		wlandev->rx.decrypt++;
35000b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	}
35100b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
35251e4896adad00a066fad65649405c1c9fa108157Edgardo Hames	e_hdr = (struct wlan_ethhdr *) (skb->data + payload_offset);
35300b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
35451e4896adad00a066fad65649405c1c9fa108157Edgardo Hames	e_llc = (struct wlan_llc *) (skb->data + payload_offset);
35582eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	e_snap =
3564eb28f7197a2cbaf7a9be778d429a5fb9bb6172eJohan Meiring	    (struct wlan_snap *) (skb->data + payload_offset +
3574eb28f7197a2cbaf7a9be778d429a5fb9bb6172eJohan Meiring		sizeof(struct wlan_llc));
35800b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
35900b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	/* Test for the various encodings */
36051e4896adad00a066fad65649405c1c9fa108157Edgardo Hames	if ((payload_length >= sizeof(struct wlan_ethhdr)) &&
36182eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	    (e_llc->dsap != 0xaa || e_llc->ssap != 0xaa) &&
36282eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	    ((memcmp(daddr, e_hdr->daddr, WLAN_ETHADDR_LEN) == 0) ||
36300b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	     (memcmp(saddr, e_hdr->saddr, WLAN_ETHADDR_LEN) == 0))) {
364a7cf7bae3297f16bb4a2f00310377fec06d0ecd6Moritz Muehlenhoff		pr_debug("802.3 ENCAP len: %d\n", payload_length);
36500b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		/* 802.3 Encapsulated */
36633ce0ca6e22e726f64ed86821da1677a00fb0e06Richard Kennedy		/* Test for an overlength frame */
36782eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff		if (payload_length > (netdev->mtu + WLAN_ETHHDR_LEN)) {
36833ce0ca6e22e726f64ed86821da1677a00fb0e06Richard Kennedy			/* A bogus length ethfrm has been encap'd. */
36933ce0ca6e22e726f64ed86821da1677a00fb0e06Richard Kennedy			/* Is someone trying an oflow attack? */
370edbd606c4671fcd439164c8d63e896044d706156Moritz Muehlenhoff			printk(KERN_ERR "ENCAP frame too large (%d > %d)\n",
37182eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff			       payload_length, netdev->mtu + WLAN_ETHHDR_LEN);
37233ce0ca6e22e726f64ed86821da1677a00fb0e06Richard Kennedy			return 1;
37333ce0ca6e22e726f64ed86821da1677a00fb0e06Richard Kennedy		}
37400b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
37500b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		/* Chop off the 802.11 header.  it's already sane. */
37600b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		skb_pull(skb, payload_offset);
37700b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		/* chop off the 802.11 CRC */
37800b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		skb_trim(skb, skb->len - WLAN_CRC_LEN);
37900b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
3804eb28f7197a2cbaf7a9be778d429a5fb9bb6172eJohan Meiring	} else if ((payload_length >= sizeof(struct wlan_llc) +
3814eb28f7197a2cbaf7a9be778d429a5fb9bb6172eJohan Meiring		sizeof(struct wlan_snap))
382e80528b78e8d33494a0784dc214e71a728162d92Adam Thompson		&& (e_llc->dsap == 0xaa)
3834eb28f7197a2cbaf7a9be778d429a5fb9bb6172eJohan Meiring		&& (e_llc->ssap == 0xaa)
3844eb28f7197a2cbaf7a9be778d429a5fb9bb6172eJohan Meiring		&& (e_llc->ctl == 0x03)
38582eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff		   &&
38682eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff		   (((memcmp(e_snap->oui, oui_rfc1042, WLAN_IEEE_OUI_LEN) == 0)
38782eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff		     && (ethconv == WLAN_ETHCONV_8021h)
38882eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff		     && (p80211_stt_findproto(le16_to_cpu(e_snap->type))))
38982eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff		    || (memcmp(e_snap->oui, oui_rfc1042, WLAN_IEEE_OUI_LEN) !=
39082eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff			0))) {
391a7cf7bae3297f16bb4a2f00310377fec06d0ecd6Moritz Muehlenhoff		pr_debug("SNAP+RFC1042 len: %d\n", payload_length);
39200b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		/* it's a SNAP + RFC1042 frame && protocol is in STT */
39300b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		/* build 802.3 + RFC1042 */
39400b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
39533ce0ca6e22e726f64ed86821da1677a00fb0e06Richard Kennedy		/* Test for an overlength frame */
39682eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff		if (payload_length > netdev->mtu) {
39733ce0ca6e22e726f64ed86821da1677a00fb0e06Richard Kennedy			/* A bogus length ethfrm has been sent. */
39833ce0ca6e22e726f64ed86821da1677a00fb0e06Richard Kennedy			/* Is someone trying an oflow attack? */
399edbd606c4671fcd439164c8d63e896044d706156Moritz Muehlenhoff			printk(KERN_ERR "SNAP frame too large (%d > %d)\n",
40082eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff			       payload_length, netdev->mtu);
40133ce0ca6e22e726f64ed86821da1677a00fb0e06Richard Kennedy			return 1;
40233ce0ca6e22e726f64ed86821da1677a00fb0e06Richard Kennedy		}
40333ce0ca6e22e726f64ed86821da1677a00fb0e06Richard Kennedy
40400b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		/* chop 802.11 header from skb. */
40500b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		skb_pull(skb, payload_offset);
40600b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
40700b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		/* create 802.3 header at beginning of skb. */
40851e4896adad00a066fad65649405c1c9fa108157Edgardo Hames		e_hdr = (struct wlan_ethhdr *) skb_push(skb, WLAN_ETHHDR_LEN);
40900b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		memcpy(e_hdr->daddr, daddr, WLAN_ETHADDR_LEN);
41000b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		memcpy(e_hdr->saddr, saddr, WLAN_ETHADDR_LEN);
41100b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		e_hdr->type = htons(payload_length);
41200b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
41300b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		/* chop off the 802.11 CRC */
41400b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		skb_trim(skb, skb->len - WLAN_CRC_LEN);
41500b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
4164eb28f7197a2cbaf7a9be778d429a5fb9bb6172eJohan Meiring	} else if ((payload_length >= sizeof(struct wlan_llc) +
4174eb28f7197a2cbaf7a9be778d429a5fb9bb6172eJohan Meiring		sizeof(struct wlan_snap))
418e80528b78e8d33494a0784dc214e71a728162d92Adam Thompson		&& (e_llc->dsap == 0xaa)
4194eb28f7197a2cbaf7a9be778d429a5fb9bb6172eJohan Meiring		&& (e_llc->ssap == 0xaa)
4204eb28f7197a2cbaf7a9be778d429a5fb9bb6172eJohan Meiring		&& (e_llc->ctl == 0x03)) {
421a7cf7bae3297f16bb4a2f00310377fec06d0ecd6Moritz Muehlenhoff		pr_debug("802.1h/RFC1042 len: %d\n", payload_length);
4224eb28f7197a2cbaf7a9be778d429a5fb9bb6172eJohan Meiring		/* it's an 802.1h frame || (an RFC1042 && protocol not in STT)
4234eb28f7197a2cbaf7a9be778d429a5fb9bb6172eJohan Meiring		   build a DIXII + RFC894 */
42400b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
42533ce0ca6e22e726f64ed86821da1677a00fb0e06Richard Kennedy		/* Test for an overlength frame */
4264eb28f7197a2cbaf7a9be778d429a5fb9bb6172eJohan Meiring		if ((payload_length - sizeof(struct wlan_llc) -
4274eb28f7197a2cbaf7a9be778d429a5fb9bb6172eJohan Meiring			sizeof(struct wlan_snap))
4284eb28f7197a2cbaf7a9be778d429a5fb9bb6172eJohan Meiring			> netdev->mtu) {
42933ce0ca6e22e726f64ed86821da1677a00fb0e06Richard Kennedy			/* A bogus length ethfrm has been sent. */
43033ce0ca6e22e726f64ed86821da1677a00fb0e06Richard Kennedy			/* Is someone trying an oflow attack? */
431edbd606c4671fcd439164c8d63e896044d706156Moritz Muehlenhoff			printk(KERN_ERR "DIXII frame too large (%ld > %d)\n",
4324eb28f7197a2cbaf7a9be778d429a5fb9bb6172eJohan Meiring			       (long int)(payload_length -
4334eb28f7197a2cbaf7a9be778d429a5fb9bb6172eJohan Meiring					sizeof(struct wlan_llc) -
4344eb28f7197a2cbaf7a9be778d429a5fb9bb6172eJohan Meiring					sizeof(struct wlan_snap)), netdev->mtu);
43533ce0ca6e22e726f64ed86821da1677a00fb0e06Richard Kennedy			return 1;
43633ce0ca6e22e726f64ed86821da1677a00fb0e06Richard Kennedy		}
43733ce0ca6e22e726f64ed86821da1677a00fb0e06Richard Kennedy
43800b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		/* chop 802.11 header from skb. */
43900b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		skb_pull(skb, payload_offset);
44000b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
44100b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		/* chop llc header from skb. */
44251e4896adad00a066fad65649405c1c9fa108157Edgardo Hames		skb_pull(skb, sizeof(struct wlan_llc));
44300b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
44400b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		/* chop snap header from skb. */
44551e4896adad00a066fad65649405c1c9fa108157Edgardo Hames		skb_pull(skb, sizeof(struct wlan_snap));
44600b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
44700b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		/* create 802.3 header at beginning of skb. */
44851e4896adad00a066fad65649405c1c9fa108157Edgardo Hames		e_hdr = (struct wlan_ethhdr *) skb_push(skb, WLAN_ETHHDR_LEN);
44900b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		e_hdr->type = e_snap->type;
45000b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		memcpy(e_hdr->daddr, daddr, WLAN_ETHADDR_LEN);
45100b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		memcpy(e_hdr->saddr, saddr, WLAN_ETHADDR_LEN);
45200b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
45300b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		/* chop off the 802.11 CRC */
45400b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		skb_trim(skb, skb->len - WLAN_CRC_LEN);
45500b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	} else {
456a7cf7bae3297f16bb4a2f00310377fec06d0ecd6Moritz Muehlenhoff		pr_debug("NON-ENCAP len: %d\n", payload_length);
45700b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		/* any NON-ENCAP */
45800b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		/* it's a generic 80211+LLC or IPX 'Raw 802.3' */
45900b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		/*  build an 802.3 frame */
46000b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		/* allocate space and setup hostbuf */
46100b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
46233ce0ca6e22e726f64ed86821da1677a00fb0e06Richard Kennedy		/* Test for an overlength frame */
46382eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff		if (payload_length > netdev->mtu) {
46433ce0ca6e22e726f64ed86821da1677a00fb0e06Richard Kennedy			/* A bogus length ethfrm has been sent. */
46533ce0ca6e22e726f64ed86821da1677a00fb0e06Richard Kennedy			/* Is someone trying an oflow attack? */
466edbd606c4671fcd439164c8d63e896044d706156Moritz Muehlenhoff			printk(KERN_ERR "OTHER frame too large (%d > %d)\n",
46782eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff			       payload_length, netdev->mtu);
46833ce0ca6e22e726f64ed86821da1677a00fb0e06Richard Kennedy			return 1;
46933ce0ca6e22e726f64ed86821da1677a00fb0e06Richard Kennedy		}
47033ce0ca6e22e726f64ed86821da1677a00fb0e06Richard Kennedy
47100b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		/* Chop off the 802.11 header. */
47200b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		skb_pull(skb, payload_offset);
47300b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
47400b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		/* create 802.3 header at beginning of skb. */
47551e4896adad00a066fad65649405c1c9fa108157Edgardo Hames		e_hdr = (struct wlan_ethhdr *) skb_push(skb, WLAN_ETHHDR_LEN);
47600b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		memcpy(e_hdr->daddr, daddr, WLAN_ETHADDR_LEN);
47700b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		memcpy(e_hdr->saddr, saddr, WLAN_ETHADDR_LEN);
47800b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		e_hdr->type = htons(payload_length);
47900b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
48000b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		/* chop off the 802.11 CRC */
48100b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		skb_trim(skb, skb->len - WLAN_CRC_LEN);
48200b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
48300b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	}
48400b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
48582eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	/*
48682eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	 * Note that eth_type_trans() expects an skb w/ skb->data pointing
48782eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	 * at the MAC header, it then sets the following skb members:
48882eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	 * skb->mac_header,
48982eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	 * skb->data, and
49082eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	 * skb->pkt_type.
49182eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	 * It then _returns_ the value that _we're_ supposed to stuff in
49282eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	 * skb->protocol.  This is nuts.
49382eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	 */
49400b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	skb->protocol = eth_type_trans(skb, netdev);
49500b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
49682eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	/* jkriegl: process signal and noise as set in hfa384x_int_rx() */
49700b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	/* jkriegl: only process signal/noise if requested by iwspy */
49882eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	if (wlandev->spy_number)
49982eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff		orinoco_spy_gather(wlandev, eth_hdr(skb)->h_source,
50082eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff				   P80211SKB_RXMETA(skb));
50100b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
50200b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	/* Free the metadata */
50300b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	p80211skb_rxmeta_detach(skb);
50400b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
50500b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	return 0;
50600b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman}
50700b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
50800b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman/*----------------------------------------------------------------
50900b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* p80211_stt_findproto
51000b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*
51100b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* Searches the 802.1h Selective Translation Table for a given
51200b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* protocol.
51300b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*
51400b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* Arguments:
51500b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*	proto	protocl number (in host order) to search for.
51600b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*
51700b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* Returns:
51800b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*	1 - if the table is empty or a match is found.
51900b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*	0 - if the table is non-empty and a match is not found.
52000b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*
52100b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* Call context:
52200b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*	May be called in interrupt or non-interrupt context
52300b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman----------------------------------------------------------------*/
524aaad430378dd128ee015c8ed6e77809317c496a5Solomon Peachyint p80211_stt_findproto(u16 proto)
52500b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman{
52600b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	/* Always return found for now.  This is the behavior used by the */
52700b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	/*  Zoom Win95 driver when 802.1h mode is selected */
52800b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	/* TODO: If necessary, add an actual search we'll probably
52982eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	   need this to match the CMAC's way of doing things.
53082eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	   Need to do some testing to confirm.
53182eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	 */
53200b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
53382eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	if (proto == 0x80f3)	/* APPLETALK */
53400b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		return 1;
53500b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
53600b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	return 0;
53700b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman}
53800b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
53900b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman/*----------------------------------------------------------------
54000b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* p80211skb_rxmeta_detach
54100b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*
54200b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* Disconnects the frmmeta and rxmeta from an skb.
54300b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*
54400b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* Arguments:
54500b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*	wlandev		The wlandev this skb belongs to.
54600b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*	skb		The skb we're attaching to.
54700b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*
54800b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* Returns:
54900b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*	0 on success, non-zero otherwise
55000b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*
55100b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* Call context:
55200b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*	May be called in interrupt or non-interrupt context
55300b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman----------------------------------------------------------------*/
55482eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoffvoid p80211skb_rxmeta_detach(struct sk_buff *skb)
55500b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman{
55651e4896adad00a066fad65649405c1c9fa108157Edgardo Hames	struct p80211_rxmeta *rxmeta;
55751e4896adad00a066fad65649405c1c9fa108157Edgardo Hames	struct p80211_frmmeta *frmmeta;
55800b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
55900b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	/* Sanity checks */
56082eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	if (skb == NULL) {	/* bad skb */
561a7cf7bae3297f16bb4a2f00310377fec06d0ecd6Moritz Muehlenhoff		pr_debug("Called w/ null skb.\n");
56200b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		goto exit;
56300b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	}
56400b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	frmmeta = P80211SKB_FRMMETA(skb);
56582eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	if (frmmeta == NULL) {	/* no magic */
566a7cf7bae3297f16bb4a2f00310377fec06d0ecd6Moritz Muehlenhoff		pr_debug("Called w/ bad frmmeta magic.\n");
56700b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		goto exit;
56800b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	}
56900b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	rxmeta = frmmeta->rx;
57082eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	if (rxmeta == NULL) {	/* bad meta ptr */
571a7cf7bae3297f16bb4a2f00310377fec06d0ecd6Moritz Muehlenhoff		pr_debug("Called w/ bad rxmeta ptr.\n");
57200b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		goto exit;
57300b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	}
57400b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
57500b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	/* Free rxmeta */
57600b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	kfree(rxmeta);
57700b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
57800b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	/* Clear skb->cb */
57900b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	memset(skb->cb, 0, sizeof(skb->cb));
58000b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartmanexit:
58100b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	return;
58200b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman}
58300b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
58400b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman/*----------------------------------------------------------------
58500b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* p80211skb_rxmeta_attach
58600b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*
58700b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* Allocates a p80211rxmeta structure, initializes it, and attaches
58800b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* it to an skb.
58900b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*
59000b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* Arguments:
59100b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*	wlandev		The wlandev this skb belongs to.
59200b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*	skb		The skb we're attaching to.
59300b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*
59400b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* Returns:
59500b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*	0 on success, non-zero otherwise
59600b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*
59700b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* Call context:
59800b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*	May be called in interrupt or non-interrupt context
59900b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman----------------------------------------------------------------*/
60082eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoffint p80211skb_rxmeta_attach(struct wlandevice *wlandev, struct sk_buff *skb)
60100b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman{
60282eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	int result = 0;
60351e4896adad00a066fad65649405c1c9fa108157Edgardo Hames	struct p80211_rxmeta *rxmeta;
60451e4896adad00a066fad65649405c1c9fa108157Edgardo Hames	struct p80211_frmmeta *frmmeta;
60500b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
60600b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	/* If these already have metadata, we error out! */
60700b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	if (P80211SKB_RXMETA(skb) != NULL) {
608edbd606c4671fcd439164c8d63e896044d706156Moritz Muehlenhoff		printk(KERN_ERR "%s: RXmeta already attached!\n",
60982eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff		       wlandev->name);
61000b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		result = 0;
61100b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		goto exit;
61200b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	}
61300b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
61400b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	/* Allocate the rxmeta */
61551e4896adad00a066fad65649405c1c9fa108157Edgardo Hames	rxmeta = kzalloc(sizeof(struct p80211_rxmeta), GFP_ATOMIC);
61600b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
61782eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	if (rxmeta == NULL) {
618edbd606c4671fcd439164c8d63e896044d706156Moritz Muehlenhoff		printk(KERN_ERR "%s: Failed to allocate rxmeta.\n",
61982eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff		       wlandev->name);
62000b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		result = 1;
62100b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		goto exit;
62200b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	}
62300b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
62400b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	/* Initialize the rxmeta */
62500b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	rxmeta->wlandev = wlandev;
62600b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	rxmeta->hosttime = jiffies;
62700b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
62800b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	/* Overlay a frmmeta_t onto skb->cb */
62951e4896adad00a066fad65649405c1c9fa108157Edgardo Hames	memset(skb->cb, 0, sizeof(struct p80211_frmmeta));
63051e4896adad00a066fad65649405c1c9fa108157Edgardo Hames	frmmeta = (struct p80211_frmmeta *) (skb->cb);
63100b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	frmmeta->magic = P80211_FRMMETA_MAGIC;
63200b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	frmmeta->rx = rxmeta;
63300b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartmanexit:
63400b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	return result;
63500b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman}
63600b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman
63700b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman/*----------------------------------------------------------------
63800b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* p80211skb_free
63900b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*
64000b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* Frees an entire p80211skb by checking and freeing the meta struct
64100b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* and then freeing the skb.
64200b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*
64300b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* Arguments:
64400b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*	wlandev		The wlandev this skb belongs to.
64500b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*	skb		The skb we're attaching to.
64600b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*
64700b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* Returns:
64800b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*	0 on success, non-zero otherwise
64900b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*
65000b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman* Call context:
65100b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman*	May be called in interrupt or non-interrupt context
65200b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman----------------------------------------------------------------*/
65382eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoffvoid p80211skb_free(struct wlandevice *wlandev, struct sk_buff *skb)
65400b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman{
65551e4896adad00a066fad65649405c1c9fa108157Edgardo Hames	struct p80211_frmmeta *meta;
6568a251b55ef34c2a03e8ddf6d17bb125b92bb4a54Moritz Muehlenhoff
65700b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	meta = P80211SKB_FRMMETA(skb);
65882eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	if (meta && meta->rx)
65900b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman		p80211skb_rxmeta_detach(skb);
66082eaca7d9a2ba1f619bf6eebb677add20235c1aaMoritz Muehlenhoff	else
661edbd606c4671fcd439164c8d63e896044d706156Moritz Muehlenhoff		printk(KERN_ERR "Freeing an skb (%p) w/ no frmmeta.\n", skb);
66200b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	dev_kfree_skb(skb);
66300b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman	return;
66400b3ed1685089ff52169a715de11106ed37df087Greg Kroah-Hartman}
665