The branch main has been updated by adrian:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=93c6906e36a4e60e59279b6b6e18403ea23d56e1

commit 93c6906e36a4e60e59279b6b6e18403ea23d56e1
Author:     EN-WEU WU <[email protected]>
AuthorDate: 2026-06-16 14:54:05 +0000
Commit:     Adrian Chadd <[email protected]>
CommitDate: 2026-06-16 14:54:55 +0000

    wtap(4): implement monitor mode and handle radiotap
    
    Implement monitor mode by simply adding IEEE80211_C_MONITOR to ic->ic_cap.
    
    To get additional informations when capturing 802.11 frames, radiotap is
     inserted by wtap_tx_tap() when TX and wtap_rx_tap() when RX.
    
    There are some type faults in struct wtap_rx_radiotap_header which are
     mainly mistakenly store unsigned values into signed integers.
    I have fixed them (wtap(4)) by complying with the types defined
     in https://www.radiotap.org/fields/defined.
    
    Becuase the struct wtap_rx_radiotap_header comes from ath(4),
    there may be another patch to fix the type faults in ath(4).
    
    Differential Review: https://reviews.freebsd.org/D36469
---
 sys/dev/wtap/if_wtap.c      | 59 ++++++++++++++++++++++++++++++++++++++++++---
 sys/dev/wtap/if_wtapioctl.h | 31 ++++++++++++------------
 2 files changed, 71 insertions(+), 19 deletions(-)

diff --git a/sys/dev/wtap/if_wtap.c b/sys/dev/wtap/if_wtap.c
index d22b79a20dc4..d23036575d7a 100644
--- a/sys/dev/wtap/if_wtap.c
+++ b/sys/dev/wtap/if_wtap.c
@@ -229,6 +229,43 @@ wtap_beacon_config(struct wtap_softc *sc, struct 
ieee80211vap *vap)
        DWTAP_PRINTF("%s\n", __func__);
 }
 
