xref: /haiku/src/libs/compat/freebsd_wlan/net80211/ieee80211_haiku.cpp (revision 86021fd407331bcef948c739a4870ca453f5c6cd)
1753c7e08SAugustin Cavalier /*
2753c7e08SAugustin Cavalier  * Copyright 2009, Colin Günther, coling@gmx.de. All rights reserved.
3*86021fd4SAugustin Cavalier  * Copyright 2018-2024, Haiku, Inc. All rights reserved.
4753c7e08SAugustin Cavalier  * Distributed under the terms of the MIT License.
5753c7e08SAugustin Cavalier  */
6753c7e08SAugustin Cavalier 
7753c7e08SAugustin Cavalier 
8753c7e08SAugustin Cavalier /*-
9753c7e08SAugustin Cavalier  * Copyright (c) 2003-2009 Sam Leffler, Errno Consulting
10753c7e08SAugustin Cavalier  * All rights reserved.
11753c7e08SAugustin Cavalier  *
12753c7e08SAugustin Cavalier  * Redistribution and use in source and binary forms, with or without
13753c7e08SAugustin Cavalier  * modification, are permitted provided that the following conditions
14753c7e08SAugustin Cavalier  * are met:
15753c7e08SAugustin Cavalier  * 1. Redistributions of source code must retain the above copyright
16753c7e08SAugustin Cavalier  *    notice, this list of conditions and the following disclaimer.
17753c7e08SAugustin Cavalier  * 2. Redistributions in binary form must reproduce the above copyright
18753c7e08SAugustin Cavalier  *    notice, this list of conditions and the following disclaimer in the
19753c7e08SAugustin Cavalier  *    documentation and/or other materials provided with the distribution.
20753c7e08SAugustin Cavalier  *
21753c7e08SAugustin Cavalier  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22753c7e08SAugustin Cavalier  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23753c7e08SAugustin Cavalier  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24753c7e08SAugustin Cavalier  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25753c7e08SAugustin Cavalier  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26753c7e08SAugustin Cavalier  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27753c7e08SAugustin Cavalier  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28753c7e08SAugustin Cavalier  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29753c7e08SAugustin Cavalier  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30753c7e08SAugustin Cavalier  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31753c7e08SAugustin Cavalier  */
32753c7e08SAugustin Cavalier 
33753c7e08SAugustin Cavalier 
34753c7e08SAugustin Cavalier /*
35753c7e08SAugustin Cavalier  * IEEE 802.11 support (Haiku-specific code)
36753c7e08SAugustin Cavalier  */
37753c7e08SAugustin Cavalier 
38753c7e08SAugustin Cavalier 
39753c7e08SAugustin Cavalier #include "ieee80211_haiku.h"
40753c7e08SAugustin Cavalier 
41753c7e08SAugustin Cavalier extern "C" {
42753c7e08SAugustin Cavalier #	include <sys/kernel.h>
43753c7e08SAugustin Cavalier #	include <sys/mbuf.h>
44753c7e08SAugustin Cavalier #	include <sys/bus.h>
45753c7e08SAugustin Cavalier #	include <sys/sockio.h>
46753c7e08SAugustin Cavalier 
47753c7e08SAugustin Cavalier #	include <net/if.h>
48753c7e08SAugustin Cavalier #	include <net/if_media.h>
49753c7e08SAugustin Cavalier #	include <net/if_types.h>
50753c7e08SAugustin Cavalier #	include <net/if_var.h>
51753c7e08SAugustin Cavalier 
52753c7e08SAugustin Cavalier #	include "ieee80211_var.h"
53753c7e08SAugustin Cavalier };
54753c7e08SAugustin Cavalier 
55753c7e08SAugustin Cavalier #include <SupportDefs.h>
56753c7e08SAugustin Cavalier 
57753c7e08SAugustin Cavalier #include <util/KMessage.h>
58753c7e08SAugustin Cavalier 
59753c7e08SAugustin Cavalier #include <ether_driver.h>
60753c7e08SAugustin Cavalier #include <net_notifications.h>
61753c7e08SAugustin Cavalier 
62753c7e08SAugustin Cavalier #include <shared.h>
63753c7e08SAugustin Cavalier 
64753c7e08SAugustin Cavalier 
65753c7e08SAugustin Cavalier #define TRACE_WLAN
66753c7e08SAugustin Cavalier #ifdef TRACE_WLAN
67753c7e08SAugustin Cavalier #	define TRACE(x...) dprintf(x);
68753c7e08SAugustin Cavalier #else
69753c7e08SAugustin Cavalier #	define TRACE(x...) ;
70753c7e08SAugustin Cavalier #endif
71753c7e08SAugustin Cavalier 
72753c7e08SAugustin Cavalier 
73753c7e08SAugustin Cavalier #define	MC_ALIGN(m, len)									\
74753c7e08SAugustin Cavalier do {														\
75753c7e08SAugustin Cavalier 	(m)->m_data += (MCLBYTES - (len)) &~ (sizeof(long) - 1);\
76753c7e08SAugustin Cavalier } while (/* CONSTCOND */ 0)
77753c7e08SAugustin Cavalier 
78753c7e08SAugustin Cavalier 
79753c7e08SAugustin Cavalier static net_notifications_module_info* sNotificationModule;
80753c7e08SAugustin Cavalier 
81753c7e08SAugustin Cavalier 
825cad57c4SJérôme Duval /*
835cad57c4SJérôme Duval  * priv(9) NET80211 checks.
845cad57c4SJérôme Duval  * Return 0 if operation is allowed, E* (usually EPERM) otherwise.
855cad57c4SJérôme Duval  */
865cad57c4SJérôme Duval int
ieee80211_priv_check_vap_getkey(u_long cmd __unused,struct ieee80211vap * vap __unused,struct ifnet * ifp __unused)875cad57c4SJérôme Duval ieee80211_priv_check_vap_getkey(u_long cmd __unused,
885cad57c4SJérôme Duval      struct ieee80211vap *vap __unused, struct ifnet *ifp __unused)
895cad57c4SJérôme Duval {
905cad57c4SJérôme Duval 	return 0;
915cad57c4SJérôme Duval }
925cad57c4SJérôme Duval 
935cad57c4SJérôme Duval int
ieee80211_priv_check_vap_manage(u_long cmd __unused,struct ieee80211vap * vap __unused,struct ifnet * ifp __unused)945cad57c4SJérôme Duval ieee80211_priv_check_vap_manage(u_long cmd __unused,
955cad57c4SJérôme Duval      struct ieee80211vap *vap __unused, struct ifnet *ifp __unused)
965cad57c4SJérôme Duval {
975cad57c4SJérôme Duval 	return 0;
985cad57c4SJérôme Duval }
995cad57c4SJérôme Duval 
1005cad57c4SJérôme Duval int
ieee80211_priv_check_vap_setmac(u_long cmd __unused,struct ieee80211vap * vap __unused,struct ifnet * ifp __unused)1015cad57c4SJérôme Duval ieee80211_priv_check_vap_setmac(u_long cmd __unused,
1025cad57c4SJérôme Duval      struct ieee80211vap *vap __unused, struct ifnet *ifp __unused)
1035cad57c4SJérôme Duval {
1045cad57c4SJérôme Duval 	return 0;
1055cad57c4SJérôme Duval }
1065cad57c4SJérôme Duval 
1075cad57c4SJérôme Duval int
ieee80211_priv_check_create_vap(u_long cmd __unused,struct ieee80211vap * vap __unused,struct ifnet * ifp __unused)1085cad57c4SJérôme Duval ieee80211_priv_check_create_vap(u_long cmd __unused,
1095cad57c4SJérôme Duval     struct ieee80211vap *vap __unused, struct ifnet *ifp __unused)
1105cad57c4SJérôme Duval {
1115cad57c4SJérôme Duval 	return 0;
1125cad57c4SJérôme Duval }
1135cad57c4SJérôme Duval 
1145cad57c4SJérôme Duval 
115753c7e08SAugustin Cavalier static struct ifnet*
get_ifnet(device_t device,int & i)116753c7e08SAugustin Cavalier get_ifnet(device_t device, int& i)
117753c7e08SAugustin Cavalier {
118753c7e08SAugustin Cavalier 	int unit = device_get_unit(device);
119753c7e08SAugustin Cavalier 
120753c7e08SAugustin Cavalier 	for (i = 0; i < MAX_DEVICES; i++) {
121753c7e08SAugustin Cavalier 		if (gDevices[i] != NULL && gDevices[i]->if_dunit == unit)
122753c7e08SAugustin Cavalier 			return gDevices[i];
123753c7e08SAugustin Cavalier 	}
124753c7e08SAugustin Cavalier 
125753c7e08SAugustin Cavalier 	return NULL;
126753c7e08SAugustin Cavalier }
127753c7e08SAugustin Cavalier 
128753c7e08SAugustin Cavalier 
129753c7e08SAugustin Cavalier status_t
init_wlan_stack(void)130753c7e08SAugustin Cavalier init_wlan_stack(void)
131753c7e08SAugustin Cavalier {
132753c7e08SAugustin Cavalier 	get_module(NET_NOTIFICATIONS_MODULE_NAME,
133753c7e08SAugustin Cavalier 		(module_info**)&sNotificationModule);
134753c7e08SAugustin Cavalier 
135753c7e08SAugustin Cavalier 	return B_OK;
136753c7e08SAugustin Cavalier }
137753c7e08SAugustin Cavalier 
138753c7e08SAugustin Cavalier 
139753c7e08SAugustin Cavalier void
uninit_wlan_stack(void)140753c7e08SAugustin Cavalier uninit_wlan_stack(void)
141753c7e08SAugustin Cavalier {
142753c7e08SAugustin Cavalier 	if (sNotificationModule != NULL)
143753c7e08SAugustin Cavalier 		put_module(NET_NOTIFICATIONS_MODULE_NAME);
144753c7e08SAugustin Cavalier }
145753c7e08SAugustin Cavalier 
146753c7e08SAugustin Cavalier 
147753c7e08SAugustin Cavalier status_t
start_wlan(device_t device)148753c7e08SAugustin Cavalier start_wlan(device_t device)
149753c7e08SAugustin Cavalier {
150753c7e08SAugustin Cavalier 	struct ieee80211com* ic = ieee80211_find_com(device->nameunit);
151753c7e08SAugustin Cavalier 	if (ic == NULL)
152753c7e08SAugustin Cavalier 		return B_BAD_VALUE;
153753c7e08SAugustin Cavalier 
154753c7e08SAugustin Cavalier 	struct ieee80211vap* vap = ic->ic_vap_create(ic, "wlan",
155753c7e08SAugustin Cavalier 		device_get_unit(device),
156753c7e08SAugustin Cavalier 		IEEE80211_M_STA,		// mode
157753c7e08SAugustin Cavalier 		0,						// flags
158753c7e08SAugustin Cavalier 		NULL,					// BSSID
159753c7e08SAugustin Cavalier 		ic->ic_macaddr);		// MAC address
160753c7e08SAugustin Cavalier 
161753c7e08SAugustin Cavalier 	if (vap == NULL)
162753c7e08SAugustin Cavalier 		return B_ERROR;
163753c7e08SAugustin Cavalier 
164753c7e08SAugustin Cavalier 	// ic_vap_create() established that gDevices[i] links to vap->iv_ifp now
165753c7e08SAugustin Cavalier 	KASSERT(gDevices[gDeviceCount - 1] == vap->iv_ifp,
166753c7e08SAugustin Cavalier 		("start_wlan: gDevices[i] != vap->iv_ifp"));
167753c7e08SAugustin Cavalier 
168753c7e08SAugustin Cavalier 	vap->iv_ifp->scan_done_sem = create_sem(0, "wlan scan done");
169753c7e08SAugustin Cavalier 
170753c7e08SAugustin Cavalier 	// We aren't connected to a WLAN, yet.
171753c7e08SAugustin Cavalier 	if_link_state_change(vap->iv_ifp, LINK_STATE_DOWN);
172753c7e08SAugustin Cavalier 
173753c7e08SAugustin Cavalier 	dprintf("%s: wlan started.\n", __func__);
174753c7e08SAugustin Cavalier 
175753c7e08SAugustin Cavalier 	return B_OK;
176753c7e08SAugustin Cavalier }
177753c7e08SAugustin Cavalier 
178753c7e08SAugustin Cavalier 
179753c7e08SAugustin Cavalier status_t
stop_wlan(device_t device)180753c7e08SAugustin Cavalier stop_wlan(device_t device)
181753c7e08SAugustin Cavalier {
182753c7e08SAugustin Cavalier 	int i;
183753c7e08SAugustin Cavalier 	struct ifnet* ifp = get_ifnet(device, i);
184753c7e08SAugustin Cavalier 	if (ifp == NULL)
185753c7e08SAugustin Cavalier 		return B_BAD_VALUE;
186753c7e08SAugustin Cavalier 
187753c7e08SAugustin Cavalier 	delete_sem(ifp->scan_done_sem);
188753c7e08SAugustin Cavalier 
189753c7e08SAugustin Cavalier 	struct ieee80211vap* vap = (ieee80211vap*)ifp->if_softc;
190753c7e08SAugustin Cavalier 	struct ieee80211com* ic = vap->iv_ic;
191753c7e08SAugustin Cavalier 
192753c7e08SAugustin Cavalier 	ic->ic_vap_delete(vap);
193753c7e08SAugustin Cavalier 
194753c7e08SAugustin Cavalier 	// ic_vap_delete freed gDevices[i]
195753c7e08SAugustin Cavalier 	KASSERT(gDevices[i] == NULL, ("stop_wlan: gDevices[i] != NULL"));
196753c7e08SAugustin Cavalier 
197753c7e08SAugustin Cavalier 	return B_OK;
198753c7e08SAugustin Cavalier }
199753c7e08SAugustin Cavalier 
200753c7e08SAugustin Cavalier 
201753c7e08SAugustin Cavalier status_t
wlan_open(void * cookie)202753c7e08SAugustin Cavalier wlan_open(void* cookie)
203753c7e08SAugustin Cavalier {
204753c7e08SAugustin Cavalier 	dprintf("wlan_open(%p)\n", cookie);
205753c7e08SAugustin Cavalier 	struct ifnet* ifp = (struct ifnet*)cookie;
206753c7e08SAugustin Cavalier 
207753c7e08SAugustin Cavalier 	ifp->if_init(ifp->if_softc);
208753c7e08SAugustin Cavalier 
209753c7e08SAugustin Cavalier 	ifp->if_flags |= IFF_UP;
210753c7e08SAugustin Cavalier 	ifp->if_ioctl(ifp, SIOCSIFFLAGS, NULL);
211753c7e08SAugustin Cavalier 
212753c7e08SAugustin Cavalier 	return B_OK;
213753c7e08SAugustin Cavalier }
214753c7e08SAugustin Cavalier 
215753c7e08SAugustin Cavalier 
216753c7e08SAugustin Cavalier status_t
wlan_close(void * cookie)217753c7e08SAugustin Cavalier wlan_close(void* cookie)
218753c7e08SAugustin Cavalier {
219753c7e08SAugustin Cavalier 	dprintf("wlan_close(%p)\n", cookie);
220753c7e08SAugustin Cavalier 	struct ifnet* ifp = (struct ifnet*)cookie;
221753c7e08SAugustin Cavalier 
222753c7e08SAugustin Cavalier 	ifp->if_flags &= ~IFF_UP;
223753c7e08SAugustin Cavalier 	ifp->if_ioctl(ifp, SIOCSIFFLAGS, NULL);
224753c7e08SAugustin Cavalier 
225753c7e08SAugustin Cavalier 	return release_sem_etc(ifp->scan_done_sem, 1, B_RELEASE_ALL);
226753c7e08SAugustin Cavalier }
227753c7e08SAugustin Cavalier 
228753c7e08SAugustin Cavalier 
229753c7e08SAugustin Cavalier status_t
wlan_control(void * cookie,uint32 op,void * arg,size_t length)230753c7e08SAugustin Cavalier wlan_control(void* cookie, uint32 op, void* arg, size_t length)
231753c7e08SAugustin Cavalier {
232753c7e08SAugustin Cavalier 	struct ifnet* ifp = (struct ifnet*)cookie;
233753c7e08SAugustin Cavalier 
234753c7e08SAugustin Cavalier 	switch (op) {
235753c7e08SAugustin Cavalier 		case SIOCG80211:
236753c7e08SAugustin Cavalier 		case SIOCS80211:
237753c7e08SAugustin Cavalier 		{
238753c7e08SAugustin Cavalier 			// FreeBSD drivers assume that the request structure has already
239753c7e08SAugustin Cavalier 			// been copied into kernel space
240753c7e08SAugustin Cavalier 			struct ieee80211req request;
241753c7e08SAugustin Cavalier 			if (user_memcpy(&request, arg, sizeof(struct ieee80211req)) != B_OK)
242753c7e08SAugustin Cavalier 				return B_BAD_ADDRESS;
243753c7e08SAugustin Cavalier 
244753c7e08SAugustin Cavalier 			if (request.i_type == IEEE80211_IOC_HAIKU_COMPAT_WLAN_UP)
245753c7e08SAugustin Cavalier 				return wlan_open(cookie);
246753c7e08SAugustin Cavalier 			else if (request.i_type == IEEE80211_IOC_HAIKU_COMPAT_WLAN_DOWN)
247753c7e08SAugustin Cavalier 				return wlan_close(cookie);
248753c7e08SAugustin Cavalier 
2496d0f2b48SAugustin Cavalier 			TRACE("wlan_control: %" B_PRIu32 ", %d\n", op, request.i_type);
250753c7e08SAugustin Cavalier 			status_t status = ifp->if_ioctl(ifp, op, (caddr_t)&request);
251753c7e08SAugustin Cavalier 			if (status != B_OK)
252753c7e08SAugustin Cavalier 				return status;
253753c7e08SAugustin Cavalier 
254753c7e08SAugustin Cavalier 			if (op == SIOCG80211 && user_memcpy(arg, &request,
255753c7e08SAugustin Cavalier 					sizeof(struct ieee80211req)) != B_OK)
256753c7e08SAugustin Cavalier 				return B_BAD_ADDRESS;
257753c7e08SAugustin Cavalier 			return B_OK;
258753c7e08SAugustin Cavalier 		}
259753c7e08SAugustin Cavalier 	}
260753c7e08SAugustin Cavalier 
261753c7e08SAugustin Cavalier 	return B_BAD_VALUE;
262753c7e08SAugustin Cavalier }
263753c7e08SAugustin Cavalier 
264753c7e08SAugustin Cavalier 
265753c7e08SAugustin Cavalier void
net80211_get_random_bytes(void * p,size_t n)266*86021fd4SAugustin Cavalier net80211_get_random_bytes(void* p, size_t n)
267753c7e08SAugustin Cavalier {
268753c7e08SAugustin Cavalier 	uint8_t* dp = (uint8_t*)p;
269753c7e08SAugustin Cavalier 
270753c7e08SAugustin Cavalier 	while (n > 0) {
271753c7e08SAugustin Cavalier 		uint32_t v = arc4random();
272753c7e08SAugustin Cavalier 		size_t nb = n > sizeof(uint32_t) ? sizeof(uint32_t) : n;
273753c7e08SAugustin Cavalier 		bcopy(&v, dp, n > sizeof(uint32_t) ? sizeof(uint32_t) : n);
274753c7e08SAugustin Cavalier 		dp += sizeof(uint32_t), n -= nb;
275753c7e08SAugustin Cavalier 	}
276753c7e08SAugustin Cavalier }
277753c7e08SAugustin Cavalier 
278753c7e08SAugustin Cavalier 
279753c7e08SAugustin Cavalier struct mbuf *
ieee80211_getmgtframe(uint8_t ** frm,int headroom,int pktlen)280753c7e08SAugustin Cavalier ieee80211_getmgtframe(uint8_t **frm, int headroom, int pktlen)
281753c7e08SAugustin Cavalier {
282753c7e08SAugustin Cavalier 	struct mbuf *m;
283753c7e08SAugustin Cavalier 	u_int len;
284753c7e08SAugustin Cavalier 
2856d0f2b48SAugustin Cavalier 	/*
2866d0f2b48SAugustin Cavalier 	 * NB: we know the mbuf routines will align the data area
2876d0f2b48SAugustin Cavalier 	 *     so we don't need to do anything special.
2886d0f2b48SAugustin Cavalier 	 */
289753c7e08SAugustin Cavalier 	len = roundup2(headroom + pktlen, 4);
290753c7e08SAugustin Cavalier 	KASSERT(len <= MCLBYTES, ("802.11 mgt frame too large: %u", len));
291753c7e08SAugustin Cavalier 	if (len < MINCLSIZE) {
292753c7e08SAugustin Cavalier 		m = m_gethdr(M_NOWAIT, MT_DATA);
2936d0f2b48SAugustin Cavalier 		/*
2946d0f2b48SAugustin Cavalier 		 * Align the data in case additional headers are added.
2956d0f2b48SAugustin Cavalier 		 * This should only happen when a WEP header is added
2966d0f2b48SAugustin Cavalier 		 * which only happens for shared key authentication mgt
2976d0f2b48SAugustin Cavalier 		 * frames which all fit in MHLEN.
2986d0f2b48SAugustin Cavalier 		 */
299753c7e08SAugustin Cavalier 		if (m != NULL)
3006d0f2b48SAugustin Cavalier 			M_ALIGN(m, len);
301753c7e08SAugustin Cavalier 	} else {
302753c7e08SAugustin Cavalier 		m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
303753c7e08SAugustin Cavalier 		if (m != NULL)
304753c7e08SAugustin Cavalier 			MC_ALIGN(m, len);
305753c7e08SAugustin Cavalier 	}
306753c7e08SAugustin Cavalier 	if (m != NULL) {
307753c7e08SAugustin Cavalier 		m->m_data += headroom;
308753c7e08SAugustin Cavalier 		*frm = (uint8_t*)m->m_data;
309753c7e08SAugustin Cavalier 	}
310753c7e08SAugustin Cavalier 	return m;
311753c7e08SAugustin Cavalier }
312753c7e08SAugustin Cavalier 
313753c7e08SAugustin Cavalier 
3145cad57c4SJérôme Duval int
ieee80211_com_vincref(struct ieee80211vap * vap)3155cad57c4SJérôme Duval ieee80211_com_vincref(struct ieee80211vap *vap)
3165cad57c4SJérôme Duval {
3175cad57c4SJérôme Duval 	uint32_t ostate;
3185cad57c4SJérôme Duval 
3195cad57c4SJérôme Duval 	ostate = atomic_fetchadd_32(&vap->iv_com_state, IEEE80211_COM_REF_ADD);
3205cad57c4SJérôme Duval 
3215cad57c4SJérôme Duval 	if (ostate & IEEE80211_COM_DETACHED) {
3225cad57c4SJérôme Duval 		atomic_subtract_32(&vap->iv_com_state, IEEE80211_COM_REF_ADD);
3235cad57c4SJérôme Duval 		return (ENETDOWN);
3245cad57c4SJérôme Duval 	}
3255cad57c4SJérôme Duval 
3265cad57c4SJérôme Duval 	if (_IEEE80211_MASKSHIFT(ostate, IEEE80211_COM_REF) ==
3275cad57c4SJérôme Duval 	    IEEE80211_COM_REF_MAX) {
3285cad57c4SJérôme Duval 		atomic_subtract_32(&vap->iv_com_state, IEEE80211_COM_REF_ADD);
3295cad57c4SJérôme Duval 		return (EOVERFLOW);
3305cad57c4SJérôme Duval 	}
3315cad57c4SJérôme Duval 
3325cad57c4SJérôme Duval 	return (0);
3335cad57c4SJérôme Duval }
3345cad57c4SJérôme Duval 
3355cad57c4SJérôme Duval 
3365cad57c4SJérôme Duval void
ieee80211_com_vdecref(struct ieee80211vap * vap)3375cad57c4SJérôme Duval ieee80211_com_vdecref(struct ieee80211vap *vap)
3385cad57c4SJérôme Duval {
3395cad57c4SJérôme Duval 	uint32_t ostate;
3405cad57c4SJérôme Duval 
3415cad57c4SJérôme Duval 	ostate = atomic_fetchadd_32(&vap->iv_com_state, -IEEE80211_COM_REF_ADD);
3425cad57c4SJérôme Duval 
3435cad57c4SJérôme Duval 	KASSERT(_IEEE80211_MASKSHIFT(ostate, IEEE80211_COM_REF) != 0,
3445cad57c4SJérôme Duval 	    ("com reference counter underflow"));
3455cad57c4SJérôme Duval 
3465cad57c4SJérôme Duval 	(void) ostate;
3475cad57c4SJérôme Duval }
3485cad57c4SJérôme Duval 
3495cad57c4SJérôme Duval 
3505cad57c4SJérôme Duval void
ieee80211_com_vdetach(struct ieee80211vap * vap)3515cad57c4SJérôme Duval ieee80211_com_vdetach(struct ieee80211vap *vap)
3525cad57c4SJérôme Duval {
3535cad57c4SJérôme Duval 	int sleep_time;
3545cad57c4SJérôme Duval 
3555cad57c4SJérôme Duval 	sleep_time = msecs_to_ticks(250);
3565cad57c4SJérôme Duval 	atomic_set_32(&vap->iv_com_state, IEEE80211_COM_DETACHED);
3575cad57c4SJérôme Duval 	while (_IEEE80211_MASKSHIFT(atomic_load_32(&vap->iv_com_state),
3585cad57c4SJérôme Duval 	    IEEE80211_COM_REF) != 0)
3595cad57c4SJérôme Duval 		pause("comref", sleep_time);
3605cad57c4SJérôme Duval }
3615cad57c4SJérôme Duval 
3625cad57c4SJérôme Duval 
363753c7e08SAugustin Cavalier /*
364753c7e08SAugustin Cavalier  * Decrements the reference-counter and
365753c7e08SAugustin Cavalier  * tests whether it became zero. If so, sets it to one.
366753c7e08SAugustin Cavalier  *
367753c7e08SAugustin Cavalier  * @return 1 reference-counter became zero
368753c7e08SAugustin Cavalier  * @return 0 reference-counter didn't became zero
369753c7e08SAugustin Cavalier  */
370753c7e08SAugustin Cavalier int
ieee80211_node_dectestref(struct ieee80211_node * ni)371753c7e08SAugustin Cavalier ieee80211_node_dectestref(struct ieee80211_node* ni)
372753c7e08SAugustin Cavalier {
373753c7e08SAugustin Cavalier 	atomic_subtract_int(&ni->ni_refcnt, 1);
374753c7e08SAugustin Cavalier 	return atomic_cmpset_int(&ni->ni_refcnt, 0, 1);
375753c7e08SAugustin Cavalier }
376753c7e08SAugustin Cavalier 
377753c7e08SAugustin Cavalier 
378753c7e08SAugustin Cavalier void
ieee80211_drain_ifq(struct ifqueue * ifq)379753c7e08SAugustin Cavalier ieee80211_drain_ifq(struct ifqueue* ifq)
380753c7e08SAugustin Cavalier {
381753c7e08SAugustin Cavalier 	struct ieee80211_node* ni;
382753c7e08SAugustin Cavalier 	struct mbuf* m;
383753c7e08SAugustin Cavalier 
384753c7e08SAugustin Cavalier 	for (;;) {
385753c7e08SAugustin Cavalier 		IF_DEQUEUE(ifq, m);
386753c7e08SAugustin Cavalier 		if (m == NULL)
387753c7e08SAugustin Cavalier 			break;
388753c7e08SAugustin Cavalier 
389753c7e08SAugustin Cavalier 		ni = (struct ieee80211_node*)m->m_pkthdr.rcvif;
390753c7e08SAugustin Cavalier 		KASSERT(ni != NULL, ("frame w/o node"));
391753c7e08SAugustin Cavalier 		ieee80211_free_node(ni);
392753c7e08SAugustin Cavalier 		m->m_pkthdr.rcvif = NULL;
393753c7e08SAugustin Cavalier 
394753c7e08SAugustin Cavalier 		m_freem(m);
395753c7e08SAugustin Cavalier 	}
396753c7e08SAugustin Cavalier }
397753c7e08SAugustin Cavalier 
398753c7e08SAugustin Cavalier 
399753c7e08SAugustin Cavalier void
ieee80211_flush_ifq(struct ifqueue * ifq,struct ieee80211vap * vap)400753c7e08SAugustin Cavalier ieee80211_flush_ifq(struct ifqueue* ifq, struct ieee80211vap* vap)
401753c7e08SAugustin Cavalier {
402753c7e08SAugustin Cavalier 	struct ieee80211_node* ni;
403753c7e08SAugustin Cavalier 	struct mbuf* m;
404753c7e08SAugustin Cavalier 	struct mbuf** mprev;
405753c7e08SAugustin Cavalier 
406753c7e08SAugustin Cavalier 	IF_LOCK(ifq);
407753c7e08SAugustin Cavalier 	mprev = &ifq->ifq_head;
408753c7e08SAugustin Cavalier 	while ((m = *mprev) != NULL) {
409753c7e08SAugustin Cavalier 		ni = (struct ieee80211_node*)m->m_pkthdr.rcvif;
410753c7e08SAugustin Cavalier 		if (ni != NULL && ni->ni_vap == vap) {
411753c7e08SAugustin Cavalier 			*mprev = m->m_nextpkt;
412753c7e08SAugustin Cavalier 				// remove from list
413753c7e08SAugustin Cavalier 			ifq->ifq_len--;
414753c7e08SAugustin Cavalier 
415753c7e08SAugustin Cavalier 			m_freem(m);
416753c7e08SAugustin Cavalier 			ieee80211_free_node(ni);
417753c7e08SAugustin Cavalier 				// reclaim ref
418753c7e08SAugustin Cavalier 		} else
419753c7e08SAugustin Cavalier 			mprev = &m->m_nextpkt;
420753c7e08SAugustin Cavalier 	}
421753c7e08SAugustin Cavalier 	// recalculate tail ptr
422753c7e08SAugustin Cavalier 	m = ifq->ifq_head;
423753c7e08SAugustin Cavalier 	for (; m != NULL && m->m_nextpkt != NULL; m = m->m_nextpkt);
424753c7e08SAugustin Cavalier 	ifq->ifq_tail = m;
425753c7e08SAugustin Cavalier 	IF_UNLOCK(ifq);
426753c7e08SAugustin Cavalier }
427753c7e08SAugustin Cavalier 
428753c7e08SAugustin Cavalier 
429753c7e08SAugustin Cavalier #ifndef __NO_STRICT_ALIGNMENT
430753c7e08SAugustin Cavalier /*
431753c7e08SAugustin Cavalier  * Re-align the payload in the mbuf.  This is mainly used (right now)
432753c7e08SAugustin Cavalier  * to handle IP header alignment requirements on certain architectures.
433753c7e08SAugustin Cavalier  */
434753c7e08SAugustin Cavalier extern "C" struct mbuf *
ieee80211_realign(struct ieee80211vap * vap,struct mbuf * m,size_t align)435753c7e08SAugustin Cavalier ieee80211_realign(struct ieee80211vap *vap, struct mbuf *m, size_t align)
436753c7e08SAugustin Cavalier {
437753c7e08SAugustin Cavalier 	int pktlen, space;
438753c7e08SAugustin Cavalier 	struct mbuf *n;
439753c7e08SAugustin Cavalier 
440753c7e08SAugustin Cavalier 	pktlen = m->m_pkthdr.len;
441753c7e08SAugustin Cavalier 	space = pktlen + align;
442753c7e08SAugustin Cavalier 	if (space < MINCLSIZE)
443753c7e08SAugustin Cavalier 		n = m_gethdr(M_NOWAIT, MT_DATA);
444753c7e08SAugustin Cavalier 	else {
445753c7e08SAugustin Cavalier 		n = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR,
446753c7e08SAugustin Cavalier 		    space <= MCLBYTES ?     MCLBYTES :
447753c7e08SAugustin Cavalier #if MJUMPAGESIZE != MCLBYTES
448753c7e08SAugustin Cavalier 		    space <= MJUMPAGESIZE ? MJUMPAGESIZE :
449753c7e08SAugustin Cavalier #endif
450753c7e08SAugustin Cavalier 		    space <= MJUM9BYTES ?   MJUM9BYTES : MJUM16BYTES);
451753c7e08SAugustin Cavalier 	}
452753c7e08SAugustin Cavalier 	if (__predict_true(n != NULL)) {
453753c7e08SAugustin Cavalier 		m_move_pkthdr(n, m);
454753c7e08SAugustin Cavalier 		n->m_data = (caddr_t)(ALIGN(n->m_data + align) - align);
455753c7e08SAugustin Cavalier 		m_copydata(m, 0, pktlen, mtod(n, caddr_t));
456753c7e08SAugustin Cavalier 		n->m_len = pktlen;
457753c7e08SAugustin Cavalier 	} else {
458753c7e08SAugustin Cavalier 		IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY,
459753c7e08SAugustin Cavalier 		    mtod(m, const struct ieee80211_frame *), NULL,
460753c7e08SAugustin Cavalier 		    "%s", "no mbuf to realign");
461753c7e08SAugustin Cavalier 		vap->iv_stats.is_rx_badalign++;
462753c7e08SAugustin Cavalier 	}
463753c7e08SAugustin Cavalier 	m_freem(m);
464753c7e08SAugustin Cavalier 	return n;
465753c7e08SAugustin Cavalier }
466753c7e08SAugustin Cavalier #endif /* !__NO_STRICT_ALIGNMENT */
467753c7e08SAugustin Cavalier 
468753c7e08SAugustin Cavalier 
469753c7e08SAugustin Cavalier int
ieee80211_add_callback(struct mbuf * m,void (* func)(struct ieee80211_node *,void *,int),void * arg)470753c7e08SAugustin Cavalier ieee80211_add_callback(struct mbuf* m,
471753c7e08SAugustin Cavalier 	void (*func)(struct ieee80211_node*, void*, int), void* arg)
472753c7e08SAugustin Cavalier {
473753c7e08SAugustin Cavalier 	struct m_tag* mtag;
474753c7e08SAugustin Cavalier 	struct ieee80211_cb* cb;
475753c7e08SAugustin Cavalier 
476753c7e08SAugustin Cavalier 	mtag = m_tag_alloc(MTAG_ABI_NET80211, NET80211_TAG_CALLBACK,
477753c7e08SAugustin Cavalier 		sizeof(struct ieee80211_cb), M_NOWAIT);
478753c7e08SAugustin Cavalier 	if (mtag == NULL)
479753c7e08SAugustin Cavalier 		return 0;
480753c7e08SAugustin Cavalier 
481753c7e08SAugustin Cavalier 	cb = (struct ieee80211_cb*)(mtag+1);
482753c7e08SAugustin Cavalier 	cb->func = func;
483753c7e08SAugustin Cavalier 	cb->arg = arg;
484753c7e08SAugustin Cavalier 	m_tag_prepend(m, mtag);
485753c7e08SAugustin Cavalier 	m->m_flags |= M_TXCB;
486753c7e08SAugustin Cavalier 	return 1;
487753c7e08SAugustin Cavalier }
488753c7e08SAugustin Cavalier 
489753c7e08SAugustin Cavalier 
490753c7e08SAugustin Cavalier void
ieee80211_process_callback(struct ieee80211_node * ni,struct mbuf * m,int status)491753c7e08SAugustin Cavalier ieee80211_process_callback(struct ieee80211_node* ni, struct mbuf* m,
492753c7e08SAugustin Cavalier 	int status)
493753c7e08SAugustin Cavalier {
494753c7e08SAugustin Cavalier 	struct m_tag* mtag;
495753c7e08SAugustin Cavalier 
496753c7e08SAugustin Cavalier 	mtag = m_tag_locate(m, MTAG_ABI_NET80211, NET80211_TAG_CALLBACK, NULL);
497753c7e08SAugustin Cavalier 	if (mtag != NULL) {
498753c7e08SAugustin Cavalier 		struct ieee80211_cb* cb = (struct ieee80211_cb*)(mtag+1);
499753c7e08SAugustin Cavalier 		cb->func(ni, cb->arg, status);
500753c7e08SAugustin Cavalier 	}
501753c7e08SAugustin Cavalier }
502753c7e08SAugustin Cavalier 
503753c7e08SAugustin Cavalier 
504753c7e08SAugustin Cavalier int
ieee80211_add_xmit_params(struct mbuf * m,const struct ieee80211_bpf_params * params)505753c7e08SAugustin Cavalier ieee80211_add_xmit_params(struct mbuf *m,
506753c7e08SAugustin Cavalier 	const struct ieee80211_bpf_params *params)
507753c7e08SAugustin Cavalier {
508753c7e08SAugustin Cavalier 	struct m_tag *mtag;
509753c7e08SAugustin Cavalier 	struct ieee80211_tx_params *tx;
510753c7e08SAugustin Cavalier 
511753c7e08SAugustin Cavalier 	mtag = m_tag_alloc(MTAG_ABI_NET80211, NET80211_TAG_XMIT_PARAMS,
512753c7e08SAugustin Cavalier 		sizeof(struct ieee80211_tx_params), M_NOWAIT);
513753c7e08SAugustin Cavalier 	if (mtag == NULL)
514753c7e08SAugustin Cavalier 		return (0);
515753c7e08SAugustin Cavalier 
516753c7e08SAugustin Cavalier 	tx = (struct ieee80211_tx_params *)(mtag+1);
517753c7e08SAugustin Cavalier 	memcpy(&tx->params, params, sizeof(struct ieee80211_bpf_params));
518753c7e08SAugustin Cavalier 	m_tag_prepend(m, mtag);
519753c7e08SAugustin Cavalier 	return (1);
520753c7e08SAugustin Cavalier }
521753c7e08SAugustin Cavalier 
522753c7e08SAugustin Cavalier 
523753c7e08SAugustin Cavalier int
ieee80211_get_xmit_params(struct mbuf * m,struct ieee80211_bpf_params * params)524753c7e08SAugustin Cavalier ieee80211_get_xmit_params(struct mbuf *m,
525753c7e08SAugustin Cavalier 	struct ieee80211_bpf_params *params)
526753c7e08SAugustin Cavalier {
527753c7e08SAugustin Cavalier 	struct m_tag *mtag;
528753c7e08SAugustin Cavalier 	struct ieee80211_tx_params *tx;
529753c7e08SAugustin Cavalier 
530753c7e08SAugustin Cavalier 	mtag = m_tag_locate(m, MTAG_ABI_NET80211, NET80211_TAG_XMIT_PARAMS,
531753c7e08SAugustin Cavalier 		NULL);
532753c7e08SAugustin Cavalier 	if (mtag == NULL)
533753c7e08SAugustin Cavalier 		return (-1);
534753c7e08SAugustin Cavalier 	tx = (struct ieee80211_tx_params *)(mtag + 1);
535753c7e08SAugustin Cavalier 	memcpy(params, &tx->params, sizeof(struct ieee80211_bpf_params));
536753c7e08SAugustin Cavalier 	return (0);
537753c7e08SAugustin Cavalier }
538753c7e08SAugustin Cavalier 
539753c7e08SAugustin Cavalier 
540753c7e08SAugustin Cavalier /*
541753c7e08SAugustin Cavalier  * Add RX parameters to the given mbuf.
542753c7e08SAugustin Cavalier  *
543753c7e08SAugustin Cavalier  * Returns 1 if OK, 0 on error.
544753c7e08SAugustin Cavalier  */
545753c7e08SAugustin Cavalier int
ieee80211_add_rx_params(struct mbuf * m,const struct ieee80211_rx_stats * rxs)546753c7e08SAugustin Cavalier ieee80211_add_rx_params(struct mbuf *m, const struct ieee80211_rx_stats *rxs)
547753c7e08SAugustin Cavalier {
548753c7e08SAugustin Cavalier 	struct m_tag *mtag;
549753c7e08SAugustin Cavalier 	struct ieee80211_rx_params *rx;
550753c7e08SAugustin Cavalier 
551753c7e08SAugustin Cavalier 	mtag = m_tag_alloc(MTAG_ABI_NET80211, NET80211_TAG_RECV_PARAMS,
552753c7e08SAugustin Cavalier 		sizeof(struct ieee80211_rx_stats), M_NOWAIT);
553753c7e08SAugustin Cavalier 	if (mtag == NULL)
554753c7e08SAugustin Cavalier 		return (0);
555753c7e08SAugustin Cavalier 
556753c7e08SAugustin Cavalier 	rx = (struct ieee80211_rx_params *)(mtag + 1);
557753c7e08SAugustin Cavalier 	memcpy(&rx->params, rxs, sizeof(*rxs));
558753c7e08SAugustin Cavalier 	m_tag_prepend(m, mtag);
559753c7e08SAugustin Cavalier 	return (1);
560753c7e08SAugustin Cavalier }
561753c7e08SAugustin Cavalier 
562753c7e08SAugustin Cavalier 
563753c7e08SAugustin Cavalier int
ieee80211_get_rx_params(struct mbuf * m,struct ieee80211_rx_stats * rxs)564753c7e08SAugustin Cavalier ieee80211_get_rx_params(struct mbuf *m, struct ieee80211_rx_stats *rxs)
565753c7e08SAugustin Cavalier {
566753c7e08SAugustin Cavalier 	struct m_tag *mtag;
567753c7e08SAugustin Cavalier 	struct ieee80211_rx_params *rx;
568753c7e08SAugustin Cavalier 
569753c7e08SAugustin Cavalier 	mtag = m_tag_locate(m, MTAG_ABI_NET80211, NET80211_TAG_RECV_PARAMS,
570753c7e08SAugustin Cavalier 		NULL);
571753c7e08SAugustin Cavalier 	if (mtag == NULL)
572753c7e08SAugustin Cavalier 		return (-1);
573753c7e08SAugustin Cavalier 	rx = (struct ieee80211_rx_params *)(mtag + 1);
574753c7e08SAugustin Cavalier 	memcpy(rxs, &rx->params, sizeof(*rxs));
575753c7e08SAugustin Cavalier 	return (0);
576753c7e08SAugustin Cavalier }
577753c7e08SAugustin Cavalier 
578753c7e08SAugustin Cavalier 
5796d0f2b48SAugustin Cavalier const struct ieee80211_rx_stats *
ieee80211_get_rx_params_ptr(struct mbuf * m)5806d0f2b48SAugustin Cavalier ieee80211_get_rx_params_ptr(struct mbuf *m)
5816d0f2b48SAugustin Cavalier {
5826d0f2b48SAugustin Cavalier 	struct m_tag *mtag;
5836d0f2b48SAugustin Cavalier 	struct ieee80211_rx_params *rx;
5846d0f2b48SAugustin Cavalier 
5856d0f2b48SAugustin Cavalier 	mtag = m_tag_locate(m, MTAG_ABI_NET80211, NET80211_TAG_RECV_PARAMS,
5866d0f2b48SAugustin Cavalier 	    NULL);
5876d0f2b48SAugustin Cavalier 	if (mtag == NULL)
5886d0f2b48SAugustin Cavalier 		return (NULL);
5896d0f2b48SAugustin Cavalier 	rx = (struct ieee80211_rx_params *)(mtag + 1);
5906d0f2b48SAugustin Cavalier 	return (&rx->params);
5916d0f2b48SAugustin Cavalier }
5926d0f2b48SAugustin Cavalier 
5936d0f2b48SAugustin Cavalier 
594753c7e08SAugustin Cavalier /*
595cf552543SAugustin Cavalier  * Add TOA parameters to the given mbuf.
596cf552543SAugustin Cavalier  */
597cf552543SAugustin Cavalier int
ieee80211_add_toa_params(struct mbuf * m,const struct ieee80211_toa_params * p)598cf552543SAugustin Cavalier ieee80211_add_toa_params(struct mbuf *m, const struct ieee80211_toa_params *p)
599cf552543SAugustin Cavalier {
600cf552543SAugustin Cavalier 	struct m_tag *mtag;
601cf552543SAugustin Cavalier 	struct ieee80211_toa_params *rp;
602cf552543SAugustin Cavalier 
603cf552543SAugustin Cavalier 	mtag = m_tag_alloc(MTAG_ABI_NET80211, NET80211_TAG_TOA_PARAMS,
604cf552543SAugustin Cavalier 	    sizeof(struct ieee80211_toa_params), M_NOWAIT);
605cf552543SAugustin Cavalier 	if (mtag == NULL)
606cf552543SAugustin Cavalier 		return (0);
607cf552543SAugustin Cavalier 
608cf552543SAugustin Cavalier 	rp = (struct ieee80211_toa_params *)(mtag + 1);
609cf552543SAugustin Cavalier 	memcpy(rp, p, sizeof(*rp));
610cf552543SAugustin Cavalier 	m_tag_prepend(m, mtag);
611cf552543SAugustin Cavalier 	return (1);
612cf552543SAugustin Cavalier }
613cf552543SAugustin Cavalier 
614cf552543SAugustin Cavalier 
615cf552543SAugustin Cavalier int
ieee80211_get_toa_params(struct mbuf * m,struct ieee80211_toa_params * p)616cf552543SAugustin Cavalier ieee80211_get_toa_params(struct mbuf *m, struct ieee80211_toa_params *p)
617cf552543SAugustin Cavalier {
618cf552543SAugustin Cavalier 	struct m_tag *mtag;
619cf552543SAugustin Cavalier 	struct ieee80211_toa_params *rp;
620cf552543SAugustin Cavalier 
621cf552543SAugustin Cavalier 	mtag = m_tag_locate(m, MTAG_ABI_NET80211, NET80211_TAG_TOA_PARAMS,
622cf552543SAugustin Cavalier 	    NULL);
623cf552543SAugustin Cavalier 	if (mtag == NULL)
624cf552543SAugustin Cavalier 		return (0);
625cf552543SAugustin Cavalier 	rp = (struct ieee80211_toa_params *)(mtag + 1);
626cf552543SAugustin Cavalier 	if (p != NULL)
627cf552543SAugustin Cavalier 		memcpy(p, rp, sizeof(*p));
628cf552543SAugustin Cavalier 	return (1);
629cf552543SAugustin Cavalier }
630cf552543SAugustin Cavalier 
631cf552543SAugustin Cavalier 
632cf552543SAugustin Cavalier /*
633753c7e08SAugustin Cavalier  * Transmit a frame to the parent interface.
634753c7e08SAugustin Cavalier  */
635753c7e08SAugustin Cavalier int
ieee80211_parent_xmitpkt(struct ieee80211com * ic,struct mbuf * m)636753c7e08SAugustin Cavalier ieee80211_parent_xmitpkt(struct ieee80211com *ic, struct mbuf *m)
637753c7e08SAugustin Cavalier {
638753c7e08SAugustin Cavalier 	int error;
639753c7e08SAugustin Cavalier 
640753c7e08SAugustin Cavalier 	/*
641753c7e08SAugustin Cavalier 	 * Assert the IC TX lock is held - this enforces the
642753c7e08SAugustin Cavalier 	 * processing -> queuing order is maintained
643753c7e08SAugustin Cavalier 	 */
644753c7e08SAugustin Cavalier 	IEEE80211_TX_LOCK_ASSERT(ic);
645753c7e08SAugustin Cavalier 	error = ic->ic_transmit(ic, m);
646753c7e08SAugustin Cavalier 	if (error) {
647753c7e08SAugustin Cavalier 		struct ieee80211_node *ni;
648753c7e08SAugustin Cavalier 
649753c7e08SAugustin Cavalier 		ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
650753c7e08SAugustin Cavalier 
651753c7e08SAugustin Cavalier 		/* XXX number of fragments */
652753c7e08SAugustin Cavalier 		if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, 1);
653753c7e08SAugustin Cavalier 		ieee80211_free_node(ni);
654753c7e08SAugustin Cavalier 		ieee80211_free_mbuf(m);
655753c7e08SAugustin Cavalier 	}
656753c7e08SAugustin Cavalier 	return (error);
657753c7e08SAugustin Cavalier }
658753c7e08SAugustin Cavalier 
659753c7e08SAugustin Cavalier 
660753c7e08SAugustin Cavalier /*
6615cad57c4SJérôme Duval  * Fetch the VAP name.
6625cad57c4SJérôme Duval  *
6635cad57c4SJérôme Duval  * This returns a const char pointer suitable for debugging,
6645cad57c4SJérôme Duval  * but don't expect it to stick around for much longer.
6655cad57c4SJérôme Duval  */
6665cad57c4SJérôme Duval const char *
ieee80211_get_vap_ifname(struct ieee80211vap * vap)6675cad57c4SJérôme Duval ieee80211_get_vap_ifname(struct ieee80211vap *vap)
6685cad57c4SJérôme Duval {
6695cad57c4SJérôme Duval 	if (vap->iv_ifp == NULL)
6705cad57c4SJérôme Duval 		return "(none)";
6715cad57c4SJérôme Duval 	return vap->iv_ifp->if_xname;
6725cad57c4SJérôme Duval }
6735cad57c4SJérôme Duval 
6745cad57c4SJérôme Duval #ifdef DEBUGNET
6755cad57c4SJérôme Duval static void
ieee80211_debugnet_init(struct ifnet * ifp,int * nrxr,int * ncl,int * clsize)6765cad57c4SJérôme Duval ieee80211_debugnet_init(struct ifnet *ifp, int *nrxr, int *ncl, int *clsize)
6775cad57c4SJérôme Duval {
6785cad57c4SJérôme Duval 	struct ieee80211vap *vap;
6795cad57c4SJérôme Duval 	struct ieee80211com *ic;
6805cad57c4SJérôme Duval 
6815cad57c4SJérôme Duval 	vap = if_getsoftc(ifp);
6825cad57c4SJérôme Duval 	ic = vap->iv_ic;
6835cad57c4SJérôme Duval 
6845cad57c4SJérôme Duval 	IEEE80211_LOCK(ic);
6855cad57c4SJérôme Duval 	ic->ic_debugnet_meth->dn8_init(ic, nrxr, ncl, clsize);
6865cad57c4SJérôme Duval 	IEEE80211_UNLOCK(ic);
6875cad57c4SJérôme Duval }
6885cad57c4SJérôme Duval 
6895cad57c4SJérôme Duval static void
ieee80211_debugnet_event(struct ifnet * ifp,enum debugnet_ev ev)6905cad57c4SJérôme Duval ieee80211_debugnet_event(struct ifnet *ifp, enum debugnet_ev ev)
6915cad57c4SJérôme Duval {
6925cad57c4SJérôme Duval 	struct ieee80211vap *vap;
6935cad57c4SJérôme Duval 	struct ieee80211com *ic;
6945cad57c4SJérôme Duval 
6955cad57c4SJérôme Duval 	vap = if_getsoftc(ifp);
6965cad57c4SJérôme Duval 	ic = vap->iv_ic;
6975cad57c4SJérôme Duval 
6985cad57c4SJérôme Duval 	IEEE80211_LOCK(ic);
6995cad57c4SJérôme Duval 	ic->ic_debugnet_meth->dn8_event(ic, ev);
7005cad57c4SJérôme Duval 	IEEE80211_UNLOCK(ic);
7015cad57c4SJérôme Duval }
7025cad57c4SJérôme Duval 
7035cad57c4SJérôme Duval static int
ieee80211_debugnet_transmit(struct ifnet * ifp,struct mbuf * m)7045cad57c4SJérôme Duval ieee80211_debugnet_transmit(struct ifnet *ifp, struct mbuf *m)
7055cad57c4SJérôme Duval {
7065cad57c4SJérôme Duval 	return (ieee80211_vap_transmit(ifp, m));
7075cad57c4SJérôme Duval }
7085cad57c4SJérôme Duval 
7095cad57c4SJérôme Duval static int
ieee80211_debugnet_poll(struct ifnet * ifp,int count)7105cad57c4SJérôme Duval ieee80211_debugnet_poll(struct ifnet *ifp, int count)
7115cad57c4SJérôme Duval {
7125cad57c4SJérôme Duval 	struct ieee80211vap *vap;
7135cad57c4SJérôme Duval 	struct ieee80211com *ic;
7145cad57c4SJérôme Duval 
7155cad57c4SJérôme Duval 	vap = if_getsoftc(ifp);
7165cad57c4SJérôme Duval 	ic = vap->iv_ic;
7175cad57c4SJérôme Duval 
7185cad57c4SJérôme Duval 	return (ic->ic_debugnet_meth->dn8_poll(ic, count));
7195cad57c4SJérôme Duval }
7205cad57c4SJérôme Duval #endif
7215cad57c4SJérôme Duval 
7225cad57c4SJérôme Duval /*
723753c7e08SAugustin Cavalier  * Transmit a frame to the VAP interface.
724753c7e08SAugustin Cavalier  */
725753c7e08SAugustin Cavalier int
ieee80211_vap_xmitpkt(struct ieee80211vap * vap,struct mbuf * m)726753c7e08SAugustin Cavalier ieee80211_vap_xmitpkt(struct ieee80211vap *vap, struct mbuf *m)
727753c7e08SAugustin Cavalier {
728753c7e08SAugustin Cavalier 	struct ifnet *ifp = vap->iv_ifp;
729753c7e08SAugustin Cavalier 
730753c7e08SAugustin Cavalier 	/*
731753c7e08SAugustin Cavalier 	 * When transmitting via the VAP, we shouldn't hold
732753c7e08SAugustin Cavalier 	 * any IC TX lock as the VAP TX path will acquire it.
733753c7e08SAugustin Cavalier 	 */
734753c7e08SAugustin Cavalier 	IEEE80211_TX_UNLOCK_ASSERT(vap->iv_ic);
735753c7e08SAugustin Cavalier 
736753c7e08SAugustin Cavalier 	return (ifp->if_transmit(ifp, m));
737753c7e08SAugustin Cavalier 
738753c7e08SAugustin Cavalier }
739753c7e08SAugustin Cavalier 
740753c7e08SAugustin Cavalier 
741753c7e08SAugustin Cavalier void
ieee80211_sysctl_vattach(struct ieee80211vap * vap)742753c7e08SAugustin Cavalier ieee80211_sysctl_vattach(struct ieee80211vap* vap)
743753c7e08SAugustin Cavalier {
744753c7e08SAugustin Cavalier 	vap->iv_debug = IEEE80211_MSG_XRATE
745753c7e08SAugustin Cavalier 		| IEEE80211_MSG_NODE
746753c7e08SAugustin Cavalier 		| IEEE80211_MSG_ASSOC
747753c7e08SAugustin Cavalier 		| IEEE80211_MSG_AUTH
748753c7e08SAugustin Cavalier 		| IEEE80211_MSG_STATE
749753c7e08SAugustin Cavalier 		| IEEE80211_MSG_WME
750753c7e08SAugustin Cavalier 		| IEEE80211_MSG_DOTH
751753c7e08SAugustin Cavalier 		| IEEE80211_MSG_INACT
752753c7e08SAugustin Cavalier 		| IEEE80211_MSG_ROAM;
753753c7e08SAugustin Cavalier }
754753c7e08SAugustin Cavalier 
755753c7e08SAugustin Cavalier 
756753c7e08SAugustin Cavalier void
ieee80211_sysctl_vdetach(struct ieee80211vap * vap)757753c7e08SAugustin Cavalier ieee80211_sysctl_vdetach(struct ieee80211vap* vap)
758753c7e08SAugustin Cavalier {
759753c7e08SAugustin Cavalier 	dprintf("%s not implemented, yet.\n", __func__);
760753c7e08SAugustin Cavalier }
761753c7e08SAugustin Cavalier 
762753c7e08SAugustin Cavalier 
763753c7e08SAugustin Cavalier void
ieee80211_vap_destroy(struct ieee80211vap * vap)764753c7e08SAugustin Cavalier ieee80211_vap_destroy(struct ieee80211vap* vap)
765753c7e08SAugustin Cavalier {
766753c7e08SAugustin Cavalier 	struct ieee80211com* ic = vap->iv_ic;
767753c7e08SAugustin Cavalier 
768753c7e08SAugustin Cavalier 	ic->ic_vap_delete(vap);
769753c7e08SAugustin Cavalier 	dprintf("%s: done.\n", __func__);
770753c7e08SAugustin Cavalier }
771753c7e08SAugustin Cavalier 
772753c7e08SAugustin Cavalier 
773753c7e08SAugustin Cavalier void
ieee80211_load_module(const char * modname)774753c7e08SAugustin Cavalier ieee80211_load_module(const char* modname)
775753c7e08SAugustin Cavalier {
7766d0f2b48SAugustin Cavalier #if 0
777753c7e08SAugustin Cavalier 	dprintf("%s not implemented, yet: modname %s\n", __func__, modname);
7786d0f2b48SAugustin Cavalier #endif
779753c7e08SAugustin Cavalier }
780753c7e08SAugustin Cavalier 
781753c7e08SAugustin Cavalier 
782753c7e08SAugustin Cavalier void
ieee80211_notify_node_join(struct ieee80211_node * ni,int newassoc)783753c7e08SAugustin Cavalier ieee80211_notify_node_join(struct ieee80211_node* ni, int newassoc)
784753c7e08SAugustin Cavalier {
785753c7e08SAugustin Cavalier 	struct ieee80211vap* vap = ni->ni_vap;
786753c7e08SAugustin Cavalier 	struct ifnet* ifp = vap->iv_ifp;
787753c7e08SAugustin Cavalier 
7886d0f2b48SAugustin Cavalier 	TRACE("%s\n", __FUNCTION__);
7896d0f2b48SAugustin Cavalier 
790753c7e08SAugustin Cavalier 	if (ni == vap->iv_bss)
791753c7e08SAugustin Cavalier 		if_link_state_change(ifp, LINK_STATE_UP);
792753c7e08SAugustin Cavalier 
793753c7e08SAugustin Cavalier 	if (sNotificationModule != NULL) {
794753c7e08SAugustin Cavalier 		char messageBuffer[512];
795753c7e08SAugustin Cavalier 		KMessage message;
796753c7e08SAugustin Cavalier 		message.SetTo(messageBuffer, sizeof(messageBuffer), B_NETWORK_MONITOR);
797753c7e08SAugustin Cavalier 		message.AddInt32("opcode", B_NETWORK_WLAN_JOINED);
798753c7e08SAugustin Cavalier 		message.AddString("interface", ifp->device_name);
799753c7e08SAugustin Cavalier 		// TODO: add data about the node
800753c7e08SAugustin Cavalier 
801753c7e08SAugustin Cavalier 		sNotificationModule->send_notification(&message);
802753c7e08SAugustin Cavalier 	}
803753c7e08SAugustin Cavalier }
804753c7e08SAugustin Cavalier 
805753c7e08SAugustin Cavalier 
806753c7e08SAugustin Cavalier void
ieee80211_notify_node_leave(struct ieee80211_node * ni)807753c7e08SAugustin Cavalier ieee80211_notify_node_leave(struct ieee80211_node* ni)
808753c7e08SAugustin Cavalier {
809753c7e08SAugustin Cavalier 	struct ieee80211vap* vap = ni->ni_vap;
810753c7e08SAugustin Cavalier 	struct ifnet* ifp = vap->iv_ifp;
811753c7e08SAugustin Cavalier 
812753c7e08SAugustin Cavalier 	if (ni == vap->iv_bss)
813753c7e08SAugustin Cavalier 		if_link_state_change(ifp, LINK_STATE_DOWN);
814753c7e08SAugustin Cavalier 
815753c7e08SAugustin Cavalier 	TRACE("%s\n", __FUNCTION__);
816753c7e08SAugustin Cavalier 
817753c7e08SAugustin Cavalier 	if (sNotificationModule != NULL) {
818753c7e08SAugustin Cavalier 		char messageBuffer[512];
819753c7e08SAugustin Cavalier 		KMessage message;
820753c7e08SAugustin Cavalier 		message.SetTo(messageBuffer, sizeof(messageBuffer), B_NETWORK_MONITOR);
821753c7e08SAugustin Cavalier 		message.AddInt32("opcode", B_NETWORK_WLAN_LEFT);
822753c7e08SAugustin Cavalier 		message.AddString("interface", ifp->device_name);
823753c7e08SAugustin Cavalier 		// TODO: add data about the node
824753c7e08SAugustin Cavalier 
825753c7e08SAugustin Cavalier 		sNotificationModule->send_notification(&message);
826753c7e08SAugustin Cavalier 	}
827753c7e08SAugustin Cavalier }
828753c7e08SAugustin Cavalier 
829753c7e08SAugustin Cavalier 
830753c7e08SAugustin Cavalier void
ieee80211_notify_scan_done(struct ieee80211vap * vap)831753c7e08SAugustin Cavalier ieee80211_notify_scan_done(struct ieee80211vap* vap)
832753c7e08SAugustin Cavalier {
833753c7e08SAugustin Cavalier 	release_sem_etc(vap->iv_ifp->scan_done_sem, 1,
834753c7e08SAugustin Cavalier 		B_DO_NOT_RESCHEDULE | B_RELEASE_ALL);
835753c7e08SAugustin Cavalier 
836753c7e08SAugustin Cavalier 	TRACE("%s\n", __FUNCTION__);
837753c7e08SAugustin Cavalier 
838753c7e08SAugustin Cavalier 	if (sNotificationModule != NULL) {
839753c7e08SAugustin Cavalier 		char messageBuffer[512];
840753c7e08SAugustin Cavalier 		KMessage message;
841753c7e08SAugustin Cavalier 		message.SetTo(messageBuffer, sizeof(messageBuffer), B_NETWORK_MONITOR);
842753c7e08SAugustin Cavalier 		message.AddInt32("opcode", B_NETWORK_WLAN_SCANNED);
843753c7e08SAugustin Cavalier 		message.AddString("interface", vap->iv_ifp->device_name);
844753c7e08SAugustin Cavalier 
845753c7e08SAugustin Cavalier 		sNotificationModule->send_notification(&message);
846753c7e08SAugustin Cavalier 	}
847753c7e08SAugustin Cavalier }
848753c7e08SAugustin Cavalier 
849753c7e08SAugustin Cavalier 
850753c7e08SAugustin Cavalier void
ieee80211_notify_replay_failure(struct ieee80211vap * vap,const struct ieee80211_frame * wh,const struct ieee80211_key * k,u_int64_t rsc,int tid)851753c7e08SAugustin Cavalier ieee80211_notify_replay_failure(struct ieee80211vap* vap,
852753c7e08SAugustin Cavalier 	const struct ieee80211_frame* wh, const struct ieee80211_key* k,
853753c7e08SAugustin Cavalier 	u_int64_t rsc, int tid)
854753c7e08SAugustin Cavalier {
855753c7e08SAugustin Cavalier 	dprintf("%s not implemented, yet.\n", __func__);
856753c7e08SAugustin Cavalier }
857753c7e08SAugustin Cavalier 
858753c7e08SAugustin Cavalier 
859753c7e08SAugustin Cavalier void
ieee80211_notify_michael_failure(struct ieee80211vap * vap,const struct ieee80211_frame * wh,u_int keyix)860753c7e08SAugustin Cavalier ieee80211_notify_michael_failure(struct ieee80211vap* vap,
861753c7e08SAugustin Cavalier 	const struct ieee80211_frame* wh, u_int keyix)
862753c7e08SAugustin Cavalier {
863753c7e08SAugustin Cavalier 	dprintf("%s not implemented, yet.\n", __func__);
864753c7e08SAugustin Cavalier }
865753c7e08SAugustin Cavalier 
866753c7e08SAugustin Cavalier 
867753c7e08SAugustin Cavalier void
ieee80211_notify_wds_discover(struct ieee80211_node * ni)868753c7e08SAugustin Cavalier ieee80211_notify_wds_discover(struct ieee80211_node* ni)
869753c7e08SAugustin Cavalier {
870753c7e08SAugustin Cavalier 	dprintf("%s not implemented, yet.\n", __func__);
871753c7e08SAugustin Cavalier }
872753c7e08SAugustin Cavalier 
873753c7e08SAugustin Cavalier 
874753c7e08SAugustin Cavalier void
ieee80211_notify_csa(struct ieee80211com * ic,const struct ieee80211_channel * c,int mode,int count)875753c7e08SAugustin Cavalier ieee80211_notify_csa(struct ieee80211com* ic,
876753c7e08SAugustin Cavalier 	const struct ieee80211_channel* c, int mode, int count)
877753c7e08SAugustin Cavalier {
878753c7e08SAugustin Cavalier 	dprintf("%s not implemented, yet.\n", __func__);
879753c7e08SAugustin Cavalier }
880753c7e08SAugustin Cavalier 
881753c7e08SAugustin Cavalier 
882753c7e08SAugustin Cavalier void
ieee80211_notify_radar(struct ieee80211com * ic,const struct ieee80211_channel * c)883753c7e08SAugustin Cavalier ieee80211_notify_radar(struct ieee80211com* ic,
884753c7e08SAugustin Cavalier 	const struct ieee80211_channel* c)
885753c7e08SAugustin Cavalier {
886753c7e08SAugustin Cavalier 	dprintf("%s not implemented, yet.\n", __func__);
887753c7e08SAugustin Cavalier }
888753c7e08SAugustin Cavalier 
889753c7e08SAugustin Cavalier 
890753c7e08SAugustin Cavalier void
ieee80211_notify_cac(struct ieee80211com * ic,const struct ieee80211_channel * c,enum ieee80211_notify_cac_event type)891753c7e08SAugustin Cavalier ieee80211_notify_cac(struct ieee80211com* ic,
892753c7e08SAugustin Cavalier 	const struct ieee80211_channel* c, enum ieee80211_notify_cac_event type)
893753c7e08SAugustin Cavalier {
894753c7e08SAugustin Cavalier 	dprintf("%s not implemented, yet.\n", __func__);
895753c7e08SAugustin Cavalier }
896753c7e08SAugustin Cavalier 
897753c7e08SAugustin Cavalier 
898753c7e08SAugustin Cavalier void
ieee80211_notify_node_deauth(struct ieee80211_node * ni)899753c7e08SAugustin Cavalier ieee80211_notify_node_deauth(struct ieee80211_node* ni)
900753c7e08SAugustin Cavalier {
901753c7e08SAugustin Cavalier 	dprintf("%s not implemented, yet.\n", __func__);
902753c7e08SAugustin Cavalier }
903753c7e08SAugustin Cavalier 
904753c7e08SAugustin Cavalier 
905753c7e08SAugustin Cavalier void
ieee80211_notify_node_auth(struct ieee80211_node * ni)906753c7e08SAugustin Cavalier ieee80211_notify_node_auth(struct ieee80211_node* ni)
907753c7e08SAugustin Cavalier {
908753c7e08SAugustin Cavalier 	dprintf("%s not implemented, yet.\n", __func__);
909753c7e08SAugustin Cavalier }
910753c7e08SAugustin Cavalier 
911753c7e08SAugustin Cavalier 
912753c7e08SAugustin Cavalier void
ieee80211_notify_country(struct ieee80211vap * vap,const uint8_t bssid[IEEE80211_ADDR_LEN],const uint8_t cc[2])913753c7e08SAugustin Cavalier ieee80211_notify_country(struct ieee80211vap* vap,
914753c7e08SAugustin Cavalier 	const uint8_t bssid[IEEE80211_ADDR_LEN], const uint8_t cc[2])
915753c7e08SAugustin Cavalier {
916753c7e08SAugustin Cavalier 	dprintf("%s not implemented, yet.\n", __func__);
917753c7e08SAugustin Cavalier }
918753c7e08SAugustin Cavalier 
919753c7e08SAugustin Cavalier 
920753c7e08SAugustin Cavalier void
ieee80211_notify_radio(struct ieee80211com * ic,int state)921753c7e08SAugustin Cavalier ieee80211_notify_radio(struct ieee80211com* ic, int state)
922753c7e08SAugustin Cavalier {
923753c7e08SAugustin Cavalier 	dprintf("%s not implemented, yet.\n", __func__);
924753c7e08SAugustin Cavalier }
925753c7e08SAugustin Cavalier 
926753c7e08SAugustin Cavalier 
927*86021fd4SAugustin Cavalier extern "C" void
ieee80211_notify_ifnet_change(struct ieee80211vap * vap,int if_flags_mask)928*86021fd4SAugustin Cavalier ieee80211_notify_ifnet_change(struct ieee80211vap *vap, int if_flags_mask)
9295cad57c4SJérôme Duval {
9305cad57c4SJérôme Duval 	dprintf("%s not implemented, yet.\n", __func__);
9315cad57c4SJérôme Duval }
9325cad57c4SJérôme Duval 
9335cad57c4SJérôme Duval 
9345cad57c4SJérôme Duval void
ieee80211_sysctl_attach(struct ieee80211com * ic)935753c7e08SAugustin Cavalier ieee80211_sysctl_attach(struct ieee80211com* ic)
936753c7e08SAugustin Cavalier {
937753c7e08SAugustin Cavalier 	dprintf("%s not implemented, yet.\n", __func__);
938753c7e08SAugustin Cavalier }
939753c7e08SAugustin Cavalier 
940753c7e08SAugustin Cavalier 
941753c7e08SAugustin Cavalier void
ieee80211_sysctl_detach(struct ieee80211com * ic)942753c7e08SAugustin Cavalier ieee80211_sysctl_detach(struct ieee80211com* ic)
943753c7e08SAugustin Cavalier {
944753c7e08SAugustin Cavalier 	dprintf("%s not implemented, yet.\n", __func__);
945753c7e08SAugustin Cavalier }
946