diff --git a/ath/if_ath.c b/ath/if_ath.c index 3364f29..f4d0ddf 100644 --- a/ath/if_ath.c +++ b/ath/if_ath.c @@ -6320,66 +6320,36 @@ ath_rxbuf_init(struct ath_softc *sc, struct ath_buf *bf) /* This function calculates the presence of, and then removes any padding * bytes between the frame header and frame body, and returns a modified - * SKB. If padding is removed and copy_skb is specified, then a new SKB is - * created, otherwise the same SKB is used. - * - * NB: MAY ALLOCATE */ -static struct sk_buff * -ath_skb_removepad(struct sk_buff *skb, unsigned int copy_skb) + * SKB. */ +static void +ath_skb_removepad(struct ieee80211com *ic, struct sk_buff *skb) { - struct sk_buff *tskb = skb; struct ieee80211_frame *wh = (struct ieee80211_frame *)skb->data; unsigned int padbytes = 0, headersize = 0; + + KASSERT(ic->ic_flags & IEEE80211_F_DATAPAD, + ("data padding not enabled?")); /* Only non-control frames have bodies, and hence padding. */ if (IEEE80211_FRM_HAS_BODY(wh)) { headersize = ieee80211_anyhdrsize(wh); padbytes = roundup(headersize, 4) - headersize; if (padbytes > 0) { - if (copy_skb) { - /* Copy skb and remove HW pad bytes */ - tskb = skb_copy(skb, GFP_ATOMIC); - if (tskb == NULL) - return NULL; - ieee80211_skb_copy_noderef(skb, tskb); - } - memmove(tskb->data + padbytes, tskb->data, headersize); - skb_pull(tskb, padbytes); + memmove(skb->data + padbytes, skb->data, headersize); + skb_pull(skb, padbytes); } } - return tskb; } -/* - * Add a prism2 header to a received frame and - * dispatch it to capture tools like kismet. - */ -static void +static __inline void ath_capture(struct net_device *dev, const struct ath_buf *bf, struct sk_buff *skb, u_int64_t tsf, unsigned int tx) { struct ath_softc *sc = dev->priv; struct ieee80211com *ic = &sc->sc_ic; - struct sk_buff *tskb = NULL; - KASSERT(ic->ic_flags & IEEE80211_F_DATAPAD, - ("data padding not enabled?")); - - if (sc->sc_nmonvaps <= 0) - return; - - /* Never copy the SKB, as it is ours on the RX side, and this is the - * last process on the TX side and we only modify our own headers. */ - tskb = ath_skb_removepad(skb, !tx /* Copy SKB */); - if (tskb == NULL) { - DPRINTF(sc, ATH_DEBUG_ANY, - "Dropping; ath_skb_removepad failed!\n"); - return; - } - - ieee80211_input_monitor(ic, tskb, bf, tx, tsf, sc); - if (tskb != skb) - ieee80211_dev_kfree_skb(&tskb); + if (sc->sc_nmonvaps > 0) + ieee80211_input_monitor(ic, skb, bf, tx, tsf, sc); } /* @@ -6640,6 +6610,7 @@ rx_accept: skb_put(skb, len); skb->protocol = __constant_htons(ETH_P_CONTROL); + ath_skb_removepad(ic, skb); ath_capture(dev, bf, skb, bf->bf_tsf, 0 /* RX */); /* Finished monitor mode handling, now reject error frames @@ -6684,7 +6655,7 @@ rx_accept: if (IFF_DUMPPKTS(sc, ATH_DEBUG_RECV)) ieee80211_dump_pkt(ic, skb->data, skb->len, sc->sc_hwmap[rs->rs_rate].ieeerate, - rs->rs_rssi); + rs->rs_rssi, 0); { struct ieee80211_frame *wh = @@ -7973,7 +7944,7 @@ ath_tx_start(struct net_device *dev, struct ieee80211_node *ni, if (IFF_DUMPPKTS(sc, ATH_DEBUG_XMIT)) /* FFXXX: need multi-skb version to dump entire FF */ ieee80211_dump_pkt(ic, skb->data, skb->len, - sc->sc_hwmap[txrate].ieeerate, -1); + sc->sc_hwmap[txrate].ieeerate, -1, 1); /* * Determine if a tx interrupt should be generated for @@ -8354,11 +8325,12 @@ ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) unsigned int i; #endif - /* ath_capture modifies skb data; must be last process - * in TX path. */ - tskb = skb->next; + /* HW is now finished with the SKB, so it is safe to + * remove padding. */ + ath_skb_removepad(&sc->sc_ic, skb); DPRINTF(sc, ATH_DEBUG_TX_PROC, "capture skb %p\n", bf->bf_skb); + tskb = skb->next; ath_capture(sc->sc_dev, bf, skb, bf->bf_tsf, 1 /* TX */); skb = tskb; @@ -8366,9 +8338,10 @@ ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) /* Handle every skb after the first one - these are FF * extra buffers */ for (i = 0; i < bf->bf_numdescff; i++) { - tskb = skb->next; + ath_skb_removepad(&sc->sc_ic, skb); /* XXX: padding for FF? */ DPRINTF(sc, ATH_DEBUG_TX_PROC, "capture skb %p\n", skb); + tskb = skb->next; ath_capture(sc->sc_dev, bf, skb, bf->bf_tsf, 1 /* TX */); skb = tskb; } diff --git a/net80211/ieee80211_input.c b/net80211/ieee80211_input.c index 8238fa0..6d91d90 100644 --- a/net80211/ieee80211_input.c +++ b/net80211/ieee80211_input.c @@ -207,7 +207,7 @@ ieee80211_input(struct ieee80211vap *vap, struct ieee80211_node *ni_or_null, #ifdef ATH_SUPERG_FF struct llc *llc; #endif - int hdrspace; + int hdrlen; u_int8_t dir, type = -1, subtype; u_int8_t *bssid; u_int16_t rxseq; @@ -431,11 +431,11 @@ ieee80211_input(struct ieee80211vap *vap, struct ieee80211_node *ni_or_null, switch (type) { case IEEE80211_FC0_TYPE_DATA: - hdrspace = ieee80211_hdrspace(ic, wh); - if (skb->len < hdrspace) { + hdrlen = ieee80211_hdrsize(wh); + if (skb->len < hdrlen) { IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY, wh, "data", "too short: len %u, expecting %u", - skb->len, hdrspace); + skb->len, hdrlen); vap->iv_stats.is_rx_tooshort++; goto out; /* XXX */ } @@ -624,7 +624,7 @@ ieee80211_input(struct ieee80211vap *vap, struct ieee80211_node *ni_or_null, IEEE80211_NODE_STAT(ni, rx_noprivacy); goto out; } - key = ieee80211_crypto_decap(ni, skb, hdrspace); + key = ieee80211_crypto_decap(ni, skb, hdrlen); if (key == NULL) { /* NB: stats+msgs handled in crypto_decap */ IEEE80211_NODE_STAT(ni, rx_wepfail); @@ -639,7 +639,7 @@ ieee80211_input(struct ieee80211vap *vap, struct ieee80211_node *ni_or_null, * Next up, any fragmentation. */ if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { - skb = ieee80211_defrag(ni, skb, hdrspace); + skb = ieee80211_defrag(ni, skb, hdrlen); if (skb == NULL) { /* Fragment dropped or frame not complete yet */ goto out; @@ -651,7 +651,7 @@ ieee80211_input(struct ieee80211vap *vap, struct ieee80211_node *ni_or_null, * Next strip any MSDU crypto bits. */ if (key != NULL && - !ieee80211_crypto_demic(vap, key, skb, hdrspace, 0)) { + !ieee80211_crypto_demic(vap, key, skb, hdrlen, 0)) { IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT, ni->ni_macaddr, "data", "%s", "demic error"); IEEE80211_NODE_STAT(ni, rx_demicfail); @@ -661,7 +661,7 @@ ieee80211_input(struct ieee80211vap *vap, struct ieee80211_node *ni_or_null, /* * Finally, strip the 802.11 header. */ - skb = ieee80211_decap(vap, skb, hdrspace); + skb = ieee80211_decap(vap, skb, hdrlen); if (skb == NULL) { /* don't count Null data frames as errors */ if (subtype == IEEE80211_FC0_SUBTYPE_NODATA) @@ -812,8 +812,8 @@ ieee80211_input(struct ieee80211vap *vap, struct ieee80211_node *ni_or_null, vap->iv_stats.is_rx_noprivacy++; goto out; } - hdrspace = ieee80211_hdrspace(ic, wh); - key = ieee80211_crypto_decap(ni, skb, hdrspace); + hdrlen = ieee80211_hdrsize(wh); + key = ieee80211_crypto_decap(ni, skb, hdrlen); if (key == NULL) { /* NB: stats+msgs handled in crypto_decap */ goto out; @@ -4245,8 +4245,7 @@ ieee80211_check_mic(struct ieee80211_node *ni, struct sk_buff *skb) struct ieee80211vap *vap = ni->ni_vap; struct ieee80211_frame *wh; struct ieee80211_key *key; - int hdrspace; - struct ieee80211com *ic = vap->iv_ic; + int hdrlen; if (skb->len < sizeof(struct ieee80211_frame_min)) { IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY, @@ -4257,13 +4256,13 @@ ieee80211_check_mic(struct ieee80211_node *ni, struct sk_buff *skb) } wh = (struct ieee80211_frame *)skb->data; - hdrspace = ieee80211_hdrspace(ic, wh); + hdrlen = ieee80211_hdrsize(wh); - key = ieee80211_crypto_decap(ni, skb, hdrspace); + key = ieee80211_crypto_decap(ni, skb, hdrlen); if (key == NULL) { /* NB: stats+msgs handled in crypto_decap */ IEEE80211_NODE_STAT(ni, rx_wepfail); - } else if (!ieee80211_crypto_demic(vap, key, skb, hdrspace, 1)) { + } else if (!ieee80211_crypto_demic(vap, key, skb, hdrlen, 1)) { IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT, ni->ni_macaddr, "data", "%s", "demic error"); IEEE80211_NODE_STAT(ni, rx_demicfail); diff --git a/net80211/ieee80211_power.c b/net80211/ieee80211_power.c index 56907b4..db2f823 100644 --- a/net80211/ieee80211_power.c +++ b/net80211/ieee80211_power.c @@ -224,7 +224,8 @@ ieee80211_pwrsave(struct sk_buff *skb) ni->ni_stats.ns_psq_drops, IEEE80211_PS_MAX_QUEUE); #ifdef IEEE80211_DEBUG if (ieee80211_msg_dumppkts(vap)) - ieee80211_dump_pkt(ni->ni_ic, skb->data, skb->len, -1, -1); + ieee80211_dump_pkt(ni->ni_ic, skb->data, + skb->len, -1, -1, 1); #endif if (SKB_NI(skb) != NULL) ieee80211_unref_node(&SKB_NI(skb)); diff --git a/net80211/ieee80211_proto.c b/net80211/ieee80211_proto.c index 6fa4c6c..89995e0 100644 --- a/net80211/ieee80211_proto.c +++ b/net80211/ieee80211_proto.c @@ -313,8 +313,8 @@ ieee80211_print_essid(const u_int8_t *essid, int len) EXPORT_SYMBOL(ieee80211_print_essid); void -ieee80211_dump_pkt(struct ieee80211com *ic, - const u_int8_t *buf, int len, int rate, int rssi) +ieee80211_dump_pkt(struct ieee80211com *ic, const u_int8_t *buf, + int len, int rate, int rssi, int tx) { const struct ieee80211_frame *wh; int i; @@ -365,7 +365,10 @@ ieee80211_dump_pkt(struct ieee80211com *ic, if (wh->i_fc[1] & IEEE80211_FC1_PROT) { int off; - off = ieee80211_anyhdrspace(ic, wh); + if (tx) + off = ieee80211_anyhdrspace(ic, wh); + else + off = ieee80211_anyhdrsize(wh); printk(" Prot. [IV %.02x %.02x %.02x", buf[off + 0], buf[off + 1], buf[off + 2]); if (buf[off + IEEE80211_WEP_IVLEN] & IEEE80211_WEP_EXTIV) diff --git a/net80211/ieee80211_proto.h b/net80211/ieee80211_proto.h index 8e6f1cf..04b910c 100644 --- a/net80211/ieee80211_proto.h +++ b/net80211/ieee80211_proto.h @@ -252,7 +252,8 @@ void ieee80211_dturbo_switch(struct ieee80211com *, int); int ieee80211_new_state(struct ieee80211vap *, enum ieee80211_state, int); void ieee80211_print_essid(const u_int8_t *, int); #ifdef IEEE80211_DEBUG -void ieee80211_dump_pkt(struct ieee80211com *, const u_int8_t *, int, int, int); +void ieee80211_dump_pkt(struct ieee80211com *, const u_int8_t *, + int, int, int, int); #else #define ieee80211_dump_pkt(...) #endif