コード例 #1
0
ファイル: tx.c プロジェクト: GAXUSXX/G935FGaXusKernel2
int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
{
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
	struct iwl_device_cmd *dev_cmd;
	struct iwl_tx_cmd *tx_cmd;
	u8 sta_id;

	if (WARN_ON_ONCE(info->flags & IEEE80211_TX_CTL_AMPDU))
		return -1;

	if (WARN_ON_ONCE(info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM &&
			 (!info->control.vif ||
			  info->hw_queue != info->control.vif->cab_queue)))
		return -1;

	/*
	 * IWL_MVM_OFFCHANNEL_QUEUE is used for ROC packets that can be used
	 * in 2 different types of vifs, P2P & STATION. P2P uses the offchannel
	 * queue. STATION (HS2.0) uses the auxiliary context of the FW,
	 * and hence needs to be sent on the aux queue
	 */
	if (IEEE80211_SKB_CB(skb)->hw_queue == IWL_MVM_OFFCHANNEL_QUEUE &&
	    info->control.vif->type == NL80211_IFTYPE_STATION)
		IEEE80211_SKB_CB(skb)->hw_queue = mvm->aux_queue;

	/*
	 * If the interface on which frame is sent is the P2P_DEVICE
	 * or an AP/GO interface use the broadcast station associated
	 * with it; otherwise use the AUX station.
	 */
	if (info->control.vif &&
	    (info->control.vif->type == NL80211_IFTYPE_P2P_DEVICE ||
	     info->control.vif->type == NL80211_IFTYPE_AP)) {
		struct iwl_mvm_vif *mvmvif =
			iwl_mvm_vif_from_mac80211(info->control.vif);
		sta_id = mvmvif->bcast_sta.sta_id;
	} else {
		sta_id = mvm->aux_sta.sta_id;
	}

	IWL_DEBUG_TX(mvm, "station Id %d, queue=%d\n", sta_id, info->hw_queue);

	dev_cmd = iwl_mvm_set_tx_params(mvm, skb, NULL, sta_id);
	if (!dev_cmd)
		return -1;

	/* From now on, we cannot access info->control */
	tx_cmd = (struct iwl_tx_cmd *)dev_cmd->payload;

	/* Copy MAC header from skb into command buffer */
	memcpy(tx_cmd->hdr, hdr, ieee80211_hdrlen(hdr->frame_control));

	if (iwl_trans_tx(mvm->trans, skb, dev_cmd, info->hw_queue)) {
		iwl_trans_free_tx_cmd(mvm->trans, dev_cmd);
		return -1;
	}

	return 0;
}
コード例 #2
0
ファイル: wep.c プロジェクト: UNwS/rtl8192su
/* Perform WEP decryption on given skb. Buffer includes whole WEP part of
 * the frame: IV (4 bytes), encrypted payload (including SNAP header),
 * ICV (4 bytes). skb->len includes ICV.
 *
 * Returns 0 if frame was decrypted successfully and ICV was correct and -1 on
 * failure. If frame is OK, IV and ICV will be removed, i.e., decrypted payload
 * is moved to the beginning of the skb and skb length will be reduced.
 */
int ieee80211_wep_decrypt(struct crypto_cipher *tfm, struct sk_buff *skb,
			  const u8 *key, const u32 iv, int keylen,
			  int keyidx)
{
	u32 klen;
	u8 rc4key[3 + WLAN_KEY_LEN_WEP104];
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
	void *data;
	size_t len, offset;

	offset = ieee80211_hdrlen(hdr->frame_control);
	data = skb->data + offset;
	len = skb->len - offset;

	klen = 3 + keylen;

	/* Prepend 24-bit IV to RC4 key */
	rc4key[0] = iv >> 16;
	rc4key[1] = iv >> 8;
	rc4key[2] = iv;

	/* Copy rest of the WEP key (the secret part) */
	memcpy(rc4key + 3, key, keylen);

	return ieee80211_wep_decrypt_data(tfm, rc4key, klen,
					  skb->data + offset, len);
}
コード例 #3
0
ファイル: wep.c プロジェクト: UNwS/rtl8192su
/* Perform WEP encryption on given skb. 4 bytes of extra space (IV) in the
 * beginning of the buffer 4 bytes of extra space (ICV) in the end of the
 * buffer will be added. Both IV and ICV will be transmitted, so the
 * payload length increases with 8 bytes.
 *
 * WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data))
 */
