diff --git a/sys/net/if_media.h b/sys/net/if_media.h index 49a41b074b02..efaa36a3a75d 100644 --- a/sys/net/if_media.h +++ b/sys/net/if_media.h @@ -194,6 +194,7 @@ int ifmedia_ioctl(struct ifnet *ifp, struct ifreq *ifr, #define IFM_IEEE80211_IBSS 0x00000400 /* Operate in IBSS mode */ #define IFM_IEEE80211_IBSSMASTER 0x00000800 /* Operate as an IBSS master */ #define IFM_IEEE80211_TURBO 0x00001000 /* Operate in turbo mode */ +#define IFM_IEEE80211_MONITOR 0x00002000 /* Operate in monitor mode */ /* operating mode for multi-mode devices */ #define IFM_IEEE80211_11A 1 /* 5Ghz, OFDM mode */ #define IFM_IEEE80211_11B 2 /* Direct Sequence mode */ @@ -443,6 +444,7 @@ struct ifmedia_description { { IFM_IEEE80211_IBSS, "ibss" }, \ { IFM_IEEE80211_IBSSMASTER, "ibss-master" }, \ { IFM_IEEE80211_TURBO, "turbo" }, \ + { IFM_IEEE80211_MONITOR, "monitor" }, \ { 0, NULL }, \ } diff --git a/sys/net80211/ieee80211.c b/sys/net80211/ieee80211.c index de56d17958c8..ad585baa1608 100644 --- a/sys/net80211/ieee80211.c +++ b/sys/net80211/ieee80211.c @@ -275,6 +275,8 @@ ieee80211_media_init(struct ifnet *ifp, ADD(ic, IFM_AUTO, mopt | IFM_IEEE80211_HOSTAP); if (ic->ic_caps & IEEE80211_C_AHDEMO) ADD(ic, IFM_AUTO, mopt | IFM_IEEE80211_ADHOC | IFM_FLAG0); + if (ic->ic_caps & IEEE80211_C_MONITOR) + ADD(ic, IFM_AUTO, mopt | IFM_IEEE80211_MONITOR); if (mode == IEEE80211_MODE_AUTO) continue; if_printf(ifp, "%s rates: ", ieee80211_phymode_name[mode]); @@ -294,6 +296,8 @@ ieee80211_media_init(struct ifnet *ifp, ADD(ic, mword, mopt | IFM_IEEE80211_HOSTAP); if (ic->ic_caps & IEEE80211_C_AHDEMO) ADD(ic, mword, mopt | IFM_IEEE80211_ADHOC | IFM_FLAG0); + if (ic->ic_caps & IEEE80211_C_MONITOR) + ADD(ic, mword, mopt | IFM_IEEE80211_MONITOR); /* * Add rate to the collection of all rates. */ @@ -325,6 +329,8 @@ ieee80211_media_init(struct ifnet *ifp, ADD(ic, mword, IFM_IEEE80211_HOSTAP); if (ic->ic_caps & IEEE80211_C_AHDEMO) ADD(ic, mword, IFM_IEEE80211_ADHOC | IFM_FLAG0); + if (ic->ic_caps & IEEE80211_C_MONITOR) + ADD(ic, mword, IFM_IEEE80211_MONITOR); } ieee80211_media_status(ifp, &imr); ifmedia_set(&ic->ic_media, imr.ifm_active); @@ -441,6 +447,8 @@ ieee80211_media_change(struct ifnet *ifp) newopmode = IEEE80211_M_HOSTAP; else if (ime->ifm_media & IFM_IEEE80211_ADHOC) newopmode = IEEE80211_M_IBSS; + else if (ime->ifm_media & IFM_IEEE80211_MONITOR) + newopmode = IEEE80211_M_MONITOR; else newopmode = IEEE80211_M_STA; @@ -486,6 +494,7 @@ ieee80211_media_change(struct ifnet *ifp) case IEEE80211_M_AHDEMO: case IEEE80211_M_HOSTAP: case IEEE80211_M_STA: + case IEEE80211_M_MONITOR: ic->ic_flags &= ~IEEE80211_F_IBSSON; break; case IEEE80211_M_IBSS: @@ -534,6 +543,9 @@ ieee80211_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; } switch (ic->ic_curmode) { case IEEE80211_MODE_11A: diff --git a/sys/net80211/ieee80211_input.c b/sys/net80211/ieee80211_input.c index dc4f46269f3d..f16ca2e5b95c 100644 --- a/sys/net80211/ieee80211_input.c +++ b/sys/net80211/ieee80211_input.c @@ -138,6 +138,9 @@ ieee80211_input(struct ifnet *ifp, struct mbuf *m, ni = ieee80211_ref_node(ic->ic_bss); } break; + case IEEE80211_M_MONITOR: + /* NB: this should collect everything */ + goto out; default: /* XXX catch bad values */ break; @@ -212,6 +215,8 @@ ieee80211_input(struct ifnet *ifp, struct mbuf *m, } ieee80211_unref_node(&ni); break; + case IEEE80211_M_MONITOR: + break; } if (wh->i_fc[1] & IEEE80211_FC1_WEP) { if (ic->ic_flags & IEEE80211_F_WEPON) { @@ -829,6 +834,8 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0, int subtype, ieee80211_new_state(ic, IEEE80211_S_ASSOC, wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK); break; + case IEEE80211_M_MONITOR: + break; } break; } diff --git a/sys/net80211/ieee80211_output.c b/sys/net80211/ieee80211_output.c index dafa64cf681f..9b79d6544fbf 100644 --- a/sys/net80211/ieee80211_output.c +++ b/sys/net80211/ieee80211_output.c @@ -172,6 +172,9 @@ ieee80211_encap(struct ifnet *ifp, struct mbuf *m) IEEE80211_ADDR_COPY(wh->i_addr2, ni->ni_bssid); IEEE80211_ADDR_COPY(wh->i_addr3, eh.ether_shost); break; + case IEEE80211_M_MONITOR: + m_freem(m), m = NULL; + break; } ieee80211_unref_node(&ni); return m; diff --git a/sys/net80211/ieee80211_var.h b/sys/net80211/ieee80211_var.h index 2b2f0b0dfe94..af47773af229 100644 --- a/sys/net80211/ieee80211_var.h +++ b/sys/net80211/ieee80211_var.h @@ -70,7 +70,8 @@ enum ieee80211_opmode { 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_HOSTAP = 6, /* Software Access Point */ + IEEE80211_M_MONITOR = 8 /* Monitor mode */ }; /* @@ -222,6 +223,7 @@ struct ieee80211com { #define IEEE80211_C_TXPMGT 0x00000040 /* CAPABILITY: tx power mgmt */ #define IEEE80211_C_SHSLOT 0x00000080 /* CAPABILITY: short slottime */ #define IEEE80211_C_SHPREAMBLE 0x00000100 /* CAPABILITY: short preamble */ +#define IEEE80211_C_MONITOR 0x00000200 /* CAPABILITY: monitor mode */ /* flags for ieee80211_fix_rate() */ #define IEEE80211_F_DOSORT 0x00000001 /* sort rate list */