aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/mwl8k.c
diff options
context:
space:
mode:
authorLennert Buytenhek <buytenh@wantstofly.org>2009-11-30 12:12:20 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-12-07 16:51:20 -0500
commitca00930153c14b323c31b97623ac5c4f7855ed6a (patch)
treea1004a5d46a70e90c1ea08aba17190619e2fa176 /drivers/net/wireless/mwl8k.c
parent20f09c3df7a8a623c290f62596c1a6b0da088030 (diff)
mwl8k: fix addr4 zeroing and payload overwrite on DMA header creation
When inserting a DMA header into a packet for transmission, mwl8k_add_dma_header() would blindly zero the addr4 field, which is not a good idea if the packet being transmitted is actually a 4-address packet. Also, if the transmitted packet was a 4-address with QoS packet, the memmove() to do the needed header reshuffling would inadvertently overwrite the first two bytes of the packet payload with the QoS field. This fixes both of these issues. Signed-off-by: Lennert Buytenhek <buytenh@marvell.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/mwl8k.c')
-rw-r--r--drivers/net/wireless/mwl8k.c29
1 files changed, 15 insertions, 14 deletions
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 6b12d81ba94b..c1cb20fceaff 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -728,35 +728,36 @@ static inline void mwl8k_remove_dma_header(struct sk_buff *skb, __le16 qos)
728static inline void mwl8k_add_dma_header(struct sk_buff *skb) 728static inline void mwl8k_add_dma_header(struct sk_buff *skb)
729{ 729{
730 struct ieee80211_hdr *wh; 730 struct ieee80211_hdr *wh;
731 u32 hdrlen, pktlen; 731 int hdrlen;
732 struct mwl8k_dma_data *tr; 732 struct mwl8k_dma_data *tr;
733 733
734 /*
735 * Add a firmware DMA header; the firmware requires that we
736 * present a 2-byte payload length followed by a 4-address
737 * header (without QoS field), followed (optionally) by any
738 * WEP/ExtIV header (but only filled in for CCMP).
739 */
734 wh = (struct ieee80211_hdr *)skb->data; 740 wh = (struct ieee80211_hdr *)skb->data;
741
735 hdrlen = ieee80211_hdrlen(wh->frame_control); 742 hdrlen = ieee80211_hdrlen(wh->frame_control);
736 pktlen = skb->len; 743 if (hdrlen != sizeof(*tr))
744 skb_push(skb, sizeof(*tr) - hdrlen);
737 745
738 /* 746 if (ieee80211_is_data_qos(wh->frame_control))
739 * Copy up/down the 802.11 header; the firmware requires 747 hdrlen -= 2;
740 * we present a 2-byte payload length followed by a
741 * 4-address header (w/o QoS), followed (optionally) by
742 * any WEP/ExtIV header (but only filled in for CCMP).
743 */
744 if (hdrlen != sizeof(struct mwl8k_dma_data))
745 skb_push(skb, sizeof(struct mwl8k_dma_data) - hdrlen);
746 748
747 tr = (struct mwl8k_dma_data *)skb->data; 749 tr = (struct mwl8k_dma_data *)skb->data;
748 if (wh != &tr->wh) 750 if (wh != &tr->wh)
749 memmove(&tr->wh, wh, hdrlen); 751 memmove(&tr->wh, wh, hdrlen);
750 752 if (hdrlen != sizeof(tr->wh))
751 /* Clear addr4 */ 753 memset(((void *)&tr->wh) + hdrlen, 0, sizeof(tr->wh) - hdrlen);
752 memset(tr->wh.addr4, 0, ETH_ALEN);
753 754
754 /* 755 /*
755 * Firmware length is the length of the fully formed "802.11 756 * Firmware length is the length of the fully formed "802.11
756 * payload". That is, everything except for the 802.11 header. 757 * payload". That is, everything except for the 802.11 header.
757 * This includes all crypto material including the MIC. 758 * This includes all crypto material including the MIC.
758 */ 759 */
759 tr->fwlen = cpu_to_le16(pktlen - hdrlen); 760 tr->fwlen = cpu_to_le16(skb->len - sizeof(*tr));
760} 761}
761 762
762 763