📄 ieee80211_tx.c
字号:
/****************************************************************************** Copyright(c) 2003 - 2005 Intel Corporation. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. The full GNU General Public License is included in this distribution in the file called LICENSE. Contact Information: James P. Ketrenos <ipw2100-admin@linux.intel.com> Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497******************************************************************************/#include <linux/compiler.h>#include <linux/config.h>#include <linux/errno.h>#include <linux/if_arp.h>#include <linux/in6.h>#include <linux/in.h>#include <linux/ip.h>#include <linux/kernel.h>#include <linux/module.h>#include <linux/netdevice.h>#include <linux/proc_fs.h>#include <linux/skbuff.h>#include <linux/slab.h>#include <linux/tcp.h>#include <linux/types.h>#include <linux/version.h>#include <linux/wireless.h>#include <linux/etherdevice.h>#include <asm/uaccess.h>#include <net/ieee80211.h>/*802.11 Data Frame ,-------------------------------------------------------------------.Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 | |------|------|---------|---------|---------|------|---------|------|Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | Frame | fcs | | | tion | (BSSID) | | | ence | data | | `--------------------------------------------------| |------'Total: 28 non-data bytes `----.----' | .- 'Frame data' expands to <---------------------------' | V ,---------------------------------------------------.Bytes | 1 | 1 | 1 | 3 | 2 | 0-2304 | |------|------|---------|----------|------|---------|Desc. | SNAP | SNAP | Control |Eth Tunnel| Type | IP | | DSAP | SSAP | | | | Packet | | 0xAA | 0xAA |0x03 (UI)|0x00-00-F8| | | `-----------------------------------------| |Total: 8 non-data bytes `----.----' | .- 'IP Packet' expands, if WEP enabled, to <--' | V ,-----------------------.Bytes | 4 | 0-2296 | 4 | |-----|-----------|-----|Desc. | IV | Encrypted | ICV | | | IP Packet | | `-----------------------'Total: 8 non-data bytes802.3 Ethernet Data Frame ,-----------------------------------------.Bytes | 6 | 6 | 2 | Variable | 4 | |-------|-------|------|-----------|------|Desc. | Dest. | Source| Type | IP Packet | fcs | | MAC | MAC | | | | `-----------------------------------------'Total: 18 non-data bytesIn the event that fragmentation is required, the incoming payload is split intoN parts of size ieee->fts. The first fragment contains the SNAP header and theremaining packets are just data.If encryption is enabled, each fragment payload size is reduced by enough spaceto add the prefix and postfix (IV and ICV totalling 8 bytes in the case of WEP)So if you have 1500 bytes of payload with ieee->fts set to 500 withoutencryption it will take 3 frames. With WEP it will take 4 frames as thepayload of each frame is reduced to 492 bytes.* SKB visualization** ,- skb->data* |* | ETHERNET HEADER ,-<-- PAYLOAD* | | 14 bytes from skb->data* | 2 bytes for Type --> ,T. | (sizeof ethhdr)* | | | |* |,-Dest.--. ,--Src.---. | | |* | 6 bytes| | 6 bytes | | | |* v | | | | | |* 0 | v 1 | v | v 2* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5* ^ | ^ | ^ |* | | | | | |* | | | | `T' <---- 2 bytes for Type* | | | |* | | '---SNAP--' <-------- 6 bytes for SNAP* | |* `-IV--' <-------------------- 4 bytes for IV (WEP)** SNAP HEADER**/static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 };static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 };static inline int ieee80211_copy_snap(u8 * data, u16 h_proto){ struct ieee80211_snap_hdr *snap; u8 *oui; snap = (struct ieee80211_snap_hdr *)data; snap->dsap = 0xaa; snap->ssap = 0xaa; snap->ctrl = 0x03; if (h_proto == 0x8137 || h_proto == 0x80f3) oui = P802_1H_OUI; else oui = RFC1042_OUI; snap->oui[0] = oui[0]; snap->oui[1] = oui[1]; snap->oui[2] = oui[2]; *(u16 *) (data + SNAP_SIZE) = htons(h_proto); return SNAP_SIZE + sizeof(u16);}static inline int ieee80211_encrypt_fragment(struct ieee80211_device *ieee, struct sk_buff *frag, int hdr_len){ struct ieee80211_crypt_data *crypt = ieee->crypt[ieee->tx_keyidx]; int res; if (crypt == NULL) return -1; /* To encrypt, frame format is: * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) */ atomic_inc(&crypt->refcnt); res = 0; if (crypt->ops && crypt->ops->encrypt_mpdu) res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv); atomic_dec(&crypt->refcnt); if (res < 0) { printk(KERN_INFO "%s: Encryption failed: len=%d.\n", ieee->dev->name, frag->len); ieee->ieee_stats.tx_discards++; return -1; } return 0;}void ieee80211_txb_free(struct ieee80211_txb *txb){ int i; if (unlikely(!txb)) return; for (i = 0; i < txb->nr_frags; i++) if (txb->fragments[i]) dev_kfree_skb_any(txb->fragments[i]); kfree(txb);}static struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size, unsigned __nocast gfp_mask){ struct ieee80211_txb *txb; int i; txb = kmalloc(sizeof(struct ieee80211_txb) + (sizeof(u8 *) * nr_frags), gfp_mask); if (!txb) return NULL; memset(txb, 0, sizeof(struct ieee80211_txb)); txb->nr_frags = nr_frags; txb->frag_size = txb_size; for (i = 0; i < nr_frags; i++) { txb->fragments[i] = dev_alloc_skb(txb_size); if (unlikely(!txb->fragments[i])) { i--; break; } } if (unlikely(i != nr_frags)) { while (i >= 0) dev_kfree_skb_any(txb->fragments[i--]); kfree(txb); return NULL; } return txb;}/* Incoming skb is converted to a txb which consists of * a block of 802.11 fragment packets (stored as skbs) */int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev){ struct ieee80211_device *ieee = netdev_priv(dev); struct ieee80211_txb *txb = NULL; struct ieee80211_hdr_3addr *frag_hdr; int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size, rts_required; unsigned long flags; struct net_device_stats *stats = &ieee->stats; int ether_type, encrypt, host_encrypt, host_encrypt_msdu, host_build_iv; int bytes, fc, hdr_len; struct sk_buff *skb_frag; struct ieee80211_hdr_3addr header = { /* Ensure zero initialized */ .duration_id = 0, .seq_ctl = 0 }; u8 dest[ETH_ALEN], src[ETH_ALEN]; struct ieee80211_crypt_data *crypt; int priority = skb->priority; int snapped = 0; if (ieee->is_queue_full && (*ieee->is_queue_full) (dev, priority)) return NETDEV_TX_BUSY; spin_lock_irqsave(&ieee->lock, flags); /* If there is no driver handler to take the TXB, dont' bother * creating it... */ if (!ieee->hard_start_xmit) { printk(KERN_WARNING "%s: No xmit handler.\n", ieee->dev->name); goto success; } if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) { printk(KERN_WARNING "%s: skb too small (%d).\n", ieee->dev->name, skb->len); goto success; } ether_type = ntohs(((struct ethhdr *)skb->data)->h_proto); crypt = ieee->crypt[ieee->tx_keyidx]; encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) && ieee->sec.encrypt; host_encrypt = ieee->host_encrypt && encrypt && crypt; host_encrypt_msdu = ieee->host_encrypt_msdu && encrypt && crypt; host_build_iv = ieee->host_build_iv && encrypt && crypt; if (!encrypt && ieee->ieee802_1x && ieee->drop_unencrypted && ether_type != ETH_P_PAE) { stats->tx_dropped++; goto success; } /* Save source and destination addresses */ memcpy(dest, skb->data, ETH_ALEN); memcpy(src, skb->data + ETH_ALEN, ETH_ALEN); /* Advance the SKB to the start of the payload */ skb_pull(skb, sizeof(struct ethhdr)); /* Determine total amount of storage required for TXB packets */ bytes = skb->len + SNAP_SIZE + sizeof(u16); if (host_encrypt)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -