1138568Ssam/*-
2178354Ssam * Copyright (c) 2003-2008 Sam Leffler, Errno Consulting
3138568Ssam * All rights reserved.
4138568Ssam *
5138568Ssam * Redistribution and use in source and binary forms, with or without
6138568Ssam * modification, are permitted provided that the following conditions
7138568Ssam * are met:
8138568Ssam * 1. Redistributions of source code must retain the above copyright
9138568Ssam *    notice, this list of conditions and the following disclaimer.
10138568Ssam * 2. Redistributions in binary form must reproduce the above copyright
11138568Ssam *    notice, this list of conditions and the following disclaimer in the
12138568Ssam *    documentation and/or other materials provided with the distribution.
13138568Ssam *
14138568Ssam * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15138568Ssam * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16138568Ssam * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17138568Ssam * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18138568Ssam * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19138568Ssam * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20138568Ssam * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21138568Ssam * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22138568Ssam * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23138568Ssam * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24138568Ssam *
25138568Ssam * $FreeBSD$
26138568Ssam */
27138568Ssam#ifndef _NET80211_IEEE80211_FREEBSD_H_
28138568Ssam#define _NET80211_IEEE80211_FREEBSD_H_
29138568Ssam
30165911Ssam#ifdef _KERNEL
31178354Ssam#include <sys/param.h>
32178354Ssam#include <sys/lock.h>
33178354Ssam#include <sys/mutex.h>
34178354Ssam#include <sys/rwlock.h>
35192473Ssam#include <sys/sysctl.h>
36191746Sthompsa#include <sys/taskqueue.h>
37178354Ssam
38138568Ssam/*
39170530Ssam * Common state locking definitions.
40170530Ssam */
41179388Ssamtypedef struct {
42179388Ssam	char		name[16];		/* e.g. "ath0_com_lock" */
43179388Ssam	struct mtx	mtx;
44179388Ssam} ieee80211_com_lock_t;
45179388Ssam#define	IEEE80211_LOCK_INIT(_ic, _name) do {				\
46179388Ssam	ieee80211_com_lock_t *cl = &(_ic)->ic_comlock;			\
47179388Ssam	snprintf(cl->name, sizeof(cl->name), "%s_com_lock", _name);	\
48179388Ssam	mtx_init(&cl->mtx, cl->name, NULL, MTX_DEF | MTX_RECURSE);	\
49179388Ssam} while (0)
50179388Ssam#define	IEEE80211_LOCK_OBJ(_ic)	(&(_ic)->ic_comlock.mtx)
51179388Ssam#define	IEEE80211_LOCK_DESTROY(_ic) mtx_destroy(IEEE80211_LOCK_OBJ(_ic))
52179388Ssam#define	IEEE80211_LOCK(_ic)	   mtx_lock(IEEE80211_LOCK_OBJ(_ic))
53179388Ssam#define	IEEE80211_UNLOCK(_ic)	   mtx_unlock(IEEE80211_LOCK_OBJ(_ic))
54170530Ssam#define	IEEE80211_LOCK_ASSERT(_ic) \
55179388Ssam	mtx_assert(IEEE80211_LOCK_OBJ(_ic), MA_OWNED)
56243532Sadrian#define	IEEE80211_UNLOCK_ASSERT(_ic) \
57243532Sadrian	mtx_assert(IEEE80211_LOCK_OBJ(_ic), MA_NOTOWNED)
58170530Ssam
59170530Ssam/*
60248069Sadrian * Transmit lock.
61248069Sadrian *
62248069Sadrian * This is a (mostly) temporary lock designed to serialise all of the
63248069Sadrian * transmission operations throughout the stack.
64248069Sadrian */
65248069Sadriantypedef struct {
66248069Sadrian	char		name[16];		/* e.g. "ath0_com_lock" */
67248069Sadrian	struct mtx	mtx;
68248069Sadrian} ieee80211_tx_lock_t;
69248069Sadrian#define	IEEE80211_TX_LOCK_INIT(_ic, _name) do {				\
70248069Sadrian	ieee80211_tx_lock_t *cl = &(_ic)->ic_txlock;			\
71248069Sadrian	snprintf(cl->name, sizeof(cl->name), "%s_tx_lock", _name);	\
72248069Sadrian	mtx_init(&cl->mtx, cl->name, NULL, MTX_DEF);	\
73248069Sadrian} while (0)
74248069Sadrian#define	IEEE80211_TX_LOCK_OBJ(_ic)	(&(_ic)->ic_txlock.mtx)
75248069Sadrian#define	IEEE80211_TX_LOCK_DESTROY(_ic) mtx_destroy(IEEE80211_TX_LOCK_OBJ(_ic))
76248069Sadrian#define	IEEE80211_TX_LOCK(_ic)	   mtx_lock(IEEE80211_TX_LOCK_OBJ(_ic))
77248069Sadrian#define	IEEE80211_TX_UNLOCK(_ic)	   mtx_unlock(IEEE80211_TX_LOCK_OBJ(_ic))
78248069Sadrian#define	IEEE80211_TX_LOCK_ASSERT(_ic) \
79248069Sadrian	mtx_assert(IEEE80211_TX_LOCK_OBJ(_ic), MA_OWNED)
80248069Sadrian#define	IEEE80211_TX_UNLOCK_ASSERT(_ic) \
81248069Sadrian	mtx_assert(IEEE80211_TX_LOCK_OBJ(_ic), MA_NOTOWNED)
82248069Sadrian
83248069Sadrian/*
84138568Ssam * Node locking definitions.
85138568Ssam */
86178354Ssamtypedef struct {
87178354Ssam	char		name[16];		/* e.g. "ath0_node_lock" */
88178354Ssam	struct mtx	mtx;
89178354Ssam} ieee80211_node_lock_t;
90178354Ssam#define	IEEE80211_NODE_LOCK_INIT(_nt, _name) do {			\
91178354Ssam	ieee80211_node_lock_t *nl = &(_nt)->nt_nodelock;		\
92178354Ssam	snprintf(nl->name, sizeof(nl->name), "%s_node_lock", _name);	\
93179388Ssam	mtx_init(&nl->mtx, nl->name, NULL, MTX_DEF | MTX_RECURSE);	\
94178354Ssam} while (0)
95179388Ssam#define	IEEE80211_NODE_LOCK_OBJ(_nt)	(&(_nt)->nt_nodelock.mtx)
96178354Ssam#define	IEEE80211_NODE_LOCK_DESTROY(_nt) \
97179388Ssam	mtx_destroy(IEEE80211_NODE_LOCK_OBJ(_nt))
98178354Ssam#define	IEEE80211_NODE_LOCK(_nt) \
99179388Ssam	mtx_lock(IEEE80211_NODE_LOCK_OBJ(_nt))
100178354Ssam#define	IEEE80211_NODE_IS_LOCKED(_nt) \
101179388Ssam	mtx_owned(IEEE80211_NODE_LOCK_OBJ(_nt))
102178354Ssam#define	IEEE80211_NODE_UNLOCK(_nt) \
103179388Ssam	mtx_unlock(IEEE80211_NODE_LOCK_OBJ(_nt))
104178354Ssam#define	IEEE80211_NODE_LOCK_ASSERT(_nt)	\
105179388Ssam	mtx_assert(IEEE80211_NODE_LOCK_OBJ(_nt), MA_OWNED)
106138568Ssam
107138568Ssam/*
108178354Ssam * Node table iteration locking definitions; this protects the
109178354Ssam * scan generation # used to iterate over the station table
110178354Ssam * while grabbing+releasing the node lock.
111138568Ssam */
112178354Ssamtypedef struct {
113178354Ssam	char		name[16];		/* e.g. "ath0_scan_lock" */
114178354Ssam	struct mtx	mtx;
115178354Ssam} ieee80211_scan_lock_t;
116178354Ssam#define	IEEE80211_NODE_ITERATE_LOCK_INIT(_nt, _name) do {		\
117178354Ssam	ieee80211_scan_lock_t *sl = &(_nt)->nt_scanlock;		\
118178354Ssam	snprintf(sl->name, sizeof(sl->name), "%s_scan_lock", _name);	\
119179388Ssam	mtx_init(&sl->mtx, sl->name, NULL, MTX_DEF);			\
120178354Ssam} while (0)
121179388Ssam#define	IEEE80211_NODE_ITERATE_LOCK_OBJ(_nt)	(&(_nt)->nt_scanlock.mtx)
122178354Ssam#define	IEEE80211_NODE_ITERATE_LOCK_DESTROY(_nt) \
123179388Ssam	mtx_destroy(IEEE80211_NODE_ITERATE_LOCK_OBJ(_nt))
124178354Ssam#define	IEEE80211_NODE_ITERATE_LOCK(_nt) \
125179388Ssam	mtx_lock(IEEE80211_NODE_ITERATE_LOCK_OBJ(_nt))
126178354Ssam#define	IEEE80211_NODE_ITERATE_UNLOCK(_nt) \
127179388Ssam	mtx_unlock(IEEE80211_NODE_ITERATE_LOCK_OBJ(_nt))
128138568Ssam
129138568Ssam/*
130184288Ssam * Power-save queue definitions.
131138568Ssam */
132184288Ssamtypedef struct mtx ieee80211_psq_lock_t;
133184288Ssam#define	IEEE80211_PSQ_INIT(_psq, _name) \
134195379Ssam	mtx_init(&(_psq)->psq_lock, _name, "802.11 ps q", MTX_DEF)
135184288Ssam#define	IEEE80211_PSQ_DESTROY(_psq)	mtx_destroy(&(_psq)->psq_lock)
136184288Ssam#define	IEEE80211_PSQ_LOCK(_psq)	mtx_lock(&(_psq)->psq_lock)
137184288Ssam#define	IEEE80211_PSQ_UNLOCK(_psq)	mtx_unlock(&(_psq)->psq_lock)
138138568Ssam
139167284Ssam#ifndef IF_PREPEND_LIST
140167284Ssam#define _IF_PREPEND_LIST(ifq, mhead, mtail, mcount) do {	\
141167284Ssam	(mtail)->m_nextpkt = (ifq)->ifq_head;			\
142167284Ssam	if ((ifq)->ifq_tail == NULL)				\
143167284Ssam		(ifq)->ifq_tail = (mtail);			\
144167284Ssam	(ifq)->ifq_head = (mhead);				\
145167284Ssam	(ifq)->ifq_len += (mcount);				\
146167284Ssam} while (0)
147167284Ssam#define IF_PREPEND_LIST(ifq, mhead, mtail, mcount) do {		\
148167284Ssam	IF_LOCK(ifq);						\
149167284Ssam	_IF_PREPEND_LIST(ifq, mhead, mtail, mcount);		\
150167284Ssam	IF_UNLOCK(ifq);						\
151167284Ssam} while (0)
152167284Ssam#endif /* IF_PREPEND_LIST */
153195379Ssam
154195379Ssam/*
155195379Ssam * Age queue definitions.
156195379Ssam */
157195379Ssamtypedef struct mtx ieee80211_ageq_lock_t;
158195379Ssam#define	IEEE80211_AGEQ_INIT(_aq, _name) \
159195379Ssam	mtx_init(&(_aq)->aq_lock, _name, "802.11 age q", MTX_DEF)
160195379Ssam#define	IEEE80211_AGEQ_DESTROY(_aq)	mtx_destroy(&(_aq)->aq_lock)
161195379Ssam#define	IEEE80211_AGEQ_LOCK(_aq)	mtx_lock(&(_aq)->aq_lock)
162195379Ssam#define	IEEE80211_AGEQ_UNLOCK(_aq)	mtx_unlock(&(_aq)->aq_lock)
163167284Ssam
164138568Ssam/*
165138568Ssam * 802.1x MAC ACL database locking definitions.
166138568Ssam */
167138568Ssamtypedef struct mtx acl_lock_t;
168138568Ssam#define	ACL_LOCK_INIT(_as, _name) \
169138568Ssam	mtx_init(&(_as)->as_lock, _name, "802.11 ACL", MTX_DEF)
170138568Ssam#define	ACL_LOCK_DESTROY(_as)		mtx_destroy(&(_as)->as_lock)
171138568Ssam#define	ACL_LOCK(_as)			mtx_lock(&(_as)->as_lock)
172138568Ssam#define	ACL_UNLOCK(_as)			mtx_unlock(&(_as)->as_lock)
173138568Ssam#define	ACL_LOCK_ASSERT(_as) \
174138568Ssam	mtx_assert((&(_as)->as_lock), MA_OWNED)
175138568Ssam
176138568Ssam/*
177206617Srpaulo * Scan table definitions.
178206617Srpaulo */
179206617Srpaulotypedef struct mtx ieee80211_scan_table_lock_t;
180206617Srpaulo#define	IEEE80211_SCAN_TABLE_LOCK_INIT(_st, _name) \
181206617Srpaulo	mtx_init(&(_st)->st_lock, _name, "802.11 scan table", MTX_DEF)
182206617Srpaulo#define	IEEE80211_SCAN_TABLE_LOCK_DESTROY(_st)	mtx_destroy(&(_st)->st_lock)
183206617Srpaulo#define	IEEE80211_SCAN_TABLE_LOCK(_st)		mtx_lock(&(_st)->st_lock)
184206617Srpaulo#define	IEEE80211_SCAN_TABLE_UNLOCK(_st)	mtx_unlock(&(_st)->st_lock)
185206617Srpaulo
186206617Srpaulo/*
187138568Ssam * Node reference counting definitions.
188138568Ssam *
189138568Ssam * ieee80211_node_initref	initialize the reference count to 1
190138568Ssam * ieee80211_node_incref	add a reference
191138568Ssam * ieee80211_node_decref	remove a reference
192138568Ssam * ieee80211_node_dectestref	remove a reference and return 1 if this
193138568Ssam *				is the last reference, otherwise 0
194138568Ssam * ieee80211_node_refcnt	reference count for printing (only)
195138568Ssam */
196138568Ssam#include <machine/atomic.h>
197138568Ssam
198138568Ssam#define ieee80211_node_initref(_ni) \
199138568Ssam	do { ((_ni)->ni_refcnt = 1); } while (0)
200138568Ssam#define ieee80211_node_incref(_ni) \
201138568Ssam	atomic_add_int(&(_ni)->ni_refcnt, 1)
202138568Ssam#define	ieee80211_node_decref(_ni) \
203138568Ssam	atomic_subtract_int(&(_ni)->ni_refcnt, 1)
204138568Ssamstruct ieee80211_node;
205144618Ssamint	ieee80211_node_dectestref(struct ieee80211_node *ni);
206138568Ssam#define	ieee80211_node_refcnt(_ni)	(_ni)->ni_refcnt
207138568Ssam
208165904Ssamstruct ifqueue;
209178354Ssamstruct ieee80211vap;
210165894Ssamvoid	ieee80211_drain_ifq(struct ifqueue *);
211178354Ssamvoid	ieee80211_flush_ifq(struct ifqueue *, struct ieee80211vap *);
212165894Ssam
213178354Ssamvoid	ieee80211_vap_destroy(struct ieee80211vap *);
214178354Ssam
215178354Ssam#define	IFNET_IS_UP_RUNNING(_ifp) \
216178354Ssam	(((_ifp)->if_flags & IFF_UP) && \
217178354Ssam	 ((_ifp)->if_drv_flags & IFF_DRV_RUNNING))
218178354Ssam
219171022Ssam#define	msecs_to_ticks(ms)	(((ms)*hz)/1000)
220178354Ssam#define	ticks_to_msecs(t)	(1000*(t) / hz)
221178354Ssam#define	ticks_to_secs(t)	((t) / hz)
222170530Ssam#define time_after(a,b) 	((long)(b) - (long)(a) < 0)
223170530Ssam#define time_before(a,b)	time_after(b,a)
224170530Ssam#define time_after_eq(a,b)	((long)(a) - (long)(b) >= 0)
225170530Ssam#define time_before_eq(a,b)	time_after_eq(b,a)
226170530Ssam
227170530Ssamstruct mbuf *ieee80211_getmgtframe(uint8_t **frm, int headroom, int pktlen);
228172054Ssam
229170530Ssam/* tx path usage */
230184286Ssam#define	M_ENCAP		M_PROTO1		/* 802.11 encap done */
231178354Ssam#define	M_EAPOL		M_PROTO3		/* PAE/EAPOL frame */
232138568Ssam#define	M_PWR_SAV	M_PROTO4		/* bypass PS handling */
233147789Ssam#define	M_MORE_DATA	M_PROTO5		/* more data frames to follow */
234178354Ssam#define	M_FF		M_PROTO6		/* fast frame */
235178354Ssam#define	M_TXCB		M_PROTO7		/* do tx complete callback */
236183247Ssam#define	M_AMPDU_MPDU	M_PROTO8		/* ok for A-MPDU aggregation */
237254640Sadrian
238254640Sadrian/*
239254640Sadrian * FreeBSD-HEAD from 1000046 retired M_*FRAG* flags and turned them
240254640Sadrian * into header flags instead.  So, we use the new protocol-specific
241254640Sadrian * flags.
242254640Sadrian *
243254640Sadrian * Earlier FreeBSD versions overload M_FRAG, M_FIRSTFRAG and M_LASTFRAG.
244254640Sadrian *
245254640Sadrian * XXX TODO: rename these fields so there are no namespace clashes!
246254640Sadrian */
247254640Sadrian#if __FreeBSD_version >= 1000046
248254526Sandre#define	M_FRAG		M_PROTO9		/* frame fragmentation */
249254526Sandre#define	M_FIRSTFRAG	M_PROTO10		/* first frame fragment */
250254526Sandre#define	M_LASTFRAG	M_PROTO11		/* last frame fragment */
251254640Sadrian#endif
252254640Sadrian
253178354Ssam#define	M_80211_TX \
254254526Sandre	(M_ENCAP|M_EAPOL|M_PWR_SAV|M_MORE_DATA|M_FF|M_TXCB| \
255254526Sandre	 M_AMPDU_MPDU|M_FRAG|M_FIRSTFRAG|M_LASTFRAG)
256172054Ssam
257170530Ssam/* rx path usage */
258183247Ssam#define	M_AMPDU		M_PROTO1		/* A-MPDU subframe */
259172054Ssam#define	M_WEP		M_PROTO2		/* WEP done by hardware */
260183247Ssam#if 0
261183247Ssam#define	M_AMPDU_MPDU	M_PROTO8		/* A-MPDU re-order done */
262183247Ssam#endif
263183247Ssam#define	M_80211_RX	(M_AMPDU|M_WEP|M_AMPDU_MPDU)
264195618Srpaulo
265254640Sadrian#if __FreeBSD_version >= 1000046
266195618Srpaulo#define	IEEE80211_MBUF_TX_FLAG_BITS \
267254527Sandre	M_FLAG_BITS \
268254527Sandre	"\15M_ENCAP\17M_EAPOL\20M_PWR_SAV\21M_MORE_DATA\22M_FF\23M_TXCB" \
269254527Sandre	"\24M_AMPDU_MPDU\25M_FRAG\26M_FIRSTFRAG\27M_LASTFRAG"
270254640Sadrian#else
271254640Sadrian/* There aren't any flag bits available for versions before this */
272254640Sadrian/* XXX TODO: implement M_FLAG_BITS for this! */
273254640Sadrian#define	IEEE80211_MBUF_TX_FLAG_BITS \
274254640Sadrian	"\15M_ENCAP\17M_EAPOL\20M_PWR_SAV\21M_MORE_DATA\22M_FF\23M_TXCB" \
275254640Sadrian	"\24M_AMPDU_MPDU"
276254640Sadrian#endif
277195618Srpaulo
278195618Srpaulo#define	IEEE80211_MBUF_RX_FLAG_BITS \
279254527Sandre	M_FLAG_BITS \
280254527Sandre	"\15M_AMPDU\16M_WEP\24M_AMPDU_MPDU"
281195618Srpaulo
282138568Ssam/*
283178354Ssam * Store WME access control bits in the vlan tag.
284178354Ssam * This is safe since it's done after the packet is classified
285178354Ssam * (where we use any previous tag) and because it's passed
286178354Ssam * directly in to the driver and there's no chance someone
287178354Ssam * else will clobber them on us.
288138568Ssam */
289138568Ssam#define	M_WME_SETAC(m, ac) \
290178354Ssam	((m)->m_pkthdr.ether_vtag = (ac))
291178354Ssam#define	M_WME_GETAC(m)	((m)->m_pkthdr.ether_vtag)
292138568Ssam
293138568Ssam/*
294138568Ssam * Mbufs on the power save queue are tagged with an age and
295138568Ssam * timed out.  We reuse the hardware checksum field in the
296138568Ssam * mbuf packet header to store this data.
297138568Ssam */
298138568Ssam#define	M_AGE_SET(m,v)		(m->m_pkthdr.csum_data = v)
299138568Ssam#define	M_AGE_GET(m)		(m->m_pkthdr.csum_data)
300138568Ssam#define	M_AGE_SUB(m,adj)	(m->m_pkthdr.csum_data -= adj)
301138568Ssam
302191571Ssam/*
303191571Ssam * Store the sequence number.
304191571Ssam */
305191571Ssam#define	M_SEQNO_SET(m, seqno) \
306191571Ssam	((m)->m_pkthdr.tso_segsz = (seqno))
307191571Ssam#define	M_SEQNO_GET(m)	((m)->m_pkthdr.tso_segsz)
308191571Ssam
309170530Ssam#define	MTAG_ABI_NET80211	1132948340	/* net80211 ABI */
310170530Ssam
311170530Ssamstruct ieee80211_cb {
312170530Ssam	void	(*func)(struct ieee80211_node *, void *, int status);
313170530Ssam	void	*arg;
314170530Ssam};
315170530Ssam#define	NET80211_TAG_CALLBACK	0	/* xmit complete callback */
316170530Ssamint	ieee80211_add_callback(struct mbuf *m,
317170530Ssam		void (*func)(struct ieee80211_node *, void *, int), void *arg);
318170530Ssamvoid	ieee80211_process_callback(struct ieee80211_node *, struct mbuf *, int);
319170530Ssam
320248069Sadrianstruct ieee80211com;
321254082Sadrianint	ieee80211_parent_xmitpkt(struct ieee80211com *, struct mbuf *);
322254082Sadrianint	ieee80211_vap_xmitpkt(struct ieee80211vap *, struct mbuf *);
323248069Sadrian
324144618Ssamvoid	get_random_bytes(void *, size_t);
325138568Ssam
326138568Ssamvoid	ieee80211_sysctl_attach(struct ieee80211com *);
327138568Ssamvoid	ieee80211_sysctl_detach(struct ieee80211com *);
328178354Ssamvoid	ieee80211_sysctl_vattach(struct ieee80211vap *);
329178354Ssamvoid	ieee80211_sysctl_vdetach(struct ieee80211vap *);
330138568Ssam
331192473SsamSYSCTL_DECL(_net_wlan);
332192473Ssamint	ieee80211_sysctl_msecs_ticks(SYSCTL_HANDLER_ARGS);
333192473Ssam
334138568Ssamvoid	ieee80211_load_module(const char *);
335170530Ssam
336178354Ssam/*
337178354Ssam * A "policy module" is an adjunct module to net80211 that provides
338178354Ssam * functionality that typically includes policy decisions.  This
339178354Ssam * modularity enables extensibility and vendor-supplied functionality.
340178354Ssam */
341178354Ssam#define	_IEEE80211_POLICY_MODULE(policy, name, version)			\
342178354Ssamtypedef void (*policy##_setup)(int);					\
343178354SsamSET_DECLARE(policy##_set, policy##_setup);				\
344170530Ssamstatic int								\
345178354Ssamwlan_##name##_modevent(module_t mod, int type, void *unused)		\
346170530Ssam{									\
347178354Ssam	policy##_setup * const *iter, f;				\
348170530Ssam	switch (type) {							\
349170530Ssam	case MOD_LOAD:							\
350178354Ssam		SET_FOREACH(iter, policy##_set) {			\
351178354Ssam			f = (void*) *iter;				\
352178354Ssam			f(type);					\
353178354Ssam		}							\
354170530Ssam		return 0;						\
355170530Ssam	case MOD_UNLOAD:						\
356170530Ssam	case MOD_QUIESCE:						\
357170530Ssam		if (nrefs) {						\
358170530Ssam			printf("wlan_##name: still in use (%u dynamic refs)\n",\
359170530Ssam				nrefs);					\
360170530Ssam			return EBUSY;					\
361170530Ssam		}							\
362178354Ssam		if (type == MOD_UNLOAD) {				\
363178354Ssam			SET_FOREACH(iter, policy##_set) {		\
364178354Ssam				f = (void*) *iter;			\
365178354Ssam				f(type);				\
366178354Ssam			}						\
367178354Ssam		}							\
368170530Ssam		return 0;						\
369170530Ssam	}								\
370170530Ssam	return EINVAL;							\
371170530Ssam}									\
372170530Ssamstatic moduledata_t name##_mod = {					\
373170530Ssam	"wlan_" #name,							\
374178354Ssam	wlan_##name##_modevent,						\
375241394Skevlo	0								\
376170530Ssam};									\
377170530SsamDECLARE_MODULE(wlan_##name, name##_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);\
378170530SsamMODULE_VERSION(wlan_##name, version);					\
379170530SsamMODULE_DEPEND(wlan_##name, wlan, 1, 1, 1)
380178354Ssam
381178354Ssam/*
382178354Ssam * Crypto modules implement cipher support.
383178354Ssam */
384178354Ssam#define	IEEE80211_CRYPTO_MODULE(name, version)				\
385178354Ssam_IEEE80211_POLICY_MODULE(crypto, name, version);			\
386178354Ssamstatic void								\
387178354Ssamname##_modevent(int type)						\
388178354Ssam{									\
389178354Ssam	if (type == MOD_LOAD)						\
390178354Ssam		ieee80211_crypto_register(&name);			\
391178354Ssam	else								\
392178354Ssam		ieee80211_crypto_unregister(&name);			\
393178354Ssam}									\
394178354SsamTEXT_SET(crypto##_set, name##_modevent)
395178354Ssam
396178354Ssam/*
397178354Ssam * Scanner modules provide scanning policy.
398178354Ssam */
399178354Ssam#define	IEEE80211_SCANNER_MODULE(name, version)				\
400178354Ssam	_IEEE80211_POLICY_MODULE(scanner, name, version)
401178354Ssam
402178354Ssam#define	IEEE80211_SCANNER_ALG(name, alg, v)				\
403178354Ssamstatic void								\
404178354Ssamname##_modevent(int type)						\
405178354Ssam{									\
406178354Ssam	if (type == MOD_LOAD)						\
407178354Ssam		ieee80211_scanner_register(alg, &v);			\
408178354Ssam	else								\
409178354Ssam		ieee80211_scanner_unregister(alg, &v);			\
410178354Ssam}									\
411178354SsamTEXT_SET(scanner_set, name##_modevent);					\
412178354Ssam
413178354Ssam/*
414178354Ssam * ACL modules implement acl policy.
415178354Ssam */
416178354Ssam#define	IEEE80211_ACL_MODULE(name, alg, version)			\
417178354Ssam_IEEE80211_POLICY_MODULE(acl, name, version);				\
418178354Ssamstatic void								\
419178354Ssamalg##_modevent(int type)						\
420178354Ssam{									\
421178354Ssam	if (type == MOD_LOAD)						\
422178354Ssam		ieee80211_aclator_register(&alg);			\
423178354Ssam	else								\
424178354Ssam		ieee80211_aclator_unregister(&alg);			\
425178354Ssam}									\
426178354SsamTEXT_SET(acl_set, alg##_modevent);					\
427178354Ssam
428178354Ssam/*
429178354Ssam * Authenticator modules handle 802.1x/WPA authentication.
430178354Ssam */
431178354Ssam#define	IEEE80211_AUTH_MODULE(name, version)				\
432178354Ssam	_IEEE80211_POLICY_MODULE(auth, name, version)
433178354Ssam
434178354Ssam#define	IEEE80211_AUTH_ALG(name, alg, v)				\
435178354Ssamstatic void								\
436178354Ssamname##_modevent(int type)						\
437178354Ssam{									\
438178354Ssam	if (type == MOD_LOAD)						\
439178354Ssam		ieee80211_authenticator_register(alg, &v);		\
440178354Ssam	else								\
441178354Ssam		ieee80211_authenticator_unregister(alg);		\
442178354Ssam}									\
443178354SsamTEXT_SET(auth_set, name##_modevent)
444178354Ssam
445178354Ssam/*
446178354Ssam * Rate control modules provide tx rate control support.
447178354Ssam */
448206358Srpaulo#define	IEEE80211_RATECTL_MODULE(alg, version)				\
449206358Srpaulo	_IEEE80211_POLICY_MODULE(ratectl, alg, version);		\
450206358Srpaulo
451206358Srpaulo#define	IEEE80211_RATECTL_ALG(name, alg, v)				\
452178354Ssamstatic void								\
453178354Ssamalg##_modevent(int type)						\
454178354Ssam{									\
455206358Srpaulo	if (type == MOD_LOAD)						\
456206358Srpaulo		ieee80211_ratectl_register(alg, &v);			\
457206358Srpaulo	else								\
458206358Srpaulo		ieee80211_ratectl_unregister(alg);			\
459178354Ssam}									\
460206358SrpauloTEXT_SET(ratectl##_set, alg##_modevent)
461138568Ssam
462190384Ssamstruct ieee80211req;
463190384Ssamtypedef int ieee80211_ioctl_getfunc(struct ieee80211vap *,
464190384Ssam    struct ieee80211req *);
465190384SsamSET_DECLARE(ieee80211_ioctl_getset, ieee80211_ioctl_getfunc);
466190384Ssam#define	IEEE80211_IOCTL_GET(_name, _get) TEXT_SET(ieee80211_ioctl_getset, _get)
467190384Ssam
468190384Ssamtypedef int ieee80211_ioctl_setfunc(struct ieee80211vap *,
469190384Ssam    struct ieee80211req *);
470190384SsamSET_DECLARE(ieee80211_ioctl_setset, ieee80211_ioctl_setfunc);
471190384Ssam#define	IEEE80211_IOCTL_SET(_name, _set) TEXT_SET(ieee80211_ioctl_setset, _set)
472190394Ssam#endif /* _KERNEL */
473190384Ssam
474138568Ssam/* XXX this stuff belongs elsewhere */
475138568Ssam/*
476138568Ssam * Message formats for messages from the net80211 layer to user
477138568Ssam * applications via the routing socket.  These messages are appended
478138568Ssam * to an if_announcemsghdr structure.
479138568Ssam */
480138568Ssamstruct ieee80211_join_event {
481138568Ssam	uint8_t		iev_addr[6];
482138568Ssam};
483138568Ssam
484138568Ssamstruct ieee80211_leave_event {
485138568Ssam	uint8_t		iev_addr[6];
486138568Ssam};
487138568Ssam
488138568Ssamstruct ieee80211_replay_event {
489138568Ssam	uint8_t		iev_src[6];	/* src MAC */
490138568Ssam	uint8_t		iev_dst[6];	/* dst MAC */
491138568Ssam	uint8_t		iev_cipher;	/* cipher type */
492138568Ssam	uint8_t		iev_keyix;	/* key id/index */
493138568Ssam	uint64_t	iev_keyrsc;	/* RSC from key */
494138568Ssam	uint64_t	iev_rsc;	/* RSC from frame */
495138568Ssam};
496138568Ssam
497138568Ssamstruct ieee80211_michael_event {
498138568Ssam	uint8_t		iev_src[6];	/* src MAC */
499138568Ssam	uint8_t		iev_dst[6];	/* dst MAC */
500138568Ssam	uint8_t		iev_cipher;	/* cipher type */
501138568Ssam	uint8_t		iev_keyix;	/* key id/index */
502138568Ssam};
503138568Ssam
504178354Ssamstruct ieee80211_wds_event {
505178354Ssam	uint8_t		iev_addr[6];
506178354Ssam};
507178354Ssam
508178354Ssamstruct ieee80211_csa_event {
509178354Ssam	uint32_t	iev_flags;	/* channel flags */
510178354Ssam	uint16_t	iev_freq;	/* setting in Mhz */
511178354Ssam	uint8_t		iev_ieee;	/* IEEE channel number */
512178354Ssam	uint8_t		iev_mode;	/* CSA mode */
513178354Ssam	uint8_t		iev_count;	/* CSA count */
514178354Ssam};
515178354Ssam
516178354Ssamstruct ieee80211_cac_event {
517178354Ssam	uint32_t	iev_flags;	/* channel flags */
518178354Ssam	uint16_t	iev_freq;	/* setting in Mhz */
519178354Ssam	uint8_t		iev_ieee;	/* IEEE channel number */
520178354Ssam	/* XXX timestamp? */
521178354Ssam	uint8_t		iev_type;	/* IEEE80211_NOTIFY_CAC_* */
522178354Ssam};
523178354Ssam
524178354Ssamstruct ieee80211_radar_event {
525178354Ssam	uint32_t	iev_flags;	/* channel flags */
526178354Ssam	uint16_t	iev_freq;	/* setting in Mhz */
527178354Ssam	uint8_t		iev_ieee;	/* IEEE channel number */
528178354Ssam	/* XXX timestamp? */
529178354Ssam};
530178354Ssam
531178354Ssamstruct ieee80211_auth_event {
532178354Ssam	uint8_t		iev_addr[6];
533178354Ssam};
534178354Ssam
535178354Ssamstruct ieee80211_deauth_event {
536178354Ssam	uint8_t		iev_addr[6];
537178354Ssam};
538178354Ssam
539178354Ssamstruct ieee80211_country_event {
540178354Ssam	uint8_t		iev_addr[6];
541178354Ssam	uint8_t		iev_cc[2];	/* ISO country code */
542178354Ssam};
543178354Ssam
544178354Ssamstruct ieee80211_radio_event {
545178354Ssam	uint8_t		iev_state;	/* 1 on, 0 off */
546178354Ssam};
547178354Ssam
548138568Ssam#define	RTM_IEEE80211_ASSOC	100	/* station associate (bss mode) */
549138568Ssam#define	RTM_IEEE80211_REASSOC	101	/* station re-associate (bss mode) */
550138568Ssam#define	RTM_IEEE80211_DISASSOC	102	/* station disassociate (bss mode) */
551138568Ssam#define	RTM_IEEE80211_JOIN	103	/* station join (ap mode) */
552138568Ssam#define	RTM_IEEE80211_LEAVE	104	/* station leave (ap mode) */
553138568Ssam#define	RTM_IEEE80211_SCAN	105	/* scan complete, results available */
554138568Ssam#define	RTM_IEEE80211_REPLAY	106	/* sequence counter replay detected */
555138568Ssam#define	RTM_IEEE80211_MICHAEL	107	/* Michael MIC failure detected */
556144302Ssam#define	RTM_IEEE80211_REJOIN	108	/* station re-associate (ap mode) */
557178354Ssam#define	RTM_IEEE80211_WDS	109	/* WDS discovery (ap mode) */
558178354Ssam#define	RTM_IEEE80211_CSA	110	/* Channel Switch Announcement event */
559178354Ssam#define	RTM_IEEE80211_RADAR	111	/* radar event */
560178354Ssam#define	RTM_IEEE80211_CAC	112	/* Channel Availability Check event */
561178354Ssam#define	RTM_IEEE80211_DEAUTH	113	/* station deauthenticate */
562178354Ssam#define	RTM_IEEE80211_AUTH	114	/* station authenticate (ap mode) */
563178354Ssam#define	RTM_IEEE80211_COUNTRY	115	/* discovered country code (sta mode) */
564178354Ssam#define	RTM_IEEE80211_RADIO	116	/* RF kill switch state change */
565138568Ssam
566160690Ssam/*
567160690Ssam * Structure prepended to raw packets sent through the bpf
568160690Ssam * interface when set to DLT_IEEE802_11_RADIO.  This allows
569160690Ssam * user applications to specify pretty much everything in
570160690Ssam * an Atheros tx descriptor.  XXX need to generalize.
571160690Ssam *
572160690Ssam * XXX cannot be more than 14 bytes as it is copied to a sockaddr's
573160690Ssam * XXX sa_data area.
574160690Ssam */
575160690Ssamstruct ieee80211_bpf_params {
576160690Ssam	uint8_t		ibp_vers;	/* version */
577160690Ssam#define	IEEE80211_BPF_VERSION	0
578160690Ssam	uint8_t		ibp_len;	/* header length in bytes */
579160690Ssam	uint8_t		ibp_flags;
580160690Ssam#define	IEEE80211_BPF_SHORTPRE	0x01	/* tx with short preamble */
581160690Ssam#define	IEEE80211_BPF_NOACK	0x02	/* tx with no ack */
582160690Ssam#define	IEEE80211_BPF_CRYPTO	0x04	/* tx with h/w encryption */
583160690Ssam#define	IEEE80211_BPF_FCS	0x10	/* frame incldues FCS */
584160690Ssam#define	IEEE80211_BPF_DATAPAD	0x20	/* frame includes data padding */
585160690Ssam#define	IEEE80211_BPF_RTS	0x40	/* tx with RTS/CTS */
586160690Ssam#define	IEEE80211_BPF_CTS	0x80	/* tx with CTS only */
587160690Ssam	uint8_t		ibp_pri;	/* WME/WMM AC+tx antenna */
588160690Ssam	uint8_t		ibp_try0;	/* series 1 try count */
589160690Ssam	uint8_t		ibp_rate0;	/* series 1 IEEE tx rate */
590160690Ssam	uint8_t		ibp_power;	/* tx power (device units) */
591160690Ssam	uint8_t		ibp_ctsrate;	/* IEEE tx rate for CTS */
592160690Ssam	uint8_t		ibp_try1;	/* series 2 try count */
593160690Ssam	uint8_t		ibp_rate1;	/* series 2 IEEE tx rate */
594160690Ssam	uint8_t		ibp_try2;	/* series 3 try count */
595160690Ssam	uint8_t		ibp_rate2;	/* series 3 IEEE tx rate */
596160690Ssam	uint8_t		ibp_try3;	/* series 4 try count */
597160690Ssam	uint8_t		ibp_rate3;	/* series 4 IEEE tx rate */
598160690Ssam};
599138568Ssam#endif /* _NET80211_IEEE80211_FREEBSD_H_ */
600