1178354Ssam/*-
2178354Ssam * Copyright (c) 2007-2008 Sam Leffler, Errno Consulting
3178354Ssam * All rights reserved.
4178354Ssam *
5178354Ssam * Redistribution and use in source and binary forms, with or without
6178354Ssam * modification, are permitted provided that the following conditions
7178354Ssam * are met:
8178354Ssam * 1. Redistributions of source code must retain the above copyright
9178354Ssam *    notice, this list of conditions and the following disclaimer.
10178354Ssam * 2. Redistributions in binary form must reproduce the above copyright
11178354Ssam *    notice, this list of conditions and the following disclaimer in the
12178354Ssam *    documentation and/or other materials provided with the distribution.
13178354Ssam *
14178354Ssam * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15178354Ssam * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16178354Ssam * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17178354Ssam * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18178354Ssam * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19178354Ssam * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20178354Ssam * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21178354Ssam * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22178354Ssam * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23178354Ssam * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24178354Ssam */
25178354Ssam
26178354Ssam#include <sys/cdefs.h>
27178354Ssam#ifdef __FreeBSD__
28178354Ssam__FBSDID("$FreeBSD$");
29178354Ssam#endif
30178354Ssam
31178354Ssam/*
32178354Ssam * IEEE 802.11 Monitor mode support.
33178354Ssam */
34178354Ssam#include "opt_inet.h"
35178354Ssam#include "opt_wlan.h"
36178354Ssam
37178354Ssam#include <sys/param.h>
38178354Ssam#include <sys/systm.h>
39178354Ssam#include <sys/mbuf.h>
40178354Ssam#include <sys/malloc.h>
41178354Ssam#include <sys/kernel.h>
42178354Ssam
43178354Ssam#include <sys/socket.h>
44178354Ssam#include <sys/sockio.h>
45178354Ssam#include <sys/endian.h>
46178354Ssam#include <sys/errno.h>
47178354Ssam#include <sys/proc.h>
48178354Ssam#include <sys/sysctl.h>
49178354Ssam
50178354Ssam#include <net/if.h>
51257176Sglebius#include <net/if_var.h>
52178354Ssam#include <net/if_media.h>
53178354Ssam#include <net/if_llc.h>
54178354Ssam#include <net/ethernet.h>
55178354Ssam
56178354Ssam#include <net/bpf.h>
57178354Ssam
58178354Ssam#include <net80211/ieee80211_var.h>
59178354Ssam#include <net80211/ieee80211_monitor.h>
60178354Ssam
61178354Ssamstatic void monitor_vattach(struct ieee80211vap *);
62178354Ssamstatic int monitor_newstate(struct ieee80211vap *, enum ieee80211_state, int);
63178354Ssamstatic int monitor_input(struct ieee80211_node *ni, struct mbuf *m,
64283535Sadrian	const struct ieee80211_rx_stats *rxs, int rssi, int nf);
65178354Ssam
66178354Ssamvoid
67178354Ssamieee80211_monitor_attach(struct ieee80211com *ic)
68178354Ssam{
69178354Ssam	ic->ic_vattach[IEEE80211_M_MONITOR] = monitor_vattach;
70178354Ssam}
71178354Ssam
72178354Ssamvoid
73178354Ssamieee80211_monitor_detach(struct ieee80211com *ic)
74178354Ssam{
75178354Ssam}
76178354Ssam
77178354Ssamstatic void
78178354Ssammonitor_vdetach(struct ieee80211vap *vap)
79178354Ssam{
80178354Ssam}
81178354Ssam
82178354Ssamstatic void
83178354Ssammonitor_vattach(struct ieee80211vap *vap)
84178354Ssam{
85178354Ssam	vap->iv_newstate = monitor_newstate;
86178354Ssam	vap->iv_input = monitor_input;
87178354Ssam	vap->iv_opdetach = monitor_vdetach;
88178354Ssam}
89178354Ssam
90178354Ssam/*
91178354Ssam * IEEE80211_M_MONITOR vap state machine handler.
92178354Ssam */
93178354Ssamstatic int
94178354Ssammonitor_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
95178354Ssam{
96178354Ssam	struct ieee80211com *ic = vap->iv_ic;
97178354Ssam	enum ieee80211_state ostate;
98178354Ssam
99178354Ssam	IEEE80211_LOCK_ASSERT(ic);
100178354Ssam
101178354Ssam	ostate = vap->iv_state;
102178354Ssam	IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE, "%s: %s -> %s (%d)\n",
103178354Ssam	    __func__, ieee80211_state_name[ostate],
104178354Ssam	    ieee80211_state_name[nstate], arg);
105178354Ssam	vap->iv_state = nstate;			/* state transition */
106178354Ssam	if (nstate == IEEE80211_S_RUN) {
107178354Ssam		switch (ostate) {
108178354Ssam		case IEEE80211_S_INIT:
109178354Ssam			ieee80211_create_ibss(vap, ic->ic_curchan);
110178354Ssam			break;
111178354Ssam		default:
112178354Ssam			break;
113178354Ssam		}
114178354Ssam		/*
115178354Ssam		 * NB: this shouldn't be here but many people use
116178354Ssam		 * monitor mode for raw packets; once we switch
117178354Ssam		 * them over to adhoc demo mode remove this.
118178354Ssam		 */
119178354Ssam		ieee80211_node_authorize(vap->iv_bss);
120178354Ssam	}
121178354Ssam	return 0;
122178354Ssam}
123178354Ssam
124178354Ssam/*
125178354Ssam * Process a received frame in monitor mode.
126178354Ssam */
127178354Ssamstatic int
128283535Sadrianmonitor_input(struct ieee80211_node *ni, struct mbuf *m,
129283535Sadrian    const struct ieee80211_rx_stats *rxs, int rssi, int nf)
130178354Ssam{
131178354Ssam	struct ieee80211vap *vap = ni->ni_vap;
132193287Ssam	struct ifnet *ifp = vap->iv_ifp;
133178354Ssam
134271861Sglebius	if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
135193287Ssam
136192765Ssam	if (ieee80211_radiotap_active_vap(vap))
137192765Ssam		ieee80211_radiotap_rx(vap, m);
138178354Ssam	m_freem(m);
139178354Ssam	return -1;
140178354Ssam}
141