void ieee80211_wep_encrypt(struct crypto_cipher *tfm, struct sk_buff *skb,
			   const u8 *key, const u32 iv, int keylen,
			   int keyidx)
{
	struct ieee80211_hdr *hdr = (void *)skb->data;
	void *data;
	size_t len, offset;
	u8 rc4key[3 + WLAN_KEY_LEN_WEP104];

	offset = ieee80211_hdrlen(hdr->frame_control) + IEEE80211_WEP_IV_LEN;
	len = skb->len - offset;
	data = skb->data + offset;

	/* Prepend 24-bit IV to RC4 key */
	rc4key[0] = iv >> 16;
	rc4key[1] = iv >> 8;
	rc4key[2] = iv;

	/* Copy rest of the WEP key (the secret part) */
	memcpy(rc4key + 3, key, keylen);

	/* Add room for ICV */
	skb_put(skb, IEEE80211_WEP_ICV_LEN);

	ieee80211_wep_encrypt_data(tfm, rc4key, keylen + 3, data, len);
}
コード例 #4
0
ファイル: aes_ccm.c プロジェクト: UNwS/rtl8192su
void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, struct sk_buff *skb,
			       const u64 pn, size_t mic_len)
{
	u8 aad[2 * AES_BLOCK_SIZE];
	u8 b_0[AES_BLOCK_SIZE];
	u8 *data, *mic;
	size_t data_len, hdr_len;
	struct ieee80211_hdr *hdr = (void *)skb->data;
	struct scatterlist sg[3];
	char aead_req_data[sizeof(struct aead_request) +
			   crypto_aead_reqsize(tfm)]
		__aligned(__alignof__(struct aead_request));
	struct aead_request *aead_req = (void *) aead_req_data;

	hdr_len = ieee80211_hdrlen(hdr->frame_control);
	data_len = skb->len - hdr_len - IEEE80211_CCMP_HDR_LEN;
	ccmp_special_blocks(hdr, hdr_len, pn, b_0, aad);

	memset(aead_req, 0, sizeof(aead_req_data));

	data = skb->data + hdr_len + IEEE80211_CCMP_HDR_LEN;
	mic = skb_put(skb, mic_len);
	sg_init_table(sg, 3);
	sg_set_buf(&sg[0], &aad[2], be16_to_cpup((__be16 *)aad));
	sg_set_buf(&sg[1], data, data_len);
	sg_set_buf(&sg[2], mic, mic_len);

	aead_request_set_tfm(aead_req, tfm);
	aead_request_set_crypt(aead_req, sg, sg, data_len, b_0);
	aead_request_set_ad(aead_req, sg[0].length);

	crypto_aead_encrypt(aead_req);
}
コード例 #5
0
ファイル: wpa.c プロジェクト: Andrew-Gazizov/linux-3.2.1-kpp
static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
{
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
	struct ieee80211_key *key = tx->key;
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
	int hdrlen, len, tail;
	u8 *pos;
	u8 pn[6];
	u64 pn64;
	u8 scratch[6 * AES_BLOCK_SIZE];

	if (info->control.hw_key &&
	    !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
		/*
		 * hwaccel has no need for preallocated room for CCMP
		 * header or MIC fields
		 */
		return 0;
	}

	hdrlen = ieee80211_hdrlen(hdr->frame_control);
	len = skb->len - hdrlen;

	if (info->control.hw_key)
		tail = 0;
	else
		tail = CCMP_MIC_LEN;

	if (WARN_ON(skb_tailroom(skb) < tail ||
		    skb_headroom(skb) < CCMP_HDR_LEN))
		return -1;

	pos = skb_push(skb, CCMP_HDR_LEN);
	memmove(pos, pos + CCMP_HDR_LEN, hdrlen);
	hdr = (struct ieee80211_hdr *) pos;
	pos += hdrlen;

	pn64 = atomic64_inc_return(&key->u.ccmp.tx_pn);

	pn[5] = pn64;
	pn[4] = pn64 >> 8;
	pn[3] = pn64 >> 16;
	pn[2] = pn64 >> 24;
	pn[1] = pn64 >> 32;
	pn[0] = pn64 >> 40;

	ccmp_pn2hdr(pos, pn, key->conf.keyidx);

	/* hwaccel - with software CCMP header */
	if (info->control.hw_key)
		return 0;

	pos += CCMP_HDR_LEN;
	ccmp_special_blocks(skb, pn, scratch, 0);
	ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, scratch, pos, len,
				  pos, skb_put(skb, CCMP_MIC_LEN));

	return 0;
}
コード例 #6
0
ファイル: wpa.c プロジェクト: johnny/CobraDroidBeta
static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
{
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
	struct ieee80211_key *key = tx->key;
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
	int hdrlen, len, tail;
	u8 *pos, *pn;
	int i;

	if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) &&
	    !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
		/* hwaccel - with no need for preallocated room for CCMP
		 * header or MIC fields */
		info->control.hw_key = &tx->key->conf;
		return 0;
	}

	hdrlen = ieee80211_hdrlen(hdr->frame_control);
	len = skb->len - hdrlen;

	if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)
		tail = 0;
	else
		tail = CCMP_MIC_LEN;

	if (WARN_ON(skb_tailroom(skb) < tail ||
		    skb_headroom(skb) < CCMP_HDR_LEN))
		return -1;

	pos = skb_push(skb, CCMP_HDR_LEN);
	memmove(pos, pos + CCMP_HDR_LEN, hdrlen);
	hdr = (struct ieee80211_hdr *) pos;
	pos += hdrlen;

	/* PN = PN + 1 */
	pn = key->u.ccmp.tx_pn;

	for (i = CCMP_PN_LEN - 1; i >= 0; i--) {
		pn[i]++;
		if (pn[i])
			break;
	}

	ccmp_pn2hdr(pos, pn, key->conf.keyidx);

	if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) {
		/* hwaccel - with preallocated room for CCMP header */
		info->control.hw_key = &tx->key->conf;
		return 0;
	}

	pos += CCMP_HDR_LEN;
	ccmp_special_blocks(skb, pn, key->u.ccmp.tx_crypto_buf, 0);
	ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, key->u.ccmp.tx_crypto_buf, pos, len,
				  pos, skb_put(skb, CCMP_MIC_LEN));

	return 0;
}
コード例 #7
0
ファイル: wpa.c プロジェクト: ANFS/ANFS-kernel
ieee80211_rx_result
ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx)
{
	u8 *data, *key = NULL, key_offset;
	size_t data_len;
	unsigned int hdrlen;
	u8 mic[MICHAEL_MIC_LEN];
	struct sk_buff *skb = rx->skb;
	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
	int authenticator = 1, wpa_test = 0;

	/* No way to verify the MIC if the hardware stripped it */
	if (status->flag & RX_FLAG_MMIC_STRIPPED)
		return RX_CONTINUE;

	if (!rx->key || rx->key->conf.cipher != WLAN_CIPHER_SUITE_TKIP ||
	    !ieee80211_has_protected(hdr->frame_control) ||
	    !ieee80211_is_data_present(hdr->frame_control))
		return RX_CONTINUE;

	hdrlen = ieee80211_hdrlen(hdr->frame_control);
	if (skb->len < hdrlen + MICHAEL_MIC_LEN)
		return RX_DROP_UNUSABLE;

	data = skb->data + hdrlen;
	data_len = skb->len - hdrlen - MICHAEL_MIC_LEN;

#if 0
	authenticator = fc & IEEE80211_FCTL_TODS; /* FIX */
#else
	authenticator = 1;
#endif
	key_offset = authenticator ?
		NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY :
		NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY;
	key = &rx->key->conf.key[key_offset];
	michael_mic(key, hdr, data, data_len, mic);
	if (memcmp(mic, data + data_len, MICHAEL_MIC_LEN) != 0 || wpa_test) {
		if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
			return RX_DROP_UNUSABLE;

		mac80211_ev_michael_mic_failure(rx->sdata, rx->key->conf.keyidx,
						(void *) skb->data, NULL,
						GFP_ATOMIC);
		return RX_DROP_UNUSABLE;
	}

	/* remove Michael MIC from payload */
	skb_trim(skb, skb->len - MICHAEL_MIC_LEN);

	/* update IV in key information to be able to detect replays */
	rx->key->u.tkip.rx[rx->queue].iv32 = rx->tkip_iv32;
	rx->key->u.tkip.rx[rx->queue].iv16 = rx->tkip_iv16;

	return RX_CONTINUE;
}
コード例 #8
0
ファイル: wpa.c プロジェクト: johnny/CobraDroidBeta
ieee80211_tx_result
ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx)
{
	u8 *data, *key, *mic, key_offset;
	size_t data_len;
	unsigned int hdrlen;
	struct ieee80211_hdr *hdr;
	struct sk_buff *skb = tx->skb;
	int authenticator;
	int wpa_test = 0;
	int tail;

	hdr = (struct ieee80211_hdr *)skb->data;
	if (!tx->key || tx->key->conf.alg != ALG_TKIP || skb->len < 24 ||
	    !ieee80211_is_data_present(hdr->frame_control))
		return TX_CONTINUE;

	hdrlen = ieee80211_hdrlen(hdr->frame_control);
	if (skb->len < hdrlen)
		return TX_DROP;

	data = skb->data + hdrlen;
	data_len = skb->len - hdrlen;

	if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) &&
	    !(tx->flags & IEEE80211_TX_FRAGMENTED) &&
	    !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) &&
	    !wpa_test) {
		/* hwaccel - with no need for preallocated room for MMIC */
		return TX_CONTINUE;
	}

	tail = MICHAEL_MIC_LEN;
	if (!(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
		tail += TKIP_ICV_LEN;

	if (WARN_ON(skb_tailroom(skb) < tail ||
		    skb_headroom(skb) < TKIP_IV_LEN))
		return TX_DROP;

#if 0
	authenticator = fc & IEEE80211_FCTL_FROMDS; /* FIX */
#else
	authenticator = 1;
#endif
	key_offset = authenticator ?
		NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY :
		NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY;
	key = &tx->key->conf.key[key_offset];
	mic = skb_put(skb, MICHAEL_MIC_LEN);
	michael_mic(key, hdr, data, data_len, mic);

	return TX_CONTINUE;
}
コード例 #9
0
ファイル: wpa.c プロジェクト: Andrew-Gazizov/linux-3.2.1-kpp
ieee80211_rx_result
ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
{
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
	int hdrlen;
	struct ieee80211_key *key = rx->key;
	struct sk_buff *skb = rx->skb;
	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
	u8 pn[CCMP_PN_LEN];
	int data_len;
	int queue;

	hdrlen = ieee80211_hdrlen(hdr->frame_control);

	if (!ieee80211_is_data(hdr->frame_control) &&
	    !ieee80211_is_robust_mgmt_frame(hdr))
		return RX_CONTINUE;

	data_len = skb->len - hdrlen - CCMP_HDR_LEN - CCMP_MIC_LEN;
	if (!rx->sta || data_len < 0)
		return RX_DROP_UNUSABLE;

	ccmp_hdr2pn(pn, skb->data + hdrlen);

	queue = rx->security_idx;

	if (memcmp(pn, key->u.ccmp.rx_pn[queue], CCMP_PN_LEN) <= 0) {
		key->u.ccmp.replays++;
		return RX_DROP_UNUSABLE;
	}

	if (!(status->flag & RX_FLAG_DECRYPTED)) {
		u8 scratch[6 * AES_BLOCK_SIZE];
		/* hardware didn't decrypt/verify MIC */
		ccmp_special_blocks(skb, pn, scratch, 1);

		if (ieee80211_aes_ccm_decrypt(
			    key->u.ccmp.tfm, scratch,
			    skb->data + hdrlen + CCMP_HDR_LEN, data_len,
			    skb->data + skb->len - CCMP_MIC_LEN,
			    skb->data + hdrlen + CCMP_HDR_LEN))
			return RX_DROP_UNUSABLE;
	}

	memcpy(key->u.ccmp.rx_pn[queue], pn, CCMP_PN_LEN);

	/* Remove CCMP header and MIC */
	skb_trim(skb, skb->len - CCMP_MIC_LEN);
	memmove(skb->data + CCMP_HDR_LEN, skb->data, hdrlen);
	skb_pull(skb, CCMP_HDR_LEN);

	return RX_CONTINUE;
}
コード例 #10
0
ファイル: wpa.c プロジェクト: johnny/CobraDroidBeta
static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
{
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
	struct ieee80211_key *key = tx->key;
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
	unsigned int hdrlen;
	int len, tail;
	u8 *pos;

	if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) &&
	    !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
		/* hwaccel - with no need for preallocated room for IV/ICV */
		info->control.hw_key = &tx->key->conf;
		return 0;
	}

	hdrlen = ieee80211_hdrlen(hdr->frame_control);
	len = skb->len - hdrlen;

	if (tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)
		tail = 0;
	else
		tail = TKIP_ICV_LEN;

	if (WARN_ON(skb_tailroom(skb) < tail ||
		    skb_headroom(skb) < TKIP_IV_LEN))
		return -1;

	pos = skb_push(skb, TKIP_IV_LEN);
	memmove(pos, pos + TKIP_IV_LEN, hdrlen);
	pos += hdrlen;

	/* Increase IV for the frame */
	key->u.tkip.tx.iv16++;
	if (key->u.tkip.tx.iv16 == 0)
		key->u.tkip.tx.iv32++;

	if (tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) {
		/* hwaccel - with preallocated room for IV */
		ieee80211_tkip_add_iv(pos, key, key->u.tkip.tx.iv16);

		info->control.hw_key = &tx->key->conf;
		return 0;
	}

	/* Add room for ICV */
	skb_put(skb, TKIP_ICV_LEN);

	hdr = (struct ieee80211_hdr *) skb->data;
	ieee80211_tkip_encrypt_data(tx->local->wep_tx_tfm,
				    key, pos, len, hdr->addr2);
	return 0;
}
コード例 #11
0
ファイル: dma.c プロジェクト: EvolutionMod/ath10-lenovo
static unsigned int ieee80211_get_hdrlen_from_buf(const u8 *data, unsigned len)
{
	const struct ieee80211_hdr *hdr = (const struct ieee80211_hdr *)data;
	unsigned int hdrlen;

	if (unlikely(len < 10))
		return 0;
	hdrlen = ieee80211_hdrlen(hdr->frame_control);
	if (unlikely(hdrlen > len))
		return 0;
	return hdrlen;
}
コード例 #12
0
ファイル: wpa.c プロジェクト: ANFS/ANFS-kernel
ieee80211_tx_result
ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx)
{
	u8 *data, *key, *mic, key_offset;
	size_t data_len;
	unsigned int hdrlen;
	struct ieee80211_hdr *hdr;
	struct sk_buff *skb = tx->skb;
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
	int authenticator;
	int tail;

	hdr = (struct ieee80211_hdr *)skb->data;
	if (!tx->key || tx->key->conf.cipher != WLAN_CIPHER_SUITE_TKIP ||
	    skb->len < 24 || !ieee80211_is_data_present(hdr->frame_control))
		return TX_CONTINUE;

	hdrlen = ieee80211_hdrlen(hdr->frame_control);
	if (skb->len < hdrlen)
		return TX_DROP;

	data = skb->data + hdrlen;
	data_len = skb->len - hdrlen;

	if (info->control.hw_key &&
	    !(tx->flags & IEEE80211_TX_FRAGMENTED) &&
	    !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) {
		/* hwaccel - with no need for SW-generated MMIC */
		return TX_CONTINUE;
	}

	tail = MICHAEL_MIC_LEN;
	if (!info->control.hw_key)
		tail += TKIP_ICV_LEN;

	if (WARN_ON(skb_tailroom(skb) < tail ||
		    skb_headroom(skb) < TKIP_IV_LEN))
		return TX_DROP;

#if 0
	authenticator = fc & IEEE80211_FCTL_FROMDS; /* FIX */
#else
	authenticator = 1;
#endif
	key_offset = authenticator ?
		NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY :
		NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY;
	key = &tx->key->conf.key[key_offset];
	mic = skb_put(skb, MICHAEL_MIC_LEN);
	michael_mic(key, hdr, data, data_len, mic);

	return TX_CONTINUE;
}
コード例 #13
0
ファイル: wpa.c プロジェクト: Andrew-Gazizov/linux-3.2.1-kpp
ieee80211_tx_result
ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx)
{
	u8 *data, *key, *mic;
	size_t data_len;
	unsigned int hdrlen;
	struct ieee80211_hdr *hdr;
	struct sk_buff *skb = tx->skb;
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
	int tail;

	hdr = (struct ieee80211_hdr *)skb->data;
	if (!tx->key || tx->key->conf.cipher != WLAN_CIPHER_SUITE_TKIP ||
	    skb->len < 24 || !ieee80211_is_data_present(hdr->frame_control))
		return TX_CONTINUE;

	hdrlen = ieee80211_hdrlen(hdr->frame_control);
	if (skb->len < hdrlen)
		return TX_DROP;

	data = skb->data + hdrlen;
	data_len = skb->len - hdrlen;

	if (unlikely(info->flags & IEEE80211_TX_INTFL_TKIP_MIC_FAILURE)) {
		/* Need to use software crypto for the test */
		info->control.hw_key = NULL;
	}

	if (info->control.hw_key &&
	    (info->flags & IEEE80211_TX_CTL_DONTFRAG ||
	     tx->local->ops->set_frag_threshold) &&
	    !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) {
		/* hwaccel - with no need for SW-generated MMIC */
		return TX_CONTINUE;
	}

	tail = MICHAEL_MIC_LEN;
	if (!info->control.hw_key)
		tail += TKIP_ICV_LEN;

	if (WARN_ON(skb_tailroom(skb) < tail ||
		    skb_headroom(skb) < TKIP_IV_LEN))
		return TX_DROP;

	key = &tx->key->conf.key[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY];
	mic = skb_put(skb, MICHAEL_MIC_LEN);
	michael_mic(key, hdr, data, data_len, mic);
	if (unlikely(info->flags & IEEE80211_TX_INTFL_TKIP_MIC_FAILURE))
		mic[0]++;

	return TX_CONTINUE;
}
コード例 #14
0
ファイル: wpa.c プロジェクト: johnny/CobraDroidBeta
ieee80211_rx_result
ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
{
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
	int hdrlen;
	struct ieee80211_key *key = rx->key;
	struct sk_buff *skb = rx->skb;
	u8 pn[CCMP_PN_LEN];
	int data_len;

	hdrlen = ieee80211_hdrlen(hdr->frame_control);

	if (!ieee80211_is_data(hdr->frame_control))
		return RX_CONTINUE;

	data_len = skb->len - hdrlen - CCMP_HDR_LEN - CCMP_MIC_LEN;
	if (!rx->sta || data_len < 0)
		return RX_DROP_UNUSABLE;

	if ((rx->status->flag & RX_FLAG_DECRYPTED) &&
	    (rx->status->flag & RX_FLAG_IV_STRIPPED))
		return RX_CONTINUE;

	ccmp_hdr2pn(pn, skb->data + hdrlen);

	if (memcmp(pn, key->u.ccmp.rx_pn[rx->queue], CCMP_PN_LEN) <= 0) {
		key->u.ccmp.replays++;
		return RX_DROP_UNUSABLE;
	}

	if (!(rx->status->flag & RX_FLAG_DECRYPTED)) {
		/* hardware didn't decrypt/verify MIC */
		ccmp_special_blocks(skb, pn, key->u.ccmp.rx_crypto_buf, 1);

		if (ieee80211_aes_ccm_decrypt(
			    key->u.ccmp.tfm, key->u.ccmp.rx_crypto_buf,
			    skb->data + hdrlen + CCMP_HDR_LEN, data_len,
			    skb->data + skb->len - CCMP_MIC_LEN,
			    skb->data + hdrlen + CCMP_HDR_LEN))
			return RX_DROP_UNUSABLE;
	}

	memcpy(key->u.ccmp.rx_pn[rx->queue], pn, CCMP_PN_LEN);

	/* Remove CCMP header and MIC */
	skb_trim(skb, skb->len - CCMP_MIC_LEN);
	memmove(skb->data + CCMP_HDR_LEN, skb->data, hdrlen);
	skb_pull(skb, CCMP_HDR_LEN);

	return RX_CONTINUE;
}
コード例 #15
0
ファイル: rx.c プロジェクト: mdamt/linux
/*
 * iwl_mvm_pass_packet_to_mac80211 - builds the packet for mac80211
 *
 * Adds the rxb to a new skb and give it to mac80211
 */
