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