diff options
Diffstat (limited to 'net/mac80211/rx.c')
-rw-r--r-- | net/mac80211/rx.c | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 7e09b30dd393..71cce0bcc5be 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -1511,6 +1511,65 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx) | |||
1511 | } | 1511 | } |
1512 | 1512 | ||
1513 | static ieee80211_rx_result debug_noinline | 1513 | static ieee80211_rx_result debug_noinline |
1514 | ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | ||
1515 | { | ||
1516 | struct ieee80211_local *local = rx->local; | ||
1517 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); | ||
1518 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; | ||
1519 | int len = rx->skb->len; | ||
1520 | |||
1521 | if (!ieee80211_is_action(mgmt->frame_control)) | ||
1522 | return RX_CONTINUE; | ||
1523 | |||
1524 | if (!rx->sta) | ||
1525 | return RX_DROP_MONITOR; | ||
1526 | |||
1527 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) | ||
1528 | return RX_DROP_MONITOR; | ||
1529 | |||
1530 | /* all categories we currently handle have action_code */ | ||
1531 | if (len < IEEE80211_MIN_ACTION_SIZE + 1) | ||
1532 | return RX_DROP_MONITOR; | ||
1533 | |||
1534 | /* | ||
1535 | * FIXME: revisit this, I'm sure we should handle most | ||
1536 | * of these frames in other modes as well! | ||
1537 | */ | ||
1538 | if (sdata->vif.type != IEEE80211_IF_TYPE_STA && | ||
1539 | sdata->vif.type != IEEE80211_IF_TYPE_IBSS) | ||
1540 | return RX_DROP_MONITOR; | ||
1541 | |||
1542 | switch (mgmt->u.action.category) { | ||
1543 | case WLAN_CATEGORY_BACK: | ||
1544 | switch (mgmt->u.action.u.addba_req.action_code) { | ||
1545 | case WLAN_ACTION_ADDBA_REQ: | ||
1546 | if (len < (IEEE80211_MIN_ACTION_SIZE + | ||
1547 | sizeof(mgmt->u.action.u.addba_req))) | ||
1548 | return RX_DROP_MONITOR; | ||
1549 | ieee80211_process_addba_request(local, rx->sta, mgmt, len); | ||
1550 | break; | ||
1551 | case WLAN_ACTION_ADDBA_RESP: | ||
1552 | if (len < (IEEE80211_MIN_ACTION_SIZE + | ||
1553 | sizeof(mgmt->u.action.u.addba_resp))) | ||
1554 | return RX_DROP_MONITOR; | ||
1555 | ieee80211_process_addba_resp(local, rx->sta, mgmt, len); | ||
1556 | break; | ||
1557 | case WLAN_ACTION_DELBA: | ||
1558 | if (len < (IEEE80211_MIN_ACTION_SIZE + | ||
1559 | sizeof(mgmt->u.action.u.delba))) | ||
1560 | return RX_DROP_MONITOR; | ||
1561 | ieee80211_process_delba(sdata, rx->sta, mgmt, len); | ||
1562 | break; | ||
1563 | } | ||
1564 | rx->sta->rx_packets++; | ||
1565 | dev_kfree_skb(rx->skb); | ||
1566 | return RX_QUEUED; | ||
1567 | } | ||
1568 | |||
1569 | return RX_CONTINUE; | ||
1570 | } | ||
1571 | |||
1572 | static ieee80211_rx_result debug_noinline | ||
1514 | ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) | 1573 | ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) |
1515 | { | 1574 | { |
1516 | struct ieee80211_sub_if_data *sdata; | 1575 | struct ieee80211_sub_if_data *sdata; |
@@ -1689,6 +1748,7 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata, | |||
1689 | CALL_RXH(ieee80211_rx_h_mesh_fwding); | 1748 | CALL_RXH(ieee80211_rx_h_mesh_fwding); |
1690 | CALL_RXH(ieee80211_rx_h_data) | 1749 | CALL_RXH(ieee80211_rx_h_data) |
1691 | CALL_RXH(ieee80211_rx_h_ctrl) | 1750 | CALL_RXH(ieee80211_rx_h_ctrl) |
1751 | CALL_RXH(ieee80211_rx_h_action) | ||
1692 | CALL_RXH(ieee80211_rx_h_mgmt) | 1752 | CALL_RXH(ieee80211_rx_h_mgmt) |
1693 | 1753 | ||
1694 | #undef CALL_RXH | 1754 | #undef CALL_RXH |