static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm,
					    struct ieee80211_sta *sta,
					    struct napi_struct *napi,
					    struct sk_buff *skb,
					    struct ieee80211_hdr *hdr, u16 len,
					    u8 crypt_len,
					    struct iwl_rx_cmd_buffer *rxb)
{
	unsigned int hdrlen = ieee80211_hdrlen(hdr->frame_control);
	unsigned int fraglen;

	/*
	 * The 'hdrlen' (plus the 8 bytes for the SNAP and the crypt_len,
	 * but those are all multiples of 4 long) all goes away, but we
	 * want the *end* of it, which is going to be the start of the IP
	 * header, to be aligned when it gets pulled in.
	 * The beginning of the skb->data is aligned on at least a 4-byte
	 * boundary after allocation. Everything here is aligned at least
	 * on a 2-byte boundary so we can just take hdrlen & 3 and pad by
	 * the result.
	 */
	skb_reserve(skb, hdrlen & 3);

	/* If frame is small enough to fit in skb->head, pull it completely.
	 * If not, only pull ieee80211_hdr (including crypto if present, and
	 * an additional 8 bytes for SNAP/ethertype, see below) so that
	 * splice() or TCP coalesce are more efficient.
	 *
	 * Since, in addition, ieee80211_data_to_8023() always pull in at
	 * least 8 bytes (possibly more for mesh) we can do the same here
	 * to save the cost of doing it later. That still doesn't pull in
	 * the actual IP header since the typical case has a SNAP header.
	 * If the latter changes (there are efforts in the standards group
	 * to do so) we should revisit this and ieee80211_data_to_8023().
	 */
	hdrlen = (len <= skb_tailroom(skb)) ? len : hdrlen + crypt_len + 8;

