summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authorsam <sam@FreeBSD.org>2003-07-21 23:20:40 +0000
committersam <sam@FreeBSD.org>2003-07-21 23:20:40 +0000
commit46a9d5a70295e3d01b8a913d8326317bca75a3e4 (patch)
tree3d338084c2f4789d68313c8db7b50628e99cb561 /sys/dev
parent6c3a9c4229994a0988cc7f7745ed0d5a74dc6119 (diff)
downloadFreeBSD-src-46a9d5a70295e3d01b8a913d8326317bca75a3e4.zip
FreeBSD-src-46a9d5a70295e3d01b8a913d8326317bca75a3e4.tar.gz
o Add monitor mode support. This tested fine with prism cards but may require
newer lucent/hermes firmware than indicated (investigating). I'm committing this now since it shouldn't hurt anything. o Vaguely related, add bogus frame length check from netbsd. Obtained from: netbsd
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/wi/if_wi.c31
1 files changed, 29 insertions, 2 deletions
diff --git a/sys/dev/wi/if_wi.c b/sys/dev/wi/if_wi.c
index 37e9ab8..91e68b1 100644
--- a/sys/dev/wi/if_wi.c
+++ b/sys/dev/wi/if_wi.c
@@ -367,8 +367,10 @@ wi_attach(device_t dev)
#endif
if (sc->sc_sta_firmware_ver >= 60000)
sc->sc_flags |= WI_FLAGS_HAS_MOR;
- if (sc->sc_sta_firmware_ver >= 60006)
+ if (sc->sc_sta_firmware_ver >= 60006) {
ic->ic_caps |= IEEE80211_C_IBSS;
+ ic->ic_caps |= IEEE80211_C_MONITOR;
+ }
sc->sc_ibss_port = htole16(1);
break;
@@ -379,8 +381,10 @@ wi_attach(device_t dev)
sc->sc_flags |= WI_FLAGS_HAS_SYSSCALE;
if (sc->sc_sta_firmware_ver > 10101)
sc->sc_flags |= WI_FLAGS_HAS_DBMADJUST;
- if (sc->sc_sta_firmware_ver >= 800)
+ if (sc->sc_sta_firmware_ver >= 800) {
ic->ic_caps |= IEEE80211_C_IBSS;
+ ic->ic_caps |= IEEE80211_C_MONITOR;
+ }
/*
* version 0.8.3 and newer are the only ones that are known
* to currently work. Earlier versions can be made to work,
@@ -622,6 +626,11 @@ wi_init(void *arg)
case IEEE80211_M_HOSTAP:
wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_HOSTAP);
break;
+ case IEEE80211_M_MONITOR:
+ if (sc->sc_firmware_type == WI_LUCENT)
+ wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_ADHOC);
+ wi_cmd(sc, WI_CMD_DEBUG | (WI_TEST_MONITOR << 8), 0, 0, 0);
+ break;
}
/* Intersil interprets this RID as joining ESS even in IBSS mode */
@@ -717,6 +726,7 @@ wi_init(void *arg)
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)
ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
@@ -1224,6 +1234,9 @@ wi_media_status(struct ifnet *ifp, struct ifmediareq *imr)
case IEEE80211_M_HOSTAP:
imr->ifm_active |= IFM_IEEE80211_HOSTAP;
break;
+ case IEEE80211_M_MONITOR:
+ imr->ifm_active |= IFM_IEEE80211_MONITOR;
+ break;
}
}
@@ -1387,6 +1400,20 @@ wi_rx_intr(struct wi_softc *sc)
len = le16toh(frmhdr.wi_dat_len);
off = ALIGN(sizeof(struct ieee80211_frame));
+ /*
+ * Sometimes the PRISM2.x returns bogusly large frames. Except
+ * in monitor mode, just throw them away.
+ */
+ if (off + len > MCLBYTES) {
+ if (ic->ic_opmode != IEEE80211_M_MONITOR) {
+ CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
+ ifp->if_ierrors++;
+ DPRINTF(("wi_rx_intr: oversized packet\n"));
+ return;
+ } else
+ len = 0;
+ }
+
MGETHDR(m, M_DONTWAIT, MT_DATA);
if (m == NULL) {
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
OpenPOWER on IntegriCloud