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