	skb_put_data(skb, hdr, hdrlen);
	fraglen = len - hdrlen;

	if (fraglen) {
		int offset = (void *)hdr + hdrlen -
			     rxb_addr(rxb) + rxb_offset(rxb);

		skb_add_rx_frag(skb, 0, rxb_steal_page(rxb), offset,
				fraglen, rxb->truesize);
	}

	ieee80211_rx_napi(mvm->hw, sta, skb, napi);
}
コード例 #16
0
ファイル: tx.c プロジェクト: sztony/wink-hub-kernel-public
int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
{
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
	struct iwl_device_cmd *dev_cmd;
	struct iwl_tx_cmd *tx_cmd;
	u8 sta_id;

	if (WARN_ON_ONCE(info->flags & IEEE80211_TX_CTL_AMPDU))
		return -1;

	if (WARN_ON_ONCE(info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM &&
			 (!info->control.vif ||
			  info->hw_queue != info->control.vif->cab_queue)))
		return -1;

	/*
	 * If the interface on which frame is sent is the P2P_DEVICE
	 * or an AP/GO interface use the broadcast station associated
	 * with it; otherwise use the AUX station.
	 */
	if (info->control.vif &&
	    (info->control.vif->type == NL80211_IFTYPE_P2P_DEVICE ||
	     info->control.vif->type == NL80211_IFTYPE_AP)) {
		struct iwl_mvm_vif *mvmvif =
			iwl_mvm_vif_from_mac80211(info->control.vif);
		sta_id = mvmvif->bcast_sta.sta_id;
	} else {
		sta_id = mvm->aux_sta.sta_id;
	}

	IWL_DEBUG_TX(mvm, "station Id %d, queue=%d\n", sta_id, info->hw_queue);

	dev_cmd = iwl_mvm_set_tx_params(mvm, skb, NULL, sta_id);
	if (!dev_cmd)
		return -1;

	/* From now on, we cannot access info->control */
	tx_cmd = (struct iwl_tx_cmd *)dev_cmd->payload;

	/* Copy MAC header from skb into command buffer */
	memcpy(tx_cmd->hdr, hdr, ieee80211_hdrlen(hdr->frame_control));

	if (iwl_trans_tx(mvm->trans, skb, dev_cmd, info->hw_queue)) {
		iwl_trans_free_tx_cmd(mvm->trans, dev_cmd);
		return -1;
	}

	return 0;
}
コード例 #17
0
ファイル: wpa.c プロジェクト: Andrew-Gazizov/linux-3.2.1-kpp
static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
{
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
	struct ieee80211_key *key = tx->key;
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
	unsigned long flags;
	unsigned int hdrlen;
	int len, tail;
	u8 *pos;

	if (info->control.hw_key &&
	    !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
		/* hwaccel - with no need for software-generated IV */
		return 0;
	}

	hdrlen = ieee80211_hdrlen(hdr->frame_control);
	len = skb->len - hdrlen;

	if (info->control.hw_key)
		tail = 0;
	else
		tail = TKIP_ICV_LEN;

	if (WARN_ON(skb_tailroom(skb) < tail ||
		    skb_headroom(skb) < TKIP_IV_LEN))
		return -1;

	pos = skb_push(skb, TKIP_IV_LEN);
	memmove(pos, pos + TKIP_IV_LEN, hdrlen);
	pos += hdrlen;

	/* Increase IV for the frame */
	spin_lock_irqsave(&key->u.tkip.txlock, flags);
	key->u.tkip.tx.iv16++;
	if (key->u.tkip.tx.iv16 == 0)
		key->u.tkip.tx.iv32++;
	pos = ieee80211_tkip_add_iv(pos, key);
	spin_unlock_irqrestore(&key->u.tkip.txlock, flags);

	/* hwaccel - with software IV */
	if (info->control.hw_key)
		return 0;

	/* Add room for ICV */
	skb_put(skb, TKIP_ICV_LEN);

	return ieee80211_tkip_encrypt_data(tx->local->wep_tx_tfm,
					   key, skb, pos, len);
}
コード例 #18
0
ファイル: rxmq.c プロジェクト: 545191228/linux
/* iwl_mvm_create_skb Adds the rxb to a new skb */
static void iwl_mvm_create_skb(struct sk_buff *skb, struct ieee80211_hdr *hdr,
			       u16 len, u8 crypt_len,
			       struct iwl_rx_cmd_buffer *rxb)
{
	struct iwl_rx_packet *pkt = rxb_addr(rxb);
	struct iwl_rx_mpdu_desc *desc = (void *)pkt->data;
	unsigned int headlen, fraglen, pad_len = 0;
	unsigned int hdrlen = ieee80211_hdrlen(hdr->frame_control);

