Search Linux Wireless

[PATCH] ath5k : Fix correct padding

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Padding the 802.11 header to a multiple of 4 bytes needs to be done only
for DATA frames. This fixes a bug where 2 bytes were missing in monitor
mode for ACK frames.

Ref: http://bugzilla.kernel.org/show_bug.cgi?id=12101 :
Signed-off-by: Benoit Papillault <benoit.papillault@xxxxxxx>
---
 drivers/net/wireless/ath5k/base.c |   49
+++++++++++++++++++++++-------------
 1 files changed, 31 insertions(+), 18 deletions(-)

diff --git a/drivers/net/wireless/ath5k/base.c
b/drivers/net/wireless/ath5k/base.c
index bfb0c49..2318b1c 100644
--- a/drivers/net/wireless/ath5k/base.c
+++ b/drivers/net/wireless/ath5k/base.c
@@ -1668,6 +1668,7 @@ ath5k_tasklet_rx(unsigned long data)
 	int ret;
 	int hdrlen;
 	int pad;
+	struct ieee80211_hdr * hdr;

 	spin_lock(&sc->rxbuflock);
 	if (list_empty(&sc->rxbuf)) {
@@ -1754,14 +1755,19 @@ accept:

 		/*
 		 * the hardware adds a padding to 4 byte boundaries between
-		 * the header and the payload data if the header length is
-		 * not multiples of 4 - remove it
+		 * the header and the payload data if the header length is not
+		 * multiple of 4 - remove it. This only affect data frames.
 		 */
-		hdrlen = ieee80211_get_hdrlen_from_skb(skb);
-		if (hdrlen & 3) {
-			pad = hdrlen % 4;
-			memmove(skb->data + pad, skb->data, hdrlen);
-			skb_pull(skb, pad);
+
+		hdr = (struct ieee80211_hdr *) skb;
+		if ((skb->len >= 2) && ieee80211_is_data(hdr->frame_control)) {
+
+			hdrlen = ieee80211_get_hdrlen_from_skb(skb);
+			if (hdrlen & 3) {
+				pad = hdrlen % 4;
+				memmove(skb->data + pad, skb->data, hdrlen);
+				skb_pull(skb, pad);
+			}
 		}

 		/*
@@ -2623,6 +2629,7 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 	unsigned long flags;
 	int hdrlen;
 	int pad;
+	const struct ieee80211_hdr * hdr = (const struct ieee80211_hdr *)skb;

 	ath5k_debug_dump_skb(sc, skb, "TX  ", 1);

@@ -2630,19 +2637,25 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff
*skb)
 		ATH5K_DBG(sc, ATH5K_DEBUG_XMIT, "tx in monitor (scan?)\n");

 	/*
-	 * the hardware expects the header padded to 4 byte boundaries
-	 * if this is not the case we add the padding after the header
+	 * the hardware expects the header padded to 4 byte boundaries for
+	 * data frames, if this is not the case we add the padding after the
+	 * header
 	 */
-	hdrlen = ieee80211_get_hdrlen_from_skb(skb);
-	if (hdrlen & 3) {
-		pad = hdrlen % 4;
-		if (skb_headroom(skb) < pad) {
-			ATH5K_ERR(sc, "tx hdrlen not %%4: %d not enough"
-				" headroom to pad %d\n", hdrlen, pad);
-			return -1;
+
+	if ((skb->len >= 2) && ieee80211_is_data(hdr->frame_control)) {
+
+		hdrlen = ieee80211_get_hdrlen_from_skb(skb);
+		if (hdrlen & 3) {
+			pad = hdrlen % 4;
+			if (skb_headroom(skb) < pad) {
+				ATH5K_ERR(sc,
+					  "tx hdrlen not %%4: %d not enough"
+					  " headroom to pad %d\n", hdrlen, pad);
+				return -1;
+			}
+			skb_push(skb, pad);
+			memmove(skb->data, skb->data+pad, hdrlen);
 		}
-		skb_push(skb, pad);
-		memmove(skb->data, skb->data+pad, hdrlen);
 	}

 	spin_lock_irqsave(&sc->txbuflock, flags);
-- 1.5.6.5

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]
  Powered by Linux