+static void
+wtap_rx_tap(struct wtap_softc *sc, uint64_t tsf)
+{
+       struct ieee80211com *ic = &sc->sc_ic;
+       const struct ieee80211_rate_table *rt = ic->ic_rt;
+       struct wtap_rx_radiotap_header *rh = &sc->sc_rx_th;
+
+       rh->wr_tsf = tsf;
+       rh->wr_flags = 0;
+       if (rt->rateCount) {
+               /* choose the fastest rate */
+               rh->wr_rate = IEEE80211_RV(rt->info[rt->rateCount - 
1].dot11Rate);
+       }
+       rh->wr_chan_flags = IEEE80211_CHAN_2GHZ;
+       rh->wr_chan_freq = ic->ic_curchan->ic_freq;
+       rh->wr_chan_ieee = ic->ic_curchan->ic_ieee;
+       rh->wr_chan_maxpow = 0;
+}
+
+static void
+wtap_tx_tap(struct wtap_softc *sc)
+{
+       struct ieee80211com *ic = &sc->sc_ic;
+       const struct ieee80211_rate_table *rt = ic->ic_rt;
+       struct wtap_tx_radiotap_header *th = &sc->sc_tx_th;
+
+       th->wt_flags = 0;
+       if (rt->rateCount) {
+               /* choose the fastest rate */
+               th->wt_rate = IEEE80211_RV(rt->info[rt->rateCount - 
1].dot11Rate);
+       }
+       th->wt_chan_flags = IEEE80211_CHAN_2GHZ;
+       th->wt_chan_freq = ic->ic_curchan->ic_freq;
+       th->wt_chan_ieee = ic->ic_curchan->ic_ieee;
+       th->wt_chan_maxpow = 0;
+}
+
 static void
 wtap_beacon_intrp(void *arg)
 {
@@ -261,8 +298,10 @@ wtap_beacon_intrp(void *arg)
        wh = mtod(m, struct ieee80211_frame *);
        memcpy(&wh[1], &tsf, sizeof(tsf));
 
-       if (ieee80211_radiotap_active_vap(vap))
-           ieee80211_radiotap_tx(vap, m);
+       if (ieee80211_radiotap_active_vap(vap)) {
+               wtap_tx_tap(sc);
+               ieee80211_radiotap_tx(vap, m);
+       }
 
 #if 0
        medium_transmit(avp->av_md, avp->id, m);
@@ -459,6 +498,8 @@ static int
 wtap_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
        const struct ieee80211_bpf_params *params)
 {
+       struct ieee80211com *ic = ni->ni_ic;
+       struct wtap_softc *sc = ic->ic_softc;
 #if 0
        DWTAP_PRINTF("%s, %p\n", __func__, m);
 #endif
@@ -466,6 +507,7 @@ wtap_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
        struct wtap_vap         *avp = WTAP_VAP(vap);
 
        if (ieee80211_radiotap_active_vap(vap)) {
+               wtap_tx_tap(sc);
                ieee80211_radiotap_tx(vap, m);
        }
        if (m->m_flags & M_TXCB)
@@ -529,6 +571,10 @@ wtap_rx_proc(void *arg, int npending)
 #if 0
                ieee80211_dump_pkt(ic, mtod(m, caddr_t), 0,0,0);
 #endif
+               if (ieee80211_radiotap_active(ic)) {
+                       uint64_t tsf = wtap_hal_get_tsf(sc->hal);
+                       wtap_rx_tap(sc, tsf);
+               }
 
                /*
                 * Use arbitrary but sane values, and do the correct conversion
@@ -600,6 +646,7 @@ wtap_transmit(struct ieee80211com *ic, struct mbuf *m)
        struct ieee80211_node *ni =
            (struct ieee80211_node *) m->m_pkthdr.rcvif;
        struct ieee80211vap *vap = ni->ni_vap;
+       struct wtap_softc *sc = ic->ic_softc;
        struct wtap_vap *avp = WTAP_VAP(vap);
        struct ieee80211_key *k;
        struct ieee80211_frame *wh;
@@ -612,8 +659,10 @@ wtap_transmit(struct ieee80211com *ic, struct mbuf *m)
                        return (ENOBUFS);
        }
 
-       if (ieee80211_radiotap_active_vap(vap))
+       if (ieee80211_radiotap_active_vap(vap)) {
+               wtap_tx_tap(sc);
                ieee80211_radiotap_tx(vap, m);
+       }
        if (m->m_flags & M_TXCB)
                ieee80211_process_callback(ni, m, 0);
        ieee80211_free_node(ni);
@@ -668,7 +717,9 @@ wtap_attach(struct wtap_softc *sc, const uint8_t *macaddr)
                | IEEE80211_C_IBSS              /* ibss, nee adhoc, mode */
                | IEEE80211_C_STA               /* station mode */
                | IEEE80211_C_HOSTAP            /* hostap mode */
-               | IEEE80211_C_WPA;              /* capable of WPA1+WPA2 */
+               | IEEE80211_C_WPA               /* capable of WPA1+WPA2 */
+               | IEEE80211_C_MONITOR           /* Enable monitor mode */
+               ;
 
        ic->ic_cryptocaps =
                  IEEE80211_CRYPTO_WEP
diff --git a/sys/dev/wtap/if_wtapioctl.h b/sys/dev/wtap/if_wtapioctl.h
index 05f88a5dcb81..f9fe35813576 100644
--- a/sys/dev/wtap/if_wtapioctl.h
+++ b/sys/dev/wtap/if_wtapioctl.h
@@ -139,41 +139,42 @@ struct wtap_stats {
 /*
  * Radio capture format.
  */
-#define WTAP_RX_RADIOTAP_PRESENT (             \
+#define WTAP_RX_RADIOTAP_PRESENT (                             \
+       (1 << IEEE80211_RADIOTAP_TSFT)          |               \
+       (1 << IEEE80211_RADIOTAP_FLAGS)         |               \
+       (1 << IEEE80211_RADIOTAP_RATE)          |               \
+       (1 << IEEE80211_RADIOTAP_XCHANNEL)      |               \
        0)
 
 struct wtap_rx_radiotap_header {
        struct ieee80211_radiotap_header wr_ihdr;
-#if 0
+
        u_int64_t       wr_tsf;
        u_int8_t        wr_flags;
        u_int8_t        wr_rate;
-       int8_t          wr_antsignal;
-       int8_t          wr_antnoise;
-       u_int8_t        wr_antenna;
-       u_int8_t        wr_pad[3];
+       u_int8_t        wr_pad[2];
        u_int32_t       wr_chan_flags;
        u_int16_t       wr_chan_freq;
        u_int8_t        wr_chan_ieee;
-       int8_t          wr_chan_maxpow;
-#endif
+       u_int8_t        wr_chan_maxpow;
 } __packed __aligned(8);
 
-#define WTAP_TX_RADIOTAP_PRESENT (             \
+#define WTAP_TX_RADIOTAP_PRESENT (                             \
+       (1 << IEEE80211_RADIOTAP_FLAGS)         |               \
+       (1 << IEEE80211_RADIOTAP_RATE)          |               \
+       (1 << IEEE80211_RADIOTAP_XCHANNEL)      |               \
        0)
 
 struct wtap_tx_radiotap_header {
        struct ieee80211_radiotap_header wt_ihdr;
-#if 0
+
        u_int8_t        wt_flags;
        u_int8_t        wt_rate;
-       u_int8_t        wt_txpower;
-       u_int8_t        wt_antenna;
+       u_int8_t        wr_pad[2];
        u_int32_t       wt_chan_flags;
        u_int16_t       wt_chan_freq;
        u_int8_t        wt_chan_ieee;
-       int8_t          wt_chan_maxpow;
-#endif
-} __packed;
+       u_int8_t        wt_chan_maxpow;
+} __packed __aligned(8);
 
 #endif

Reply via email to