	if (desc->mac_flags2 & IWL_RX_MPDU_MFLG2_PAD)
		pad_len = 2;
	len -= pad_len;

	/* If frame is small enough to fit in skb->head, pull it completely.
	 * If not, only pull ieee80211_hdr (including crypto if present, and
	 * an additional 8 bytes for SNAP/ethertype, see below) so that
	 * splice() or TCP coalesce are more efficient.
	 *
	 * Since, in addition, ieee80211_data_to_8023() always pull in at
	 * least 8 bytes (possibly more for mesh) we can do the same here
	 * to save the cost of doing it later. That still doesn't pull in
	 * the actual IP header since the typical case has a SNAP header.
	 * If the latter changes (there are efforts in the standards group
	 * to do so) we should revisit this and ieee80211_data_to_8023().
	 */
	headlen = (len <= skb_tailroom(skb)) ? len :
					       hdrlen + crypt_len + 8;

	/* The firmware may align the packet to DWORD.
	 * The padding is inserted after the IV.
	 * After copying the header + IV skip the padding if
	 * present before copying packet data.
	 */
	hdrlen += crypt_len;
	memcpy(skb_put(skb, hdrlen), hdr, hdrlen);
	memcpy(skb_put(skb, headlen - hdrlen), (u8 *)hdr + hdrlen + pad_len,
	       headlen - hdrlen);

	fraglen = len - headlen;

	if (fraglen) {
		int offset = (void *)hdr + headlen + pad_len -
			     rxb_addr(rxb) + rxb_offset(rxb);

		skb_add_rx_frag(skb, 0, rxb_steal_page(rxb), offset,
				fraglen, rxb->truesize);
	}
}
コード例 #19
0
ファイル: wpa.c プロジェクト: johnny/CobraDroidBeta
ieee80211_rx_result
ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx)
{
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
	int hdrlen, res, hwaccel = 0, wpa_test = 0;
	struct ieee80211_key *key = rx->key;
	struct sk_buff *skb = rx->skb;

	hdrlen = ieee80211_hdrlen(hdr->frame_control);

	if (!ieee80211_is_data(hdr->frame_control))
		return RX_CONTINUE;

	if (!rx->sta || skb->len - hdrlen < 12)
		return RX_DROP_UNUSABLE;

	if (rx->status->flag & RX_FLAG_DECRYPTED) {
		if (rx->status->flag & RX_FLAG_IV_STRIPPED) {
			/*
			 * Hardware took care of all processing, including
			 * replay protection, and stripped the ICV/IV so
			 * we cannot do any checks here.
			 */
			return RX_CONTINUE;
		}

		/* let TKIP code verify IV, but skip decryption */
		hwaccel = 1;
	}

	res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_tfm,
					  key, skb->data + hdrlen,
					  skb->len - hdrlen, rx->sta->sta.addr,
					  hdr->addr1, hwaccel, rx->queue,
					  &rx->tkip_iv32,
					  &rx->tkip_iv16);
	if (res != TKIP_DECRYPT_OK || wpa_test)
		return RX_DROP_UNUSABLE;

	/* Trim ICV */
	skb_trim(skb, skb->len - TKIP_ICV_LEN);

	/* Remove IV */
	memmove(skb->data + TKIP_IV_LEN, skb->data, hdrlen);
	skb_pull(skb, TKIP_IV_LEN);

	return RX_CONTINUE;
}
コード例 #20
0
ファイル: wpa.c プロジェクト: 1yankeedt/D710BST_FL24_Kernel
ieee80211_rx_result
ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx)
{
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
	int hdrlen, res, hwaccel = 0;
	struct ieee80211_key *key = rx->key;
	struct sk_buff *skb = rx->skb;
	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
	int queue = rx->queue;

	/* otherwise, TKIP is vulnerable to TID 0 vs. non-QoS replays */
	if (rx->queue == NUM_RX_DATA_QUEUES - 1)
		queue = 0;

	hdrlen = ieee80211_hdrlen(hdr->frame_control);

	if (!ieee80211_is_data(hdr->frame_control))
		return RX_CONTINUE;

	if (!rx->sta || skb->len - hdrlen < 12)
		return RX_DROP_UNUSABLE;

	/*
	 * Let TKIP code verify IV, but skip decryption.
	 * In the case where hardware checks the IV as well,
	 * we don't even get here, see ieee80211_rx_h_decrypt()
	 */
	if (status->flag & RX_FLAG_DECRYPTED)
		hwaccel = 1;

	res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_tfm,
					  key, skb->data + hdrlen,
					  skb->len - hdrlen, rx->sta->sta.addr,
					  hdr->addr1, hwaccel, queue,
					  &rx->tkip_iv32,
					  &rx->tkip_iv16);
	if (res != TKIP_DECRYPT_OK)
		return RX_DROP_UNUSABLE;

	/* Trim ICV */
	skb_trim(skb, skb->len - TKIP_ICV_LEN);

	/* Remove IV */
	memmove(skb->data + TKIP_IV_LEN, skb->data, hdrlen);
	skb_pull(skb, TKIP_IV_LEN);

	return RX_CONTINUE;
}
コード例 #21
0
static void ath9k_htc_tx(struct ieee80211_hw *hw,
			 struct ieee80211_tx_control *control,
			 struct sk_buff *skb)
{
	struct ieee80211_hdr *hdr;
	struct ath9k_htc_priv *priv = hw->priv;
	struct ath_common *common = ath9k_hw_common(priv->ah);
	int padpos, padsize, ret, slot;

	hdr = (struct ieee80211_hdr *) skb->data;

	/* Add the padding after the header if this is not already done */
	padpos = ieee80211_hdrlen(hdr->frame_control);
	padsize = padpos & 3;
	if (padsize && skb->len > padpos) {
		if (skb_headroom(skb) < padsize) {
			ath_dbg(common, XMIT, "No room for padding\n");
			goto fail_tx;
		}
		skb_push(skb, padsize);
		memmove(skb->data, skb->data + padsize, padpos);
	}

