Subject: Re: PRISM2 monitor mode patch
To: None <tech-net@netbsd.org>
From: David Young <dyoung@ojctech.com>
List: tech-net
Date: 11/08/2002 16:14:03
This is useful. Thanks for doing this.
Are RTS/CTS frames exposed? It will help me to prove a bug in the Prism
firmware to monitor those. Fragments?
In monitor mode, is a frame header is no larger than a wi_frame? I had
thought that explained why the "generic" libpcap expects an enormous
header for DLT_PRISM_HEADER.
BTW, I have patched tcpdump/libpcap/wi(4) so that you can monitor RSSI
and other aspects of the Prism header using tcpdump. You can see the
patches at http://che.ojctech.com/~dyoung/patches/. If these patches
look generally useful, I will commit them.
Dave
On Fri, Nov 08, 2002 at 01:54:18AM -0800, Kevin Lahey wrote:
>
> This patch introduces a new mediaopt, "monitor" for 802.11 wireless
> devices. This option will put the wireless device into monitor mode,
> where it can see all incoming packets. (We can see *most* packets
> in "hostap" mode, except for probes.)
>
> This currently only works for the 'wi' device driver, for PRISM2
> wireless devices. It doesn't yet put the Orinoco based cards into
> monitor mode, but that doesn't seem like it'd be too hard to add this.
>
> Does this seem useful?
>
> Kevin
> kml@patheticgeek.net
>
>
> Index: dev/ic/wi.c
> ===================================================================
> RCS file: /cvsroot/syssrc/sys/dev/ic/wi.c,v
> retrieving revision 1.101
> diff -c -r1.101 wi.c
> *** dev/ic/wi.c 2002/10/25 01:35:12 1.101
> --- dev/ic/wi.c 2002/11/03 02:56:53
> ***************
> *** 292,297 ****
> --- 292,298 ----
> if (sc->sc_sta_firmware_ver >= 800) {
> ic->ic_flags |= IEEE80211_F_HASHOSTAP;
> ic->ic_flags |= IEEE80211_F_HASIBSS;
> + ic->ic_flags |= IEEE80211_F_HASMONITOR;
> }
> sc->sc_ibss_port = 0;
> break;
> ***************
> *** 337,342 ****
> --- 338,345 ----
> ADD(IFM_AUTO, IFM_IEEE80211_HOSTAP);
> if (ic->ic_flags & IEEE80211_F_HASIBSS)
> ADD(IFM_AUTO, IFM_IEEE80211_ADHOC);
> + if (ic->ic_flags & IEEE80211_F_HASMONITOR)
> + ADD(IFM_AUTO, IFM_IEEE80211_MONITOR);
> ADD(IFM_AUTO, IFM_IEEE80211_ADHOC | IFM_FLAG0);
> for (i = 0; i < nrate; i++) {
> r = ic->ic_sup_rates[i];
> ***************
> *** 350,355 ****
> --- 353,360 ----
> ADD(mword, IFM_IEEE80211_HOSTAP);
> if (ic->ic_flags & IEEE80211_F_HASIBSS)
> ADD(mword, IFM_IEEE80211_ADHOC);
> + if (ic->ic_flags & IEEE80211_F_HASMONITOR)
> + ADD(mword, IFM_IEEE80211_MONITOR);
> ADD(mword, IFM_IEEE80211_ADHOC | IFM_FLAG0);
> }
> printf("\n");
> ***************
> *** 544,549 ****
> --- 549,557 ----
> case IEEE80211_M_HOSTAP:
> wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_HOSTAP);
> break;
> + case IEEE80211_M_MONITOR:
> + wi_cmd(sc, WI_CMD_TEST | (WI_TEST_MONITOR << 8), 0, 0, 0);
> + break;
> }
>
> /* Intersil interprets this RID as joining ESS even in IBSS mode */
> ***************
> *** 630,635 ****
> --- 638,644 ----
> ifp->if_flags |= IFF_RUNNING;
> ifp->if_flags &= ~IFF_OACTIVE;
> if (ic->ic_opmode == IEEE80211_M_AHDEMO ||
> + ic->ic_opmode == IEEE80211_M_MONITOR ||
> ic->ic_opmode == IEEE80211_M_HOSTAP)
> wi_newstate(sc, IEEE80211_S_RUN);
>
> ***************
> *** 981,986 ****
> --- 990,997 ----
> newmode = IEEE80211_M_IBSS;
> else if (ime->ifm_media & IFM_IEEE80211_HOSTAP)
> newmode = IEEE80211_M_HOSTAP;
> + else if (ime->ifm_media & IFM_IEEE80211_MONITOR)
> + newmode = IEEE80211_M_MONITOR;
> else
> newmode = IEEE80211_M_STA;
> if (ic->ic_opmode != newmode) {
> ***************
> *** 1046,1051 ****
> --- 1057,1065 ----
> case IEEE80211_M_HOSTAP:
> imr->ifm_active |= IFM_IEEE80211_HOSTAP;
> break;
> + case IEEE80211_M_MONITOR:
> + imr->ifm_active |= IFM_IEEE80211_MONITOR;
> + break;
> }
> }
>
> ***************
> *** 1087,1092 ****
> --- 1101,1115 ----
>
> len = le16toh(frmhdr.wi_dat_len);
> off = ALIGN(sizeof(struct ieee80211_frame));
> +
> + /*
> + * Sometimes the PRISM2 returns bogusly large frames, especially
> + * in monitor mode. This will try to fix them up so that we can
> + * read at least the IEEE 802.11 header.
> + */
> +
> + if (len > IEEE80211_MAX_LEN)
> + len = 0;
>
> MGETHDR(m, M_DONTWAIT, MT_DATA);
> if (m == NULL) {
> Index: dev/ic/wireg.h
> ===================================================================
> RCS file: /cvsroot/syssrc/sys/dev/ic/wireg.h,v
> retrieving revision 1.42
> diff -c -r1.42 wireg.h
> *** dev/ic/wireg.h 2002/10/21 11:57:25 1.42
> --- dev/ic/wireg.h 2002/11/03 02:56:55
> ***************
> *** 117,122 ****
> --- 117,123 ----
> #define WI_CMD_ACCESS 0x0021
> #define WI_CMD_PROGRAM 0x0022
> #define WI_CMD_READEE 0x0030
> + #define WI_CMD_TEST 0x0038 /* PRISM2 test mode */
>
> #define WI_CMD_CODE_MASK 0x003F
>
> ***************
> *** 139,144 ****
> --- 140,150 ----
> #define WI_PROGRAM_ENABLE_RAM 0x0100
> #define WI_PROGRAM_ENABLE_NVRAM 0x0200
> #define WI_PROGRAM_NVRAM 0x0300
> +
> + /*
> + * DEBUG mode options.
> + */
> + #define WI_TEST_MONITOR 0x0B /* monitor mode for testing */
>
> /* Status register values */
> #define WI_STAT_CMD_CODE 0x003F
> Index: net/if_ieee80211.h
> ===================================================================
> RCS file: /cvsroot/syssrc/sys/net/if_ieee80211.h,v
> retrieving revision 1.23
> diff -c -r1.23 if_ieee80211.h
> *** net/if_ieee80211.h 2002/10/15 08:51:50 1.23
> --- net/if_ieee80211.h 2002/11/03 02:57:03
> ***************
> *** 377,383 ****
> IEEE80211_M_STA = 1, /* infrastructure station */
> IEEE80211_M_IBSS = 0, /* IBSS (adhoc) station */
> IEEE80211_M_AHDEMO = 3, /* Old lucent compatible adhoc demo */
> ! IEEE80211_M_HOSTAP = 6 /* Software Access Point */
> };
>
> enum ieee80211_state {
> --- 377,385 ----
> IEEE80211_M_STA = 1, /* infrastructure station */
> IEEE80211_M_IBSS = 0, /* IBSS (adhoc) station */
> IEEE80211_M_AHDEMO = 3, /* Old lucent compatible adhoc demo */
> ! IEEE80211_M_HOSTAP = 6, /* Software Access Point */
> ! IEEE80211_M_MONITOR = 8 /* Monitor mode (doesn't correspond
> ! to a PRISM port like the others) */
> };
>
> enum ieee80211_state {
> ***************
> *** 502,507 ****
> --- 504,510 ----
> #define IEEE80211_F_HASPMGT 0x00040000 /* CAPABILITY: Power mgmt */
> #define IEEE80211_F_HASHOSTAP 0x00080000 /* CAPABILITY: HOSTAP avail */
> #define IEEE80211_F_HASAHDEMO 0x00100000 /* CAPABILITY: Old Adhoc Demo */
> + #define IEEE80211_F_HASMONITOR 0x00200000 /* CAPABILITY: Monitor mode */
>
> /* flags for ieee80211_fix_rate() */
> #define IEEE80211_F_DOSORT 0x00000001 /* sort rate list */
> Index: net/if_ieee80211subr.c
> ===================================================================
> RCS file: /cvsroot/syssrc/sys/net/if_ieee80211subr.c,v
> retrieving revision 1.22
> diff -c -r1.22 if_ieee80211subr.c
> *** net/if_ieee80211subr.c 2002/10/16 11:29:30 1.22
> --- net/if_ieee80211subr.c 2002/11/03 02:57:08
> ***************
> *** 288,293 ****
> --- 288,295 ----
> ni = &ic->ic_bss; /* XXX allocate? */
> }
> break;
> + case IEEE80211_M_MONITOR:
> + goto out;
> }
> ni->ni_rssi = rssi;
> ni->ni_rstamp = rstamp;
> ***************
> *** 354,359 ****
> --- 356,364 ----
> goto err;
> }
> break;
> + case IEEE80211_M_MONITOR:
> + /* Should never get here */
> + break;
> }
> if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
> if (ic->ic_flags & IEEE80211_F_WEPON) {
> ***************
> *** 601,606 ****
> --- 606,615 ----
> IEEE80211_ADDR_COPY(wh->i_addr2, ni->ni_bssid);
> IEEE80211_ADDR_COPY(wh->i_addr3, eh.ether_shost);
> break;
> + case IEEE80211_M_MONITOR:
> + /* Should never get here! */
> + m_freem(m);
> + return NULL;
> }
> return m;
> }
> ***************
> *** 1884,1889 ****
> --- 1893,1899 ----
> break;
>
> case IEEE80211_M_AHDEMO:
> + case IEEE80211_M_MONITOR:
> /* should not come here */
> break;
>
> Index: net/if_media.h
> ===================================================================
> RCS file: /cvsroot/syssrc/sys/net/if_media.h,v
> retrieving revision 1.29
> diff -c -r1.29 if_media.h
> *** net/if_media.h 2002/09/27 05:27:20 1.29
> --- net/if_media.h 2002/11/03 02:57:09
> ***************
> *** 216,221 ****
> --- 216,222 ----
>
> #define IFM_IEEE80211_ADHOC 0x00000100 /* Operate in Adhoc mode */
> #define IFM_IEEE80211_HOSTAP 0x00000200 /* Operate in Host AP mode */
> + #define IFM_IEEE80211_MONITOR 0x00000400 /* Operate in Monitor mode */
>
> /*
> * Shared media sub-types
> ***************
> *** 418,423 ****
> --- 419,425 ----
> { IFM_IEEE80211|IFM_IEEE80211_ADHOC, "adhoc" }, \
> { IFM_IEEE80211|IFM_IEEE80211_ADHOC, "ibss" }, \
> { IFM_IEEE80211|IFM_IEEE80211_HOSTAP, "hostap" }, \
> + { IFM_IEEE80211|IFM_IEEE80211_MONITOR, "monitor" }, \
> \
> { 0, NULL }, \
> }
--
David Young OJC Technologies
dyoung@ojctech.com Engineering from the Right Brain
Urbana, IL * (217) 278-3933