diff options
-rw-r--r-- | net/mac80211/rx.c | 24 | ||||
-rw-r--r-- | net/mac80211/sta_info.h | 8 |
2 files changed, 25 insertions, 7 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 2ed882f8a9f..5f6751a0740 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -1342,15 +1342,20 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
1342 | 1342 | ||
1343 | /* | 1343 | /* |
1344 | * If we receive a 4-addr nullfunc frame from a STA | 1344 | * If we receive a 4-addr nullfunc frame from a STA |
1345 | * that was not moved to a 4-addr STA vlan yet, drop | 1345 | * that was not moved to a 4-addr STA vlan yet send |
1346 | * the frame to the monitor interface, to make sure | 1346 | * the event to userspace and for older hostapd drop |
1347 | * that hostapd sees it | 1347 | * the frame to the monitor interface. |
1348 | */ | 1348 | */ |
1349 | if (ieee80211_has_a4(hdr->frame_control) && | 1349 | if (ieee80211_has_a4(hdr->frame_control) && |
1350 | (rx->sdata->vif.type == NL80211_IFTYPE_AP || | 1350 | (rx->sdata->vif.type == NL80211_IFTYPE_AP || |
1351 | (rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && | 1351 | (rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && |
1352 | !rx->sdata->u.vlan.sta))) | 1352 | !rx->sdata->u.vlan.sta))) { |
1353 | if (!test_and_set_sta_flag(sta, WLAN_STA_4ADDR_EVENT)) | ||
1354 | cfg80211_rx_unexpected_4addr_frame( | ||
1355 | rx->sdata->dev, sta->sta.addr, | ||
1356 | GFP_ATOMIC); | ||
1353 | return RX_DROP_MONITOR; | 1357 | return RX_DROP_MONITOR; |
1358 | } | ||
1354 | /* | 1359 | /* |
1355 | * Update counter and free packet here to avoid | 1360 | * Update counter and free packet here to avoid |
1356 | * counting this as a dropped packed. | 1361 | * counting this as a dropped packed. |
@@ -2028,12 +2033,17 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx) | |||
2028 | return RX_DROP_MONITOR; | 2033 | return RX_DROP_MONITOR; |
2029 | 2034 | ||
2030 | /* | 2035 | /* |
2031 | * Allow the cooked monitor interface of an AP to see 4-addr frames so | 2036 | * Send unexpected-4addr-frame event to hostapd. For older versions, |
2032 | * that a 4-addr station can be detected and moved into a separate VLAN | 2037 | * also drop the frame to cooked monitor interfaces. |
2033 | */ | 2038 | */ |
2034 | if (ieee80211_has_a4(hdr->frame_control) && | 2039 | if (ieee80211_has_a4(hdr->frame_control) && |
2035 | sdata->vif.type == NL80211_IFTYPE_AP) | 2040 | sdata->vif.type == NL80211_IFTYPE_AP) { |
2041 | if (rx->sta && | ||
2042 | !test_and_set_sta_flag(rx->sta, WLAN_STA_4ADDR_EVENT)) | ||
2043 | cfg80211_rx_unexpected_4addr_frame( | ||
2044 | rx->sdata->dev, rx->sta->sta.addr, GFP_ATOMIC); | ||
2036 | return RX_DROP_MONITOR; | 2045 | return RX_DROP_MONITOR; |
2046 | } | ||
2037 | 2047 | ||
2038 | err = __ieee80211_data_to_8023(rx, &port_control); | 2048 | err = __ieee80211_data_to_8023(rx, &port_control); |
2039 | if (unlikely(err)) | 2049 | if (unlikely(err)) |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 8c8ce05ad26..c5923ab8a07 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -52,6 +52,7 @@ | |||
52 | * unblocks the station. | 52 | * unblocks the station. |
53 | * @WLAN_STA_SP: Station is in a service period, so don't try to | 53 | * @WLAN_STA_SP: Station is in a service period, so don't try to |
54 | * reply to other uAPSD trigger frames or PS-Poll. | 54 | * reply to other uAPSD trigger frames or PS-Poll. |
55 | * @WLAN_STA_4ADDR_EVENT: 4-addr event was already sent for this frame. | ||
55 | */ | 56 | */ |
56 | enum ieee80211_sta_info_flags { | 57 | enum ieee80211_sta_info_flags { |
57 | WLAN_STA_AUTH, | 58 | WLAN_STA_AUTH, |
@@ -71,6 +72,7 @@ enum ieee80211_sta_info_flags { | |||
71 | WLAN_STA_TDLS_PEER_AUTH, | 72 | WLAN_STA_TDLS_PEER_AUTH, |
72 | WLAN_STA_UAPSD, | 73 | WLAN_STA_UAPSD, |
73 | WLAN_STA_SP, | 74 | WLAN_STA_SP, |
75 | WLAN_STA_4ADDR_EVENT, | ||
74 | }; | 76 | }; |
75 | 77 | ||
76 | #define STA_TID_NUM 16 | 78 | #define STA_TID_NUM 16 |
@@ -390,6 +392,12 @@ static inline int test_and_clear_sta_flag(struct sta_info *sta, | |||
390 | return test_and_clear_bit(flag, &sta->_flags); | 392 | return test_and_clear_bit(flag, &sta->_flags); |
391 | } | 393 | } |
392 | 394 | ||
395 | static inline int test_and_set_sta_flag(struct sta_info *sta, | ||
396 | enum ieee80211_sta_info_flags flag) | ||
397 | { | ||
398 | return test_and_set_bit(flag, &sta->_flags); | ||
399 | } | ||
400 | |||
393 | void ieee80211_assign_tid_tx(struct sta_info *sta, int tid, | 401 | void ieee80211_assign_tid_tx(struct sta_info *sta, int tid, |
394 | struct tid_ampdu_tx *tid_tx); | 402 | struct tid_ampdu_tx *tid_tx); |
395 | 403 | ||