brintos

brintos / linux-shallow public Read only

0
0
Text · 14.2 KiB · e22a673 Raw
519 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/******************************************************************************3 4  Copyright(c) 2003 - 2005 Intel Corporation. All rights reserved.5 6 7  Contact Information:8  Intel Linux Wireless <ilw@linux.intel.com>9  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-649710 11******************************************************************************/12#include <linux/compiler.h>13#include <linux/errno.h>14#include <linux/if_arp.h>15#include <linux/in6.h>16#include <linux/in.h>17#include <linux/ip.h>18#include <linux/kernel.h>19#include <linux/module.h>20#include <linux/netdevice.h>21#include <linux/proc_fs.h>22#include <linux/skbuff.h>23#include <linux/slab.h>24#include <linux/tcp.h>25#include <linux/types.h>26#include <linux/wireless.h>27#include <linux/etherdevice.h>28#include <linux/uaccess.h>29 30#include "libipw.h"31 32/*33 34802.11 Data Frame35 36      ,-------------------------------------------------------------------.37Bytes |  2   |  2   |    6    |    6    |    6    |  2   | 0..2312 |   4  |38      |------|------|---------|---------|---------|------|---------|------|39Desc. | ctrl | dura |  DA/RA  |   TA    |    SA   | Sequ |  Frame  |  fcs |40      |      | tion | (BSSID) |         |         | ence |  data   |      |41      `--------------------------------------------------|         |------'42Total: 28 non-data bytes                                 `----.----'43							      |44       .- 'Frame data' expands, if WEP enabled, to <----------'45       |46       V47      ,-----------------------.48Bytes |  4  |   0-2296  |  4  |49      |-----|-----------|-----|50Desc. | IV  | Encrypted | ICV |51      |     | Packet    |     |52      `-----|           |-----'53	    `-----.-----'54		  |55       .- 'Encrypted Packet' expands to56       |57       V58      ,---------------------------------------------------.59Bytes |  1   |  1   |    1    |    3     |  2   |  0-2304 |60      |------|------|---------|----------|------|---------|61Desc. | SNAP | SNAP | Control |Eth Tunnel| Type | IP      |62      | DSAP | SSAP |         |          |      | Packet  |63      | 0xAA | 0xAA |0x03 (UI)|0x00-00-F8|      |         |64      `----------------------------------------------------65Total: 8 non-data bytes66 67802.3 Ethernet Data Frame68 69      ,-----------------------------------------.70Bytes |   6   |   6   |  2   |  Variable |   4  |71      |-------|-------|------|-----------|------|72Desc. | Dest. | Source| Type | IP Packet |  fcs |73      |  MAC  |  MAC  |      |           |      |74      `-----------------------------------------'75Total: 18 non-data bytes76 77In the event that fragmentation is required, the incoming payload is split into78N parts of size ieee->fts.  The first fragment contains the SNAP header and the79remaining packets are just data.80 81If encryption is enabled, each fragment payload size is reduced by enough space82to add the prefix and postfix (IV and ICV totalling 8 bytes in the case of WEP)83So if you have 1500 bytes of payload with ieee->fts set to 500 without84encryption it will take 3 frames.  With WEP it will take 4 frames as the85payload of each frame is reduced to 492 bytes.86 87* SKB visualization88*89*  ,- skb->data90* |91* |    ETHERNET HEADER        ,-<-- PAYLOAD92* |                           |     14 bytes from skb->data93* |  2 bytes for Type --> ,T. |     (sizeof ethhdr)94* |                       | | |95* |,-Dest.--. ,--Src.---. | | |96* |  6 bytes| | 6 bytes | | | |97* v         | |         | | | |98* 0         | v       1 | v | v           299* 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 5100*     ^     | ^         | ^ |101*     |     | |         | | |102*     |     | |         | `T' <---- 2 bytes for Type103*     |     | |         |104*     |     | '---SNAP--' <-------- 6 bytes for SNAP105*     |     |106*     `-IV--' <-------------------- 4 bytes for IV (WEP)107*108*      SNAP HEADER109*110*/111 112static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 };113static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 };114 115static int libipw_copy_snap(u8 * data, __be16 h_proto)116{117	struct libipw_snap_hdr *snap;118	u8 *oui;119 120	snap = (struct libipw_snap_hdr *)data;121	snap->dsap = 0xaa;122	snap->ssap = 0xaa;123	snap->ctrl = 0x03;124 125	if (h_proto == htons(ETH_P_AARP) || h_proto == htons(ETH_P_IPX))126		oui = P802_1H_OUI;127	else128		oui = RFC1042_OUI;129	snap->oui[0] = oui[0];130	snap->oui[1] = oui[1];131	snap->oui[2] = oui[2];132 133	memcpy(data + SNAP_SIZE, &h_proto, sizeof(u16));134 135	return SNAP_SIZE + sizeof(u16);136}137 138static int libipw_encrypt_fragment(struct libipw_device *ieee,139					     struct sk_buff *frag, int hdr_len)140{141	struct lib80211_crypt_data *crypt =142		ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx];143	int res;144 145	if (crypt == NULL)146		return -1;147 148	/* To encrypt, frame format is:149	 * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) */150	atomic_inc(&crypt->refcnt);151	res = 0;152	if (crypt->ops && crypt->ops->encrypt_mpdu)153		res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv);154 155	atomic_dec(&crypt->refcnt);156	if (res < 0) {157		printk(KERN_INFO "%s: Encryption failed: len=%d.\n",158		       ieee->dev->name, frag->len);159		ieee->ieee_stats.tx_discards++;160		return -1;161	}162 163	return 0;164}165 166void libipw_txb_free(struct libipw_txb *txb)167{168	int i;169	if (unlikely(!txb))170		return;171	for (i = 0; i < txb->nr_frags; i++)172		if (txb->fragments[i])173			dev_kfree_skb_any(txb->fragments[i]);174	kfree(txb);175}176 177static struct libipw_txb *libipw_alloc_txb(int nr_frags, int txb_size,178						 int headroom, gfp_t gfp_mask)179{180	struct libipw_txb *txb;181	int i;182 183	txb = kzalloc(struct_size(txb, fragments, nr_frags), gfp_mask);184	if (!txb)185		return NULL;186 187	txb->nr_frags = nr_frags;188	txb->frag_size = txb_size;189 190	for (i = 0; i < nr_frags; i++) {191		txb->fragments[i] = __dev_alloc_skb(txb_size + headroom,192						    gfp_mask);193		if (unlikely(!txb->fragments[i])) {194			i--;195			break;196		}197		skb_reserve(txb->fragments[i], headroom);198	}199	if (unlikely(i != nr_frags)) {200		while (i >= 0)201			dev_kfree_skb_any(txb->fragments[i--]);202		kfree(txb);203		return NULL;204	}205	return txb;206}207 208static int libipw_classify(struct sk_buff *skb)209{210	struct ethhdr *eth;211	struct iphdr *ip;212 213	eth = (struct ethhdr *)skb->data;214	if (eth->h_proto != htons(ETH_P_IP))215		return 0;216 217	ip = ip_hdr(skb);218	switch (ip->tos & 0xfc) {219	case 0x20:220		return 2;221	case 0x40:222		return 1;223	case 0x60:224		return 3;225	case 0x80:226		return 4;227	case 0xa0:228		return 5;229	case 0xc0:230		return 6;231	case 0xe0:232		return 7;233	default:234		return 0;235	}236}237 238/* Incoming skb is converted to a txb which consists of239 * a block of 802.11 fragment packets (stored as skbs) */240netdev_tx_t libipw_xmit(struct sk_buff *skb, struct net_device *dev)241{242	struct libipw_device *ieee = netdev_priv(dev);243	struct libipw_txb *txb = NULL;244	struct libipw_hdr_3addrqos *frag_hdr;245	int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size,246	    rts_required;247	unsigned long flags;248	int encrypt, host_encrypt, host_encrypt_msdu;249	__be16 ether_type;250	int bytes, fc, hdr_len;251	struct sk_buff *skb_frag;252	struct libipw_hdr_3addrqos header = {/* Ensure zero initialized */253		.duration_id = 0,254		.seq_ctl = 0,255		.qos_ctl = 0256	};257	u8 dest[ETH_ALEN], src[ETH_ALEN];258	struct lib80211_crypt_data *crypt;259	int priority = skb->priority;260	int snapped = 0;261 262	if (ieee->is_queue_full && (*ieee->is_queue_full) (dev, priority))263		return NETDEV_TX_BUSY;264 265	spin_lock_irqsave(&ieee->lock, flags);266 267	/* If there is no driver handler to take the TXB, dont' bother268	 * creating it... */269	if (!ieee->hard_start_xmit) {270		printk(KERN_WARNING "%s: No xmit handler.\n", ieee->dev->name);271		goto success;272	}273 274	if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) {275		printk(KERN_WARNING "%s: skb too small (%d).\n",276		       ieee->dev->name, skb->len);277		goto success;278	}279 280	ether_type = ((struct ethhdr *)skb->data)->h_proto;281 282	crypt = ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx];283 284	encrypt = !(ether_type == htons(ETH_P_PAE) && ieee->ieee802_1x) &&285	    ieee->sec.encrypt;286 287	host_encrypt = ieee->host_encrypt && encrypt && crypt;288	host_encrypt_msdu = ieee->host_encrypt_msdu && encrypt && crypt;289 290	if (!encrypt && ieee->ieee802_1x &&291	    ieee->drop_unencrypted && ether_type != htons(ETH_P_PAE)) {292		dev->stats.tx_dropped++;293		goto success;294	}295 296	/* Save source and destination addresses */297	skb_copy_from_linear_data(skb, dest, ETH_ALEN);298	skb_copy_from_linear_data_offset(skb, ETH_ALEN, src, ETH_ALEN);299 300	if (host_encrypt)301		fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA |302		    IEEE80211_FCTL_PROTECTED;303	else304		fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA;305 306	if (ieee->iw_mode == IW_MODE_INFRA) {307		fc |= IEEE80211_FCTL_TODS;308		/* To DS: Addr1 = BSSID, Addr2 = SA, Addr3 = DA */309		memcpy(header.addr1, ieee->bssid, ETH_ALEN);310		memcpy(header.addr2, src, ETH_ALEN);311		memcpy(header.addr3, dest, ETH_ALEN);312	} else if (ieee->iw_mode == IW_MODE_ADHOC) {313		/* not From/To DS: Addr1 = DA, Addr2 = SA, Addr3 = BSSID */314		memcpy(header.addr1, dest, ETH_ALEN);315		memcpy(header.addr2, src, ETH_ALEN);316		memcpy(header.addr3, ieee->bssid, ETH_ALEN);317	}318	hdr_len = LIBIPW_3ADDR_LEN;319 320	if (ieee->is_qos_active && ieee->is_qos_active(dev, skb)) {321		fc |= IEEE80211_STYPE_QOS_DATA;322		hdr_len += 2;323 324		skb->priority = libipw_classify(skb);325		header.qos_ctl |= cpu_to_le16(skb->priority & LIBIPW_QCTL_TID);326	}327	header.frame_ctl = cpu_to_le16(fc);328 329	/* Advance the SKB to the start of the payload */330	skb_pull(skb, sizeof(struct ethhdr));331 332	/* Determine total amount of storage required for TXB packets */333	bytes = skb->len + SNAP_SIZE + sizeof(u16);334 335	/* Encrypt msdu first on the whole data packet. */336	if ((host_encrypt || host_encrypt_msdu) &&337	    crypt && crypt->ops && crypt->ops->encrypt_msdu) {338		int res = 0;339		int len = bytes + hdr_len + crypt->ops->extra_msdu_prefix_len +340		    crypt->ops->extra_msdu_postfix_len;341		struct sk_buff *skb_new = dev_alloc_skb(len);342 343		if (unlikely(!skb_new))344			goto failed;345 346		skb_reserve(skb_new, crypt->ops->extra_msdu_prefix_len);347		skb_put_data(skb_new, &header, hdr_len);348		snapped = 1;349		libipw_copy_snap(skb_put(skb_new, SNAP_SIZE + sizeof(u16)),350				    ether_type);351		skb_copy_from_linear_data(skb, skb_put(skb_new, skb->len), skb->len);352		res = crypt->ops->encrypt_msdu(skb_new, hdr_len, crypt->priv);353		if (res < 0) {354			LIBIPW_ERROR("msdu encryption failed\n");355			dev_kfree_skb_any(skb_new);356			goto failed;357		}358		dev_kfree_skb_any(skb);359		skb = skb_new;360		bytes += crypt->ops->extra_msdu_prefix_len +361		    crypt->ops->extra_msdu_postfix_len;362		skb_pull(skb, hdr_len);363	}364 365	if (host_encrypt || ieee->host_open_frag) {366		/* Determine fragmentation size based on destination (multicast367		 * and broadcast are not fragmented) */368		if (is_multicast_ether_addr(dest) ||369		    is_broadcast_ether_addr(dest))370			frag_size = MAX_FRAG_THRESHOLD;371		else372			frag_size = ieee->fts;373 374		/* Determine amount of payload per fragment.  Regardless of if375		 * this stack is providing the full 802.11 header, one will376		 * eventually be affixed to this fragment -- so we must account377		 * for it when determining the amount of payload space. */378		bytes_per_frag = frag_size - hdr_len;379		if (ieee->config &380		    (CFG_LIBIPW_COMPUTE_FCS | CFG_LIBIPW_RESERVE_FCS))381			bytes_per_frag -= LIBIPW_FCS_LEN;382 383		/* Each fragment may need to have room for encryption384		 * pre/postfix */385		if (host_encrypt && crypt && crypt->ops)386			bytes_per_frag -= crypt->ops->extra_mpdu_prefix_len +387			    crypt->ops->extra_mpdu_postfix_len;388 389		/* Number of fragments is the total390		 * bytes_per_frag / payload_per_fragment */391		nr_frags = bytes / bytes_per_frag;392		bytes_last_frag = bytes % bytes_per_frag;393		if (bytes_last_frag)394			nr_frags++;395		else396			bytes_last_frag = bytes_per_frag;397	} else {398		nr_frags = 1;399		bytes_per_frag = bytes_last_frag = bytes;400		frag_size = bytes + hdr_len;401	}402 403	rts_required = (frag_size > ieee->rts404			&& ieee->config & CFG_LIBIPW_RTS);405	if (rts_required)406		nr_frags++;407 408	/* When we allocate the TXB we allocate enough space for the reserve409	 * and full fragment bytes (bytes_per_frag doesn't include prefix,410	 * postfix, header, FCS, etc.) */411	txb = libipw_alloc_txb(nr_frags, frag_size,412				  ieee->tx_headroom, GFP_ATOMIC);413	if (unlikely(!txb)) {414		printk(KERN_WARNING "%s: Could not allocate TXB\n",415		       ieee->dev->name);416		goto failed;417	}418	txb->encrypted = encrypt;419	if (host_encrypt)420		txb->payload_size = frag_size * (nr_frags - 1) +421		    bytes_last_frag;422	else423		txb->payload_size = bytes;424 425	if (rts_required) {426		skb_frag = txb->fragments[0];427		frag_hdr = skb_put(skb_frag, hdr_len);428 429		/*430		 * Set header frame_ctl to the RTS.431		 */432		header.frame_ctl =433		    cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS);434		memcpy(frag_hdr, &header, hdr_len);435 436		/*437		 * Restore header frame_ctl to the original data setting.438		 */439		header.frame_ctl = cpu_to_le16(fc);440 441		if (ieee->config &442		    (CFG_LIBIPW_COMPUTE_FCS | CFG_LIBIPW_RESERVE_FCS))443			skb_put(skb_frag, 4);444 445		txb->rts_included = 1;446		i = 1;447	} else448		i = 0;449 450	for (; i < nr_frags; i++) {451		skb_frag = txb->fragments[i];452 453		if (host_encrypt)454			skb_reserve(skb_frag,455				    crypt->ops->extra_mpdu_prefix_len);456 457		frag_hdr = skb_put_data(skb_frag, &header, hdr_len);458 459		/* If this is not the last fragment, then add the MOREFRAGS460		 * bit to the frame control */461		if (i != nr_frags - 1) {462			frag_hdr->frame_ctl =463			    cpu_to_le16(fc | IEEE80211_FCTL_MOREFRAGS);464			bytes = bytes_per_frag;465		} else {466			/* The last fragment takes the remaining length */467			bytes = bytes_last_frag;468		}469 470		if (i == 0 && !snapped) {471			libipw_copy_snap(skb_put472					    (skb_frag, SNAP_SIZE + sizeof(u16)),473					    ether_type);474			bytes -= SNAP_SIZE + sizeof(u16);475		}476 477		skb_copy_from_linear_data(skb, skb_put(skb_frag, bytes), bytes);478 479		/* Advance the SKB... */480		skb_pull(skb, bytes);481 482		/* Encryption routine will move the header forward in order483		 * to insert the IV between the header and the payload */484		if (host_encrypt)485			libipw_encrypt_fragment(ieee, skb_frag, hdr_len);486 487		if (ieee->config &488		    (CFG_LIBIPW_COMPUTE_FCS | CFG_LIBIPW_RESERVE_FCS))489			skb_put(skb_frag, 4);490	}491 492      success:493	spin_unlock_irqrestore(&ieee->lock, flags);494 495	dev_kfree_skb_any(skb);496 497	if (txb) {498		netdev_tx_t ret = (*ieee->hard_start_xmit)(txb, dev, priority);499		if (ret == NETDEV_TX_OK) {500			dev->stats.tx_packets++;501			dev->stats.tx_bytes += txb->payload_size;502			return NETDEV_TX_OK;503		}504 505		libipw_txb_free(txb);506	}507 508	return NETDEV_TX_OK;509 510      failed:511	spin_unlock_irqrestore(&ieee->lock, flags);512	netif_stop_queue(dev);513	dev->stats.tx_errors++;514	return NETDEV_TX_BUSY;515}516EXPORT_SYMBOL(libipw_xmit);517 518EXPORT_SYMBOL(libipw_txb_free);519