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