aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorHelmut Schaa <helmut.schaa@googlemail.com>2011-08-01 05:32:52 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-08-09 15:52:01 -0400
commitf75f5c6f61b4d34bf92625fcd1131dd58921e1b5 (patch)
tree509f5c5361ca793c43ccc87d130580638cb38820 /net/mac80211
parent12c5ffb5c4601a11b08533609d4bf119e2f22cf5 (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.c20
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;