diff options
author | Michael Braun <michael-dev@fami-braun.de> | 2016-10-15 13:28:19 +0200 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2016-10-17 11:43:33 +0200 |
commit | a3e2f4b6ed9de85086850fe49801f9b00adb6ae1 (patch) | |
tree | e3cbc8f949893d90583a81f0a47bfd5fe848c172 | |
parent | 06f2bb1e017166c6413debc28cf72087679242fb (diff) | |
download | linux-a3e2f4b6ed9de85086850fe49801f9b00adb6ae1.tar.gz linux-a3e2f4b6ed9de85086850fe49801f9b00adb6ae1.tar.bz2 linux-a3e2f4b6ed9de85086850fe49801f9b00adb6ae1.zip |
mac80211: fix A-MSDU outer SA/DA
According to IEEE 802.11-2012 section 8.3.2 table 8-19, the outer SA/DA
of A-MSDU frames need to be changed depending on FromDS/ToDS values.
Signed-off-by: Michael Braun <michael-dev@fami-braun.de>
[use ether_addr_copy and add alignment annotations]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r-- | include/net/mac80211.h | 2 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 2 | ||||
-rw-r--r-- | net/mac80211/tx.c | 23 |
3 files changed, 25 insertions, 2 deletions
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index a810dfcb83c2..e50c9e02889a 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1438,7 +1438,7 @@ enum ieee80211_vif_flags { struct ieee80211_vif { enum nl80211_iftype type; struct ieee80211_bss_conf bss_conf; - u8 addr[ETH_ALEN]; + u8 addr[ETH_ALEN] __aligned(2); bool p2p; bool csa_active; bool mu_mimo_owner; diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 103187ca9474..42d194a04e1a 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -443,7 +443,7 @@ struct ieee80211_if_managed { struct ieee80211_mgd_auth_data *auth_data; struct ieee80211_mgd_assoc_data *assoc_data; - u8 bssid[ETH_ALEN]; + u8 bssid[ETH_ALEN] __aligned(2); u16 aid; diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 9661f5441686..772e36909fa3 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -3064,6 +3064,7 @@ static bool ieee80211_amsdu_prepare_head(struct ieee80211_sub_if_data *sdata, int subframe_len = skb->len - hdr_len; void *data; u8 *qc, *h_80211_src, *h_80211_dst; + const u8 *bssid; if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) return false; @@ -3087,6 +3088,28 @@ static bool ieee80211_amsdu_prepare_head(struct ieee80211_sub_if_data *sdata, ether_addr_copy(amsdu_hdr->h_source, h_80211_src); ether_addr_copy(amsdu_hdr->h_dest, h_80211_dst); + /* according to IEEE 802.11-2012 8.3.2 table 8-19, the outer SA/DA + * fields needs to be changed to BSSID for A-MSDU frames depending + * on FromDS/ToDS values. + */ + switch (sdata->vif.type) { + case NL80211_IFTYPE_STATION: + bssid = sdata->u.mgd.bssid; + break; + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_AP_VLAN: + bssid = sdata->vif.addr; + break; + default: + bssid = NULL; + } + + if (bssid && ieee80211_has_fromds(hdr->frame_control)) + ether_addr_copy(h_80211_src, bssid); + + if (bssid && ieee80211_has_tods(hdr->frame_control)) + ether_addr_copy(h_80211_dst, bssid); + qc = ieee80211_get_qos_ctl(hdr); *qc |= IEEE80211_QOS_CTL_A_MSDU_PRESENT; |