| 1 | /*- |
| 2 | * SPDX-License-Identifier: BSD-2-Clause |
| 3 | * |
| 4 | * Copyright (c) 2003-2008 Sam Leffler, Errno Consulting |
| 5 | * All rights reserved. |
| 6 | * |
| 7 | * Redistribution and use in source and binary forms, with or without |
| 8 | * modification, are permitted provided that the following conditions |
| 9 | * are met: |
| 10 | * 1. Redistributions of source code must retain the above copyright |
| 11 | * notice, this list of conditions and the following disclaimer. |
| 12 | * 2. Redistributions in binary form must reproduce the above copyright |
| 13 | * notice, this list of conditions and the following disclaimer in the |
| 14 | * documentation and/or other materials provided with the distribution. |
| 15 | * |
| 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
| 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| 18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
| 19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
| 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
| 21 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| 25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 26 | */ |
| 27 | #ifndef _NET80211_IEEE80211_FREEBSD_H_ |
| 28 | #define _NET80211_IEEE80211_FREEBSD_H_ |
| 29 | |
| 30 | #ifdef _KERNEL |
| 31 | #include <sys/param.h> |
| 32 | #include <sys/systm.h> |
| 33 | #include <sys/counter.h> |
| 34 | #include <sys/lock.h> |
| 35 | #include <sys/mutex.h> |
| 36 | #include <sys/rwlock.h> |
| 37 | #include <sys/sysctl.h> |
| 38 | #include <sys/taskqueue.h> |
| 39 | #include <sys/time.h> |
| 40 | |
| 41 | #include <net/debugnet.h> |
| 42 | |
| 43 | /* |
| 44 | * priv(9) NET80211 checks. |
| 45 | */ |
| 46 | struct ieee80211vap; |
| 47 | int ieee80211_priv_check_vap_getkey(u_long, struct ieee80211vap *, |
| 48 | struct ifnet *); |
| 49 | int ieee80211_priv_check_vap_manage(u_long, struct ieee80211vap *, |
| 50 | struct ifnet *); |
| 51 | int ieee80211_priv_check_vap_setmac(u_long, struct ieee80211vap *, |
| 52 | struct ifnet *); |
| 53 | int ieee80211_priv_check_create_vap(u_long, struct ieee80211vap *, |
| 54 | struct ifnet *); |
| 55 | |
| 56 | /* |
| 57 | * Common state locking definitions. |
| 58 | */ |
| 59 | typedef struct { |
| 60 | 	char		name[16];		/* e.g. "ath0_com_lock" */ |
| 61 | 	struct mtx	mtx; |
| 62 | } ieee80211_com_lock_t; |
| 63 | #define	IEEE80211_LOCK_INIT(_ic, _name) do {				\ |
| 64 | 	ieee80211_com_lock_t *cl = &(_ic)->ic_comlock;			\ |
| 65 | 	snprintf(cl->name, sizeof(cl->name), "%s_com_lock", _name);	\ |
| 66 | 	mtx_init(&cl->mtx, cl->name, NULL, MTX_DEF | MTX_RECURSE);	\ |
| 67 | } while (0) |
| 68 | #define	IEEE80211_LOCK_OBJ(_ic)	(&(_ic)->ic_comlock.mtx) |
| 69 | #define	IEEE80211_LOCK_DESTROY(_ic) mtx_destroy(IEEE80211_LOCK_OBJ(_ic)) |
| 70 | #define	IEEE80211_LOCK(_ic)	 mtx_lock(IEEE80211_LOCK_OBJ(_ic)) |
| 71 | #define	IEEE80211_UNLOCK(_ic)	 mtx_unlock(IEEE80211_LOCK_OBJ(_ic)) |
| 72 | #define	IEEE80211_LOCK_ASSERT(_ic) \ |
| 73 | 	mtx_assert(IEEE80211_LOCK_OBJ(_ic), MA_OWNED) |
| 74 | #define	IEEE80211_UNLOCK_ASSERT(_ic) \ |
| 75 | 	mtx_assert(IEEE80211_LOCK_OBJ(_ic), MA_NOTOWNED) |
| 76 | #define	IEEE80211_IS_LOCKED(_ic) \ |
| 77 | 	mtx_owned(IEEE80211_LOCK_OBJ(_ic)) |
| 78 | |
| 79 | /* |
| 80 | * Transmit lock. |
| 81 | * |
| 82 | * This is a (mostly) temporary lock designed to serialise all of the |
| 83 | * transmission operations throughout the stack. |
| 84 | */ |
| 85 | typedef struct { |
| 86 | 	char		name[16];		/* e.g. "ath0_tx_lock" */ |
| 87 | 	struct mtx	mtx; |
| 88 | } ieee80211_tx_lock_t; |
| 89 | #define	IEEE80211_TX_LOCK_INIT(_ic, _name) do {				\ |
| 90 | 	ieee80211_tx_lock_t *cl = &(_ic)->ic_txlock;			\ |
| 91 | 	snprintf(cl->name, sizeof(cl->name), "%s_tx_lock", _name);	\ |
| 92 | 	mtx_init(&cl->mtx, cl->name, NULL, MTX_DEF);	\ |
| 93 | } while (0) |
| 94 | #define	IEEE80211_TX_LOCK_OBJ(_ic)	(&(_ic)->ic_txlock.mtx) |
| 95 | #define	IEEE80211_TX_LOCK_DESTROY(_ic) mtx_destroy(IEEE80211_TX_LOCK_OBJ(_ic)) |
| 96 | #define	IEEE80211_TX_LOCK(_ic) do { \ |
| 97 | 	if (!IEEE80211_CONF_SEQNO_OFFLOAD(_ic)) \ |
| 98 | 		mtx_lock(IEEE80211_TX_LOCK_OBJ(_ic)); \ |
| 99 | 	} while (0); |
| 100 | #define	IEEE80211_TX_UNLOCK(_ic) do { \ |
| 101 | 	if (!IEEE80211_CONF_SEQNO_OFFLOAD(_ic)) \ |
| 102 | 		mtx_unlock(IEEE80211_TX_LOCK_OBJ(_ic)); \ |
| 103 | 	} while (0); |
| 104 | #define	IEEE80211_TX_LOCK_ASSERT(_ic) do { \ |
| 105 | 	if (!IEEE80211_CONF_SEQNO_OFFLOAD(_ic)) \ |
| 106 | 		mtx_assert(IEEE80211_TX_LOCK_OBJ(_ic), MA_OWNED); \ |
| 107 | 	} while (0) |
| 108 | #define	IEEE80211_TX_UNLOCK_ASSERT(_ic) { \ |
| 109 | 	if (!IEEE80211_CONF_SEQNO_OFFLOAD(_ic)) \ |
| 110 | 		mtx_assert(IEEE80211_TX_LOCK_OBJ(_ic), MA_NOTOWNED); \ |
| 111 | 	} while (0) |
| 112 | |
| 113 | /* |
| 114 | * Stageq / ni_tx_superg lock |
| 115 | */ |
| 116 | typedef struct { |
| 117 | 	char		name[16];		/* e.g. "ath0_ff_lock" */ |
| 118 | 	struct mtx	mtx; |
| 119 | } ieee80211_ff_lock_t; |
| 120 | #define IEEE80211_FF_LOCK_INIT(_ic, _name) do {				\ |
| 121 | 	ieee80211_ff_lock_t *fl = &(_ic)->ic_fflock;			\ |
| 122 | 	snprintf(fl->name, sizeof(fl->name), "%s_ff_lock", _name);	\ |
| 123 | 	mtx_init(&fl->mtx, fl->name, NULL, MTX_DEF);			\ |
| 124 | } while (0) |
| 125 | #define IEEE80211_FF_LOCK_OBJ(_ic)	(&(_ic)->ic_fflock.mtx) |
| 126 | #define IEEE80211_FF_LOCK_DESTROY(_ic)	mtx_destroy(IEEE80211_FF_LOCK_OBJ(_ic)) |
| 127 | #define IEEE80211_FF_LOCK(_ic)		mtx_lock(IEEE80211_FF_LOCK_OBJ(_ic)) |
| 128 | #define IEEE80211_FF_UNLOCK(_ic)	mtx_unlock(IEEE80211_FF_LOCK_OBJ(_ic)) |
| 129 | #define IEEE80211_FF_LOCK_ASSERT(_ic) \ |
| 130 | 	mtx_assert(IEEE80211_FF_LOCK_OBJ(_ic), MA_OWNED) |
| 131 | |
| 132 | /* |
| 133 | * Node locking definitions. |
| 134 | */ |
| 135 | typedef struct { |
| 136 | 	char		name[16];		/* e.g. "ath0_node_lock" */ |
| 137 | 	struct mtx	mtx; |
| 138 | } ieee80211_node_lock_t; |
| 139 | #define	IEEE80211_NODE_LOCK_INIT(_nt, _name) do {			\ |
| 140 | 	ieee80211_node_lock_t *nl = &(_nt)->nt_nodelock;		\ |
| 141 | 	snprintf(nl->name, sizeof(nl->name), "%s_node_lock", _name);	\ |
| 142 | 	mtx_init(&nl->mtx, nl->name, NULL, MTX_DEF | MTX_RECURSE);	\ |
| 143 | } while (0) |
| 144 | #define	IEEE80211_NODE_LOCK_OBJ(_nt)	(&(_nt)->nt_nodelock.mtx) |
| 145 | #define	IEEE80211_NODE_LOCK_DESTROY(_nt) \ |
| 146 | 	mtx_destroy(IEEE80211_NODE_LOCK_OBJ(_nt)) |
| 147 | #define	IEEE80211_NODE_LOCK(_nt) \ |
| 148 | 	mtx_lock(IEEE80211_NODE_LOCK_OBJ(_nt)) |
| 149 | #define	IEEE80211_NODE_IS_LOCKED(_nt) \ |
| 150 | 	mtx_owned(IEEE80211_NODE_LOCK_OBJ(_nt)) |
| 151 | #define	IEEE80211_NODE_UNLOCK(_nt) \ |
| 152 | 	mtx_unlock(IEEE80211_NODE_LOCK_OBJ(_nt)) |
| 153 | #define	IEEE80211_NODE_LOCK_ASSERT(_nt)	\ |
| 154 | 	mtx_assert(IEEE80211_NODE_LOCK_OBJ(_nt), MA_OWNED) |
| 155 | |
| 156 | /* |
| 157 | * Power-save queue definitions. |
| 158 | */ |
| 159 | typedef struct mtx ieee80211_psq_lock_t; |
| 160 | #define	IEEE80211_PSQ_INIT(_psq, _name) \ |
| 161 | 	mtx_init(&(_psq)->psq_lock, _name, "802.11 ps q", MTX_DEF) |
| 162 | #define	IEEE80211_PSQ_DESTROY(_psq)	mtx_destroy(&(_psq)->psq_lock) |
| 163 | #define	IEEE80211_PSQ_LOCK(_psq)	mtx_lock(&(_psq)->psq_lock) |
| 164 | #define	IEEE80211_PSQ_UNLOCK(_psq)	mtx_unlock(&(_psq)->psq_lock) |
| 165 | |
| 166 | #ifndef IF_PREPEND_LIST |
| 167 | #define _IF_PREPEND_LIST(ifq, mhead, mtail, mcount) do {	\ |
| 168 | 	(mtail)->m_nextpkt = (ifq)->ifq_head;			\ |
| 169 | 	if ((ifq)->ifq_tail == NULL)				\ |
| 170 | 		(ifq)->ifq_tail = (mtail);			\ |
| 171 | 	(ifq)->ifq_head = (mhead);				\ |
| 172 | 	(ifq)->ifq_len += (mcount);				\ |
| 173 | } while (0) |
| 174 | #define IF_PREPEND_LIST(ifq, mhead, mtail, mcount) do {		\ |
| 175 | 	IF_LOCK(ifq);						\ |
| 176 | 	_IF_PREPEND_LIST(ifq, mhead, mtail, mcount);		\ |
| 177 | 	IF_UNLOCK(ifq);						\ |
| 178 | } while (0) |
| 179 | #endif /* IF_PREPEND_LIST */ |
| 180 | |
| 181 | /* |
| 182 | * Age queue definitions. |
| 183 | */ |
| 184 | typedef struct mtx ieee80211_ageq_lock_t; |
| 185 | #define	IEEE80211_AGEQ_INIT(_aq, _name) \ |
| 186 | 	mtx_init(&(_aq)->aq_lock, _name, "802.11 age q", MTX_DEF) |
| 187 | #define	IEEE80211_AGEQ_DESTROY(_aq)	mtx_destroy(&(_aq)->aq_lock) |
| 188 | #define	IEEE80211_AGEQ_LOCK(_aq)	mtx_lock(&(_aq)->aq_lock) |
| 189 | #define	IEEE80211_AGEQ_UNLOCK(_aq)	mtx_unlock(&(_aq)->aq_lock) |
| 190 | |
| 191 | /* |
| 192 | * 802.1x MAC ACL database locking definitions. |
| 193 | */ |
| 194 | typedef struct mtx acl_lock_t; |
| 195 | #define	ACL_LOCK_INIT(_as, _name) \ |
| 196 | 	mtx_init(&(_as)->as_lock, _name, "802.11 ACL", MTX_DEF) |
| 197 | #define	ACL_LOCK_DESTROY(_as)		mtx_destroy(&(_as)->as_lock) |
| 198 | #define	ACL_LOCK(_as)			mtx_lock(&(_as)->as_lock) |
| 199 | #define	ACL_UNLOCK(_as)			mtx_unlock(&(_as)->as_lock) |
| 200 | #define	ACL_LOCK_ASSERT(_as) \ |
| 201 | 	mtx_assert((&(_as)->as_lock), MA_OWNED) |
| 202 | |
| 203 | /* |
| 204 | * Scan table definitions. |
| 205 | */ |
| 206 | typedef struct mtx ieee80211_scan_table_lock_t; |
| 207 | #define	IEEE80211_SCAN_TABLE_LOCK_INIT(_st, _name) \ |
| 208 | 	mtx_init(&(_st)->st_lock, _name, "802.11 scan table", MTX_DEF) |
| 209 | #define	IEEE80211_SCAN_TABLE_LOCK_DESTROY(_st)	mtx_destroy(&(_st)->st_lock) |
| 210 | #define	IEEE80211_SCAN_TABLE_LOCK(_st)		mtx_lock(&(_st)->st_lock) |
| 211 | #define	IEEE80211_SCAN_TABLE_UNLOCK(_st)	mtx_unlock(&(_st)->st_lock) |
| 212 | |
| 213 | typedef struct mtx ieee80211_scan_iter_lock_t; |
| 214 | #define	IEEE80211_SCAN_ITER_LOCK_INIT(_st, _name) \ |
| 215 | 	mtx_init(&(_st)->st_scanlock, _name, "802.11 scangen", MTX_DEF) |
| 216 | #define	IEEE80211_SCAN_ITER_LOCK_DESTROY(_st)	mtx_destroy(&(_st)->st_scanlock) |
| 217 | #define	IEEE80211_SCAN_ITER_LOCK(_st)		mtx_lock(&(_st)->st_scanlock) |
| 218 | #define	IEEE80211_SCAN_ITER_UNLOCK(_st)	mtx_unlock(&(_st)->st_scanlock) |
| 219 | |
| 220 | /* |
| 221 | * Mesh node/routing definitions. |
| 222 | */ |
| 223 | typedef struct mtx ieee80211_rte_lock_t; |
| 224 | #define	MESH_RT_ENTRY_LOCK_INIT(_rt, _name) \ |
| 225 | 	mtx_init(&(rt)->rt_lock, _name, "802.11s route entry", MTX_DEF) |
| 226 | #define	MESH_RT_ENTRY_LOCK_DESTROY(_rt) \ |
| 227 | 	mtx_destroy(&(_rt)->rt_lock) |
| 228 | #define	MESH_RT_ENTRY_LOCK(rt)	mtx_lock(&(rt)->rt_lock) |
| 229 | #define	MESH_RT_ENTRY_LOCK_ASSERT(rt) mtx_assert(&(rt)->rt_lock, MA_OWNED) |
| 230 | #define	MESH_RT_ENTRY_UNLOCK(rt)	mtx_unlock(&(rt)->rt_lock) |
| 231 | |
| 232 | typedef struct mtx ieee80211_rt_lock_t; |
| 233 | #define	MESH_RT_LOCK(ms)	mtx_lock(&(ms)->ms_rt_lock) |
| 234 | #define	MESH_RT_LOCK_ASSERT(ms)	mtx_assert(&(ms)->ms_rt_lock, MA_OWNED) |
| 235 | #define	MESH_RT_UNLOCK(ms)	mtx_unlock(&(ms)->ms_rt_lock) |
| 236 | #define	MESH_RT_LOCK_INIT(ms, name) \ |
| 237 | 	mtx_init(&(ms)->ms_rt_lock, name, "802.11s routing table", MTX_DEF) |
| 238 | #define	MESH_RT_LOCK_DESTROY(ms) \ |
| 239 | 	mtx_destroy(&(ms)->ms_rt_lock) |
| 240 | |
| 241 | /* |
| 242 | * Node reference counting definitions. |
| 243 | * |
| 244 | * ieee80211_node_initref	initialize the reference count to 1 |
| 245 | * ieee80211_node_incref	add a reference |
| 246 | * ieee80211_node_decref	remove a reference |
| 247 | * ieee80211_node_dectestref	remove a reference and return 1 if this |
| 248 | *				is the last reference, otherwise 0 |
| 249 | * ieee80211_node_refcnt	reference count for printing (only) |
| 250 | */ |
| 251 | #include <machine/atomic.h> |
| 252 | |
| 253 | struct ieee80211vap; |
| 254 | int	ieee80211_com_vincref(struct ieee80211vap *); |
| 255 | void	ieee80211_com_vdecref(struct ieee80211vap *); |
| 256 | void	ieee80211_com_vdetach(struct ieee80211vap *); |
| 257 | |
| 258 | #define ieee80211_node_initref(_ni) \ |
| 259 | 	do { ((_ni)->ni_refcnt = 1); } while (0) |
| 260 | #define ieee80211_node_incref(_ni) \ |
| 261 | 	atomic_add_int(&(_ni)->ni_refcnt, 1) |
| 262 | #define	ieee80211_node_decref(_ni) \ |
| 263 | 	atomic_subtract_int(&(_ni)->ni_refcnt, 1) |
| 264 | struct ieee80211_node; |
| 265 | int	ieee80211_node_dectestref(struct ieee80211_node *ni); |
| 266 | #define	ieee80211_node_refcnt(_ni)	(_ni)->ni_refcnt |
| 267 | |
| 268 | struct ifqueue; |
| 269 | void	ieee80211_drain_ifq(struct ifqueue *); |
| 270 | void	ieee80211_flush_ifq(struct ifqueue *, struct ieee80211vap *); |
| 271 | |
| 272 | void	ieee80211_vap_destroy(struct ieee80211vap *); |
| 273 | const char *	ieee80211_get_vap_ifname(struct ieee80211vap *); |
| 274 | |
| 275 | #define	IFNET_IS_UP_RUNNING(_ifp)				\ |
| 276 | 	(((if_getflags(_ifp) & IFF_UP) != 0) &&			\ |
| 277 | 	 ((if_getdrvflags(_ifp) & IFF_DRV_RUNNING) != 0)) |
| 278 | |
| 279 | #define	msecs_to_ticks(ms)	MSEC_2_TICKS(ms) |
| 280 | #define	ticks_to_msecs(t)	TICKS_2_MSEC(t) |
| 281 | #define	ticks_to_secs(t)	((t) / hz) |
| 282 | |
| 283 | #define ieee80211_time_after(a,b) 	((int)(b) - (int)(a) < 0) |
| 284 | #define ieee80211_time_before(a,b)	ieee80211_time_after(b,a) |
| 285 | #define ieee80211_time_after_eq(a,b)	((int)(a) - (int)(b) >= 0) |
| 286 | #define ieee80211_time_before_eq(a,b)	ieee80211_time_after_eq(b,a) |
| 287 | |
| 288 | struct mbuf *ieee80211_getmgtframe(uint8_t **frm, int headroom, int pktlen); |
| 289 | |
| 290 | /* tx path usage */ |
| 291 | #define	M_ENCAP		M_PROTO1		/* 802.11 encap done */ |
| 292 | #define	M_EAPOL		M_PROTO3		/* PAE/EAPOL frame */ |
| 293 | #define	M_PWR_SAV	M_PROTO4		/* bypass PS handling */ |
| 294 | #define	M_MORE_DATA	M_PROTO5		/* more data frames to follow */ |
| 295 | #define	M_FF		M_PROTO6		/* fast frame / A-MSDU */ |
| 296 | #define	M_TXCB		M_PROTO7		/* do tx complete callback */ |
| 297 | #define	M_AMPDU_MPDU	M_PROTO8		/* ok for A-MPDU aggregation */ |
| 298 | #define	M_FRAG		M_PROTO9		/* frame fragmentation */ |
| 299 | #define	M_FIRSTFRAG	M_PROTO10		/* first frame fragment */ |
| 300 | #define	M_LASTFRAG	M_PROTO11		/* last frame fragment */ |
| 301 | |
| 302 | #define	M_80211_TX \ |
| 303 | 	(M_ENCAP|M_EAPOL|M_PWR_SAV|M_MORE_DATA|M_FF|M_TXCB| \ |
| 304 | 	 M_AMPDU_MPDU|M_FRAG|M_FIRSTFRAG|M_LASTFRAG) |
| 305 | |
| 306 | /* rx path usage */ |
| 307 | #define	M_AMPDU		M_PROTO1		/* A-MPDU subframe */ |
| 308 | #define	M_WEP		M_PROTO2		/* WEP done by hardware */ |
| 309 | #if 0 |
| 310 | #define	M_AMPDU_MPDU	M_PROTO8		/* A-MPDU re-order done */ |
| 311 | #endif |
| 312 | #define	M_80211_RX	(M_AMPDU|M_WEP|M_AMPDU_MPDU) |
| 313 | |
| 314 | #define	IEEE80211_MBUF_TX_FLAG_BITS \ |
| 315 | 	M_FLAG_BITS \ |
| 316 | 	"\15M_ENCAP\17M_EAPOL\20M_PWR_SAV\21M_MORE_DATA\22M_FF\23M_TXCB" \ |
| 317 | 	"\24M_AMPDU_MPDU\25M_FRAG\26M_FIRSTFRAG\27M_LASTFRAG" |
| 318 | |
| 319 | #define	IEEE80211_MBUF_RX_FLAG_BITS \ |
| 320 | 	M_FLAG_BITS \ |
| 321 | 	"\15M_AMPDU\16M_WEP\24M_AMPDU_MPDU" |
| 322 | |
| 323 | /* |
| 324 | * Store WME access control bits in the vlan tag. |
| 325 | * This is safe since it's done after the packet is classified |
| 326 | * (where we use any previous tag) and because it's passed |
| 327 | * directly in to the driver and there's no chance someone |
| 328 | * else will clobber them on us. |
| 329 | */ |
| 330 | #define	M_WME_SETAC(m, ac) \ |
| 331 | 	((m)->m_pkthdr.ether_vtag = (ac)) |
| 332 | #define	M_WME_GETAC(m)	((m)->m_pkthdr.ether_vtag) |
| 333 | |
| 334 | /* |
| 335 | * Mbufs on the power save queue are tagged with an age and |
| 336 | * timed out. We reuse the hardware checksum field in the |
| 337 | * mbuf packet header to store this data. |
| 338 | */ |
| 339 | #define	M_AGE_SET(m,v)		(m->m_pkthdr.csum_data = v) |
| 340 | #define	M_AGE_GET(m)		(m->m_pkthdr.csum_data) |
| 341 | #define	M_AGE_SUB(m,adj)	(m->m_pkthdr.csum_data -= adj) |
| 342 | |
| 343 | /* |
| 344 | * Store / retrieve the sequence number in an mbuf. |
| 345 | * |
| 346 | * The sequence number being stored/retreived is the 12 bit |
| 347 | * base sequence number, not the 16 bit sequence number field. |
| 348 | * I.e., it's from 0..4095 inclusive, with no 4 bit padding for |
| 349 | * fragment numbers. |
| 350 | */ |
| 351 | #define	M_SEQNO_SET(m, seqno) \ |
| 352 | 	((m)->m_pkthdr.tso_segsz = ((seqno) % IEEE80211_SEQ_RANGE)) |
| 353 | #define	M_SEQNO_GET(m)	(((m)->m_pkthdr.tso_segsz) % IEEE80211_SEQ_RANGE) |
| 354 | |
| 355 | #define	MTAG_ABI_NET80211	1132948340	/* net80211 ABI */ |
| 356 | |
| 357 | struct ieee80211_cb { |
| 358 | 	void	(*func)(struct ieee80211_node *, void *, int status); |
| 359 | 	void	*arg; |
| 360 | }; |
| 361 | #define	NET80211_TAG_CALLBACK	0	/* xmit complete callback */ |
| 362 | int	ieee80211_add_callback(struct mbuf *m, |
| 363 | 		void (*func)(struct ieee80211_node *, void *, int), void *arg); |
| 364 | void	ieee80211_process_callback(struct ieee80211_node *, struct mbuf *, int); |
| 365 | |
| 366 | #define	NET80211_TAG_XMIT_PARAMS	1 |
| 367 | /* See below; this is after the bpf_params definition */ |
| 368 | |
| 369 | #define	NET80211_TAG_RECV_PARAMS	2 |
| 370 | |
| 371 | #define	NET80211_TAG_TOA_PARAMS		3 |
| 372 | |
| 373 | struct ieee80211com; |
| 374 | int	ieee80211_parent_xmitpkt(struct ieee80211com *, struct mbuf *); |
| 375 | int	ieee80211_vap_xmitpkt(struct ieee80211vap *, struct mbuf *); |
| 376 | |
| 377 | void	net80211_get_random_bytes(void *, size_t); |
| 378 | |
| 379 | void	ieee80211_sysctl_attach(struct ieee80211com *); |
| 380 | void	ieee80211_sysctl_detach(struct ieee80211com *); |
| 381 | void	ieee80211_sysctl_vattach(struct ieee80211vap *); |
| 382 | void	ieee80211_sysctl_vdetach(struct ieee80211vap *); |
| 383 | |
| 384 | SYSCTL_DECL(_net_wlan); |
| 385 | int	ieee80211_sysctl_msecs_ticks(SYSCTL_HANDLER_ARGS); |
| 386 | |
| 387 | void	ieee80211_load_module(const char *); |
| 388 | |
| 389 | /* |
| 390 | * A "policy module" is an adjunct module to net80211 that provides |
| 391 | * functionality that typically includes policy decisions. This |
| 392 | * modularity enables extensibility and vendor-supplied functionality. |
| 393 | */ |
| 394 | #define	_IEEE80211_POLICY_MODULE(policy, name, version)			\ |
| 395 | typedef void (*policy##_setup)(int);					\ |
| 396 | SET_DECLARE(policy##_set, policy##_setup);				\ |
| 397 | static int								\ |
| 398 | wlan_##name##_modevent(module_t mod, int type, void *unused)		\ |
| 399 | {									\ |
| 400 | 	policy##_setup * const *iter, f;				\ |
| 401 | 	switch (type) {							\ |
| 402 | 	case MOD_LOAD:							\ |
| 403 | 		SET_FOREACH(iter, policy##_set) {			\ |
| 404 | 			f = (void*) *iter;				\ |
| 405 | 			f(type);					\ |
| 406 | 		}							\ |
| 407 | 		return 0;						\ |
| 408 | 	case MOD_UNLOAD:						\ |
| 409 | 	case MOD_QUIESCE:						\ |
| 410 | 		if (nrefs) {						\ |
| 411 | 			printf("wlan_" #name ": still in use "		\ |
| 412 | 				"(%u dynamic refs)\n", nrefs);		\ |
| 413 | 			return EBUSY;					\ |
| 414 | 		}							\ |
| 415 | 		if (type == MOD_UNLOAD) {				\ |
| 416 | 			SET_FOREACH(iter, policy##_set) {		\ |
| 417 | 				f = (void*) *iter;			\ |
| 418 | 				f(type);				\ |
| 419 | 			}						\ |
| 420 | 		}							\ |
| 421 | 		return 0;						\ |
| 422 | 	}								\ |
| 423 | 	return EINVAL;							\ |
| 424 | }									\ |
| 425 | static moduledata_t name##_mod = {					\ |
| 426 | 	"wlan_" #name,							\ |
| 427 | 	wlan_##name##_modevent,						\ |
| 428 | 	0								\ |
| 429 | };									\ |
| 430 | DECLARE_MODULE(wlan_##name, name##_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);\ |
| 431 | MODULE_VERSION(wlan_##name, version);					\ |
| 432 | MODULE_DEPEND(wlan_##name, wlan, 1, 1, 1) |
| 433 | |
| 434 | /* |
| 435 | * Crypto modules implement cipher support. |
| 436 | */ |
| 437 | #define	IEEE80211_CRYPTO_MODULE_ADD(name)				\ |
| 438 | static void								\ |
| 439 | name##_modevent(int type)						\ |
| 440 | {									\ |
| 441 | 	if (type == MOD_LOAD)						\ |
| 442 | 		ieee80211_crypto_register(&name);			\ |
| 443 | 	else								\ |
| 444 | 		ieee80211_crypto_unregister(&name);			\ |
| 445 | }									\ |
| 446 | TEXT_SET(crypto##_set, name##_modevent) |
| 447 | |
| 448 | #define	IEEE80211_CRYPTO_MODULE(name, version)				\ |
| 449 | 	_IEEE80211_POLICY_MODULE(crypto, name, version);		\ |
| 450 | 	IEEE80211_CRYPTO_MODULE_ADD(name) |
| 451 | |
| 452 | /* |
| 453 | * Scanner modules provide scanning policy. |
| 454 | */ |
| 455 | #define	IEEE80211_SCANNER_MODULE(name, version)				\ |
| 456 | 	_IEEE80211_POLICY_MODULE(scanner, name, version) |
| 457 | |
| 458 | #define	IEEE80211_SCANNER_ALG(name, alg, v)				\ |
| 459 | static void								\ |
| 460 | name##_modevent(int type)						\ |
| 461 | {									\ |
| 462 | 	if (type == MOD_LOAD)						\ |
| 463 | 		ieee80211_scanner_register(alg, &v);			\ |
| 464 | 	else								\ |
| 465 | 		ieee80211_scanner_unregister(alg, &v);			\ |
| 466 | }									\ |
| 467 | TEXT_SET(scanner_set, name##_modevent);					\ |
| 468 | |
| 469 | /* |
| 470 | * ACL modules implement acl policy. |
| 471 | */ |
| 472 | #define	IEEE80211_ACL_MODULE(name, alg, version)			\ |
| 473 | _IEEE80211_POLICY_MODULE(acl, name, version);				\ |
| 474 | static void								\ |
| 475 | alg##_modevent(int type)						\ |
| 476 | {									\ |
| 477 | 	if (type == MOD_LOAD)						\ |
| 478 | 		ieee80211_aclator_register(&alg);			\ |
| 479 | 	else								\ |
| 480 | 		ieee80211_aclator_unregister(&alg);			\ |
| 481 | }									\ |
| 482 | TEXT_SET(acl_set, alg##_modevent);					\ |
| 483 | |
| 484 | /* |
| 485 | * Authenticator modules handle 802.1x/WPA authentication. |
| 486 | */ |
| 487 | #define	IEEE80211_AUTH_MODULE(name, version)				\ |
| 488 | 	_IEEE80211_POLICY_MODULE(auth, name, version) |
| 489 | |
| 490 | #define	IEEE80211_AUTH_ALG(name, alg, v)				\ |
| 491 | static void								\ |
| 492 | name##_modevent(int type)						\ |
| 493 | {									\ |
| 494 | 	if (type == MOD_LOAD)						\ |
| 495 | 		ieee80211_authenticator_register(alg, &v);		\ |
| 496 | 	else								\ |
| 497 | 		ieee80211_authenticator_unregister(alg);		\ |
| 498 | }									\ |
| 499 | TEXT_SET(auth_set, name##_modevent) |
| 500 | |
| 501 | /* |
| 502 | * Rate control modules provide tx rate control support. |
| 503 | */ |
| 504 | #define	IEEE80211_RATECTL_MODULE(alg, version)				\ |
| 505 | 	_IEEE80211_POLICY_MODULE(ratectl, alg, version);		\ |
| 506 | |
| 507 | #define	IEEE80211_RATECTL_ALG(name, alg, v)				\ |
| 508 | static void								\ |
| 509 | alg##_modevent(int type)						\ |
| 510 | {									\ |
| 511 | 	if (type == MOD_LOAD)						\ |
| 512 | 		ieee80211_ratectl_register(alg, &v);			\ |
| 513 | 	else								\ |
| 514 | 		ieee80211_ratectl_unregister(alg);			\ |
| 515 | }									\ |
| 516 | TEXT_SET(ratectl##_set, alg##_modevent) |
| 517 | |
| 518 | struct ieee80211req; |
| 519 | typedef int ieee80211_ioctl_getfunc(struct ieee80211vap *, |
| 520 | struct ieee80211req *); |
| 521 | SET_DECLARE(ieee80211_ioctl_getset, ieee80211_ioctl_getfunc); |
| 522 | #define	IEEE80211_IOCTL_GET(_name, _get) TEXT_SET(ieee80211_ioctl_getset, _get) |
| 523 | |
| 524 | typedef int ieee80211_ioctl_setfunc(struct ieee80211vap *, |
| 525 | struct ieee80211req *); |
| 526 | SET_DECLARE(ieee80211_ioctl_setset, ieee80211_ioctl_setfunc); |
| 527 | #define	IEEE80211_IOCTL_SET(_name, _set) TEXT_SET(ieee80211_ioctl_setset, _set) |
| 528 | |
| 529 | #ifdef DEBUGNET |
| 530 | typedef void debugnet80211_init_t(struct ieee80211com *, int *nrxr, int *ncl, |
| 531 | int *clsize); |
| 532 | typedef void debugnet80211_event_t(struct ieee80211com *, enum debugnet_ev); |
| 533 | typedef int debugnet80211_poll_t(struct ieee80211com *, int); |
| 534 | |
| 535 | struct debugnet80211_methods { |
| 536 | 	debugnet80211_init_t		*dn8_init; |
| 537 | 	debugnet80211_event_t		*dn8_event; |
| 538 | 	debugnet80211_poll_t		*dn8_poll; |
| 539 | }; |
| 540 | |
| 541 | #define	DEBUGNET80211_DEFINE(driver)					\ |
| 542 | 	static debugnet80211_init_t driver##_debugnet80211_init;		\ |
| 543 | 	static debugnet80211_event_t driver##_debugnet80211_event;	\ |
| 544 | 	static debugnet80211_poll_t driver##_debugnet80211_poll;		\ |
| 545 | 									\ |
| 546 | 	static struct debugnet80211_methods driver##_debugnet80211_methods = { \ |
| 547 | 		.dn8_init = driver##_debugnet80211_init,			\ |
| 548 | 		.dn8_event = driver##_debugnet80211_event,		\ |
| 549 | 		.dn8_poll = driver##_debugnet80211_poll,			\ |
| 550 | 	} |
| 551 | #define DEBUGNET80211_SET(ic, driver)					\ |
| 552 | 	(ic)->ic_debugnet_meth = &driver##_debugnet80211_methods |
| 553 | #else |
| 554 | #define DEBUGNET80211_DEFINE(driver) |
| 555 | #define DEBUGNET80211_SET(ic, driver) |
| 556 | #endif /* DEBUGNET */ |
| 557 | |
| 558 | void ieee80211_vap_sync_mac_address(struct ieee80211vap *); |
| 559 | void ieee80211_vap_copy_mac_address(struct ieee80211vap *); |
| 560 | void ieee80211_vap_deliver_data(struct ieee80211vap *, struct mbuf *); |
| 561 | bool ieee80211_vap_ifp_check_is_monitor(struct ieee80211vap *); |
| 562 | bool ieee80211_vap_ifp_check_is_simplex(struct ieee80211vap *); |
| 563 | bool ieee80211_vap_ifp_check_is_running(struct ieee80211vap *); |
| 564 | void ieee80211_vap_ifp_set_running_state(struct ieee80211vap *, bool); |
| 565 | const uint8_t * ieee80211_vap_get_broadcast_address(struct ieee80211vap *); |
| 566 | |
| 567 | void	net80211_printf(const char *fmt, ...) __printflike(1, 2); |
| 568 | void	net80211_vap_printf(const struct ieee80211vap *, const char *fmt, ...) |
| 569 | 	 __printflike(2, 3); |
| 570 | void	net80211_ic_printf(const struct ieee80211com *, const char *fmt, ...) |
| 571 | 	 __printflike(2, 3); |
| 572 | |
| 573 | #endif /* _KERNEL */ |
| 574 | |
| 575 | /* XXX this stuff belongs elsewhere */ |
| 576 | /* |
| 577 | * Message formats for messages from the net80211 layer to user |
| 578 | * applications via the routing socket. These messages are appended |
| 579 | * to an if_announcemsghdr structure. |
| 580 | */ |
| 581 | struct ieee80211_join_event { |
| 582 | 	uint8_t		iev_addr[6]; |
| 583 | }; |
| 584 | |
| 585 | struct ieee80211_leave_event { |
| 586 | 	uint8_t		iev_addr[6]; |
| 587 | }; |
| 588 | |
| 589 | struct ieee80211_replay_event { |
| 590 | 	uint8_t		iev_src[6];	/* src MAC */ |
| 591 | 	uint8_t		iev_dst[6];	/* dst MAC */ |
| 592 | 	uint8_t		iev_cipher;	/* cipher type */ |
| 593 | 	uint8_t		iev_keyix;	/* key id/index */ |
| 594 | 	uint64_t	iev_keyrsc;	/* RSC from key */ |
| 595 | 	uint64_t	iev_rsc;	/* RSC from frame */ |
| 596 | }; |
| 597 | |
| 598 | struct ieee80211_michael_event { |
| 599 | 	uint8_t		iev_src[6];	/* src MAC */ |
| 600 | 	uint8_t		iev_dst[6];	/* dst MAC */ |
| 601 | 	uint8_t		iev_cipher;	/* cipher type */ |
| 602 | 	uint8_t		iev_keyix;	/* key id/index */ |
| 603 | }; |
| 604 | |
| 605 | struct ieee80211_wds_event { |
| 606 | 	uint8_t		iev_addr[6]; |
| 607 | }; |
| 608 | |
| 609 | struct ieee80211_csa_event { |
| 610 | 	uint32_t	iev_flags;	/* channel flags */ |
| 611 | 	uint16_t	iev_freq;	/* setting in Mhz */ |
| 612 | 	uint8_t		iev_ieee;	/* IEEE channel number */ |
| 613 | 	uint8_t		iev_mode;	/* CSA mode */ |
| 614 | 	uint8_t		iev_count;	/* CSA count */ |
| 615 | }; |
| 616 | |
| 617 | struct ieee80211_cac_event { |
| 618 | 	uint32_t	iev_flags;	/* channel flags */ |
| 619 | 	uint16_t	iev_freq;	/* setting in Mhz */ |
| 620 | 	uint8_t		iev_ieee;	/* IEEE channel number */ |
| 621 | 	/* XXX timestamp? */ |
| 622 | 	uint8_t		iev_type;	/* IEEE80211_NOTIFY_CAC_* */ |
| 623 | }; |
| 624 | |
| 625 | struct ieee80211_radar_event { |
| 626 | 	uint32_t	iev_flags;	/* channel flags */ |
| 627 | 	uint16_t	iev_freq;	/* setting in Mhz */ |
| 628 | 	uint8_t		iev_ieee;	/* IEEE channel number */ |
| 629 | 	/* XXX timestamp? */ |
| 630 | }; |
| 631 | |
| 632 | struct ieee80211_auth_event { |
| 633 | 	uint8_t		iev_addr[6]; |
| 634 | }; |
| 635 | |
| 636 | struct ieee80211_deauth_event { |
| 637 | 	uint8_t		iev_addr[6]; |
| 638 | }; |
| 639 | |
| 640 | struct ieee80211_country_event { |
| 641 | 	uint8_t		iev_addr[6]; |
| 642 | 	uint8_t		iev_cc[2];	/* ISO country code */ |
| 643 | }; |
| 644 | |
| 645 | struct ieee80211_radio_event { |
| 646 | 	uint8_t		iev_state;	/* 1 on, 0 off */ |
| 647 | }; |
| 648 | |
| 649 | #define	RTM_IEEE80211_ASSOC	100	/* station associate (bss mode) */ |
| 650 | #define	RTM_IEEE80211_REASSOC	101	/* station re-associate (bss mode) */ |
| 651 | #define	RTM_IEEE80211_DISASSOC	102	/* station disassociate (bss mode) */ |
| 652 | #define	RTM_IEEE80211_JOIN	103	/* station join (ap mode) */ |
| 653 | #define	RTM_IEEE80211_LEAVE	104	/* station leave (ap mode) */ |
| 654 | #define	RTM_IEEE80211_SCAN	105	/* scan complete, results available */ |
| 655 | #define	RTM_IEEE80211_REPLAY	106	/* sequence counter replay detected */ |
| 656 | #define	RTM_IEEE80211_MICHAEL	107	/* Michael MIC failure detected */ |
| 657 | #define	RTM_IEEE80211_REJOIN	108	/* station re-associate (ap mode) */ |
| 658 | #define	RTM_IEEE80211_WDS	109	/* WDS discovery (ap mode) */ |
| 659 | #define	RTM_IEEE80211_CSA	110	/* Channel Switch Announcement event */ |
| 660 | #define	RTM_IEEE80211_RADAR	111	/* radar event */ |
| 661 | #define	RTM_IEEE80211_CAC	112	/* Channel Availability Check event */ |
| 662 | #define	RTM_IEEE80211_DEAUTH	113	/* station deauthenticate */ |
| 663 | #define	RTM_IEEE80211_AUTH	114	/* station authenticate (ap mode) */ |
| 664 | #define	RTM_IEEE80211_COUNTRY	115	/* discovered country code (sta mode) */ |
| 665 | #define	RTM_IEEE80211_RADIO	116	/* RF kill switch state change */ |
| 666 | |
| 667 | /* |
| 668 | * Structure prepended to raw packets sent through the bpf |
| 669 | * interface when set to DLT_IEEE802_11_RADIO. This allows |
| 670 | * user applications to specify pretty much everything in |
| 671 | * an Atheros tx descriptor. XXX need to generalize. |
| 672 | * |
| 673 | * XXX cannot be more than 14 bytes as it is copied to a sockaddr's |
| 674 | * XXX sa_data area. |
| 675 | */ |
| 676 | struct ieee80211_bpf_params { |
| 677 | 	uint8_t		ibp_vers;	/* version */ |
| 678 | #define	IEEE80211_BPF_VERSION	0 |
| 679 | 	uint8_t		ibp_len;	/* header length in bytes */ |
| 680 | 	uint8_t		ibp_flags; |
| 681 | #define	IEEE80211_BPF_SHORTPRE	0x01	/* tx with short preamble */ |
| 682 | #define	IEEE80211_BPF_NOACK	0x02	/* tx with no ack */ |
| 683 | #define	IEEE80211_BPF_CRYPTO	0x04	/* tx with h/w encryption */ |
| 684 | #define	IEEE80211_BPF_FCS	0x10	/* frame incldues FCS */ |
| 685 | #define	IEEE80211_BPF_DATAPAD	0x20	/* frame includes data padding */ |
| 686 | #define	IEEE80211_BPF_RTS	0x40	/* tx with RTS/CTS */ |
| 687 | #define	IEEE80211_BPF_CTS	0x80	/* tx with CTS only */ |
| 688 | 	uint8_t		ibp_pri;	/* WME/WMM AC+tx antenna */ |
| 689 | 	uint8_t		ibp_try0;	/* series 1 try count */ |
| 690 | 	uint8_t		ibp_rate0;	/* series 1 IEEE tx rate */ |
| 691 | 	uint8_t		ibp_power;	/* tx power (device units) */ |
| 692 | 	uint8_t		ibp_ctsrate;	/* IEEE tx rate for CTS */ |
| 693 | 	uint8_t		ibp_try1;	/* series 2 try count */ |
| 694 | 	uint8_t		ibp_rate1;	/* series 2 IEEE tx rate */ |
| 695 | 	uint8_t		ibp_try2;	/* series 3 try count */ |
| 696 | 	uint8_t		ibp_rate2;	/* series 3 IEEE tx rate */ |
| 697 | 	uint8_t		ibp_try3;	/* series 4 try count */ |
| 698 | 	uint8_t		ibp_rate3;	/* series 4 IEEE tx rate */ |
| 699 | }; |
| 700 | |
| 701 | #ifdef _KERNEL |
| 702 | struct ieee80211_tx_params { |
| 703 | 	struct ieee80211_bpf_params params; |
| 704 | }; |
| 705 | int	ieee80211_add_xmit_params(struct mbuf *m, |
| 706 | 	 const struct ieee80211_bpf_params *); |
| 707 | int	ieee80211_get_xmit_params(struct mbuf *m, |
| 708 | 	 struct ieee80211_bpf_params *); |
| 709 | |
| 710 | struct ieee80211_rx_params; |
| 711 | struct ieee80211_rx_stats; |
| 712 | |
| 713 | int	ieee80211_add_rx_params(struct mbuf *m, |
| 714 | 	 const struct ieee80211_rx_stats *rxs); |
| 715 | int	ieee80211_get_rx_params(struct mbuf *m, |
| 716 | 	 struct ieee80211_rx_stats *rxs); |
| 717 | const struct ieee80211_rx_stats * ieee80211_get_rx_params_ptr(struct mbuf *m); |
| 718 | |
| 719 | struct ieee80211_toa_params { |
| 720 | 	int request_id; |
| 721 | }; |
| 722 | int	ieee80211_add_toa_params(struct mbuf *m, |
| 723 | 	 const struct ieee80211_toa_params *p); |
| 724 | int	ieee80211_get_toa_params(struct mbuf *m, |
| 725 | 	 struct ieee80211_toa_params *p); |
| 726 | |
| 727 | #define	IEEE80211_F_SURVEY_TIME		0x00000001 |
| 728 | #define	IEEE80211_F_SURVEY_TIME_BUSY	0x00000002 |
| 729 | #define	IEEE80211_F_SURVEY_NOISE_DBM	0x00000004 |
| 730 | #define	IEEE80211_F_SURVEY_TSC		0x00000008 |
| 731 | struct ieee80211_channel_survey { |
| 732 | 	uint32_t s_flags; |
| 733 | 	uint32_t s_time; |
| 734 | 	uint32_t s_time_busy; |
| 735 | 	int32_t s_noise; |
| 736 | 	uint64_t s_tsc; |
| 737 | }; |
| 738 | |
| 739 | #endif /* _KERNEL */ |
| 740 | |
| 741 | /* |
| 742 | * Malloc API. Other BSD operating systems have slightly |
| 743 | * different malloc/free namings (eg DragonflyBSD.) |
| 744 | */ |
| 745 | #define	IEEE80211_MALLOC	malloc |
| 746 | #define	IEEE80211_FREE		free |
| 747 | |
| 748 | /* XXX TODO: get rid of WAITOK, fix all the users of it? */ |
| 749 | #define	IEEE80211_M_NOWAIT	M_NOWAIT |
| 750 | #define	IEEE80211_M_WAITOK	M_WAITOK |
| 751 | #define	IEEE80211_M_ZERO	M_ZERO |
| 752 | |
| 753 | /* XXX TODO: the type fields */ |
| 754 | |
| 755 | #endif /* _NET80211_IEEE80211_FREEBSD_H_ */ |