Merge tag 'mac80211-next-for-davem-2019-04-26' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
Johannes Berg says: ==================== Various updates, notably: * extended key ID support (from 802.11-2016) * per-STA TX power control support * mac80211 TX performance improvements * HE (802.11ax) updates * mesh link probing support * enhancements of multi-BSSID support (also related to HE) * OWE userspace processing support ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
@@ -1005,23 +1005,43 @@ static int ieee80211_get_mmie_keyidx(struct sk_buff *skb)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int ieee80211_get_cs_keyid(const struct ieee80211_cipher_scheme *cs,
|
||||
struct sk_buff *skb)
|
||||
static int ieee80211_get_keyid(struct sk_buff *skb,
|
||||
const struct ieee80211_cipher_scheme *cs)
|
||||
{
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
__le16 fc;
|
||||
int hdrlen;
|
||||
int minlen;
|
||||
u8 key_idx_off;
|
||||
u8 key_idx_shift;
|
||||
u8 keyid;
|
||||
|
||||
fc = hdr->frame_control;
|
||||
hdrlen = ieee80211_hdrlen(fc);
|
||||
|
||||
if (skb->len < hdrlen + cs->hdr_len)
|
||||
if (cs) {
|
||||
minlen = hdrlen + cs->hdr_len;
|
||||
key_idx_off = hdrlen + cs->key_idx_off;
|
||||
key_idx_shift = cs->key_idx_shift;
|
||||
} else {
|
||||
/* WEP, TKIP, CCMP and GCMP */
|
||||
minlen = hdrlen + IEEE80211_WEP_IV_LEN;
|
||||
key_idx_off = hdrlen + 3;
|
||||
key_idx_shift = 6;
|
||||
}
|
||||
|
||||
if (unlikely(skb->len < minlen))
|
||||
return -EINVAL;
|
||||
|
||||
skb_copy_bits(skb, hdrlen + cs->key_idx_off, &keyid, 1);
|
||||
keyid &= cs->key_idx_mask;
|
||||
keyid >>= cs->key_idx_shift;
|
||||
skb_copy_bits(skb, key_idx_off, &keyid, 1);
|
||||
|
||||
if (cs)
|
||||
keyid &= cs->key_idx_mask;
|
||||
keyid >>= key_idx_shift;
|
||||
|
||||
/* cs could use more than the usual two bits for the keyid */
|
||||
if (unlikely(keyid >= NUM_DEFAULT_KEYS))
|
||||
return -EINVAL;
|
||||
|
||||
return keyid;
|
||||
}
|
||||
@@ -1860,9 +1880,9 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
|
||||
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
int keyidx;
|
||||
int hdrlen;
|
||||
ieee80211_rx_result result = RX_DROP_UNUSABLE;
|
||||
struct ieee80211_key *sta_ptk = NULL;
|
||||
struct ieee80211_key *ptk_idx = NULL;
|
||||
int mmie_keyidx = -1;
|
||||
__le16 fc;
|
||||
const struct ieee80211_cipher_scheme *cs = NULL;
|
||||
@@ -1900,21 +1920,24 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
|
||||
|
||||
if (rx->sta) {
|
||||
int keyid = rx->sta->ptk_idx;
|
||||
sta_ptk = rcu_dereference(rx->sta->ptk[keyid]);
|
||||
|
||||
if (ieee80211_has_protected(fc) && rx->sta->cipher_scheme) {
|
||||
if (ieee80211_has_protected(fc)) {
|
||||
cs = rx->sta->cipher_scheme;
|
||||
keyid = ieee80211_get_cs_keyid(cs, rx->skb);
|
||||
keyid = ieee80211_get_keyid(rx->skb, cs);
|
||||
|
||||
if (unlikely(keyid < 0))
|
||||
return RX_DROP_UNUSABLE;
|
||||
|
||||
ptk_idx = rcu_dereference(rx->sta->ptk[keyid]);
|
||||
}
|
||||
sta_ptk = rcu_dereference(rx->sta->ptk[keyid]);
|
||||
}
|
||||
|
||||
if (!ieee80211_has_protected(fc))
|
||||
mmie_keyidx = ieee80211_get_mmie_keyidx(rx->skb);
|
||||
|
||||
if (!is_multicast_ether_addr(hdr->addr1) && sta_ptk) {
|
||||
rx->key = sta_ptk;
|
||||
rx->key = ptk_idx ? ptk_idx : sta_ptk;
|
||||
if ((status->flag & RX_FLAG_DECRYPTED) &&
|
||||
(status->flag & RX_FLAG_IV_STRIPPED))
|
||||
return RX_CONTINUE;
|
||||
@@ -1974,8 +1997,6 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
|
||||
}
|
||||
return RX_CONTINUE;
|
||||
} else {
|
||||
u8 keyid;
|
||||
|
||||
/*
|
||||
* The device doesn't give us the IV so we won't be
|
||||
* able to look up the key. That's ok though, we
|
||||
@@ -1989,23 +2010,10 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
|
||||
(status->flag & RX_FLAG_IV_STRIPPED))
|
||||
return RX_CONTINUE;
|
||||
|
||||
hdrlen = ieee80211_hdrlen(fc);
|
||||
keyidx = ieee80211_get_keyid(rx->skb, cs);
|
||||
|
||||
if (cs) {
|
||||
keyidx = ieee80211_get_cs_keyid(cs, rx->skb);
|
||||
|
||||
if (unlikely(keyidx < 0))
|
||||
return RX_DROP_UNUSABLE;
|
||||
} else {
|
||||
if (rx->skb->len < 8 + hdrlen)
|
||||
return RX_DROP_UNUSABLE; /* TODO: count this? */
|
||||
/*
|
||||
* no need to call ieee80211_wep_get_keyidx,
|
||||
* it verifies a bunch of things we've done already
|
||||
*/
|
||||
skb_copy_bits(rx->skb, hdrlen + 3, &keyid, 1);
|
||||
keyidx = keyid >> 6;
|
||||
}
|
||||
if (unlikely(keyidx < 0))
|
||||
return RX_DROP_UNUSABLE;
|
||||
|
||||
/* check per-station GTK first, if multicast packet */
|
||||
if (is_multicast_ether_addr(hdr->addr1) && rx->sta)
|
||||
@@ -4050,12 +4058,8 @@ void ieee80211_check_fast_rx(struct sta_info *sta)
|
||||
case WLAN_CIPHER_SUITE_GCMP_256:
|
||||
break;
|
||||
default:
|
||||
/* we also don't want to deal with WEP or cipher scheme
|
||||
* since those require looking up the key idx in the
|
||||
* frame, rather than assuming the PTK is used
|
||||
* (we need to revisit this once we implement the real
|
||||
* PTK index, which is now valid in the spec, but we
|
||||
* haven't implemented that part yet)
|
||||
/* We also don't want to deal with
|
||||
* WEP or cipher scheme.
|
||||
*/
|
||||
goto clear_rcu;
|
||||
}
|
||||
|
Reference in New Issue
Block a user