	slot = ath9k_htc_tx_get_slot(priv);
	if (slot < 0) {
		ath_dbg(common, XMIT, "No free TX slot\n");
		goto fail_tx;
	}

	ret = ath9k_htc_tx_start(priv, control->sta, skb, slot, false);
	if (ret != 0) {
		ath_dbg(common, XMIT, "Tx failed\n");
		goto clear_slot;
	}

	ath9k_htc_check_stop_queues(priv);

	return;

clear_slot:
	ath9k_htc_tx_clear_slot(priv, slot);
fail_tx:
	dev_kfree_skb_any(skb);
}
コード例 #22
0
ファイル: common.c プロジェクト: 513855417/linux
void ath9k_cmn_rx_skb_postprocess(struct ath_common *common,
				  struct sk_buff *skb,
				  struct ath_rx_status *rx_stats,
				  struct ieee80211_rx_status *rxs,
				  bool decrypt_error)
{
	struct ath_hw *ah = common->ah;
	struct ieee80211_hdr *hdr;
	int hdrlen, padpos, padsize;
	u8 keyix;
	__le16 fc;

	/* see if any padding is done by the hw and remove it */
	hdr = (struct ieee80211_hdr *) skb->data;
	hdrlen = ieee80211_get_hdrlen_from_skb(skb);
	fc = hdr->frame_control;
	padpos = ieee80211_hdrlen(fc);

	/* The MAC header is padded to have 32-bit boundary if the
	 * packet payload is non-zero. The general calculation for
	 * padsize would take into account odd header lengths:
	 * padsize = (4 - padpos % 4) % 4; However, since only
	 * even-length headers are used, padding can only be 0 or 2
	 * bytes and we can optimize this a bit. In addition, we must
	 * not try to remove padding from short control frames that do
	 * not have payload. */
	padsize = padpos & 3;
	if (padsize && skb->len>=padpos+padsize+FCS_LEN) {
		memmove(skb->data + padsize, skb->data, padpos);
		skb_pull(skb, padsize);
	}

	keyix = rx_stats->rs_keyix;

	if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error &&
	    ieee80211_has_protected(fc)) {
		rxs->flag |= RX_FLAG_DECRYPTED;
	} else if (ieee80211_has_protected(fc)
		   && !decrypt_error && skb->len >= hdrlen + 4) {
		keyix = skb->data[hdrlen + 3] >> 6;

		if (test_bit(keyix, common->keymap))
			rxs->flag |= RX_FLAG_DECRYPTED;
	}
コード例 #23
0
ファイル: mwl_rx.c プロジェクト: Nihtilan/mwlwifi
static inline void mwl_rx_remove_dma_header(struct sk_buff *skb, u16 qos)
{
	struct mwl_dma_data *tr;
	int hdrlen;

	tr = (struct mwl_dma_data *)skb->data;
	hdrlen = ieee80211_hdrlen(tr->wh.frame_control);

	if (hdrlen != sizeof(tr->wh)) {
		if (ieee80211_is_data_qos(tr->wh.frame_control)) {
			memmove(tr->data - hdrlen, &tr->wh, hdrlen - 2);
			*((u16 *)(tr->data - 2)) = qos;
		} else {
			memmove(tr->data - hdrlen, &tr->wh, hdrlen);
		}
	}

	if (hdrlen != sizeof(*tr))
		skb_pull(skb, sizeof(*tr) - hdrlen);
}
コード例 #24
0
ファイル: tx.c プロジェクト: chinawrj/mwlwifi
static inline void mwl_tx_add_dma_header(struct mwl_priv *priv,
					 struct sk_buff *skb,
					 int head_pad,
					 int tail_pad)
{
	struct ieee80211_hdr *wh;
	int hdrlen;
	int reqd_hdrlen;
	struct mwl_dma_data *tr;

	/* Add a firmware DMA header; the firmware requires that we
	 * present a 2-byte payload length followed by a 4-address
	 * header (without QoS field), followed (optionally) by any
	 * WEP/ExtIV header (but only filled in for CCMP).
	 */
	wh = (struct ieee80211_hdr *)skb->data;

	hdrlen = ieee80211_hdrlen(wh->frame_control);

	reqd_hdrlen = sizeof(*tr) + head_pad;

	if (hdrlen != reqd_hdrlen)
		skb_push(skb, reqd_hdrlen - hdrlen);

	if (ieee80211_is_data_qos(wh->frame_control))
		hdrlen -= IEEE80211_QOS_CTL_LEN;

	tr = (struct mwl_dma_data *)skb->data;

	if (wh != &tr->wh)
		memmove(&tr->wh, wh, hdrlen);

	if (hdrlen != sizeof(tr->wh))
		memset(((void *)&tr->wh) + hdrlen, 0, sizeof(tr->wh) - hdrlen);

	/* Firmware length is the length of the fully formed "802.11
	 * payload".  That is, everything except for the 802.11 header.
	 * This includes all crypto material including the MIC.
	 */
	tr->fwlen = cpu_to_le16(skb->len - sizeof(*tr) + tail_pad);
}
コード例 #25
0
ファイル: tx-gen2.c プロジェクト: AlexShiLucky/linux
static
struct iwl_tfh_tfd *iwl_pcie_gen2_build_tfd(struct iwl_trans *trans,
					    struct iwl_txq *txq,
					    struct iwl_device_cmd *dev_cmd,
					    struct sk_buff *skb,
					    struct iwl_cmd_meta *out_meta)
{
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
	int idx = iwl_pcie_get_cmd_index(txq, txq->write_ptr);
	struct iwl_tfh_tfd *tfd = iwl_pcie_get_tfd(trans, txq, idx);
	int len, hdr_len;
	bool amsdu;

	/* There must be data left over for TB1 or this code must be changed */
	BUILD_BUG_ON(sizeof(struct iwl_tx_cmd_gen2) < IWL_FIRST_TB_SIZE);

	memset(tfd, 0, sizeof(*tfd));

	if (trans->cfg->device_family < IWL_DEVICE_FAMILY_22560)
		len = sizeof(struct iwl_tx_cmd_gen2);
	else
		len = sizeof(struct iwl_tx_cmd_gen3);

	amsdu = ieee80211_is_data_qos(hdr->frame_control) &&
			(*ieee80211_get_qos_ctl(hdr) &
			 IEEE80211_QOS_CTL_A_MSDU_PRESENT);

	hdr_len = ieee80211_hdrlen(hdr->frame_control);

	/*
	 * Only build A-MSDUs here if doing so by GSO, otherwise it may be
	 * an A-MSDU for other reasons, e.g. NAN or an A-MSDU having been
	 * built in the higher layers already.
	 */
	if (amsdu && skb_shinfo(skb)->gso_size)
		return iwl_pcie_gen2_build_tx_amsdu(trans, txq, dev_cmd, skb,
						    out_meta, hdr_len, len);

