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> 51178354Ssam#include <net/if_media.h> 52178354Ssam#include <net/if_llc.h> 53178354Ssam#include <net/ethernet.h> 54178354Ssam 55178354Ssam#include <net/bpf.h> 56178354Ssam 57178354Ssam#include <net80211/ieee80211_var.h> 58178354Ssam#include <net80211/ieee80211_monitor.h> 59178354Ssam 60178354Ssamstatic void monitor_vattach(struct ieee80211vap *); 61178354Ssamstatic int monitor_newstate(struct ieee80211vap *, enum ieee80211_state, int); 62178354Ssamstatic int monitor_input(struct ieee80211_node *ni, struct mbuf *m, 63192468Ssam int rssi, int nf); 64178354Ssam 65178354Ssamvoid 66178354Ssamieee80211_monitor_attach(struct ieee80211com *ic) 67178354Ssam{ 68178354Ssam ic->ic_vattach[IEEE80211_M_MONITOR] = monitor_vattach; 69178354Ssam} 70178354Ssam 71178354Ssamvoid 72178354Ssamieee80211_monitor_detach(struct ieee80211com *ic) 73178354Ssam{ 74178354Ssam} 75178354Ssam 76178354Ssamstatic void 77178354Ssammonitor_vdetach(struct ieee80211vap *vap) 78178354Ssam{ 79178354Ssam} 80178354Ssam 81178354Ssamstatic void 82178354Ssammonitor_vattach(struct ieee80211vap *vap) 83178354Ssam{ 84178354Ssam vap->iv_newstate = monitor_newstate; 85178354Ssam vap->iv_input = monitor_input; 86178354Ssam vap->iv_opdetach = monitor_vdetach; 87178354Ssam} 88178354Ssam 89178354Ssam/* 90178354Ssam * IEEE80211_M_MONITOR vap state machine handler. 91178354Ssam */ 92178354Ssamstatic int 93178354Ssammonitor_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) 94178354Ssam{ 95178354Ssam struct ieee80211com *ic = vap->iv_ic; 96178354Ssam enum ieee80211_state ostate; 97178354Ssam 98178354Ssam IEEE80211_LOCK_ASSERT(ic); 99178354Ssam 100178354Ssam ostate = vap->iv_state; 101178354Ssam IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE, "%s: %s -> %s (%d)\n", 102178354Ssam __func__, ieee80211_state_name[ostate], 103178354Ssam ieee80211_state_name[nstate], arg); 104178354Ssam vap->iv_state = nstate; /* state transition */ 105178354Ssam if (nstate == IEEE80211_S_RUN) { 106178354Ssam switch (ostate) { 107178354Ssam case IEEE80211_S_INIT: 108178354Ssam ieee80211_create_ibss(vap, ic->ic_curchan); 109178354Ssam break; 110178354Ssam default: 111178354Ssam break; 112178354Ssam } 113178354Ssam /* 114178354Ssam * NB: this shouldn't be here but many people use 115178354Ssam * monitor mode for raw packets; once we switch 116178354Ssam * them over to adhoc demo mode remove this. 117178354Ssam */ 118178354Ssam ieee80211_node_authorize(vap->iv_bss); 119178354Ssam } 120178354Ssam return 0; 121178354Ssam} 122178354Ssam 123178354Ssam/* 124178354Ssam * Process a received frame in monitor mode. 125178354Ssam */ 126178354Ssamstatic int 127192468Ssammonitor_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf) 128178354Ssam{ 129178354Ssam struct ieee80211vap *vap = ni->ni_vap; 130193287Ssam struct ifnet *ifp = vap->iv_ifp; 131178354Ssam 132193287Ssam ifp->if_ipackets++; 133193287Ssam 134192765Ssam if (ieee80211_radiotap_active_vap(vap)) 135192765Ssam ieee80211_radiotap_rx(vap, m); 136178354Ssam m_freem(m); 137178354Ssam return -1; 138178354Ssam} 139