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