	return iwl_pcie_gen2_build_tx(trans, txq, dev_cmd, skb, out_meta,
				      hdr_len, len, !amsdu);
}
コード例 #26
0
ファイル: capwap_private.c プロジェクト: nm-mrt/smartcapwap
static void sc_send_80211(struct sk_buff *skb, struct net_device *dev)
{
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
	struct ieee80211_hdr *hdr;
	int hdrlen;

	printk(KERN_DEBUG "capwap inject: %s: hdr: %p\n",
	       dev->name, skb->data);

	/* detach skb from CAPWAP */
	skb_orphan(skb);
	secpath_reset(skb);

	/* drop any routing info */
	skb_dst_drop(skb);

	/* drop conntrack reference */
	nf_reset(skb);

	hdr = (struct ieee80211_hdr *)skb->data;
	hdrlen = ieee80211_hdrlen(hdr->frame_control);

	skb->dev = dev;

	skb_set_mac_header(skb, hdrlen);
	skb_set_network_header(skb, hdrlen);
	skb_set_transport_header(skb, hdrlen);

	skb->protocol = htons(ETH_P_CONTROL);
	info->flags |= IEEE80211_TX_CTL_INJECTED;

	/* Force the device to verify it. */
	skb->ip_summed = CHECKSUM_NONE;

	dev_queue_xmit(skb);
}
コード例 #27
0
ファイル: wpa.c プロジェクト: johnny/CobraDroidBeta
static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch,
				int encrypted)
{
	__le16 mask_fc;
	int a4_included;
	u8 qos_tid;
	u8 *b_0, *aad;
	u16 data_len, len_a;
	unsigned int hdrlen;
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;

	b_0 = scratch + 3 * AES_BLOCK_LEN;
	aad = scratch + 4 * AES_BLOCK_LEN;

	/*
	 * Mask FC: zero subtype b4 b5 b6
	 * Retry, PwrMgt, MoreData; set Protected
	 */
	mask_fc = hdr->frame_control;
	mask_fc &= ~cpu_to_le16(0x0070 | IEEE80211_FCTL_RETRY |
				IEEE80211_FCTL_PM | IEEE80211_FCTL_MOREDATA);
	mask_fc |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);

	hdrlen = ieee80211_hdrlen(hdr->frame_control);
	len_a = hdrlen - 2;
	a4_included = ieee80211_has_a4(hdr->frame_control);

	if (ieee80211_is_data_qos(hdr->frame_control))
		qos_tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
	else
		qos_tid = 0;

	data_len = skb->len - hdrlen - CCMP_HDR_LEN;
	if (encrypted)
		data_len -= CCMP_MIC_LEN;

	/* First block, b_0 */
	b_0[0] = 0x59; /* flags: Adata: 1, M: 011, L: 001 */
	/* Nonce: QoS Priority | A2 | PN */
	b_0[1] = qos_tid;
	memcpy(&b_0[2], hdr->addr2, ETH_ALEN);
	memcpy(&b_0[8], pn, CCMP_PN_LEN);
	/* l(m) */
	put_unaligned_be16(data_len, &b_0[14]);

	/* AAD (extra authenticate-only data) / masked 802.11 header
	 * FC | A1 | A2 | A3 | SC | [A4] | [QC] */
	put_unaligned_be16(len_a, &aad[0]);
	put_unaligned(mask_fc, (__le16 *)&aad[2]);
	memcpy(&aad[4], &hdr->addr1, 3 * ETH_ALEN);

	/* Mask Seq#, leave Frag# */
	aad[22] = *((u8 *) &hdr->seq_ctrl) & 0x0f;
	aad[23] = 0;

	if (a4_included) {
		memcpy(&aad[24], hdr->addr4, ETH_ALEN);
		aad[30] = qos_tid;
		aad[31] = 0;
	} else {
		memset(&aad[24], 0, ETH_ALEN + IEEE80211_QOS_CTL_LEN);
		aad[24] = qos_tid;
	}
}
コード例 #28
0
ファイル: tx.c プロジェクト: chinawrj/mwlwifi
static inline struct sk_buff *mwl_tx_do_amsdu(struct mwl_priv *priv,
					      int desc_num,
					      struct sk_buff *tx_skb,
					      struct ieee80211_tx_info *tx_info)
{
	struct ieee80211_sta *sta;
	struct mwl_sta *sta_info;
	struct mwl_tx_ctrl *tx_ctrl = (struct mwl_tx_ctrl *)&tx_info->status;
	struct ieee80211_tx_info *amsdu_info;
	struct sk_buff_head *amsdu_pkts;
	struct mwl_amsdu_frag *amsdu;
	int amsdu_allow_size;
	struct ieee80211_hdr *wh;
	int wh_len;
	u16 len;
	u8 *data;

	sta = (struct ieee80211_sta *)tx_ctrl->sta;
	sta_info = mwl_dev_get_sta(sta);

	if (!sta_info->is_amsdu_allowed)
		return tx_skb;

	wh = (struct ieee80211_hdr *)tx_skb->data;
	if (sta_info->is_mesh_node && is_multicast_ether_addr(wh->addr3))
		return tx_skb;

	if (sta_info->amsdu_ctrl.cap == MWL_AMSDU_SIZE_4K)
		amsdu_allow_size = SYSADPT_AMSDU_4K_MAX_SIZE;
	else if (sta_info->amsdu_ctrl.cap == MWL_AMSDU_SIZE_8K)
		amsdu_allow_size = SYSADPT_AMSDU_8K_MAX_SIZE;
	else
		return tx_skb;

	spin_lock_bh(&sta_info->amsdu_lock);
	amsdu = &sta_info->amsdu_ctrl.frag[desc_num];

	if (tx_skb->len > SYSADPT_AMSDU_ALLOW_SIZE) {
		if (amsdu->num) {
			mwl_tx_skb(priv, desc_num, amsdu->skb);
			amsdu->num = 0;
			amsdu->cur_pos = NULL;

			if (!mwl_tx_available(priv, desc_num)) {
				skb_queue_head(&priv->txq[desc_num], tx_skb);
				spin_unlock_bh(&sta_info->amsdu_lock);
				return NULL;
			}
		}
		spin_unlock_bh(&sta_info->amsdu_lock);
		return tx_skb;
	}

	/* potential amsdu size, should add amsdu header 14 bytes +
	 * maximum padding 3.
	 */
	wh_len = ieee80211_hdrlen(wh->frame_control);
	len = tx_skb->len - wh_len + 17;

	if (amsdu->num) {
		if ((amsdu->skb->len + len) > amsdu_allow_size) {
			mwl_tx_skb(priv, desc_num, amsdu->skb);
			amsdu->num = 0;
			amsdu->cur_pos = NULL;
		}
	}

	amsdu->jiffies = jiffies;
	len = tx_skb->len - wh_len;

