diff options
author | Helmut Schaa <helmut.schaa@googlemail.com> | 2011-08-01 05:32:52 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-08-09 15:52:01 -0400 |
commit | f75f5c6f61b4d34bf92625fcd1131dd58921e1b5 (patch) | |
tree | 509f5c5361ca793c43ccc87d130580638cb38820 /net/mac80211 | |
parent | 12c5ffb5c4601a11b08533609d4bf119e2f22cf5 (diff) |
mac80211: Fill in skb->protocol information for injected frames
Some drivers (ath9k for example) are using skb->protocol to treat EAPOL
frames somehow special (disallow aggregation for example).
When running in AP mode hostapd injects the EAPOL frames through a
monitor interface and thus skb->protocol isn't set at all. Hence, if the
injected frame is a data frame and carries a rfc1042 headaer update the
skb->protocol field accordingly.
Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/tx.c | 20 |
1 files changed, 20 insertions, 0 deletions
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 8cb0d2d0ac69..69fd494f32f9 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -1608,7 +1608,9 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, | |||
1608 | struct ieee80211_radiotap_header *prthdr = | 1608 | struct ieee80211_radiotap_header *prthdr = |
1609 | (struct ieee80211_radiotap_header *)skb->data; | 1609 | (struct ieee80211_radiotap_header *)skb->data; |
1610 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1610 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1611 | struct ieee80211_hdr *hdr; | ||
1611 | u16 len_rthdr; | 1612 | u16 len_rthdr; |
1613 | u8 *payload; | ||
1612 | 1614 | ||
1613 | /* | 1615 | /* |
1614 | * Frame injection is not allowed if beaconing is not allowed | 1616 | * Frame injection is not allowed if beaconing is not allowed |
@@ -1659,6 +1661,24 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, | |||
1659 | skb_set_network_header(skb, len_rthdr); | 1661 | skb_set_network_header(skb, len_rthdr); |
1660 | skb_set_transport_header(skb, len_rthdr); | 1662 | skb_set_transport_header(skb, len_rthdr); |
1661 | 1663 | ||
1664 | /* | ||
1665 | * Initialize skb->protocol if the injected frame is a data frame | ||
1666 | * carrying a rfc1042 header | ||
1667 | */ | ||
1668 | if (skb->len > len_rthdr + 2) { | ||
1669 | hdr = (struct ieee80211_hdr *)(skb->data + len_rthdr); | ||
1670 | if (ieee80211_is_data(hdr->frame_control) && | ||
1671 | skb->len >= len_rthdr + | ||
1672 | ieee80211_hdrlen(hdr->frame_control) + | ||
1673 | sizeof(rfc1042_header) + 2) { | ||
1674 | payload = (u8 *)hdr + | ||
1675 | ieee80211_hdrlen(hdr->frame_control); | ||
1676 | if (compare_ether_addr(payload, rfc1042_header) == 0) | ||
1677 | skb->protocol = cpu_to_be16((payload[6] << 8) | | ||
1678 | payload[7]); | ||
1679 | } | ||
1680 | } | ||
1681 | |||
1662 | memset(info, 0, sizeof(*info)); | 1682 | memset(info, 0, sizeof(*info)); |
1663 | 1683 | ||
1664 | info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; | 1684 | info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; |