aboutsummaryrefslogtreecommitdiff
path: root/net/mac80211
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/Kconfig3
-rw-r--r--net/mac80211/aes_ccm.c51
-rw-r--r--net/mac80211/aes_ccm.h4
-rw-r--r--net/mac80211/ieee80211_i.h3
-rw-r--r--net/mac80211/main.c33
-rw-r--r--net/mac80211/michael.c20
-rw-r--r--net/mac80211/michael.h2
-rw-r--r--net/mac80211/mlme.c34
-rw-r--r--net/mac80211/rx.c135
-rw-r--r--net/mac80211/sta_info.c1
-rw-r--r--net/mac80211/sta_info.h81
-rw-r--r--net/mac80211/wext.c2
-rw-r--r--net/mac80211/wme.c5
-rw-r--r--net/mac80211/wme.h8
-rw-r--r--net/mac80211/wpa.c183
15 files changed, 310 insertions, 255 deletions
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig
index 11a1e7fa195..40f1add1775 100644
--- a/net/mac80211/Kconfig
+++ b/net/mac80211/Kconfig
@@ -207,7 +207,6 @@ config MAC80211_LOWTX_FRAME_DUMP
config MAC80211_DEBUG_COUNTERS
bool "Extra statistics for TX/RX debugging"
- depends on MAC80211_DEBUG
depends on MAC80211_DEBUG_MENU
depends on MAC80211_DEBUGFS
---help---
@@ -219,7 +218,7 @@ config MAC80211_DEBUG_COUNTERS
config MAC80211_VERBOSE_SPECT_MGMT_DEBUG
bool "Verbose Spectrum Management (IEEE 802.11h)debugging"
- depends on MAC80211_DEBUG
+ depends on MAC80211_DEBUG_MENU
---help---
Say Y here to print out verbose Spectrum Management (IEEE 802.11h)
debug messages.
diff --git a/net/mac80211/aes_ccm.c b/net/mac80211/aes_ccm.c
index 4d4c2dfcf9a..a87cb3ba2df 100644
--- a/net/mac80211/aes_ccm.c
+++ b/net/mac80211/aes_ccm.c
@@ -16,31 +16,28 @@
#include "key.h"
#include "aes_ccm.h"
-
-static void ieee80211_aes_encrypt(struct crypto_cipher *tfm,
- const u8 pt[16], u8 ct[16])
-{
- crypto_cipher_encrypt_one(tfm, ct, pt);
-}
-
-
-static inline void aes_ccm_prepare(struct crypto_cipher *tfm, u8 *b_0, u8 *aad,
- u8 *b, u8 *s_0, u8 *a)
+static void aes_ccm_prepare(struct crypto_cipher *tfm, u8 *scratch, u8 *a)
{
int i;
+ u8 *b_0, *aad, *b, *s_0;
- ieee80211_aes_encrypt(tfm, b_0, b);
+ b_0 = scratch + 3 * AES_BLOCK_LEN;
+ aad = scratch + 4 * AES_BLOCK_LEN;
+ b = scratch;
+ s_0 = scratch + AES_BLOCK_LEN;
+
+ crypto_cipher_encrypt_one(tfm, b, b_0);
/* Extra Authenticate-only data (always two AES blocks) */
for (i = 0; i < AES_BLOCK_LEN; i++)
aad[i] ^= b[i];
- ieee80211_aes_encrypt(tfm, aad, b);
+ crypto_cipher_encrypt_one(tfm, b, aad);
aad += AES_BLOCK_LEN;
for (i = 0; i < AES_BLOCK_LEN; i++)
aad[i] ^= b[i];
- ieee80211_aes_encrypt(tfm, aad, a);
+ crypto_cipher_encrypt_one(tfm, a, aad);
/* Mask out bits from auth-only-b_0 */
b_0[0] &= 0x07;
@@ -48,24 +45,26 @@ static inline void aes_ccm_prepare(struct crypto_cipher *tfm, u8 *b_0, u8 *aad,
/* S_0 is used to encrypt T (= MIC) */
b_0[14] = 0;
b_0[15] = 0;
- ieee80211_aes_encrypt(tfm, b_0, s_0);
+ crypto_cipher_encrypt_one(tfm, s_0, b_0);
}
void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch,
- u8 *b_0, u8 *aad, u8 *data, size_t data_len,
+ u8 *data, size_t data_len,
u8 *cdata, u8 *mic)
{
int i, j, last_len, num_blocks;
- u8 *pos, *cpos, *b, *s_0, *e;
+ u8 *pos, *cpos, *b, *s_0, *e, *b_0, *aad;
b = scratch;
s_0 = scratch + AES_BLOCK_LEN;
e = scratch + 2 * AES_BLOCK_LEN;
+ b_0 = scratch + 3 * AES_BLOCK_LEN;
+ aad = scratch + 4 * AES_BLOCK_LEN;
num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_LEN);
last_len = data_len % AES_BLOCK_LEN;
- aes_ccm_prepare(tfm, b_0, aad, b, s_0, b);
+ aes_ccm_prepare(tfm, scratch, b);
/* Process payload blocks */
pos = data;
@@ -77,11 +76,11 @@ void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch,
/* Authentication followed by encryption */
for (i = 0; i < blen; i++)
b[i] ^= pos[i];
- ieee80211_aes_encrypt(tfm, b, b);
+ crypto_cipher_encrypt_one(tfm, b, b);
b_0[14] = (j >> 8) & 0xff;
b_0[15] = j & 0xff;
- ieee80211_aes_encrypt(tfm, b_0, e);
+ crypto_cipher_encrypt_one(tfm, e, b_0);
for (i = 0; i < blen; i++)
*cpos++ = *pos++ ^ e[i];
}
@@ -92,19 +91,20 @@ void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch,
int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch,
- u8 *b_0, u8 *aad, u8 *cdata, size_t data_len,
- u8 *mic, u8 *data)
+ u8 *cdata, size_t data_len, u8 *mic, u8 *data)
{
int i, j, last_len, num_blocks;
- u8 *pos, *cpos, *b, *s_0, *a;
+ u8 *pos, *cpos, *b, *s_0, *a, *b_0, *aad;
b = scratch;
s_0 = scratch + AES_BLOCK_LEN;
a = scratch + 2 * AES_BLOCK_LEN;
+ b_0 = scratch + 3 * AES_BLOCK_LEN;
+ aad = scratch + 4 * AES_BLOCK_LEN;
num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_LEN);
last_len = data_len % AES_BLOCK_LEN;
- aes_ccm_prepare(tfm, b_0, aad, b, s_0, a);
+ aes_ccm_prepare(tfm, scratch, a);
/* Process payload blocks */
cpos = cdata;
@@ -116,13 +116,12 @@ int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch,
/* Decryption followed by authentication */
b_0[14] = (j >> 8) & 0xff;
b_0[15] = j & 0xff;
- ieee80211_aes_encrypt(tfm, b_0, b);
+ crypto_cipher_encrypt_one(tfm, b, b_0);
for (i = 0; i < blen; i++) {
*pos = *cpos++ ^ b[i];
a[i] ^= *pos++;
}
-
- ieee80211_aes_encrypt(tfm, a, a);
+ crypto_cipher_encrypt_one(tfm, a, a);
}
for (i = 0; i < CCMP_MIC_LEN; i++) {
diff --git a/net/mac80211/aes_ccm.h b/net/mac80211/aes_ccm.h
index 8cd0f14aab4..6e7820ef344 100644
--- a/net/mac80211/aes_ccm.h
+++ b/net/mac80211/aes_ccm.h
@@ -16,10 +16,10 @@
struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[]);
void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch,
- u8 *b_0, u8 *aad, u8 *data, size_t data_len,
+ u8 *data, size_t data_len,
u8 *cdata, u8 *mic);
int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch,
- u8 *b_0, u8 *aad, u8 *cdata, size_t data_len,
+ u8 *cdata, size_t data_len,
u8 *mic, u8 *data);
void ieee80211_aes_key_free(struct crypto_cipher *tfm);
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index f90da1bbec4..02a8753a4ec 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -893,7 +893,7 @@ int ieee80211_sta_deauthenticate(struct net_device *dev, u16 reason);
int ieee80211_sta_disassociate(struct net_device *dev, u16 reason);
void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
u32 changed);
-void ieee80211_reset_erp_info(struct net_device *dev);
+u32 ieee80211_reset_erp_info(struct net_device *dev);
int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie,
struct ieee80211_ht_info *ht_info);
int ieee80211_ht_addt_info_ie_to_ht_bss_info(
@@ -904,6 +904,7 @@ void ieee80211_send_addba_request(struct net_device *dev, const u8 *da,
u16 agg_size, u16 timeout);
void ieee80211_send_delba(struct net_device *dev, const u8 *da, u16 tid,
u16 initiator, u16 reason_code);
+void ieee80211_send_bar(struct net_device *dev, u8 *ra, u16 tid, u16 ssn);
void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *da,
u16 tid, u16 initiator, u16 reason);
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index f18cfd72787..cc756e93e6c 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -182,10 +182,11 @@ static int ieee80211_open(struct net_device *dev)
{
struct ieee80211_sub_if_data *sdata, *nsdata;
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+ struct sta_info *sta;
struct ieee80211_if_init_conf conf;
+ u32 changed = 0;
int res;
bool need_hw_reconfig = 0;
- struct sta_info *sta;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
@@ -329,7 +330,8 @@ static int ieee80211_open(struct net_device *dev)
goto err_stop;
ieee80211_if_config(dev);
- ieee80211_reset_erp_info(dev);
+ changed |= ieee80211_reset_erp_info(dev);
+ ieee80211_bss_info_change_notify(sdata, changed);
ieee80211_enable_keys(sdata);
if (sdata->vif.type == IEEE80211_IF_TYPE_STA &&
@@ -1190,15 +1192,13 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
changed);
}
-void ieee80211_reset_erp_info(struct net_device *dev)
+u32 ieee80211_reset_erp_info(struct net_device *dev)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
sdata->bss_conf.use_cts_prot = 0;
sdata->bss_conf.use_short_preamble = 0;
- ieee80211_bss_info_change_notify(sdata,
- BSS_CHANGED_ERP_CTS_PROT |
- BSS_CHANGED_ERP_PREAMBLE);
+ return BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_ERP_PREAMBLE;
}
void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw,
@@ -1404,14 +1404,15 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
struct ieee80211_local *local = hw_to_local(hw);
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
u16 frag, type;
+ __le16 fc;
struct ieee80211_tx_status_rtap_hdr *rthdr;
struct ieee80211_sub_if_data *sdata;
struct net_device *prev_dev = NULL;
+ struct sta_info *sta;
rcu_read_lock();
if (info->status.excessive_retries) {
- struct sta_info *sta;
sta = sta_info_get(local, hdr->addr1);
if (sta) {
if (test_sta_flags(sta, WLAN_STA_PS)) {
@@ -1426,8 +1427,24 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
}
}
+ fc = hdr->frame_control;
+
+ if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) &&
+ (ieee80211_is_data_qos(fc))) {
+ u16 tid, ssn;
+ u8 *qc;
+ sta = sta_info_get(local, hdr->addr1);
+ if (sta) {
+ qc = ieee80211_get_qos_ctl(hdr);
+ tid = qc[0] & 0xf;
+ ssn = ((le16_to_cpu(hdr->seq_ctrl) + 0x10)
+ & IEEE80211_SCTL_SEQ);
+ ieee80211_send_bar(sta->sdata->dev, hdr->addr1,
+ tid, ssn);
+ }
+ }
+
if (info->flags & IEEE80211_TX_STAT_TX_FILTERED) {
- struct sta_info *sta;
sta = sta_info_get(local, hdr->addr1);
if (sta) {
ieee80211_handle_filtered_frame(local, sta, skb);
diff --git a/net/mac80211/michael.c b/net/mac80211/michael.c
index 1fcdf38cf60..408649bd470 100644
--- a/net/mac80211/michael.c
+++ b/net/mac80211/michael.c
@@ -8,6 +8,7 @@
*/
#include <linux/types.h>
#include <linux/bitops.h>
+#include <linux/ieee80211.h>
#include <asm/unaligned.h>
#include "michael.h"
@@ -26,9 +27,18 @@ static void michael_block(struct michael_mic_ctx *mctx, u32 val)
mctx->l += mctx->r;
}
-static void michael_mic_hdr(struct michael_mic_ctx *mctx,
- const u8 *key, const u8 *da, const u8 *sa, u8 priority)
+static void michael_mic_hdr(struct michael_mic_ctx *mctx, const u8 *key,
+ struct ieee80211_hdr *hdr)
{
+ u8 *da, *sa, tid;
+
+ da = ieee80211_get_DA(hdr);
+ sa = ieee80211_get_SA(hdr);
+ if (ieee80211_is_data_qos(hdr->frame_control))
+ tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
+ else
+ tid = 0;
+
mctx->l = get_unaligned_le32(key);
mctx->r = get_unaligned_le32(key + 4);
@@ -40,17 +50,17 @@ static void michael_mic_hdr(struct michael_mic_ctx *mctx,
michael_block(mctx, get_unaligned_le16(&da[4]) |
(get_unaligned_le16(sa) << 16));
michael_block(mctx, get_unaligned_le32(&sa[2]));
- michael_block(mctx, priority);
+ michael_block(mctx, tid);
}
-void michael_mic(const u8 *key, const u8 *da, const u8 *sa, u8 priority,
+void michael_mic(const u8 *key, struct ieee80211_hdr *hdr,
const u8 *data, size_t data_len, u8 *mic)
{
u32 val;
size_t block, blocks, left;
struct michael_mic_ctx mctx;
- michael_mic_hdr(&mctx, key, da, sa, priority);
+ michael_mic_hdr(&mctx, key, hdr);
/* Real data */
blocks = data_len / 4;
diff --git a/net/mac80211/michael.h b/net/mac80211/michael.h
index 69b4501f13b..3b848dad958 100644
--- a/net/mac80211/michael.h
+++ b/net/mac80211/michael.h
@@ -18,7 +18,7 @@ struct michael_mic_ctx {
u32 l, r;
};
-void michael_mic(const u8 *key, const u8 *da, const u8 *sa, u8 priority,
+void michael_mic(const u8 *key, struct ieee80211_hdr *hdr,
const u8 *data, size_t data_len, u8 *mic);
#endif /* MICHAEL_H */
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 4a3bddd206d..37ea04f5bab 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -366,8 +366,10 @@ static u32 ieee80211_handle_protect_preamb(struct ieee80211_sub_if_data *sdata,
bool use_short_preamble)
{
struct ieee80211_bss_conf *bss_conf = &sdata->bss_conf;
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
struct ieee80211_if_sta *ifsta = &sdata->u.sta;
DECLARE_MAC_BUF(mac);
+#endif
u32 changed = 0;
if (use_protection != bss_conf->use_cts_prot) {
@@ -571,7 +573,7 @@ static void ieee80211_set_associated(struct net_device *dev,
ieee80211_sta_tear_down_BA_sessions(dev, ifsta->bssid);
ifsta->flags &= ~IEEE80211_STA_ASSOCIATED;
netif_carrier_off(dev);
- ieee80211_reset_erp_info(dev);
+ changed |= ieee80211_reset_erp_info(dev);
sdata->bss_conf.assoc_ht = 0;
sdata->bss_conf.ht_conf = NULL;
@@ -1536,6 +1538,35 @@ void ieee80211_send_delba(struct net_device *dev, const u8 *da, u16 tid,
ieee80211_sta_tx(dev, skb, 0);
}
+void ieee80211_send_bar(struct net_device *dev, u8 *ra, u16 tid, u16 ssn)
+{
+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+ struct sk_buff *skb;
+ struct ieee80211_bar *bar;
+ u16 bar_control = 0;
+
+ skb = dev_alloc_skb(sizeof(*bar) + local->hw.extra_tx_headroom);
+ if (!skb) {
+ printk(KERN_ERR "%s: failed to allocate buffer for "
+ "bar frame\n", dev->name);
+ return;
+ }
+ skb_reserve(skb, local->hw.extra_tx_headroom);
+ bar = (struct ieee80211_bar *)skb_put(skb, sizeof(*bar));
+ memset(bar, 0, sizeof(*bar));
+ bar->frame_control = IEEE80211_FC(IEEE80211_FTYPE_CTL,
+ IEEE80211_STYPE_BACK_REQ);
+ memcpy(bar->ra, ra, ETH_ALEN);
+ memcpy(bar->ta, dev->dev_addr, ETH_ALEN);
+ bar_control |= (u16)IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL;
+ bar_control |= (u16)IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA;
+ bar_control |= (u16)(tid << 12);
+ bar->control = cpu_to_le16(bar_control);
+ bar->start_seq_num = cpu_to_le16(ssn);
+
+ ieee80211_sta_tx(dev, skb, 0);
+}
+
void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *ra, u16 tid,
u16 initiator, u16 reason)
{
@@ -2481,6 +2512,7 @@ static int ieee80211_sta_join_ibss(struct net_device *dev,
control->flags |= IEEE80211_TX_CTL_SHORT_PREAMBLE;
control->antenna_sel_tx = local->hw.conf.antenna_sel_tx;
control->flags |= IEEE80211_TX_CTL_NO_ACK;
+ control->flags |= IEEE80211_TX_CTL_DO_NOT_ENCRYPT;
control->control.retry_limit = 1;
ifsta->probe_resp = skb_copy(skb, GFP_ATOMIC);
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 6a88e8f9bff..fab443d717e 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -321,20 +321,20 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
static void ieee80211_parse_qos(struct ieee80211_rx_data *rx)
{
- u8 *data = rx->skb->data;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
int tid;
/* does the frame have a qos control field? */
- if (WLAN_FC_IS_QOS_DATA(rx->fc)) {
- u8 *qc = data + ieee80211_get_hdrlen(rx->fc) - QOS_CONTROL_LEN;
+ if (ieee80211_is_data_qos(hdr->frame_control)) {
+ u8 *qc = ieee80211_get_qos_ctl(hdr);
/* frame has qos control */
- tid = qc[0] & QOS_CONTROL_TID_MASK;
- if (qc[0] & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT)
+ tid = *qc & IEEE80211_QOS_CTL_TID_MASK;
+ if (*qc & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT)
rx->flags |= IEEE80211_RX_AMSDU;
else
rx->flags &= ~IEEE80211_RX_AMSDU;
} else {
- if (unlikely((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT)) {
+ if (unlikely(ieee80211_is_mgmt(hdr->frame_control))) {
/* Separate TID for management frames */
tid = NUM_RX_DATA_QUEUES - 1;
} else {
@@ -352,9 +352,10 @@ static void ieee80211_parse_qos(struct ieee80211_rx_data *rx)
static void ieee80211_verify_ip_alignment(struct ieee80211_rx_data *rx)
{
#ifdef CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
int hdrlen;
- if (!WLAN_FC_DATA_PRESENT(rx->fc))
+ if (!ieee80211_is_data_present(hdr->frame_control))
return;
/*
@@ -376,7 +377,7 @@ static void ieee80211_verify_ip_alignment(struct ieee80211_rx_data *rx)
* header and the payload is not supported, the driver is required
* to move the 802.11 header further back in that case.
*/
- hdrlen = ieee80211_get_hdrlen(rx->fc);
+ hdrlen = ieee80211_hdrlen(hdr->frame_control);
if (rx->flags & IEEE80211_RX_AMSDU)
hdrlen += ETH_HLEN;
WARN_ON_ONCE(((unsigned long)(rx->skb->data + hdrlen)) & 3);
@@ -415,14 +416,11 @@ ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx)
static ieee80211_rx_result
ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
{
- int hdrlen = ieee80211_get_hdrlen(rx->fc);
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
+ unsigned int hdrlen = ieee80211_hdrlen(hdr->frame_control);
-#define msh_h_get(h, l) ((struct ieee80211s_hdr *) ((u8 *)h + l))
-
- if ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) {
- if (!((rx->fc & IEEE80211_FCTL_FROMDS) &&
- (rx->fc & IEEE80211_FCTL_TODS)))
+ if (ieee80211_is_data(hdr->frame_control)) {
+ if (!ieee80211_has_a4(hdr->frame_control))
return RX_DROP_MONITOR;
if (memcmp(hdr->addr4, rx->dev->dev_addr, ETH_ALEN) == 0)
return RX_DROP_MONITOR;
@@ -435,27 +433,30 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
if (!rx->sta || sta_plink_state(rx->sta) != PLINK_ESTAB) {
struct ieee80211_mgmt *mgmt;
- if ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT)
+ if (!ieee80211_is_mgmt(hdr->frame_control))
return RX_DROP_MONITOR;
- switch (rx->fc & IEEE80211_FCTL_STYPE) {
- case IEEE80211_STYPE_ACTION:
+ if (ieee80211_is_action(hdr->frame_control)) {
mgmt = (struct ieee80211_mgmt *)hdr;
if (mgmt->u.action.category != PLINK_CATEGORY)
return RX_DROP_MONITOR;
- /* fall through on else */
- case IEEE80211_STYPE_PROBE_REQ:
- case IEEE80211_STYPE_PROBE_RESP:
- case IEEE80211_STYPE_BEACON:
return RX_CONTINUE;
- break;
- default:
- return RX_DROP_MONITOR;
}
- } else if ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA &&
- is_multicast_ether_addr(hdr->addr1) &&
- mesh_rmc_check(hdr->addr4, msh_h_get(hdr, hdrlen), rx->dev))
+ if (ieee80211_is_probe_req(hdr->frame_control) ||
+ ieee80211_is_probe_resp(hdr->frame_control) ||
+ ieee80211_is_beacon(hdr->frame_control))
+ return RX_CONTINUE;
+
+ return RX_DROP_MONITOR;
+
+ }
+
+#define msh_h_get(h, l) ((struct ieee80211s_hdr *) ((u8 *)h + l))
+
+ if (ieee80211_is_data(hdr->frame_control) &&
+ is_multicast_ether_addr(hdr->addr1) &&
+ mesh_rmc_check(hdr->addr4, msh_h_get(hdr, hdrlen), rx->dev))
return RX_DROP_MONITOR;
#undef msh_h_get
@@ -466,13 +467,11 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
static ieee80211_rx_result debug_noinline
ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
{
- struct ieee80211_hdr *hdr;
-
- hdr = (struct ieee80211_hdr *) rx->skb->data;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
/* Drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.2.9) */
if (rx->sta && !is_multicast_ether_addr(hdr->addr1)) {
- if (unlikely(rx->fc & IEEE80211_FCTL_RETRY &&
+ if (unlikely(ieee80211_has_retry(hdr->frame_control) &&
rx->sta->last_seq_ctrl[rx->queue] ==
hdr->seq_ctrl)) {
if (rx->flags & IEEE80211_RX_RA_MATCH) {
@@ -501,15 +500,14 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
if (ieee80211_vif_is_mesh(&rx->sdata->vif))
return ieee80211_rx_mesh_check(rx);
- if (unlikely(((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA ||
- ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL &&
- (rx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PSPOLL)) &&
+ if (unlikely((ieee80211_is_data(hdr->frame_control) ||
+ ieee80211_is_pspoll(hdr->frame_control)) &&
rx->sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
(!rx->sta || !test_sta_flags(rx->sta, WLAN_STA_ASSOC)))) {
- if ((!(rx->fc & IEEE80211_FCTL_FROMDS) &&
- !(rx->fc & IEEE80211_FCTL_TODS) &&
- (rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)
- || !(rx->flags & IEEE80211_RX_RA_MATCH)) {
+ if ((!ieee80211_has_fromds(hdr->frame_control) &&
+ !ieee80211_has_tods(hdr->frame_control) &&
+ ieee80211_is_data(hdr->frame_control)) ||
+ !(rx->flags & IEEE80211_RX_RA_MATCH)) {
/* Drop IBSS frames and frames for other hosts
* silently. */
return RX_DROP_MONITOR;
@@ -525,7 +523,7 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
static ieee80211_rx_result debug_noinline
ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
{
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
int keyidx;
int hdrlen;
ieee80211_rx_result result = RX_DROP_UNUSABLE;
@@ -557,7 +555,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
* possible.
*/
- if (!(rx->fc & IEEE80211_FCTL_PROTECTED))
+ if (!ieee80211_has_protected(hdr->frame_control))
return RX_CONTINUE;
/*
@@ -586,7 +584,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
(rx->status->flag & RX_FLAG_IV_STRIPPED))
return RX_CONTINUE;
- hdrlen = ieee80211_get_hdrlen(rx->fc);
+ hdrlen = ieee80211_hdrlen(hdr->frame_control);
if (rx->skb->len < 8 + hdrlen)
return RX_DROP_UNUSABLE; /* TODO: count this? */
@@ -618,7 +616,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
/* Check for weak IVs if possible */
if (rx->sta && rx->key->conf.alg == ALG_WEP &&
- ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) &&
+ ieee80211_is_data(hdr->frame_control) &&
(!(rx->status->flag & RX_FLAG_IV_STRIPPED) ||
!(rx->status->flag & RX_FLAG_DECRYPTED)) &&
ieee80211_wep_is_weak_iv(rx->skb, rx->key))
@@ -710,7 +708,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
{
struct sta_info *sta = rx->sta;
struct net_device *dev = rx->dev;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
if (!sta)
return RX_CONTINUE;
@@ -744,21 +742,20 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
sta->last_qual = rx->status->qual;
sta->last_noise = rx->status->noise;
- if (!(rx->fc & IEEE80211_FCTL_MOREFRAGS)) {
+ if (!ieee80211_has_morefrags(hdr->frame_control)) {
/* Change STA power saving mode only in the end of a frame
* exchange sequence */
if (test_sta_flags(sta, WLAN_STA_PS) &&
- !(rx->fc & IEEE80211_FCTL_PM))
+ !ieee80211_has_pm(hdr->frame_control))
rx->sent_ps_buffered += ap_sta_ps_end(dev, sta);
else if (!test_sta_flags(sta, WLAN_STA_PS) &&
- (rx->fc & IEEE80211_FCTL_PM))
+ ieee80211_has_pm(hdr->frame_control))
ap_sta_ps_start(dev, sta);
}
/* Drop data::nullfunc frames silently, since they are used only to
* control station power saving mode. */
- if ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA &&
- (rx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_NULLFUNC) {
+ if (ieee80211_is_nullfunc(hdr->frame_control)) {
I802_DEBUG_INC(rx->local->rx_handlers_drop_nullfunc);
/* Update counter and free packet here to avoid counting this
* as a dropped packed. */
@@ -1037,19 +1034,19 @@ ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx)
static ieee80211_rx_result debug_noinline
ieee80211_rx_h_remove_qos_control(struct ieee80211_rx_data *rx)
{
- u16 fc = rx->fc;
u8 *data = rx->skb->data;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) data;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)data;
- if (!WLAN_FC_IS_QOS_DATA(fc))
+ if (!ieee80211_is_data_qos(hdr->frame_control))
return RX_CONTINUE;
/* remove the qos control field, update frame type and meta-data */
- memmove(data + 2, data, ieee80211_get_hdrlen(fc) - 2);
- hdr = (struct ieee80211_hdr *) skb_pull(rx->skb, 2);
+ memmove(data + IEEE80211_QOS_CTL_LEN, data,
+ ieee80211_hdrlen(hdr->frame_control) - IEEE80211_QOS_CTL_LEN);
+ hdr = (struct ieee80211_hdr *)skb_pull(rx->skb, IEEE80211_QOS_CTL_LEN);
/* change frame type to non QOS */
- rx->fc = fc &= ~IEEE80211_STYPE_QOS_DATA;
- hdr->frame_control = cpu_to_le16(fc);
+ rx->fc &= ~IEEE80211_STYPE_QOS_DATA;
+ hdr->frame_control &= ~cpu_to_le16(IEEE80211_STYPE_QOS_DATA);
return RX_CONTINUE;
}
@@ -1465,15 +1462,15 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx)
struct ieee80211_local *local = rx->local;
struct ieee80211_hw *hw = &local->hw;
struct sk_buff *skb = rx->skb;
- struct ieee80211_bar *bar = (struct ieee80211_bar *) skb->data;
+ struct ieee80211_bar *bar = (struct ieee80211_bar *)skb->data;
struct tid_ampdu_rx *tid_agg_rx;
u16 start_seq_num;
u16 tid;
- if (likely((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_CTL))
+ if (likely(!ieee80211_is_ctl(bar->frame_control)))
return RX_CONTINUE;
- if ((rx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BACK_REQ) {
+ if (ieee80211_is_back_req(bar->frame_control)) {
if (!rx->sta)
return RX_CONTINUE;
tid = le16_to_cpu(bar->control) >> 12;
@@ -1527,11 +1524,12 @@ static void ieee80211_rx_michael_mic_report(struct net_device *dev,
struct ieee80211_hdr *hdr,
struct ieee80211_rx_data *rx)
{
- int keyidx, hdrlen;
+ int keyidx;
+ unsigned int hdrlen;
DECLARE_MAC_BUF(mac);
DECLARE_MAC_BUF(mac2);
- hdrlen = ieee80211_get_hdrlen_from_skb(rx->skb);
+ hdrlen = ieee80211_hdrlen(hdr->frame_control);
if (rx->skb->len >= hdrlen + 4)
keyidx = rx->skb->data[hdrlen + 3] >> 6;
else
@@ -1545,7 +1543,7 @@ static void ieee80211_rx_michael_mic_report(struct net_device *dev,
goto ignore;
}
- if (!(rx->fc & IEEE80211_FCTL_PROTECTED))
+ if (!ieee80211_has_protected(hdr->frame_control))
goto ignore;
if (rx->sdata->vif.type == IEEE80211_IF_TYPE_AP && keyidx) {
@@ -1558,9 +1556,8 @@ static void ieee80211_rx_michael_mic_report(struct net_device *dev,
goto ignore;
}
- if ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA &&
- ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT ||
- (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_AUTH))
+ if (!ieee80211_is_data(hdr->frame_control) &&
+ !ieee80211_is_auth(hdr->frame_control))
goto ignore;
mac80211_ev_michael_mic_failure(rx->dev, keyidx, hdr);
@@ -1731,8 +1728,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
case IEEE80211_IF_TYPE_IBSS:
if (!bssid)
return 0;
- if ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT &&
- (rx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON) {
+ if (ieee80211_is_beacon(hdr->frame_control)) {
if (!rx->sta)
rx->sta = ieee80211_ibss_add_sta(sdata->dev,
rx->skb, bssid, hdr->addr2,
@@ -1783,8 +1779,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
return 0;
break;
case IEEE80211_IF_TYPE_WDS:
- if (bssid ||
- (rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA)
+ if (bssid || !ieee80211_is_data(hdr->frame_control))
return 0;
if (compare_ether_addr(sdata->u.wds.remote_addr, hdr->addr2))
return 0;
@@ -2044,7 +2039,7 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local,
if (!ieee80211_is_data_qos(hdr->frame_control))
goto end_reorder;
- tid = *ieee80211_get_qos_ctl(hdr) & QOS_CONTROL_TID_MASK;
+ tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_OPERATIONAL)
goto end_reorder;
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index d8a16b7f6a6..47d2c1bbfca 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -135,6 +135,7 @@ struct sta_info *sta_info_get_by_idx(struct ieee80211_local *local, int idx,
/**
* __sta_info_free - internal STA free helper
*
+ * @local: pointer to the global information
* @sta: STA info to free
*
* This function must undo everything done by sta_info_alloc()
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index fd228c198e3..94311dcfe04 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -160,11 +160,21 @@ struct sta_ampdu_mlme {
* @list: global linked list entry
* @hnext: hash table linked list pointer
* @local: pointer to the global information
+ * @sdata: TBD
+ * @key: TBD
+ * @rate_ctrl: TBD
+ * @rate_ctrl_priv: TBD
+ * @lock: used for locking all fields that require locking, see comments
+ * in the header file.
+ * @flaglock: spinlock for flags accesses
+ * @ht_info: HT capabilities of this STA
+ * @supp_rates: Bitmap of supported rates (per band)
* @addr: MAC address of this STA
* @aid: STA's unique AID (1..2007, 0 = not assigned yet),
* only used in AP (and IBSS?) mode
+ * @listen_interval: TBD
+ * @pin_status: TBD
* @flags: STA flags, see &enum ieee80211_sta_info_flags
- * @flaglock: spinlock for flags accesses
* @ps_tx_buf: buffer of frames to transmit to this station
* when it leaves power saving state
* @tx_filtered: buffer of frames we already tried to transmit
@@ -172,10 +182,41 @@ struct sta_ampdu_mlme {
* power saving state
* @rx_packets: Number of MSDUs received from this STA
* @rx_bytes: Number of bytes received from this STA
- * @supp_rates: Bitmap of supported rates (per band)
- * @ht_info: HT capabilities of this STA
- * @lock: used for locking all fields that require locking, see comments
- * in the header file.
+ * @wep_weak_iv_count: TBD
+ * @last_rx: TBD
+ * @num_duplicates: number of duplicate frames received from this STA
+ * @rx_fragments: number of received MPDUs
+ * @rx_dropped: number of dropped MPDUs from this STA
+ * @last_signal: signal of last received frame from this STA
+ * @last_qual: qual of last received frame from this STA
+ * @last_noise: noise of last received frame from this STA
+ * @last_seq_ctrl: last received seq/frag number from this STA (per RX queue)
+ * @wme_rx_queue: TBD
+ * @tx_filtered_count: TBD
+ * @tx_retry_failed: TBD
+ * @tx_retry_count: TBD
+ * @tx_num_consecutive_failures: TBD
+ * @tx_num_mpdu_ok: TBD
+ * @tx_num_mpdu_fail: TBD
+ * @fail_avg: moving percentage of failed MSDUs
+ * @tx_packets: number of RX/TX MSDUs
+ * @tx_bytes: TBD
+ * @tx_fragments: number of transmitted MPDUs
+ * @txrate_idx: TBD
+ * @last_txrate_idx: TBD
+ * @wme_tx_queue: TBD
+ * @ampdu_mlme: TBD
+ * @timer_to_tid: identity mapping to ID timers
+ * @tid_to_tx_q: map tid to tx queue
+ * @llid: Local link ID
+ * @plid: Peer link ID
+ * @reason: Cancel reason on PLINK_HOLDING state
+ * @plink_retries: Retries in establishment
+ * @ignore_plink_timer: TBD
+ * @plink_state plink_state: TBD
+ * @plink_timeout: TBD
+ * @plink_timer: TBD
+ * @debugfs: debug filesystem info
*/
struct sta_info {
/* General information, mostly static */
@@ -217,14 +258,12 @@ struct sta_info {
unsigned long rx_packets, rx_bytes;
unsigned long wep_weak_iv_count;
unsigned long last_rx;
- unsigned long num_duplicates; /* number of duplicate frames received
- * from this STA */
- unsigned long rx_fragments; /* number of received MPDUs */
- unsigned long rx_dropped; /* number of dropped MPDUs from this STA */
- int last_signal; /* signal of last received frame from this STA */
- int last_qual; /* qual of last received frame from this STA */
- int last_noise; /* noise of last received frame from this STA */
- /* last received seq/frag number from this STA (per RX queue) */
+ unsigned long num_duplicates;
+ unsigned long rx_fragments;
+ unsigned long rx_dropped;
+ int last_signal;
+ int last_qual;
+ int last_noise;
__le16 last_seq_ctrl[NUM_RX_DATA_QUEUES];
#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
unsigned int wme_rx_queue[NUM_RX_DATA_QUEUES];
@@ -241,9 +280,9 @@ struct sta_info {
unsigned int fail_avg;
/* Updated from TX path only, no locking requirements */
- unsigned long tx_packets; /* number of RX/TX MSDUs */
+ unsigned long tx_packets;
unsigned long tx_bytes;
- unsigned long tx_fragments; /* number of transmitted MPDUs */
+ unsigned long tx_fragments;
int txrate_idx;
int last_txrate_idx;
#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
@@ -254,18 +293,18 @@ struct sta_info {
* Aggregation information, locked with lock.
*/
struct sta_ampdu_mlme ampdu_mlme;
- u8 timer_to_tid[STA_TID_NUM]; /* identity mapping to ID timers */
- u8 tid_to_tx_q[STA_TID_NUM]; /* map tid to tx queue */
+ u8 timer_to_tid[STA_TID_NUM];
+ u8 tid_to_tx_q[STA_TID_NUM];
#ifdef CONFIG_MAC80211_MESH
/*
* Mesh peer link attributes
* TODO: move to a sub-structure that is referenced with pointer?
*/
- __le16 llid; /* Local link ID */
- __le16 plid; /* Peer link ID */
- __le16 reason; /* Cancel reason on PLINK_HOLDING state */
- u8 plink_retries; /* Retries in establishment */
+ __le16 llid;
+ __le16 plid;
+ __le16 reason;
+ u8 plink_retries;
bool ignore_plink_timer;
enum plink_state plink_state;
u32 plink_timeout;
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c
index 1babb979fe0..736c32e340f 100644
--- a/net/mac80211/wext.c
+++ b/net/mac80211/wext.c
@@ -800,6 +800,8 @@ static int ieee80211_ioctl_siwfrag(struct net_device *dev,
if (frag->disabled)
local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
+ else if (!frag->fixed)
+ local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
else if (frag->value < 256 ||
frag->value > IEEE80211_MAX_FRAG_THRESHOLD)
return -EINVAL;
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c
index ffe1af82fa4..5c666f7eda8 100644
--- a/net/mac80211/wme.c
+++ b/net/mac80211/wme.c
@@ -154,7 +154,7 @@ static int wme_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd)
queue = skb_get_queue_mapping(skb);
rcu_read_lock();
sta = sta_info_get(local, hdr->addr1);
- tid = skb->priority & QOS_CONTROL_TAG1D_MASK;
+ tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
if (sta) {
int ampdu_queue = sta->tid_to_tx_q[tid];
if ((ampdu_queue < QD_NUM(hw)) &&
@@ -181,7 +181,7 @@ static int wme_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd)
if (ieee80211_is_data_qos(hdr->frame_control)) {
u8 *p = ieee80211_get_qos_ctl(hdr);
u8 ack_policy = 0;
- tid = skb->priority & QOS_CONTROL_TAG1D_MASK;
+ tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
if (local->wifi_wme_noack_test)
ack_policy |= QOS_CONTROL_ACK_POLICY_NOACK <<
QOS_CONTROL_ACK_POLICY_SHIFT;
@@ -210,7 +210,6 @@ static int wme_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd)
kfree_skb(skb);
err = NET_XMIT_DROP;
} else {
- tid = skb->priority & QOS_CONTROL_TAG1D_MASK;
skb_set_queue_mapping(skb, queue);
qdisc = q->queues[queue];
err = qdisc->enqueue(skb, qdisc);
diff --git a/net/mac80211/wme.h b/net/mac80211/wme.h
index bbdb5334481..1aca609eccf 100644
--- a/net/mac80211/wme.h
+++ b/net/mac80211/wme.h
@@ -19,18 +19,10 @@
#define QOS_CONTROL_ACK_POLICY_NORMAL 0
#define QOS_CONTROL_ACK_POLICY_NOACK 1
-#define QOS_CONTROL_TID_MASK 0x0f
#define QOS_CONTROL_ACK_POLICY_SHIFT 5
-#define QOS_CONTROL_TAG1D_MASK 0x07
-
extern const int ieee802_1d_to_ac[8];
-static inline int WLAN_FC_IS_QOS_DATA(u16 fc)
-{
- return (fc & 0x8C) == 0x88;
-}
-
#ifdef CONFIG_MAC80211_QOS
void ieee80211_install_qdisc(struct net_device *dev);
int ieee80211_qdisc_installed(struct net_device *dev);
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index b414d5d92f3..2f33df0dccc 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -11,6 +11,8 @@
#include <linux/slab.h>
#include <linux/skbuff.h>
#include <linux/compiler.h>
+#include <linux/ieee80211.h>
+#include <asm/unaligned.h>
#include <net/mac80211.h>
#include "ieee80211_i.h"
@@ -19,53 +21,30 @@
#include "aes_ccm.h"
#include "wpa.h"
-static int ieee80211_get_hdr_info(const struct sk_buff *skb, u8 **sa, u8 **da,
- u8 *qos_tid, u8 **data, size_t *data_len)
-{
- struct ieee80211_hdr *hdr;
- size_t hdrlen;
- __le16 fc;
-
- hdr = (struct ieee80211_hdr *)skb->data;
- fc = hdr->frame_control;
-
- hdrlen = ieee80211_hdrlen(fc);
-
- *sa = ieee80211_get_SA(hdr);
- *da = ieee80211_get_DA(hdr);
-
- *data = skb->data + hdrlen;
- *data_len = skb->len - hdrlen;
-
- if (ieee80211_is_data_qos(fc))
- *qos_tid = (*ieee80211_get_qos_ctl(hdr) & 0x0f) | 0x80;
- else
- *qos_tid = 0;
-
- return skb->len < hdrlen ? -1 : 0;
-}
-
-
ieee80211_tx_result
ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx)
{
- u8 *data, *sa, *da, *key, *mic, qos_tid, key_offset;
+ u8 *data, *key, *mic, key_offset;
size_t data_len;
- u16 fc;
+ unsigned int hdrlen;
+ struct ieee80211_hdr *hdr;
struct sk_buff *skb = tx->skb;
int authenticator;
int wpa_test = 0;
int tail;
- fc = tx->fc;
-
+ hdr = (struct ieee80211_hdr *)skb->data;
if (!tx->key || tx->key->conf.alg != ALG_TKIP || skb->len < 24 ||
- !WLAN_FC_DATA_PRESENT(fc))
+ !ieee80211_is_data_present(hdr->frame_control))
return TX_CONTINUE;
- if (ieee80211_get_hdr_info(skb, &sa, &da, &qos_tid, &data, &data_len))
+ 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) &&
@@ -95,7 +74,7 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx)
NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY;
key = &tx->key->conf.key[key_offset];
mic = skb_put(skb, MICHAEL_MIC_LEN);
- michael_mic(key, da, sa, qos_tid & 0x0f, data, data_len, mic);
+ michael_mic(key, hdr, data, data_len, mic);
return TX_CONTINUE;
}
@@ -104,31 +83,33 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx)
ieee80211_rx_result
ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx)
{
- u8 *data, *sa, *da, *key = NULL, qos_tid, key_offset;
+ u8 *data, *key = NULL, key_offset;
size_t data_len;
- u16 fc;
+ unsigned int hdrlen;
+ struct ieee80211_hdr *hdr;
u8 mic[MICHAEL_MIC_LEN];
struct sk_buff *skb = rx->skb;
int authenticator = 1, wpa_test = 0;
DECLARE_MAC_BUF(mac);
- fc = rx->fc;
-
/*
* No way to verify the MIC if the hardware stripped it
*/
if (rx->status->flag & RX_FLAG_MMIC_STRIPPED)
return RX_CONTINUE;
+ hdr = (struct ieee80211_hdr *)skb->data;
if (!rx->key || rx->key->conf.alg != ALG_TKIP ||
- !(rx->fc & IEEE80211_FCTL_PROTECTED) || !WLAN_FC_DATA_PRESENT(fc))
+ !ieee80211_has_protected(hdr->frame_control) ||
+ !ieee80211_is_data_present(hdr->frame_control))
return RX_CONTINUE;
- if (ieee80211_get_hdr_info(skb, &sa, &da, &qos_tid, &data, &data_len)
- || data_len < MICHAEL_MIC_LEN)
+ hdrlen = ieee80211_hdrlen(hdr->frame_control);
+ if (skb->len < hdrlen + MICHAEL_MIC_LEN)
return RX_DROP_UNUSABLE;
- data_len -= MICHAEL_MIC_LEN;
+ data = skb->data + hdrlen;
+ data_len = skb->len - hdrlen - MICHAEL_MIC_LEN;
#if 0
authenticator = fc & IEEE80211_FCTL_TODS; /* FIX */
@@ -141,7 +122,7 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx)
NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY :
NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY;
key = &rx->key->conf.key[key_offset];
- michael_mic(key, da, sa, qos_tid & 0x0f, data, data_len, mic);
+ michael_mic(key, hdr, data, data_len, mic);
if (memcmp(mic, data + data_len, MICHAEL_MIC_LEN) != 0 || wpa_test) {
if (!(rx->flags & IEEE80211_RX_RA_MATCH))
return RX_DROP_UNUSABLE;
@@ -253,7 +234,7 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx)
hdrlen = ieee80211_hdrlen(hdr->frame_control);
- if ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA)
+ if (!ieee80211_is_data(hdr->frame_control))
return RX_CONTINUE;
if (!rx->sta || skb->len - hdrlen < 12)
@@ -293,70 +274,68 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx)
}
-static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad,
+static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch,
int encrypted)
{
- u16 fc;
- int a4_included, qos_included;
- u8 qos_tid, *fc_pos, *data, *sa, *da;
- int len_a;
- size_t data_len;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+ __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;
- fc_pos = (u8 *) &hdr->frame_control;
- fc = fc_pos[0] ^ (fc_pos[1] << 8);
- a4_included = (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
- (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS);
-
- ieee80211_get_hdr_info(skb, &sa, &da, &qos_tid, &data, &data_len);
- data_len -= CCMP_HDR_LEN + (encrypted ? CCMP_MIC_LEN : 0);
- if (qos_tid & 0x80) {
- qos_included = 1;
- qos_tid &= 0x0f;
- } else
- qos_included = 0;
- /* First block, b_0 */
+ 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, 6);
+ memcpy(&b_0[2], hdr->addr2, ETH_ALEN);
memcpy(&b_0[8], pn, CCMP_PN_LEN);
/* l(m) */
- b_0[14] = (data_len >> 8) & 0xff;
- b_0[15] = data_len & 0xff;
-
+ put_unaligned_be16(data_len, &b_0[14]);
/* AAD (extra authenticate-only data) / masked 802.11 header
* FC | A1 | A2 | A3 | SC | [A4] | [QC] */
-
- len_a = a4_included ? 28 : 22;
- if (qos_included)
- len_a += 2;
-
- aad[0] = 0; /* (len_a >> 8) & 0xff; */
- aad[1] = len_a & 0xff;
- /* Mask FC: zero subtype b4 b5 b6 */
- aad[2] = fc_pos[0] & ~(BIT(4) | BIT(5) | BIT(6));
- /* Retry, PwrMgt, MoreData; set Protected */
- aad[3] = (fc_pos[1] & ~(BIT(3) | BIT(4) | BIT(5))) | BIT(6);
- memcpy(&aad[4], &hdr->addr1, 18);
+ 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, 6);
- aad[30] = 0;
+ memcpy(&aad[24], hdr->addr4, ETH_ALEN);
+ aad[30] = qos_tid;
aad[31] = 0;
- } else
- memset(&aad[24], 0, 8);
- if (qos_included) {
- u8 *dpos = &aad[a4_included ? 30 : 24];
-
- /* Mask QoS Control field */
- dpos[0] = qos_tid;
- dpos[1] = 0;
+ } else {
+ memset(&aad[24], 0, ETH_ALEN + IEEE80211_QOS_CTL_LEN);
+ aad[24] = qos_tid;
}
}
@@ -392,7 +371,7 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
struct ieee80211_key *key = tx->key;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
int hdrlen, len, tail;
- u8 *pos, *pn, *b_0, *aad, *scratch;
+ u8 *pos, *pn;
int i;
info->control.icv_len = CCMP_MIC_LEN;
@@ -406,10 +385,6 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
return 0;
}
- scratch = key->u.ccmp.tx_crypto_buf;
- b_0 = scratch + 3 * AES_BLOCK_LEN;
- aad = scratch + 4 * AES_BLOCK_LEN;
-
hdrlen = ieee80211_hdrlen(hdr->frame_control);
len = skb->len - hdrlen;
@@ -445,8 +420,8 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
}
pos += CCMP_HDR_LEN;
- ccmp_special_blocks(skb, pn, b_0, aad, 0);
- ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, scratch, b_0, aad, pos, 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;
@@ -478,7 +453,7 @@ ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx)
ieee80211_rx_result
ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
{
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
int hdrlen;
struct ieee80211_key *key = rx->key;
struct sk_buff *skb = rx->skb;
@@ -488,7 +463,7 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
hdrlen = ieee80211_hdrlen(hdr->frame_control);
- if ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA)
+ if (!ieee80211_is_data(hdr->frame_control))
return RX_CONTINUE;
data_len = skb->len - hdrlen - CCMP_HDR_LEN - CCMP_MIC_LEN;
@@ -508,16 +483,10 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
if (!(rx->status->flag & RX_FLAG_DECRYPTED)) {
/* hardware didn't decrypt/verify MIC */
- u8 *scratch, *b_0, *aad;
-
- scratch = key->u.ccmp.rx_crypto_buf;
- b_0 = scratch + 3 * AES_BLOCK_LEN;
- aad = scratch + 4 * AES_BLOCK_LEN;
-
- ccmp_special_blocks(skb, pn, b_0, aad, 1);
+ ccmp_special_blocks(skb, pn, key->u.ccmp.rx_crypto_buf, 1);
if (ieee80211_aes_ccm_decrypt(
- key->u.ccmp.tfm, scratch, b_0, aad,
+ 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)) {