	if (amsdu->num == 0) {
		struct sk_buff *newskb;

		amsdu_pkts = (struct sk_buff_head *)
			kmalloc(sizeof(*amsdu_pkts), GFP_ATOMIC);
		if (!amsdu_pkts) {
			spin_unlock_bh(&sta_info->amsdu_lock);
			return tx_skb;
		}
		newskb = dev_alloc_skb(amsdu_allow_size +
				       SYSADPT_MIN_BYTES_HEADROOM);
		if (!newskb) {
			spin_unlock_bh(&sta_info->amsdu_lock);
			kfree(amsdu_pkts);
			return tx_skb;
		}

		data = newskb->data;
		memcpy(data, tx_skb->data, wh_len);
		if (sta_info->is_mesh_node) {
			ether_addr_copy(data + wh_len, wh->addr3);
			ether_addr_copy(data + wh_len + ETH_ALEN, wh->addr4);
		} else {
			ether_addr_copy(data + wh_len,
					ieee80211_get_DA(wh));
			ether_addr_copy(data + wh_len + ETH_ALEN,
					ieee80211_get_SA(wh));
		}
		*(u8 *)(data + wh_len + ETH_HLEN - 1) = len & 0xff;
		*(u8 *)(data + wh_len + ETH_HLEN - 2) = (len >> 8) & 0xff;
		memcpy(data + wh_len + ETH_HLEN, tx_skb->data + wh_len, len);

		skb_put(newskb, tx_skb->len + ETH_HLEN);
		tx_ctrl->qos_ctrl |= IEEE80211_QOS_CTL_A_MSDU_PRESENT;
		amsdu_info = IEEE80211_SKB_CB(newskb);
		memcpy(amsdu_info, tx_info, sizeof(*tx_info));
		skb_queue_head_init(amsdu_pkts);
		((struct mwl_tx_ctrl *)&amsdu_info->status)->amsdu_pkts =
			(void *)amsdu_pkts;
		amsdu->skb = newskb;
	} else {
コード例 #29
0
ファイル: wpa.c プロジェクト: Andrew-Gazizov/linux-3.2.1-kpp
ieee80211_rx_result
ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx)
{
	u8 *data, *key = NULL;
	size_t data_len;
	unsigned int hdrlen;
	u8 mic[MICHAEL_MIC_LEN];
	struct sk_buff *skb = rx->skb;
	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;

	/*
	 * it makes no sense to check for MIC errors on anything other
	 * than data frames.
	 */
	if (!ieee80211_is_data_present(hdr->frame_control))
		return RX_CONTINUE;

	/*
	 * No way to verify the MIC if the hardware stripped it or
	 * the IV with the key index. In this case we have solely rely
	 * on the driver to set RX_FLAG_MMIC_ERROR in the event of a
	 * MIC failure report.
	 */
	if (status->flag & (RX_FLAG_MMIC_STRIPPED | RX_FLAG_IV_STRIPPED)) {
		if (status->flag & RX_FLAG_MMIC_ERROR)
			goto mic_fail;

		if (!(status->flag & RX_FLAG_IV_STRIPPED))
			goto update_iv;

		return RX_CONTINUE;
	}

	/*
	 * Some hardware seems to generate Michael MIC failure reports; even
	 * though, the frame was not encrypted with TKIP and therefore has no
	 * MIC. Ignore the flag them to avoid triggering countermeasures.
	 */
	if (!rx->key || rx->key->conf.cipher != WLAN_CIPHER_SUITE_TKIP ||
	    !(status->flag & RX_FLAG_DECRYPTED))
		return RX_CONTINUE;

	if (rx->sdata->vif.type == NL80211_IFTYPE_AP && rx->key->conf.keyidx) {
		/*
		 * APs with pairwise keys should never receive Michael MIC
		 * errors for non-zero keyidx because these are reserved for
		 * group keys and only the AP is sending real multicast
		 * frames in the BSS. (
		 */
		return RX_DROP_UNUSABLE;
	}

	if (status->flag & RX_FLAG_MMIC_ERROR)
		goto mic_fail;

	hdrlen = ieee80211_hdrlen(hdr->frame_control);
	if (skb->len < hdrlen + MICHAEL_MIC_LEN)
		return RX_DROP_UNUSABLE;

	data = skb->data + hdrlen;
	data_len = skb->len - hdrlen - MICHAEL_MIC_LEN;
	key = &rx->key->conf.key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY];
	michael_mic(key, hdr, data, data_len, mic);
	if (memcmp(mic, data + data_len, MICHAEL_MIC_LEN) != 0)
		goto mic_fail;

	/* remove Michael MIC from payload */
	skb_trim(skb, skb->len - MICHAEL_MIC_LEN);

update_iv:
	/* update IV in key information to be able to detect replays */
	rx->key->u.tkip.rx[rx->security_idx].iv32 = rx->tkip_iv32;
	rx->key->u.tkip.rx[rx->security_idx].iv16 = rx->tkip_iv16;

	return RX_CONTINUE;

mic_fail:
	/*
	 * In some cases the key can be unset - e.g. a multicast packet, in
	 * a driver that supports HW encryption. Send up the key idx only if
	 * the key is set.
	 */
	mac80211_ev_michael_mic_failure(rx->sdata,
					rx->key ? rx->key->conf.keyidx : -1,
					(void *) skb->data, NULL, GFP_ATOMIC);
	return RX_DROP_UNUSABLE;
}
コード例 #30
0
ファイル: ABPS_mac80211.c プロジェクト: amengo/ABPS-4.0
int ABPS_extract_pkt_info(struct ieee80211_hdr *hdr)
{
	struct ABPS_info *packet_info;
	struct ieee80211_hdr_4addr *hdr4 = (struct ieee80211_hdr_4addr *)hdr;
	size_t hdrlen;
	u16 fc, type, stype, sc;
	unsigned int frag;
	u8 *payload;
	u8 *IPdatagram;
	u16 ethertype;
	int flen;
	IPdgramInfo *p_IPDGInfo;
	fc = le16_to_cpu(hdr->frame_control) ;
	stype = WLAN_FC_GET_STYPE(fc);

	switch (WLAN_FC_GET_TYPE(fc)) {
		case IEEE80211_FTYPE_DATA:
			break;
			return 0;
	}
	p_IPDGInfo = kmalloc(sizeof (IPdgramInfo), GFP_ATOMIC);
	packet_info = kmalloc(sizeof(struct ABPS_info), GFP_ATOMIC);

    packet_info->id = hdr->seq_ctrl;

	fc = le16_to_cpu(hdr4->frame_ctl);
	type = WLAN_FC_GET_TYPE(fc);
	stype = WLAN_FC_GET_STYPE(fc);
	sc = le16_to_cpu(hdr4->seq_ctl);
	frag = WLAN_GET_SEQ_FRAG(sc);

	/* OLD hdrlen = ieee80211_get_hdrlen(fc); */
	hdrlen = ieee80211_hdrlen(fc);

	stype &= ~IEEE80211_STYPE_QOS_DATA;

	if (stype != IEEE80211_STYPE_DATA &&
		   stype != IEEE80211_STYPE_DATA_CFACK &&
		   stype != IEEE80211_STYPE_DATA_CFPOLL &&
		   stype != IEEE80211_STYPE_DATA_CFACKPOLL)
		goto rx_dropped;

	payload = ((u8*)(hdr4)) + hdrlen;
	ethertype = (payload[6] << 8) | payload[7];
	if (ethertype == ETH_P_IP) {
		int ris;
		IPdatagram = ((u8*)hdr4) + hdrlen + 8;
		flen = sizeof(struct iphdr) + sizeof(struct udphdr);
		ris = get_udp_info(IPdatagram, flen, &(p_IPDGInfo->saddr),
							&(p_IPDGInfo->daddr), &(p_IPDGInfo->sport),
							&(p_IPDGInfo->dport), &(p_IPDGInfo->ipdgramid),
							&(p_IPDGInfo->fragment_data_len),
							/* only data, not header */
							&(p_IPDGInfo->fragment_offset),
							&(p_IPDGInfo->more_fragment));
		if (ris > 0) {
			/* set the fields of the ABPS_info that will be put in the
			 * ABPS_info list*/
			packet_info->datagram_info.ip_id = p_IPDGInfo->ipdgramid;
				/* maybe ntohs, not sure */
			packet_info->datagram_info.udp_sport = p_IPDGInfo->sport;
			packet_info->datagram_info.fragment_data_len = p_IPDGInfo->fragment_data_len;
			packet_info->datagram_info.fragment_offset = p_IPDGInfo->fragment_offset;
			packet_info->datagram_info.more_fragment = p_IPDGInfo->more_fragment;
			packet_info->tx_time = CURRENT_TIME;
			ABPS_info_add(packet_info);
			return(1);
		}
		return(0);
	}
rx_dropped:
		return 0;
}