132176cfdSRui Paulo /*-
232176cfdSRui Paulo * Copyright (c) 2007-2008 Sam Leffler, Errno Consulting
332176cfdSRui Paulo * All rights reserved.
432176cfdSRui Paulo *
532176cfdSRui Paulo * Redistribution and use in source and binary forms, with or without
632176cfdSRui Paulo * modification, are permitted provided that the following conditions
732176cfdSRui Paulo * are met:
832176cfdSRui Paulo * 1. Redistributions of source code must retain the above copyright
932176cfdSRui Paulo * notice, this list of conditions and the following disclaimer.
1032176cfdSRui Paulo * 2. Redistributions in binary form must reproduce the above copyright
1132176cfdSRui Paulo * notice, this list of conditions and the following disclaimer in the
1232176cfdSRui Paulo * documentation and/or other materials provided with the distribution.
1332176cfdSRui Paulo *
1432176cfdSRui Paulo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1532176cfdSRui Paulo * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1632176cfdSRui Paulo * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1732176cfdSRui Paulo * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1832176cfdSRui Paulo * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
1932176cfdSRui Paulo * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2032176cfdSRui Paulo * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2132176cfdSRui Paulo * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2232176cfdSRui Paulo * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2332176cfdSRui Paulo * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2432176cfdSRui Paulo */
2532176cfdSRui Paulo
26085ff963SMatthew Dillon #include <sys/cdefs.h>
27085ff963SMatthew Dillon #ifdef __FreeBSD__
28085ff963SMatthew Dillon __FBSDID("$FreeBSD$");
29085ff963SMatthew Dillon #endif
30085ff963SMatthew Dillon
3132176cfdSRui Paulo /*
3232176cfdSRui Paulo * IEEE 802.11 Monitor mode support.
3332176cfdSRui Paulo */
3432176cfdSRui Paulo #include "opt_inet.h"
3532176cfdSRui Paulo #include "opt_wlan.h"
3632176cfdSRui Paulo
3732176cfdSRui Paulo #include <sys/param.h>
3832176cfdSRui Paulo #include <sys/systm.h>
3932176cfdSRui Paulo #include <sys/mbuf.h>
4032176cfdSRui Paulo #include <sys/malloc.h>
4132176cfdSRui Paulo #include <sys/kernel.h>
4232176cfdSRui Paulo
4332176cfdSRui Paulo #include <sys/socket.h>
4432176cfdSRui Paulo #include <sys/sockio.h>
4532176cfdSRui Paulo #include <sys/endian.h>
4632176cfdSRui Paulo #include <sys/errno.h>
4732176cfdSRui Paulo #include <sys/proc.h>
4832176cfdSRui Paulo #include <sys/sysctl.h>
4932176cfdSRui Paulo
5032176cfdSRui Paulo #include <net/if.h>
51085ff963SMatthew Dillon #include <net/if_var.h>
5232176cfdSRui Paulo #include <net/if_media.h>
5332176cfdSRui Paulo #include <net/if_llc.h>
5432176cfdSRui Paulo #include <net/ethernet.h>
5532176cfdSRui Paulo
5632176cfdSRui Paulo #include <net/bpf.h>
5732176cfdSRui Paulo
5832176cfdSRui Paulo #include <netproto/802_11/ieee80211_var.h>
5932176cfdSRui Paulo #include <netproto/802_11/ieee80211_monitor.h>
6032176cfdSRui Paulo
6132176cfdSRui Paulo static void monitor_vattach(struct ieee80211vap *);
6232176cfdSRui Paulo static int monitor_newstate(struct ieee80211vap *, enum ieee80211_state, int);
6332176cfdSRui Paulo static int monitor_input(struct ieee80211_node *ni, struct mbuf *m,
644f898719SImre Vadász const struct ieee80211_rx_stats *rxs, int rssi, int nf);
6532176cfdSRui Paulo
6632176cfdSRui Paulo void
ieee80211_monitor_attach(struct ieee80211com * ic)6732176cfdSRui Paulo ieee80211_monitor_attach(struct ieee80211com *ic)
6832176cfdSRui Paulo {
6932176cfdSRui Paulo ic->ic_vattach[IEEE80211_M_MONITOR] = monitor_vattach;
7032176cfdSRui Paulo }
7132176cfdSRui Paulo
7232176cfdSRui Paulo void
ieee80211_monitor_detach(struct ieee80211com * ic)7332176cfdSRui Paulo ieee80211_monitor_detach(struct ieee80211com *ic)
7432176cfdSRui Paulo {
7532176cfdSRui Paulo }
7632176cfdSRui Paulo
7732176cfdSRui Paulo static void
monitor_vdetach(struct ieee80211vap * vap)7832176cfdSRui Paulo monitor_vdetach(struct ieee80211vap *vap)
7932176cfdSRui Paulo {
8032176cfdSRui Paulo }
8132176cfdSRui Paulo
8232176cfdSRui Paulo static void
monitor_vattach(struct ieee80211vap * vap)8332176cfdSRui Paulo monitor_vattach(struct ieee80211vap *vap)
8432176cfdSRui Paulo {
8532176cfdSRui Paulo vap->iv_newstate = monitor_newstate;
8632176cfdSRui Paulo vap->iv_input = monitor_input;
8732176cfdSRui Paulo vap->iv_opdetach = monitor_vdetach;
8832176cfdSRui Paulo }
8932176cfdSRui Paulo
9032176cfdSRui Paulo /*
9132176cfdSRui Paulo * IEEE80211_M_MONITOR vap state machine handler.
9232176cfdSRui Paulo */
9332176cfdSRui Paulo static int
monitor_newstate(struct ieee80211vap * vap,enum ieee80211_state nstate,int arg)9432176cfdSRui Paulo monitor_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
9532176cfdSRui Paulo {
9632176cfdSRui Paulo struct ieee80211com *ic = vap->iv_ic;
9732176cfdSRui Paulo enum ieee80211_state ostate;
9832176cfdSRui Paulo
99085ff963SMatthew Dillon IEEE80211_LOCK_ASSERT(ic);
100085ff963SMatthew Dillon
10132176cfdSRui Paulo ostate = vap->iv_state;
10232176cfdSRui Paulo IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE, "%s: %s -> %s (%d)\n",
10332176cfdSRui Paulo __func__, ieee80211_state_name[ostate],
10432176cfdSRui Paulo ieee80211_state_name[nstate], arg);
10532176cfdSRui Paulo vap->iv_state = nstate; /* state transition */
10632176cfdSRui Paulo if (nstate == IEEE80211_S_RUN) {
10732176cfdSRui Paulo switch (ostate) {
10832176cfdSRui Paulo case IEEE80211_S_INIT:
10932176cfdSRui Paulo ieee80211_create_ibss(vap, ic->ic_curchan);
11032176cfdSRui Paulo break;
11132176cfdSRui Paulo default:
11232176cfdSRui Paulo break;
11332176cfdSRui Paulo }
11432176cfdSRui Paulo /*
11532176cfdSRui Paulo * NB: this shouldn't be here but many people use
11632176cfdSRui Paulo * monitor mode for raw packets; once we switch
11732176cfdSRui Paulo * them over to adhoc demo mode remove this.
11832176cfdSRui Paulo */
11932176cfdSRui Paulo ieee80211_node_authorize(vap->iv_bss);
12032176cfdSRui Paulo }
12132176cfdSRui Paulo return 0;
12232176cfdSRui Paulo }
12332176cfdSRui Paulo
12432176cfdSRui Paulo /*
12532176cfdSRui Paulo * Process a received frame in monitor mode.
12632176cfdSRui Paulo */
12732176cfdSRui Paulo static int
monitor_input(struct ieee80211_node * ni,struct mbuf * m,const struct ieee80211_rx_stats * rxs,int rssi,int nf)1284f898719SImre Vadász monitor_input(struct ieee80211_node *ni, struct mbuf *m,
1294f898719SImre Vadász const struct ieee80211_rx_stats *rxs, int rssi, int nf)
13032176cfdSRui Paulo {
13132176cfdSRui Paulo struct ieee80211vap *vap = ni->ni_vap;
13232176cfdSRui Paulo struct ifnet *ifp = vap->iv_ifp;
13332176cfdSRui Paulo
134*4f655ef5SMatthew Dillon if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
13532176cfdSRui Paulo
13632176cfdSRui Paulo if (ieee80211_radiotap_active_vap(vap))
13732176cfdSRui Paulo ieee80211_radiotap_rx(vap, m);
13832176cfdSRui Paulo m_freem(m);
13932176cfdSRui Paulo return -1;
14032176cfdSRui Paulo }
141