xref: /dflybsd-src/sys/netproto/802_11/wlan/ieee80211_monitor.c (revision 4f655ef568316df0b575f05cebf37546415c0d24)
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