Accommodate the variety of RF front-ends when radiotapping frames:

tap only RSSI when there is a Philips RF front-end.  Tap both Barker
lock quality and RSSI when there is any other RF front-end.

Provide radiotap listeners a more complete picture of channel
activity:

    in promiscuous mode, tap frames who do not pass the CRC32 check.
    Flag packets that were received with a short preamble.  Ask
    the NIC to pass us 802.11 Control frames.  Pass frames to
    radiotap listeners before stripping the FCS.  Re-order operations
    in rtw_intr_rx() in order to accomplish all of this, taking
    care not to pass a broken packet to net80211!

Do not provide a flags field when tapping xmitted frames.

Assert sane Rx packet lengths.  Really should check and drop instead
of KASSERTing.  I will revisit this, soon.

Update copyright.
This commit is contained in:
dyoung 2007-11-16 23:35:19 +00:00
parent 223dc4f56f
commit 5c5f8f488c
3 changed files with 69 additions and 32 deletions

View File

@ -1,6 +1,7 @@
/* $NetBSD: rtw.c,v 1.92 2007/11/15 22:55:50 dyoung Exp $ */
/* $NetBSD: rtw.c,v 1.93 2007/11/16 23:35:19 dyoung Exp $ */
/*-
* Copyright (c) 2004, 2005 David Young. All rights reserved.
* Copyright (c) 2004, 2005, 2006, 2007 David Young. All rights
* reserved.
*
* Programmed for NetBSD by David Young.
*
@ -34,7 +35,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: rtw.c,v 1.92 2007/11/15 22:55:50 dyoung Exp $");
__KERNEL_RCSID(0, "$NetBSD: rtw.c,v 1.93 2007/11/16 23:35:19 dyoung Exp $");
#include "bpfilter.h"
@ -1450,7 +1451,7 @@ rtw_intr_rx(struct rtw_softc *sc, uint16_t isr)
for (next = rdb->rdb_next; ; next = rdb->rdb_next) {
KASSERT(next < rdb->rdb_ndesc);
rtw_rxdescs_sync(rdb, next, 1,
BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
rd = &rdb->rdb_desc[next];
@ -1517,9 +1518,8 @@ rtw_intr_rx(struct rtw_softc *sc, uint16_t isr)
sc->sc_ic.ic_stats.is_rx_tooshort++;
goto next;
}
/* CRC is included with the packet; trim it off. */
len -= IEEE80211_CRC_LEN;
KASSERT(len <= m->m_pkthdr.len);
KASSERT(len <= m->m_len);
hwrate = __SHIFTOUT(hstat, RTW_RXSTAT_RATE_MASK);
if (hwrate >= __arraycount(ratetbl)) {
@ -1537,10 +1537,6 @@ rtw_intr_rx(struct rtw_softc *sc, uint16_t isr)
(rate * 5) % 10, htsfth, htsftl));
#endif /* RTW_DEBUG */
if ((hstat & RTW_RXSTAT_RES) != 0 &&
sc->sc_ic.ic_opmode != IEEE80211_M_MONITOR)
goto next;
/* if bad flags, skip descriptor */
if ((hstat & RTW_RXSTAT_ONESEG) != RTW_RXSTAT_ONESEG) {
printf("%s: too many rx segments, "
@ -1568,8 +1564,10 @@ rtw_intr_rx(struct rtw_softc *sc, uint16_t isr)
sc->sc_dev.dv_xname);
}
sq = __SHIFTOUT(hrssi, RTW_RXRSSI_SQ);
if (sc->sc_rfchipid == RTW_RFCHIPID_PHILIPS)
rssi = __SHIFTOUT(hrssi, RTW_RXRSSI_RSSI);
rssi = UINT8_MAX - sq;
else {
rssi = __SHIFTOUT(hrssi, RTW_RXRSSI_IMR_RSSI);
/* TBD find out each front-end's LNA gain in the
@ -1578,7 +1576,6 @@ rtw_intr_rx(struct rtw_softc *sc, uint16_t isr)
if ((hrssi & RTW_RXRSSI_IMR_LNA) == 0)
rssi |= 0x80;
}
sq = __SHIFTOUT(hrssi, RTW_RXRSSI_SQ);
/* Note well: now we cannot recycle the rs_mbuf unless
* we restore its original length.
@ -1590,8 +1587,6 @@ rtw_intr_rx(struct rtw_softc *sc, uint16_t isr)
if (!IS_BEACON(wh->i_fc[0]))
sc->sc_led_state.ls_event |= RTW_LED_S_RX;
/* TBD use _MAR, _BAR, _PAR flags as hints to _find_rxnode? */
ni = ieee80211_find_rxnode(&sc->sc_ic, wh);
sc->sc_tsfth = htsfth;
@ -1610,19 +1605,38 @@ rtw_intr_rx(struct rtw_softc *sc, uint16_t isr)
rr->rr_tsft =
htole64(((uint64_t)htsfth << 32) | htsftl);
rr->rr_flags = IEEE80211_RADIOTAP_F_FCS;
if ((hstat & RTW_RXSTAT_SPLCP) != 0)
rr->rr_flags = IEEE80211_RADIOTAP_F_SHORTPRE;
rr->rr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
if ((hstat & RTW_RXSTAT_CRC32) != 0)
rr->rr_flags |= IEEE80211_RADIOTAP_F_BADFCS;
rr->rr_flags = 0;
rr->rr_rate = rate;
rr->rr_antsignal = rssi;
rr->rr_barker_lock = htole16(sq);
bpf_mtap2(sc->sc_radiobpf, (void *)rr,
if (sc->sc_rfchipid == RTW_RFCHIPID_PHILIPS)
rr->rr_u.u_philips.p_antsignal = rssi;
else {
rr->rr_u.u_other.o_antsignal = rssi;
rr->rr_u.u_other.o_barker_lock =
htole16(UINT8_MAX - sq);
}
bpf_mtap2(sc->sc_radiobpf, rr,
sizeof(sc->sc_rxtapu), m);
}
#endif /* NBPFILTER > 0 */
if ((hstat & RTW_RXSTAT_RES) != 0) {
m_freem(m);
goto next;
}
/* CRC is included with the packet; trim it off. */
m_adj(m, -IEEE80211_CRC_LEN);
/* TBD use _MAR, _BAR, _PAR flags as hints to _find_rxnode? */
ni = ieee80211_find_rxnode(&sc->sc_ic, wh);
ieee80211_input(&sc->sc_ic, m, ni, rssi, htsftl);
ieee80211_free_node(ni);
next:
@ -2626,6 +2640,8 @@ rtw_pktfilt_load(struct rtw_softc *sc)
if (ifp->if_flags & IFF_PROMISC) {
sc->sc_rcr |= RTW_RCR_AB; /* accept all broadcast */
sc->sc_rcr |= RTW_RCR_ACRC32; /* accept frames failing CRC */
sc->sc_rcr |= RTW_RCR_AICV; /* accept frames failing ICV */
ifp->if_flags |= IFF_ALLMULTI;
}
@ -3332,7 +3348,6 @@ rtw_start(struct ifnet *ifp)
if (sc->sc_radiobpf != NULL) {
struct rtw_tx_radiotap_header *rt = &sc->sc_txtap;
rt->rt_flags = 0;
rt->rt_rate = rate;
bpf_mtap2(sc->sc_radiobpf, (void *)rt,
@ -3816,9 +3831,16 @@ rtw_disestablish_hooks(struct rtw_hooks *hooks, const char *dvname,
static inline void
rtw_init_radiotap(struct rtw_softc *sc)
{
uint32_t present;
memset(&sc->sc_rxtapu, 0, sizeof(sc->sc_rxtapu));
sc->sc_rxtap.rr_ihdr.it_len = htole16(sizeof(sc->sc_rxtapu));
sc->sc_rxtap.rr_ihdr.it_present = htole32(RTW_RX_RADIOTAP_PRESENT);
if (sc->sc_rfchipid == RTW_RFCHIPID_PHILIPS)
present = htole32(RTW_PHILIPS_RX_RADIOTAP_PRESENT);
else
present = htole32(RTW_RX_RADIOTAP_PRESENT);
sc->sc_rxtap.rr_ihdr.it_present = present;
memset(&sc->sc_txtapu, 0, sizeof(sc->sc_txtapu));
sc->sc_txtap.rt_ihdr.it_len = htole16(sizeof(sc->sc_txtapu));

View File

@ -1,4 +1,4 @@
/* $NetBSD: rtwreg.h,v 1.23 2007/01/06 08:27:53 dyoung Exp $ */
/* $NetBSD: rtwreg.h,v 1.24 2007/11/16 23:35:19 dyoung Exp $ */
/*-
* Copyright (c) 2004, 2005 David Young. All rights reserved.
*
@ -283,6 +283,7 @@
/* Receive power-management frames and mgmt/ctrl/data frames. */
#define RTW_RCR_PKTFILTER_DEFAULT ( \
RTW_RCR_ACF | \
RTW_RCR_ADF | \
RTW_RCR_AMF | \
RTW_RCR_APM | \

View File

@ -1,4 +1,4 @@
/* $NetBSD: rtwvar.h,v 1.31 2007/03/04 06:02:01 christos Exp $ */
/* $NetBSD: rtwvar.h,v 1.32 2007/11/16 23:35:19 dyoung Exp $ */
/*-
* Copyright (c) 2004, 2005 David Young. All rights reserved.
*
@ -236,27 +236,41 @@ struct rtw_descs {
(1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL) | \
0)
#define RTW_PHILIPS_RX_RADIOTAP_PRESENT \
((1 << IEEE80211_RADIOTAP_TSFT) | \
(1 << IEEE80211_RADIOTAP_FLAGS) | \
(1 << IEEE80211_RADIOTAP_RATE) | \
(1 << IEEE80211_RADIOTAP_CHANNEL) | \
(1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL) | \
0)
struct rtw_rx_radiotap_header {
struct ieee80211_radiotap_header rr_ihdr;
uint64_t rr_tsft;
uint8_t rr_flags;
uint8_t rr_rate;
uint8_t rr_flags;
uint8_t rr_rate;
uint16_t rr_chan_freq;
uint16_t rr_chan_flags;
uint16_t rr_barker_lock;
uint8_t rr_antsignal;
union {
struct {
uint16_t o_barker_lock;
uint8_t o_antsignal;
} u_other;
struct {
uint8_t p_antsignal;
} u_philips;
} rr_u;
} __attribute__((__packed__));
#define RTW_TX_RADIOTAP_PRESENT \
((1 << IEEE80211_RADIOTAP_FLAGS) | \
(1 << IEEE80211_RADIOTAP_RATE) | \
((1 << IEEE80211_RADIOTAP_RATE) | \
(1 << IEEE80211_RADIOTAP_CHANNEL) | \
0)
struct rtw_tx_radiotap_header {
struct ieee80211_radiotap_header rt_ihdr;
uint8_t rt_flags;
uint8_t rt_rate;
uint8_t rt_rate;
uint8_t rt_pad;
uint16_t rt_chan_freq;
uint16_t rt_chan_flags;
} __attribute__((__packed__));