Subject: PRISM2 monitor mode patch
To: None <tech-net@netbsd.org>
From: Kevin Lahey <kml@patheticgeek.net>
List: tech-net
Date: 11/08/2002 01:54:18
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 }, \
}