1220908Sadrian/*- 2220908Sadrian * Copyright (c) 2011 Adrian Chadd, Xenion Lty Ltd 3220908Sadrian * All rights reserved. 4220908Sadrian * 5220908Sadrian * Redistribution and use in source and binary forms, with or without 6220908Sadrian * modification, are permitted provided that the following conditions 7220908Sadrian * are met: 8220908Sadrian * 1. Redistributions of source code must retain the above copyright 9220908Sadrian * notice, this list of conditions and the following disclaimer. 10220908Sadrian * 2. Redistributions in binary form must reproduce the above copyright 11220908Sadrian * notice, this list of conditions and the following disclaimer in the 12220908Sadrian * documentation and/or other materials provided with the distribution. 13220908Sadrian * 14220908Sadrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15220908Sadrian * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16220908Sadrian * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17220908Sadrian * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18220908Sadrian * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19220908Sadrian * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20220908Sadrian * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21220908Sadrian * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22220908Sadrian * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23220908Sadrian * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24220908Sadrian */ 25220908Sadrian 26220908Sadrian#include <sys/cdefs.h> 27220908Sadrian#ifdef __FreeBSD__ 28220908Sadrian__FBSDID("$FreeBSD$"); 29220908Sadrian#endif 30220908Sadrian 31220908Sadrian/* 32220908Sadrian * net80211 fast-logging support, primarily for debugging. 33220908Sadrian * 34220908Sadrian * This implements a single debugging queue which includes 35220908Sadrian * per-device enumeration where needed. 36220908Sadrian */ 37220908Sadrian 38220908Sadrian#include "opt_wlan.h" 39220908Sadrian 40220908Sadrian#include <sys/param.h> 41220908Sadrian#include <sys/systm.h> 42220908Sadrian#include <sys/mbuf.h> 43220908Sadrian#include <sys/malloc.h> 44220908Sadrian#include <sys/endian.h> 45220908Sadrian#include <sys/kernel.h> 46220908Sadrian#include <sys/sysctl.h> 47220908Sadrian#include <sys/pcpu.h> 48220908Sadrian#include <sys/proc.h> 49220908Sadrian#include <sys/ucred.h> 50220908Sadrian#include <sys/alq.h> 51220908Sadrian 52220908Sadrian#include <sys/socket.h> 53220908Sadrian 54220908Sadrian#include <net/if.h> 55220908Sadrian#include <net/if_var.h> 56220908Sadrian#include <net/if_dl.h> 57220908Sadrian#include <net/if_clone.h> 58220908Sadrian#include <net/if_media.h> 59220908Sadrian#include <net/if_types.h> 60220908Sadrian 61220908Sadrian#include <net80211/ieee80211_var.h> 62220908Sadrian#include <net80211/ieee80211_freebsd.h> 63220908Sadrian#include <net80211/ieee80211_alq.h> 64220908Sadrian 65220908Sadrianstatic struct alq *ieee80211_alq; 66220908Sadrianstatic int ieee80211_alq_lost; 67221781Sadrianstatic int ieee80211_alq_logged; 68221782Sadrianstatic char ieee80211_alq_logfile[MAXPATHLEN] = "/tmp/net80211.log"; 69220908Sadrianstatic unsigned int ieee80211_alq_qsize = 64*1024; 70220908Sadrian 71220908Sadrianstatic int 72220908Sadrianieee80211_alq_setlogging(int enable) 73220908Sadrian{ 74220908Sadrian int error; 75220908Sadrian 76220908Sadrian if (enable) { 77220908Sadrian if (ieee80211_alq) 78220908Sadrian alq_close(ieee80211_alq); 79220908Sadrian 80220908Sadrian error = alq_open(&ieee80211_alq, 81220908Sadrian ieee80211_alq_logfile, 82220908Sadrian curthread->td_ucred, 83220908Sadrian ALQ_DEFAULT_CMODE, 84220908Sadrian sizeof (struct ieee80211_alq_rec), 85220908Sadrian ieee80211_alq_qsize); 86220908Sadrian ieee80211_alq_lost = 0; 87221782Sadrian ieee80211_alq_logged = 0; 88221782Sadrian printf("net80211: logging to %s enabled; struct size %d bytes\n", 89221782Sadrian ieee80211_alq_logfile, sizeof(struct ieee80211_alq_rec)); 90220908Sadrian } else { 91220908Sadrian if (ieee80211_alq) 92220908Sadrian alq_close(ieee80211_alq); 93220908Sadrian ieee80211_alq = NULL; 94220908Sadrian printf("net80211: logging disabled\n"); 95220908Sadrian error = 0; 96220908Sadrian } 97220908Sadrian return (error); 98220908Sadrian} 99220908Sadrian 100220908Sadrianstatic int 101220908Sadriansysctl_ieee80211_alq_log(SYSCTL_HANDLER_ARGS) 102220908Sadrian{ 103220908Sadrian int error, enable; 104220908Sadrian 105220908Sadrian enable = (ieee80211_alq != NULL); 106220908Sadrian error = sysctl_handle_int(oidp, &enable, 0, req); 107220908Sadrian if (error || !req->newptr) 108220908Sadrian return (error); 109220908Sadrian else 110220908Sadrian return (ieee80211_alq_setlogging(enable)); 111220908Sadrian} 112220908Sadrian 113220908SadrianSYSCTL_PROC(_net_wlan, OID_AUTO, alq, CTLTYPE_INT|CTLFLAG_RW, 114220908Sadrian 0, 0, sysctl_ieee80211_alq_log, "I", "Enable net80211 alq logging"); 115220908SadrianSYSCTL_INT(_net_wlan, OID_AUTO, alq_size, CTLFLAG_RW, 116220908Sadrian &ieee80211_alq_qsize, 0, "In-memory log size (#records)"); 117220908SadrianSYSCTL_INT(_net_wlan, OID_AUTO, alq_lost, CTLFLAG_RW, 118220908Sadrian &ieee80211_alq_lost, 0, "Debugging operations not logged"); 119221781SadrianSYSCTL_INT(_net_wlan, OID_AUTO, alq_logged, CTLFLAG_RW, 120221781Sadrian &ieee80211_alq_logged, 0, "Debugging operations logged"); 121220908Sadrian 122220908Sadrianstatic struct ale * 123220908Sadrianieee80211_alq_get(void) 124220908Sadrian{ 125220908Sadrian struct ale *ale; 126220908Sadrian 127220908Sadrian ale = alq_get(ieee80211_alq, ALQ_NOWAIT); 128220908Sadrian if (!ale) 129220908Sadrian ieee80211_alq_lost++; 130221781Sadrian else 131221781Sadrian ieee80211_alq_logged++; 132220908Sadrian return ale; 133220908Sadrian} 134220908Sadrian 135220908Sadrianvoid 136220908Sadrianieee80211_alq_log(struct ieee80211vap *vap, uint8_t op, u_char *p, int l) 137220908Sadrian{ 138220908Sadrian struct ale *ale; 139220908Sadrian struct ieee80211_alq_rec *r; 140220908Sadrian 141221781Sadrian if (ieee80211_alq == NULL) 142221781Sadrian return; 143221781Sadrian 144220908Sadrian ale = ieee80211_alq_get(); 145220908Sadrian if (! ale) 146220908Sadrian return; 147220908Sadrian 148221782Sadrian r = (struct ieee80211_alq_rec *) ale->ae_data; 149221781Sadrian r->r_timestamp = htonl(ticks); 150220908Sadrian r->r_version = 1; 151221781Sadrian r->r_wlan = htons(vap->iv_ifp->if_dunit); 152220908Sadrian r->r_op = op; 153220908Sadrian memcpy(&r->r_payload, p, MIN(l, sizeof(r->r_payload))); 154221781Sadrian alq_post(ieee80211_alq, ale); 155220908Sadrian} 156