* [patch 1/7] mac80211: move sta_process rx handler later
2007-09-26 15:53 [patch 0/7] more mac80211 cleanups and fixes Johannes Berg
@ 2007-09-26 15:53 ` Johannes Berg
2007-09-26 15:53 ` [patch 2/7] mac80211: consolidate decryption more Johannes Berg
` (5 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Johannes Berg @ 2007-09-26 15:53 UTC (permalink / raw)
To: Michael Wu, John Linville; +Cc: linux-wireless
This moves the sta_process RX handler to after decryption
so that frames that cannot be decrypted don't influence
statistics, it is likely that they were injected or something
else is totally wrong.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
net/mac80211/rx.c | 96 +++++++++++++++++++++++++++---------------------------
1 file changed, 48 insertions(+), 48 deletions(-)
--- wireless-dev.orig/net/mac80211/rx.c 2007-09-26 15:56:17.608936654 +0200
+++ wireless-dev/net/mac80211/rx.c 2007-09-26 15:56:22.718936654 +0200
@@ -512,6 +512,53 @@ ieee80211_rx_h_load_key(struct ieee80211
return TXRX_CONTINUE;
}
+static ieee80211_txrx_result
+ieee80211_rx_h_wep_weak_iv_detection(struct ieee80211_txrx_data *rx)
+{
+ if (!rx->sta || !(rx->fc & IEEE80211_FCTL_PROTECTED) ||
+ (rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA ||
+ !rx->key || rx->key->conf.alg != ALG_WEP ||
+ !(rx->flags & IEEE80211_TXRXD_RXRA_MATCH))
+ return TXRX_CONTINUE;
+
+ /* Check for weak IVs, if hwaccel did not remove IV from the frame */
+ if (!(rx->u.rx.status->flag & RX_FLAG_IV_STRIPPED) ||
+ !(rx->u.rx.status->flag & RX_FLAG_DECRYPTED))
+ if (ieee80211_wep_is_weak_iv(rx->skb, rx->key))
+ rx->sta->wep_weak_iv_count++;
+
+ return TXRX_CONTINUE;
+}
+
+static ieee80211_txrx_result
+ieee80211_rx_h_decrypt(struct ieee80211_txrx_data *rx)
+{
+ if (!(rx->fc & IEEE80211_FCTL_PROTECTED))
+ return TXRX_CONTINUE;
+
+ if (!rx->key) {
+ if (net_ratelimit())
+ printk(KERN_DEBUG "%s: RX protected frame,"
+ " but have no key\n", rx->dev->name);
+ return TXRX_DROP;
+ }
+
+ switch (rx->key->conf.alg) {
+ case ALG_WEP:
+ return ieee80211_crypto_wep_decrypt(rx);
+ case ALG_TKIP:
+ return ieee80211_crypto_tkip_decrypt(rx);
+ case ALG_CCMP:
+ return ieee80211_crypto_ccmp_decrypt(rx);
+ case ALG_NONE:
+ return TXRX_CONTINUE;
+ }
+
+ /* not reached */
+ WARN_ON(1);
+ return TXRX_DROP;
+}
+
static void ap_sta_ps_start(struct net_device *dev, struct sta_info *sta)
{
struct ieee80211_sub_if_data *sdata;
@@ -637,53 +684,6 @@ ieee80211_rx_h_sta_process(struct ieee80
return TXRX_CONTINUE;
} /* ieee80211_rx_h_sta_process */
-static ieee80211_txrx_result
-ieee80211_rx_h_wep_weak_iv_detection(struct ieee80211_txrx_data *rx)
-{
- if (!rx->sta || !(rx->fc & IEEE80211_FCTL_PROTECTED) ||
- (rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA ||
- !rx->key || rx->key->conf.alg != ALG_WEP ||
- !(rx->flags & IEEE80211_TXRXD_RXRA_MATCH))
- return TXRX_CONTINUE;
-
- /* Check for weak IVs, if hwaccel did not remove IV from the frame */
- if (!(rx->u.rx.status->flag & RX_FLAG_IV_STRIPPED) ||
- !(rx->u.rx.status->flag & RX_FLAG_DECRYPTED))
- if (ieee80211_wep_is_weak_iv(rx->skb, rx->key))
- rx->sta->wep_weak_iv_count++;
-
- return TXRX_CONTINUE;
-}
-
-static ieee80211_txrx_result
-ieee80211_rx_h_decrypt(struct ieee80211_txrx_data *rx)
-{
- if (!(rx->fc & IEEE80211_FCTL_PROTECTED))
- return TXRX_CONTINUE;
-
- if (!rx->key) {
- if (net_ratelimit())
- printk(KERN_DEBUG "%s: RX protected frame,"
- " but have no key\n", rx->dev->name);
- return TXRX_DROP;
- }
-
- switch (rx->key->conf.alg) {
- case ALG_WEP:
- return ieee80211_crypto_wep_decrypt(rx);
- case ALG_TKIP:
- return ieee80211_crypto_tkip_decrypt(rx);
- case ALG_CCMP:
- return ieee80211_crypto_ccmp_decrypt(rx);
- case ALG_NONE:
- return TXRX_CONTINUE;
- }
-
- /* not reached */
- WARN_ON(1);
- return TXRX_DROP;
-}
-
static inline struct ieee80211_fragment_entry *
ieee80211_reassemble_add(struct ieee80211_sub_if_data *sdata,
unsigned int frag, unsigned int seq, int rx_queue,
@@ -1349,9 +1349,9 @@ ieee80211_rx_handler ieee80211_rx_handle
ieee80211_rx_h_passive_scan,
ieee80211_rx_h_check,
ieee80211_rx_h_load_key,
- ieee80211_rx_h_sta_process,
ieee80211_rx_h_wep_weak_iv_detection,
ieee80211_rx_h_decrypt,
+ ieee80211_rx_h_sta_process,
ieee80211_rx_h_defragment,
ieee80211_rx_h_ps_poll,
ieee80211_rx_h_michael_mic_verify,
--
^ permalink raw reply [flat|nested] 9+ messages in thread* [patch 2/7] mac80211: consolidate decryption more
2007-09-26 15:53 [patch 0/7] more mac80211 cleanups and fixes Johannes Berg
2007-09-26 15:53 ` [patch 1/7] mac80211: move sta_process rx handler later Johannes Berg
@ 2007-09-26 15:53 ` Johannes Berg
2007-09-26 15:53 ` [patch 3/7] mac80211: use RX_FLAG_DECRYPTED for sw decrypted as well Johannes Berg
` (4 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Johannes Berg @ 2007-09-26 15:53 UTC (permalink / raw)
To: Michael Wu, John Linville; +Cc: linux-wireless
Currently, we have three RX handlers doing the decryption.
This patch changes it to have only one handler doing
everything, thereby getting rid of many duplicate checks.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
net/mac80211/rx.c | 46 ++++++++++++----------------------------------
1 file changed, 12 insertions(+), 34 deletions(-)
--- wireless-dev.orig/net/mac80211/rx.c 2007-09-26 17:21:46.987337342 +0200
+++ wireless-dev/net/mac80211/rx.c 2007-09-26 17:21:48.997337342 +0200
@@ -419,7 +419,7 @@ ieee80211_rx_h_check(struct ieee80211_tx
static ieee80211_txrx_result
-ieee80211_rx_h_load_key(struct ieee80211_txrx_data *rx)
+ieee80211_rx_h_decrypt(struct ieee80211_txrx_data *rx)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
int keyidx;
@@ -456,7 +456,7 @@ ieee80211_rx_h_load_key(struct ieee80211
return TXRX_CONTINUE;
/*
- * No point in finding a key if the frame is neither
+ * No point in finding a key and decrypting if the frame is neither
* addressed to us nor a multicast frame.
*/
if (!(rx->flags & IEEE80211_TXRXD_RXRA_MATCH))
@@ -507,42 +507,21 @@ ieee80211_rx_h_load_key(struct ieee80211
if (rx->key) {
rx->key->tx_rx_count++;
/* TODO: add threshold stuff again */
- }
-
- return TXRX_CONTINUE;
-}
-
-static ieee80211_txrx_result
-ieee80211_rx_h_wep_weak_iv_detection(struct ieee80211_txrx_data *rx)
-{
- if (!rx->sta || !(rx->fc & IEEE80211_FCTL_PROTECTED) ||
- (rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA ||
- !rx->key || rx->key->conf.alg != ALG_WEP ||
- !(rx->flags & IEEE80211_TXRXD_RXRA_MATCH))
- return TXRX_CONTINUE;
-
- /* Check for weak IVs, if hwaccel did not remove IV from the frame */
- if (!(rx->u.rx.status->flag & RX_FLAG_IV_STRIPPED) ||
- !(rx->u.rx.status->flag & RX_FLAG_DECRYPTED))
- if (ieee80211_wep_is_weak_iv(rx->skb, rx->key))
- rx->sta->wep_weak_iv_count++;
-
- return TXRX_CONTINUE;
-}
-
-static ieee80211_txrx_result
-ieee80211_rx_h_decrypt(struct ieee80211_txrx_data *rx)
-{
- if (!(rx->fc & IEEE80211_FCTL_PROTECTED))
- return TXRX_CONTINUE;
-
- if (!rx->key) {
+ } else {
if (net_ratelimit())
printk(KERN_DEBUG "%s: RX protected frame,"
" but have no key\n", rx->dev->name);
return TXRX_DROP;
}
+ /* Check for weak IVs if possible */
+ if (rx->sta && rx->key->conf.alg == ALG_WEP &&
+ ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) &&
+ (!(rx->u.rx.status->flag & RX_FLAG_IV_STRIPPED) ||
+ !(rx->u.rx.status->flag & RX_FLAG_DECRYPTED)) &&
+ ieee80211_wep_is_weak_iv(rx->skb, rx->key))
+ rx->sta->wep_weak_iv_count++;
+
switch (rx->key->conf.alg) {
case ALG_WEP:
return ieee80211_crypto_wep_decrypt(rx);
@@ -551,6 +530,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_
case ALG_CCMP:
return ieee80211_crypto_ccmp_decrypt(rx);
case ALG_NONE:
+ WARN_ON(1);
return TXRX_CONTINUE;
}
@@ -1348,8 +1328,6 @@ ieee80211_rx_handler ieee80211_rx_handle
ieee80211_rx_h_if_stats,
ieee80211_rx_h_passive_scan,
ieee80211_rx_h_check,
- ieee80211_rx_h_load_key,
- ieee80211_rx_h_wep_weak_iv_detection,
ieee80211_rx_h_decrypt,
ieee80211_rx_h_sta_process,
ieee80211_rx_h_defragment,
--
^ permalink raw reply [flat|nested] 9+ messages in thread* [patch 3/7] mac80211: use RX_FLAG_DECRYPTED for sw decrypted as well
2007-09-26 15:53 [patch 0/7] more mac80211 cleanups and fixes Johannes Berg
2007-09-26 15:53 ` [patch 1/7] mac80211: move sta_process rx handler later Johannes Berg
2007-09-26 15:53 ` [patch 2/7] mac80211: consolidate decryption more Johannes Berg
@ 2007-09-26 15:53 ` Johannes Berg
2007-09-26 15:53 ` [patch 4/7] mac80211: remove ALG_NONE Johannes Berg
` (3 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Johannes Berg @ 2007-09-26 15:53 UTC (permalink / raw)
To: Michael Wu, John Linville; +Cc: linux-wireless
This makes mac80211 set the RX_FLAG_DECRYPTED flag for frames
decrypted in software allowing us to handle some things more
uniformly.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
net/mac80211/rx.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
--- wireless-dev.orig/net/mac80211/rx.c 2007-09-26 17:21:48.997337342 +0200
+++ wireless-dev/net/mac80211/rx.c 2007-09-26 17:39:36.717337342 +0200
@@ -522,6 +522,9 @@ ieee80211_rx_h_decrypt(struct ieee80211_
ieee80211_wep_is_weak_iv(rx->skb, rx->key))
rx->sta->wep_weak_iv_count++;
+ /* either the frame will be decrypted or dropped */
+ rx->u.rx.status->flag |= RX_FLAG_DECRYPTED;
+
switch (rx->key->conf.alg) {
case ALG_WEP:
return ieee80211_crypto_wep_decrypt(rx);
@@ -530,8 +533,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_
case ALG_CCMP:
return ieee80211_crypto_ccmp_decrypt(rx);
case ALG_NONE:
- WARN_ON(1);
- return TXRX_CONTINUE;
+ /* fall through, not reached */
}
/* not reached */
@@ -993,9 +995,8 @@ ieee80211_rx_h_drop_unencrypted(struct i
if (unlikely(!(rx->fc & IEEE80211_FCTL_PROTECTED) &&
(rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA &&
(rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_NULLFUNC &&
- (rx->key || rx->sdata->drop_unencrypted) &&
- (rx->sdata->eapol == 0 ||
- !ieee80211_is_eapol(rx->skb)))) {
+ rx->sdata->drop_unencrypted &&
+ (rx->sdata->eapol == 0 || !ieee80211_is_eapol(rx->skb)))) {
if (net_ratelimit())
printk(KERN_DEBUG "%s: RX non-WEP frame, but expected "
"encryption\n", rx->dev->name);
--
^ permalink raw reply [flat|nested] 9+ messages in thread* [patch 4/7] mac80211: remove ALG_NONE
2007-09-26 15:53 [patch 0/7] more mac80211 cleanups and fixes Johannes Berg
` (2 preceding siblings ...)
2007-09-26 15:53 ` [patch 3/7] mac80211: use RX_FLAG_DECRYPTED for sw decrypted as well Johannes Berg
@ 2007-09-26 15:53 ` Johannes Berg
2007-09-27 1:03 ` Zhu Yi
2007-09-26 15:53 ` [patch 5/7] mac80211: improve radiotap injection Johannes Berg
` (2 subsequent siblings)
6 siblings, 1 reply; 9+ messages in thread
From: Johannes Berg @ 2007-09-26 15:53 UTC (permalink / raw)
To: Michael Wu, John Linville; +Cc: linux-wireless, Michael Buesch, Zhu Yi
This "algorithm" is used only internally and is not useful.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Michael Buesch <mb@bu3sch.de>
Cc: Zhu Yi <yi.zhu@intel.com>
---
drivers/net/wireless/b43/main.c | 3 ---
drivers/net/wireless/iwlwifi/iwl3945-base.c | 4 ----
drivers/net/wireless/iwlwifi/iwl4965-base.c | 4 ----
include/net/mac80211.h | 2 --
net/mac80211/ieee80211_ioctl.c | 19 +++++++++++--------
net/mac80211/key.c | 1 -
net/mac80211/rx.c | 2 --
net/mac80211/tx.c | 2 --
8 files changed, 11 insertions(+), 26 deletions(-)
--- wireless-dev.orig/include/net/mac80211.h 2007-09-26 17:43:17.217337342 +0200
+++ wireless-dev/include/net/mac80211.h 2007-09-26 17:43:21.277337342 +0200
@@ -538,13 +538,11 @@ struct ieee80211_if_conf {
/**
* enum ieee80211_key_alg - key algorithm
- * @ALG_NONE: Unset key algorithm, will never be passed to the driver
* @ALG_WEP: WEP40 or WEP104
* @ALG_TKIP: TKIP
* @ALG_CCMP: CCMP (AES)
*/
enum ieee80211_key_alg {
- ALG_NONE,
ALG_WEP,
ALG_TKIP,
ALG_CCMP,
--- wireless-dev.orig/net/mac80211/ieee80211_ioctl.c 2007-09-26 17:41:53.227337342 +0200
+++ wireless-dev/net/mac80211/ieee80211_ioctl.c 2007-09-26 17:44:40.867337342 +0200
@@ -27,8 +27,9 @@
static int ieee80211_set_encryption(struct net_device *dev, u8 *sta_addr,
- int idx, int alg, int set_tx_key,
- const u8 *_key, size_t key_len)
+ int idx, int alg, int remove,
+ int set_tx_key, const u8 *_key,
+ size_t key_len)
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
int ret = 0;
@@ -75,7 +76,7 @@ static int ieee80211_set_encryption(stru
key = sta->key;
}
- if (alg == ALG_NONE) {
+ if (remove) {
ieee80211_key_free(key);
key = NULL;
} else {
@@ -827,6 +828,7 @@ static int ieee80211_ioctl_siwencode(str
struct ieee80211_sub_if_data *sdata;
int idx, i, alg = ALG_WEP;
u8 bcaddr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+ int remove = 0;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
@@ -845,7 +847,7 @@ static int ieee80211_ioctl_siwencode(str
idx--;
if (erq->flags & IW_ENCODE_DISABLED)
- alg = ALG_NONE;
+ remove = 1;
else if (erq->length == 0) {
/* No key data - just set the default TX key index */
ieee80211_set_default_key(sdata, idx);
@@ -854,7 +856,7 @@ static int ieee80211_ioctl_siwencode(str
return ieee80211_set_encryption(
dev, bcaddr,
- idx, alg,
+ idx, alg, remove,
!sdata->default_key,
keybuf, erq->length);
}
@@ -1005,11 +1007,11 @@ static int ieee80211_ioctl_siwencodeext(
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct iw_encode_ext *ext = (struct iw_encode_ext *) extra;
- int alg, idx, i;
+ int uninitialized_var(alg), idx, i, remove = 0;
switch (ext->alg) {
case IW_ENCODE_ALG_NONE:
- alg = ALG_NONE;
+ remove = 1;
break;
case IW_ENCODE_ALG_WEP:
alg = ALG_WEP;
@@ -1025,7 +1027,7 @@ static int ieee80211_ioctl_siwencodeext(
}
if (erq->flags & IW_ENCODE_DISABLED)
- alg = ALG_NONE;
+ remove = 1;
idx = erq->flags & IW_ENCODE_INDEX;
if (idx < 1 || idx > 4) {
@@ -1044,6 +1046,7 @@ static int ieee80211_ioctl_siwencodeext(
idx--;
return ieee80211_set_encryption(dev, ext->addr.sa_data, idx, alg,
+ remove,
ext->ext_flags &
IW_ENCODE_EXT_SET_TX_KEY,
ext->key, ext->key_len);
--- wireless-dev.orig/net/mac80211/key.c 2007-09-26 17:43:08.097337342 +0200
+++ wireless-dev/net/mac80211/key.c 2007-09-26 17:43:11.157337342 +0200
@@ -121,7 +121,6 @@ struct ieee80211_key *ieee80211_key_allo
struct ieee80211_key *key;
BUG_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS);
- BUG_ON(alg == ALG_NONE);
key = kzalloc(sizeof(struct ieee80211_key) + key_len, GFP_KERNEL);
if (!key)
--- wireless-dev.orig/net/mac80211/rx.c 2007-09-26 17:45:01.447337342 +0200
+++ wireless-dev/net/mac80211/rx.c 2007-09-26 17:45:32.207337342 +0200
@@ -532,8 +532,6 @@ ieee80211_rx_h_decrypt(struct ieee80211_
return ieee80211_crypto_tkip_decrypt(rx);
case ALG_CCMP:
return ieee80211_crypto_ccmp_decrypt(rx);
- case ALG_NONE:
- /* fall through, not reached */
}
/* not reached */
--- wireless-dev.orig/net/mac80211/tx.c 2007-09-26 17:45:43.277337342 +0200
+++ wireless-dev/net/mac80211/tx.c 2007-09-26 17:45:46.507337342 +0200
@@ -554,8 +554,6 @@ ieee80211_tx_h_encrypt(struct ieee80211_
return ieee80211_crypto_tkip_encrypt(tx);
case ALG_CCMP:
return ieee80211_crypto_ccmp_encrypt(tx);
- case ALG_NONE:
- return TXRX_CONTINUE;
}
/* not reached */
--- wireless-dev.orig/drivers/net/wireless/b43/main.c 2007-09-26 17:46:27.737337342 +0200
+++ wireless-dev/drivers/net/wireless/b43/main.c 2007-09-26 17:46:43.467337342 +0200
@@ -2893,9 +2893,6 @@ static int b43_dev_set_key(struct ieee80
if (!dev)
return -ENODEV;
switch (key->alg) {
- case ALG_NONE:
- algorithm = B43_SEC_ALGO_NONE;
- break;
case ALG_WEP:
if (key->keylen == 5)
algorithm = B43_SEC_ALGO_WEP40;
--- wireless-dev.orig/drivers/net/wireless/iwlwifi/iwl3945-base.c 2007-09-26 17:47:05.597337342 +0200
+++ wireless-dev/drivers/net/wireless/iwlwifi/iwl3945-base.c 2007-09-26 17:47:15.057337342 +0200
@@ -2595,10 +2595,6 @@ static void iwl_build_tx_cmd_hwcrypto(st
"with key %d\n", ctl->key_idx);
break;
- case ALG_NONE:
- IWL_DEBUG_TX("Tx packet in the clear (encrypt requested).\n");
- break;
-
default:
printk(KERN_ERR "Unknown encode alg %d\n", keyinfo->alg);
break;
--- wireless-dev.orig/drivers/net/wireless/iwlwifi/iwl4965-base.c 2007-09-26 17:47:20.237337342 +0200
+++ wireless-dev/drivers/net/wireless/iwlwifi/iwl4965-base.c 2007-09-26 17:47:23.817337342 +0200
@@ -2673,10 +2673,6 @@ static void iwl_build_tx_cmd_hwcrypto(st
"with key %d\n", ctl->key_idx);
break;
- case ALG_NONE:
- IWL_DEBUG_TX("Tx packet in the clear (encrypt requested).\n");
- break;
-
default:
printk(KERN_ERR "Unknown encode alg %d\n", keyinfo->alg);
break;
--
^ permalink raw reply [flat|nested] 9+ messages in thread* [patch 5/7] mac80211: improve radiotap injection
2007-09-26 15:53 [patch 0/7] more mac80211 cleanups and fixes Johannes Berg
` (3 preceding siblings ...)
2007-09-26 15:53 ` [patch 4/7] mac80211: remove ALG_NONE Johannes Berg
@ 2007-09-26 15:53 ` Johannes Berg
2007-09-26 15:53 ` [patch 6/7] mac80211: allow only one IBSS interface Johannes Berg
2007-09-26 15:53 ` [patch 7/7] mac80211: make userspace-mlme a per-interface setting Johannes Berg
6 siblings, 0 replies; 9+ messages in thread
From: Johannes Berg @ 2007-09-26 15:53 UTC (permalink / raw)
To: Michael Wu, John Linville; +Cc: linux-wireless, Andy Green
This improves radiotap injection by removing the shortcut over TX handlers
that led to BUGS when injecting frames without setting a rate and also
resulted in various other quirks. Now, TX handlers are run but some
information that was present in the radiotap header is used instead of
automatic settings.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Andy Green <andy@warmcat.com>
---
Documentation/networking/mac80211-injection.txt | 32 +++
net/mac80211/ieee80211_i.h | 1
net/mac80211/tx.c | 195 ++++++++++++------------
3 files changed, 131 insertions(+), 97 deletions(-)
--- wireless-dev.orig/net/mac80211/tx.c 2007-09-26 17:45:46.507337342 +0200
+++ wireless-dev/net/mac80211/tx.c 2007-09-26 17:51:21.617337342 +0200
@@ -222,6 +222,9 @@ ieee80211_tx_h_check_assoc(struct ieee80
#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
u32 sta_flags;
+ if (unlikely(tx->flags & IEEE80211_TXRXD_TX_INJECTED))
+ return TXRX_CONTINUE;
+
if (unlikely(tx->local->sta_scanning != 0) &&
((tx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT ||
(tx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_PROBE_REQ))
@@ -566,22 +569,27 @@ ieee80211_tx_h_rate_ctrl(struct ieee8021
{
struct rate_control_extra extra;
- memset(&extra, 0, sizeof(extra));
- extra.mode = tx->u.tx.mode;
- extra.ethertype = tx->ethertype;
-
- tx->u.tx.rate = rate_control_get_rate(tx->local, tx->dev, tx->skb,
- &extra);
- if (unlikely(extra.probe != NULL)) {
- tx->u.tx.control->flags |= IEEE80211_TXCTL_RATE_CTRL_PROBE;
- tx->flags |= IEEE80211_TXRXD_TXPROBE_LAST_FRAG;
- tx->u.tx.control->alt_retry_rate = tx->u.tx.rate->val;
- tx->u.tx.rate = extra.probe;
- } else {
+ if (likely(!tx->u.tx.rate)) {
+ memset(&extra, 0, sizeof(extra));
+ extra.mode = tx->u.tx.mode;
+ extra.ethertype = tx->ethertype;
+
+ tx->u.tx.rate = rate_control_get_rate(tx->local, tx->dev,
+ tx->skb, &extra);
+ if (unlikely(extra.probe != NULL)) {
+ tx->u.tx.control->flags |=
+ IEEE80211_TXCTL_RATE_CTRL_PROBE;
+ tx->flags |= IEEE80211_TXRXD_TXPROBE_LAST_FRAG;
+ tx->u.tx.control->alt_retry_rate = tx->u.tx.rate->val;
+ tx->u.tx.rate = extra.probe;
+ } else
+ tx->u.tx.control->alt_retry_rate = -1;
+
+ if (!tx->u.tx.rate)
+ return TXRX_DROP;
+ } else
tx->u.tx.control->alt_retry_rate = -1;
- }
- if (!tx->u.tx.rate)
- return TXRX_DROP;
+
if (tx->u.tx.mode->mode == MODE_IEEE80211G &&
(tx->sdata->flags & IEEE80211_SDATA_USE_PROTECTION) &&
(tx->flags & IEEE80211_TXRXD_FRAGMENTED) && extra.nonerp) {
@@ -611,19 +619,24 @@ ieee80211_tx_h_misc(struct ieee80211_txr
struct ieee80211_tx_control *control = tx->u.tx.control;
struct ieee80211_hw_mode *mode = tx->u.tx.mode;
- if (!is_multicast_ether_addr(hdr->addr1)) {
- if (tx->skb->len + FCS_LEN > tx->local->rts_threshold &&
- tx->local->rts_threshold < IEEE80211_MAX_RTS_THRESHOLD) {
- control->flags |= IEEE80211_TXCTL_USE_RTS_CTS;
- control->flags |= IEEE80211_TXCTL_LONG_RETRY_LIMIT;
- control->retry_limit =
- tx->local->long_retry_limit;
+ if (!control->retry_limit) {
+ if (!is_multicast_ether_addr(hdr->addr1)) {
+ if (tx->skb->len + FCS_LEN > tx->local->rts_threshold
+ && tx->local->rts_threshold <
+ IEEE80211_MAX_RTS_THRESHOLD) {
+ control->flags |=
+ IEEE80211_TXCTL_USE_RTS_CTS;
+ control->flags |=
+ IEEE80211_TXCTL_LONG_RETRY_LIMIT;
+ control->retry_limit =
+ tx->local->long_retry_limit;
+ } else {
+ control->retry_limit =
+ tx->local->short_retry_limit;
+ }
} else {
- control->retry_limit =
- tx->local->short_retry_limit;
+ control->retry_limit = 1;
}
- } else {
- control->retry_limit = 1;
}
if (tx->flags & IEEE80211_TXRXD_FRAGMENTED) {
@@ -785,9 +798,8 @@ ieee80211_tx_handler ieee80211_tx_handle
* with Radiotap Header -- only called for monitor mode interface
*/
static ieee80211_txrx_result
-__ieee80211_parse_tx_radiotap(
- struct ieee80211_txrx_data *tx,
- struct sk_buff *skb, struct ieee80211_tx_control *control)
+__ieee80211_parse_tx_radiotap(struct ieee80211_txrx_data *tx,
+ struct sk_buff *skb)
{
/*
* this is the moment to interpret and discard the radiotap header that
@@ -802,18 +814,11 @@ __ieee80211_parse_tx_radiotap(
(struct ieee80211_radiotap_header *) skb->data;
struct ieee80211_hw_mode *mode = tx->local->hw.conf.mode;
int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len);
+ struct ieee80211_tx_control *control = tx->u.tx.control;
- /*
- * default control situation for all injected packets
- * FIXME: this does not suit all usage cases, expand to allow control
- */
-
- control->retry_limit = 1; /* no retry */
- control->flags &= ~(IEEE80211_TXCTL_USE_RTS_CTS |
- IEEE80211_TXCTL_USE_CTS_PROTECT);
- control->flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT |
- IEEE80211_TXCTL_NO_ACK;
- control->antenna_sel_tx = 0; /* default to default antenna */
+ control->flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT;
+ tx->flags |= IEEE80211_TXRXD_TX_INJECTED;
+ tx->flags &= ~IEEE80211_TXRXD_FRAGMENTED;
/*
* for every radiotap entry that is present
@@ -846,19 +851,10 @@ __ieee80211_parse_tx_radiotap(
for (i = 0; i < mode->num_rates; i++) {
struct ieee80211_rate *r = &mode->rates[i];
- if (r->rate > target_rate)
- continue;
-
- control->rate = r;
-
- if (r->flags & IEEE80211_RATE_PREAMBLE2)
- control->tx_rate = r->val2;
- else
- control->tx_rate = r->val;
-
- /* end on exact match */
- if (r->rate == target_rate)
- i = mode->num_rates;
+ if (r->rate == target_rate) {
+ tx->u.tx.rate = r;
+ break;
+ }
}
break;
@@ -888,8 +884,19 @@ __ieee80211_parse_tx_radiotap(
skb_trim(skb, skb->len - FCS_LEN);
}
+ if (*iterator.this_arg & IEEE80211_RADIOTAP_F_WEP)
+ control->flags &=
+ ~IEEE80211_TXCTL_DO_NOT_ENCRYPT;
+ if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FRAG)
+ tx->flags |= IEEE80211_TXRXD_FRAGMENTED;
break;
+ /*
+ * Please update the file
+ * Documentation/networking/mac80211-injection.txt
+ * when parsing new fields here.
+ */
+
default:
break;
}
@@ -908,14 +915,17 @@ __ieee80211_parse_tx_radiotap(
return TXRX_CONTINUE;
}
-static ieee80211_txrx_result inline
+/*
+ * initialises @tx
+ */
+static ieee80211_txrx_result
__ieee80211_tx_prepare(struct ieee80211_txrx_data *tx,
struct sk_buff *skb,
struct net_device *dev,
struct ieee80211_tx_control *control)
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+ struct ieee80211_hdr *hdr;
struct ieee80211_sub_if_data *sdata;
ieee80211_txrx_result res = TXRX_CONTINUE;
@@ -926,33 +936,31 @@ __ieee80211_tx_prepare(struct ieee80211_
tx->dev = dev; /* use original interface */
tx->local = local;
tx->sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
+ tx->u.tx.control = control;
/*
- * set defaults for things that can be set by
- * injected radiotap headers
+ * Set this flag (used below to indicate "automatic fragmentation"),
+ * it will be cleared/left by radiotap as desired.
*/
- control->power_level = local->hw.conf.power_level;
- control->antenna_sel_tx = local->hw.conf.antenna_sel_tx;
+ tx->flags |= IEEE80211_TXRXD_FRAGMENTED;
/* process and remove the injection radiotap header */
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (unlikely(sdata->type == IEEE80211_IF_TYPE_MNTR)) {
- if (__ieee80211_parse_tx_radiotap(tx, skb, control) ==
- TXRX_DROP) {
+ if (__ieee80211_parse_tx_radiotap(tx, skb) == TXRX_DROP)
return TXRX_DROP;
- }
+
/*
- * we removed the radiotap header after this point,
- * we filled control with what we could use
- * set to the actual ieee header now
+ * __ieee80211_parse_tx_radiotap has now removed
+ * the radiotap header that was present and pre-filled
+ * 'tx' with tx control information.
*/
- hdr = (struct ieee80211_hdr *) skb->data;
- res = TXRX_QUEUED; /* indication it was monitor packet */
}
+ hdr = (struct ieee80211_hdr *) skb->data;
+
tx->sta = sta_info_get(local, hdr->addr1);
tx->fc = le16_to_cpu(hdr->frame_control);
- tx->u.tx.control = control;
+
if (is_multicast_ether_addr(hdr->addr1)) {
tx->flags &= ~IEEE80211_TXRXD_TXUNICAST;
control->flags |= IEEE80211_TXCTL_NO_ACK;
@@ -960,19 +968,23 @@ __ieee80211_tx_prepare(struct ieee80211_
tx->flags |= IEEE80211_TXRXD_TXUNICAST;
control->flags &= ~IEEE80211_TXCTL_NO_ACK;
}
- if (local->fragmentation_threshold < IEEE80211_MAX_FRAG_THRESHOLD &&
- (tx->flags & IEEE80211_TXRXD_TXUNICAST) &&
- skb->len + FCS_LEN > local->fragmentation_threshold &&
- !local->ops->set_frag_threshold)
- tx->flags |= IEEE80211_TXRXD_FRAGMENTED;
- else
- tx->flags &= ~IEEE80211_TXRXD_FRAGMENTED;
+
+ if (tx->flags & IEEE80211_TXRXD_FRAGMENTED) {
+ if ((tx->flags & IEEE80211_TXRXD_TXUNICAST) &&
+ skb->len + FCS_LEN > local->fragmentation_threshold &&
+ !local->ops->set_frag_threshold)
+ tx->flags |= IEEE80211_TXRXD_FRAGMENTED;
+ else
+ tx->flags &= ~IEEE80211_TXRXD_FRAGMENTED;
+ }
+
if (!tx->sta)
control->flags |= IEEE80211_TXCTL_CLEAR_DST_MASK;
else if (tx->sta->clear_dst_mask) {
control->flags |= IEEE80211_TXCTL_CLEAR_DST_MASK;
tx->sta->clear_dst_mask = 0;
}
+
hdrlen = ieee80211_get_hdrlen(tx->fc);
if (skb->len > hdrlen + sizeof(rfc1042_header) + 2) {
u8 *pos = &skb->data[hdrlen + sizeof(rfc1042_header)];
@@ -984,11 +996,14 @@ __ieee80211_tx_prepare(struct ieee80211_
}
/* Device in tx->dev has a reference added; use dev_put(tx->dev) when
- * finished with it. */
-static int inline ieee80211_tx_prepare(struct ieee80211_txrx_data *tx,
- struct sk_buff *skb,
- struct net_device *mdev,
- struct ieee80211_tx_control *control)
+ * finished with it.
+ *
+ * NB: @tx is uninitialised when passed in here
+ */
+static int ieee80211_tx_prepare(struct ieee80211_txrx_data *tx,
+ struct sk_buff *skb,
+ struct net_device *mdev,
+ struct ieee80211_tx_control *control)
{
struct ieee80211_tx_packet_data *pkt_data;
struct net_device *dev;
@@ -1001,6 +1016,7 @@ static int inline ieee80211_tx_prepare(s
}
if (unlikely(!dev))
return -ENODEV;
+ /* initialises tx with control */
__ieee80211_tx_prepare(tx, skb, dev, control);
return 0;
}
@@ -1081,6 +1097,7 @@ static int ieee80211_tx(struct net_devic
return 0;
}
+ /* initialises tx */
res_prepare = __ieee80211_tx_prepare(&tx, skb, dev, control);
if (res_prepare == TXRX_DROP) {
@@ -1097,15 +1114,11 @@ static int ieee80211_tx(struct net_devic
sta = tx.sta;
tx.u.tx.mode = local->hw.conf.mode;
- if (res_prepare == TXRX_QUEUED) { /* if it was an injected packet */
- res = TXRX_CONTINUE;
- } else {
- for (handler = local->tx_handlers; *handler != NULL;
- handler++) {
- res = (*handler)(&tx);
- if (res != TXRX_CONTINUE)
- break;
- }
+ for (handler = local->tx_handlers; *handler != NULL;
+ handler++) {
+ res = (*handler)(&tx);
+ if (res != TXRX_CONTINUE)
+ break;
}
skb = tx.skb; /* handlers are allowed to change skb */
@@ -1857,7 +1870,7 @@ ieee80211_get_buffered_bc(struct ieee802
cpu_to_le16(IEEE80211_FCTL_MOREDATA);
}
- if (ieee80211_tx_prepare(&tx, skb, local->mdev, control) == 0)
+ if (!ieee80211_tx_prepare(&tx, skb, local->mdev, control))
break;
dev_kfree_skb_any(skb);
}
--- wireless-dev.orig/Documentation/networking/mac80211-injection.txt 2007-09-26 17:38:20.637337342 +0200
+++ wireless-dev/Documentation/networking/mac80211-injection.txt 2007-09-26 17:51:21.617337342 +0200
@@ -13,15 +13,35 @@ The radiotap format is discussed in
./Documentation/networking/radiotap-headers.txt.
Despite 13 radiotap argument types are currently defined, most only make sense
-to appear on received packets. Currently three kinds of argument are used by
-the injection code, although it knows to skip any other arguments that are
-present (facilitating replay of captured radiotap headers directly):
+to appear on received packets. The following information is parsed from the
+radiotap headers and used to control injection:
- - IEEE80211_RADIOTAP_RATE - u8 arg in 500kbps units (0x02 --> 1Mbps)
+ * IEEE80211_RADIOTAP_RATE
- - IEEE80211_RADIOTAP_ANTENNA - u8 arg, 0x00 = ant1, 0x01 = ant2
+ rate in 500kbps units, automatic if invalid or not present
- - IEEE80211_RADIOTAP_DBM_TX_POWER - u8 arg, dBm
+
+ * IEEE80211_RADIOTAP_ANTENNA
+
+ antenna to use, automatic if not present
+
+
+ * IEEE80211_RADIOTAP_DBM_TX_POWER
+
+ transmit power in dBm, automatic if not present
+
+
+ * IEEE80211_RADIOTAP_FLAGS
+
+ IEEE80211_RADIOTAP_F_FCS: FCS will be removed and recalculated
+ IEEE80211_RADIOTAP_F_WEP: frame will be encrypted if key available
+ IEEE80211_RADIOTAP_F_FRAG: frame will be fragmented if longer than the
+ current fragmentation threshold. Note that
+ this flag is only reliable when software
+ fragmentation is enabled)
+
+The injection code can also skip all other currently defined radiotap fields
+facilitating replay of captured radiotap headers directly.
Here is an example valid radiotap header defining these three parameters
--- wireless-dev.orig/net/mac80211/ieee80211_i.h 2007-09-26 17:38:20.567337342 +0200
+++ wireless-dev/net/mac80211/ieee80211_i.h 2007-09-26 17:51:21.617337342 +0200
@@ -122,6 +122,7 @@ typedef enum {
#define IEEE80211_TXRXD_RXIN_SCAN BIT(4)
/* frame is destined to interface currently processed (incl. multicast frames) */
#define IEEE80211_TXRXD_RXRA_MATCH BIT(5)
+#define IEEE80211_TXRXD_TX_INJECTED BIT(6)
struct ieee80211_txrx_data {
struct sk_buff *skb;
struct net_device *dev;
--
^ permalink raw reply [flat|nested] 9+ messages in thread* [patch 6/7] mac80211: allow only one IBSS interface
2007-09-26 15:53 [patch 0/7] more mac80211 cleanups and fixes Johannes Berg
` (4 preceding siblings ...)
2007-09-26 15:53 ` [patch 5/7] mac80211: improve radiotap injection Johannes Berg
@ 2007-09-26 15:53 ` Johannes Berg
2007-09-26 15:53 ` [patch 7/7] mac80211: make userspace-mlme a per-interface setting Johannes Berg
6 siblings, 0 replies; 9+ messages in thread
From: Johannes Berg @ 2007-09-26 15:53 UTC (permalink / raw)
To: Michael Wu, John Linville; +Cc: linux-wireless
Consider the case of multiple virtual IBSS interfaces
trying to join the same IBSS. They wouldn't see beacons
that the other virtual interface sent of course so this
leads to problems. Disallow it.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
net/mac80211/ieee80211.c | 21 +++++++++++++++++++--
1 file changed, 19 insertions(+), 2 deletions(-)
--- wireless-dev.orig/net/mac80211/ieee80211.c 2007-09-26 17:21:42.667337342 +0200
+++ wireless-dev/net/mac80211/ieee80211.c 2007-09-26 17:21:51.317337342 +0200
@@ -170,8 +170,25 @@ static int ieee80211_open(struct net_dev
list_for_each_entry(nsdata, &local->interfaces, list) {
struct net_device *ndev = nsdata->dev;
- if (ndev != dev && ndev != local->mdev && netif_running(ndev) &&
- compare_ether_addr(dev->dev_addr, ndev->dev_addr) == 0) {
+ if (ndev != dev && ndev != local->mdev &&
+ netif_running(ndev)) {
+ /*
+ * We really only support one IBSS interface, think
+ * what would happen if they tried to be in the same
+ * BSS.
+ */
+ if (sdata->type == IEEE80211_IF_TYPE_IBSS &&
+ nsdata->type == IEEE80211_IF_TYPE_IBSS &&
+ netif_running(nsdata->dev))
+ return -EBUSY;
+
+ /*
+ * The remaining checks are only done for devices
+ * with the same MAC address.
+ */
+ if (compare_ether_addr(dev->dev_addr, ndev->dev_addr))
+ continue;
+
/*
* check whether it may have the same address
*/
--
^ permalink raw reply [flat|nested] 9+ messages in thread* [patch 7/7] mac80211: make userspace-mlme a per-interface setting
2007-09-26 15:53 [patch 0/7] more mac80211 cleanups and fixes Johannes Berg
` (5 preceding siblings ...)
2007-09-26 15:53 ` [patch 6/7] mac80211: allow only one IBSS interface Johannes Berg
@ 2007-09-26 15:53 ` Johannes Berg
6 siblings, 0 replies; 9+ messages in thread
From: Johannes Berg @ 2007-09-26 15:53 UTC (permalink / raw)
To: Michael Wu, John Linville; +Cc: linux-wireless
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
net/mac80211/ieee80211.c | 2 +-
net/mac80211/ieee80211_i.h | 3 +--
net/mac80211/ieee80211_ioctl.c | 12 +++++-------
net/mac80211/rx.c | 2 +-
4 files changed, 8 insertions(+), 11 deletions(-)
--- wireless-dev.orig/net/mac80211/ieee80211_i.h 2007-09-26 17:51:21.617337342 +0200
+++ wireless-dev/net/mac80211/ieee80211_i.h 2007-09-26 17:51:25.817337342 +0200
@@ -287,6 +287,7 @@ struct ieee80211_if_sta {
* generator reports that there are no present stations that cannot support short
* preambles */
#define IEEE80211_SDATA_SHORT_PREAMBLE BIT(3)
+#define IEEE80211_SDATA_USERSPACE_MLME BIT(4)
struct ieee80211_sub_if_data {
struct list_head list;
enum ieee80211_if_types type;
@@ -553,8 +554,6 @@ struct ieee80211_local {
unsigned int hw_modes; /* bitfield of supported hardware modes;
* (1 << MODE_*) */
- int user_space_mlme;
-
#ifdef CONFIG_MAC80211_DEBUGFS
struct local_debugfsdentries {
struct dentry *channel;
--- wireless-dev.orig/net/mac80211/ieee80211.c 2007-09-26 17:51:24.757337342 +0200
+++ wireless-dev/net/mac80211/ieee80211.c 2007-09-26 17:51:25.827337342 +0200
@@ -267,7 +267,7 @@ static int ieee80211_open(struct net_dev
ieee80211_enable_keys(sdata);
if (sdata->type == IEEE80211_IF_TYPE_STA &&
- !local->user_space_mlme)
+ !(sdata->flags & IEEE80211_SDATA_USERSPACE_MLME))
netif_carrier_off(dev);
else
netif_carrier_on(dev);
--- wireless-dev.orig/net/mac80211/ieee80211_ioctl.c 2007-09-26 17:44:40.867337342 +0200
+++ wireless-dev/net/mac80211/ieee80211_ioctl.c 2007-09-26 17:51:25.827337342 +0200
@@ -105,12 +105,12 @@ static int ieee80211_ioctl_siwgenie(stru
struct iw_point *data, char *extra)
{
struct ieee80211_sub_if_data *sdata;
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
- if (local->user_space_mlme)
+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+ if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME)
return -EOPNOTSUPP;
- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (sdata->type == IEEE80211_IF_TYPE_STA ||
sdata->type == IEEE80211_IF_TYPE_IBSS) {
int ret = ieee80211_sta_set_extra_ie(dev, extra, data->length);
@@ -374,7 +374,6 @@ static int ieee80211_ioctl_siwessid(stru
struct iw_request_info *info,
struct iw_point *data, char *ssid)
{
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_sub_if_data *sdata;
size_t len = data->length;
@@ -386,7 +385,7 @@ static int ieee80211_ioctl_siwessid(stru
if (sdata->type == IEEE80211_IF_TYPE_STA ||
sdata->type == IEEE80211_IF_TYPE_IBSS) {
int ret;
- if (local->user_space_mlme) {
+ if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) {
if (len > IEEE80211_MAX_SSID_LEN)
return -EINVAL;
memcpy(sdata->u.sta.ssid, ssid, len);
@@ -451,14 +450,13 @@ static int ieee80211_ioctl_siwap(struct
struct iw_request_info *info,
struct sockaddr *ap_addr, char *extra)
{
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_sub_if_data *sdata;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (sdata->type == IEEE80211_IF_TYPE_STA ||
sdata->type == IEEE80211_IF_TYPE_IBSS) {
int ret;
- if (local->user_space_mlme) {
+ if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) {
memcpy(sdata->u.sta.bssid, (u8 *) &ap_addr->sa_data,
ETH_ALEN);
return 0;
--- wireless-dev.orig/net/mac80211/rx.c 2007-09-26 17:45:32.207337342 +0200
+++ wireless-dev/net/mac80211/rx.c 2007-09-26 17:51:25.837337342 +0200
@@ -1199,7 +1199,7 @@ ieee80211_rx_h_mgmt(struct ieee80211_txr
sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev);
if ((sdata->type == IEEE80211_IF_TYPE_STA ||
sdata->type == IEEE80211_IF_TYPE_IBSS) &&
- !rx->local->user_space_mlme)
+ !(sdata->flags & IEEE80211_SDATA_USERSPACE_MLME))
ieee80211_sta_rx_mgmt(rx->dev, rx->skb, rx->u.rx.status);
else
return TXRX_DROP;
--
^ permalink raw reply [flat|nested] 9+ messages in thread