1 /*
2 * Copyright 2009, Colin Günther, coling@gmx.de. All rights reserved.
3 * Copyright 2018-2024, Haiku, Inc. All rights reserved.
4 * Distributed under the terms of the MIT License.
5 */
6
7
8 /*-
9 * Copyright (c) 2003-2009 Sam Leffler, Errno Consulting
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33
34 /*
35 * IEEE 802.11 support (Haiku-specific code)
36 */
37
38
39 #include "ieee80211_haiku.h"
40
41 extern "C" {
42 # include <sys/kernel.h>
43 # include <sys/mbuf.h>
44 # include <sys/bus.h>
45 # include <sys/sockio.h>
46
47 # include <net/if.h>
48 # include <net/if_media.h>
49 # include <net/if_types.h>
50 # include <net/if_var.h>
51
52 # include "ieee80211_var.h"
53 };
54
55 #include <SupportDefs.h>
56
57 #include <util/KMessage.h>
58
59 #include <ether_driver.h>
60 #include <net_notifications.h>
61
62 #include <shared.h>
63
64
65 #define TRACE_WLAN
66 #ifdef TRACE_WLAN
67 # define TRACE(x...) dprintf(x);
68 #else
69 # define TRACE(x...) ;
70 #endif
71
72
73 #define MC_ALIGN(m, len) \
74 do { \
75 (m)->m_data += (MCLBYTES - (len)) &~ (sizeof(long) - 1);\
76 } while (/* CONSTCOND */ 0)
77
78
79 static net_notifications_module_info* sNotificationModule;
80
81
82 /*
83 * priv(9) NET80211 checks.
84 * Return 0 if operation is allowed, E* (usually EPERM) otherwise.
85 */
86 int
ieee80211_priv_check_vap_getkey(u_long cmd __unused,struct ieee80211vap * vap __unused,struct ifnet * ifp __unused)87 ieee80211_priv_check_vap_getkey(u_long cmd __unused,
88 struct ieee80211vap *vap __unused, struct ifnet *ifp __unused)
89 {
90 return 0;
91 }
92
93 int
ieee80211_priv_check_vap_manage(u_long cmd __unused,struct ieee80211vap * vap __unused,struct ifnet * ifp __unused)94 ieee80211_priv_check_vap_manage(u_long cmd __unused,
95 struct ieee80211vap *vap __unused, struct ifnet *ifp __unused)
96 {
97 return 0;
98 }
99
100 int
ieee80211_priv_check_vap_setmac(u_long cmd __unused,struct ieee80211vap * vap __unused,struct ifnet * ifp __unused)101 ieee80211_priv_check_vap_setmac(u_long cmd __unused,
102 struct ieee80211vap *vap __unused, struct ifnet *ifp __unused)
103 {
104 return 0;
105 }
106
107 int
ieee80211_priv_check_create_vap(u_long cmd __unused,struct ieee80211vap * vap __unused,struct ifnet * ifp __unused)108 ieee80211_priv_check_create_vap(u_long cmd __unused,
109 struct ieee80211vap *vap __unused, struct ifnet *ifp __unused)
110 {
111 return 0;
112 }
113
114
115 static struct ifnet*
get_ifnet(device_t device,int & i)116 get_ifnet(device_t device, int& i)
117 {
118 int unit = device_get_unit(device);
119
120 for (i = 0; i < MAX_DEVICES; i++) {
121 if (gDevices[i] != NULL && gDevices[i]->if_dunit == unit)
122 return gDevices[i];
123 }
124
125 return NULL;
126 }
127
128
129 status_t
init_wlan_stack(void)130 init_wlan_stack(void)
131 {
132 get_module(NET_NOTIFICATIONS_MODULE_NAME,
133 (module_info**)&sNotificationModule);
134
135 return B_OK;
136 }
137
138
139 void
uninit_wlan_stack(void)140 uninit_wlan_stack(void)
141 {
142 if (sNotificationModule != NULL)
143 put_module(NET_NOTIFICATIONS_MODULE_NAME);
144 }
145
146
147 status_t
start_wlan(device_t device)148 start_wlan(device_t device)
149 {
150 struct ieee80211com* ic = ieee80211_find_com(device->nameunit);
151 if (ic == NULL)
152 return B_BAD_VALUE;
153
154 struct ieee80211vap* vap = ic->ic_vap_create(ic, "wlan",
155 device_get_unit(device),
156 IEEE80211_M_STA, // mode
157 0, // flags
158 NULL, // BSSID
159 ic->ic_macaddr); // MAC address
160
161 if (vap == NULL)
162 return B_ERROR;
163
164 // ic_vap_create() established that gDevices[i] links to vap->iv_ifp now
165 KASSERT(gDevices[gDeviceCount - 1] == vap->iv_ifp,
166 ("start_wlan: gDevices[i] != vap->iv_ifp"));
167
168 vap->iv_ifp->scan_done_sem = create_sem(0, "wlan scan done");
169
170 // We aren't connected to a WLAN, yet.
171 if_link_state_change(vap->iv_ifp, LINK_STATE_DOWN);
172
173 dprintf("%s: wlan started.\n", __func__);
174
175 return B_OK;
176 }
177
178
179 status_t
stop_wlan(device_t device)180 stop_wlan(device_t device)
181 {
182 int i;
183 struct ifnet* ifp = get_ifnet(device, i);
184 if (ifp == NULL)
185 return B_BAD_VALUE;
186
187 delete_sem(ifp->scan_done_sem);
188
189 struct ieee80211vap* vap = (ieee80211vap*)ifp->if_softc;
190 struct ieee80211com* ic = vap->iv_ic;
191
192 ic->ic_vap_delete(vap);
193
194 // ic_vap_delete freed gDevices[i]
195 KASSERT(gDevices[i] == NULL, ("stop_wlan: gDevices[i] != NULL"));
196
197 return B_OK;
198 }
199
200
201 status_t
wlan_open(void * cookie)202 wlan_open(void* cookie)
203 {
204 dprintf("wlan_open(%p)\n", cookie);
205 struct ifnet* ifp = (struct ifnet*)cookie;
206
207 ifp->if_init(ifp->if_softc);
208
209 ifp->if_flags |= IFF_UP;
210 ifp->if_ioctl(ifp, SIOCSIFFLAGS, NULL);
211
212 return B_OK;
213 }
214
215
216 status_t
wlan_close(void * cookie)217 wlan_close(void* cookie)
218 {
219 dprintf("wlan_close(%p)\n", cookie);
220 struct ifnet* ifp = (struct ifnet*)cookie;
221
222 ifp->if_flags &= ~IFF_UP;
223 ifp->if_ioctl(ifp, SIOCSIFFLAGS, NULL);
224
225 return release_sem_etc(ifp->scan_done_sem, 1, B_RELEASE_ALL);
226 }
227
228
229 status_t
wlan_control(void * cookie,uint32 op,void * arg,size_t length)230 wlan_control(void* cookie, uint32 op, void* arg, size_t length)
231 {
232 struct ifnet* ifp = (struct ifnet*)cookie;
233
234 switch (op) {
235 case SIOCG80211:
236 case SIOCS80211:
237 {
238 // FreeBSD drivers assume that the request structure has already
239 // been copied into kernel space
240 struct ieee80211req request;
241 if (user_memcpy(&request, arg, sizeof(struct ieee80211req)) != B_OK)
242 return B_BAD_ADDRESS;
243
244 if (request.i_type == IEEE80211_IOC_HAIKU_COMPAT_WLAN_UP)
245 return wlan_open(cookie);
246 else if (request.i_type == IEEE80211_IOC_HAIKU_COMPAT_WLAN_DOWN)
247 return wlan_close(cookie);
248
249 TRACE("wlan_control: %" B_PRIu32 ", %d\n", op, request.i_type);
250 status_t status = ifp->if_ioctl(ifp, op, (caddr_t)&request);
251 if (status != B_OK)
252 return status;
253
254 if (op == SIOCG80211 && user_memcpy(arg, &request,
255 sizeof(struct ieee80211req)) != B_OK)
256 return B_BAD_ADDRESS;
257 return B_OK;
258 }
259 }
260
261 return B_BAD_VALUE;
262 }
263
264
265 void
net80211_get_random_bytes(void * p,size_t n)266 net80211_get_random_bytes(void* p, size_t n)
267 {
268 uint8_t* dp = (uint8_t*)p;
269
270 while (n > 0) {
271 uint32_t v = arc4random();
272 size_t nb = n > sizeof(uint32_t) ? sizeof(uint32_t) : n;
273 bcopy(&v, dp, n > sizeof(uint32_t) ? sizeof(uint32_t) : n);
274 dp += sizeof(uint32_t), n -= nb;
275 }
276 }
277
278
279 struct mbuf *
ieee80211_getmgtframe(uint8_t ** frm,int headroom,int pktlen)280 ieee80211_getmgtframe(uint8_t **frm, int headroom, int pktlen)
281 {
282 struct mbuf *m;
283 u_int len;
284
285 /*
286 * NB: we know the mbuf routines will align the data area
287 * so we don't need to do anything special.
288 */
289 len = roundup2(headroom + pktlen, 4);
290 KASSERT(len <= MCLBYTES, ("802.11 mgt frame too large: %u", len));
291 if (len < MINCLSIZE) {
292 m = m_gethdr(M_NOWAIT, MT_DATA);
293 /*
294 * Align the data in case additional headers are added.
295 * This should only happen when a WEP header is added
296 * which only happens for shared key authentication mgt
297 * frames which all fit in MHLEN.
298 */
299 if (m != NULL)
300 M_ALIGN(m, len);
301 } else {
302 m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
303 if (m != NULL)
304 MC_ALIGN(m, len);
305 }
306 if (m != NULL) {
307 m->m_data += headroom;
308 *frm = (uint8_t*)m->m_data;
309 }
310 return m;
311 }
312
313
314 int
ieee80211_com_vincref(struct ieee80211vap * vap)315 ieee80211_com_vincref(struct ieee80211vap *vap)
316 {
317 uint32_t ostate;
318
319 ostate = atomic_fetchadd_32(&vap->iv_com_state, IEEE80211_COM_REF_ADD);
320
321 if (ostate & IEEE80211_COM_DETACHED) {
322 atomic_subtract_32(&vap->iv_com_state, IEEE80211_COM_REF_ADD);
323 return (ENETDOWN);
324 }
325
326 if (_IEEE80211_MASKSHIFT(ostate, IEEE80211_COM_REF) ==
327 IEEE80211_COM_REF_MAX) {
328 atomic_subtract_32(&vap->iv_com_state, IEEE80211_COM_REF_ADD);
329 return (EOVERFLOW);
330 }
331
332 return (0);
333 }
334
335
336 void
ieee80211_com_vdecref(struct ieee80211vap * vap)337 ieee80211_com_vdecref(struct ieee80211vap *vap)
338 {
339 uint32_t ostate;
340
341 ostate = atomic_fetchadd_32(&vap->iv_com_state, -IEEE80211_COM_REF_ADD);
342
343 KASSERT(_IEEE80211_MASKSHIFT(ostate, IEEE80211_COM_REF) != 0,
344 ("com reference counter underflow"));
345
346 (void) ostate;
347 }
348
349
350 void
ieee80211_com_vdetach(struct ieee80211vap * vap)351 ieee80211_com_vdetach(struct ieee80211vap *vap)
352 {
353 int sleep_time;
354
355 sleep_time = msecs_to_ticks(250);
356 atomic_set_32(&vap->iv_com_state, IEEE80211_COM_DETACHED);
357 while (_IEEE80211_MASKSHIFT(atomic_load_32(&vap->iv_com_state),
358 IEEE80211_COM_REF) != 0)
359 pause("comref", sleep_time);
360 }
361
362
363 /*
364 * Decrements the reference-counter and
365 * tests whether it became zero. If so, sets it to one.
366 *
367 * @return 1 reference-counter became zero
368 * @return 0 reference-counter didn't became zero
369 */
370 int
ieee80211_node_dectestref(struct ieee80211_node * ni)371 ieee80211_node_dectestref(struct ieee80211_node* ni)
372 {
373 atomic_subtract_int(&ni->ni_refcnt, 1);
374 return atomic_cmpset_int(&ni->ni_refcnt, 0, 1);
375 }
376
377
378 void
ieee80211_drain_ifq(struct ifqueue * ifq)379 ieee80211_drain_ifq(struct ifqueue* ifq)
380 {
381 struct ieee80211_node* ni;
382 struct mbuf* m;
383
384 for (;;) {
385 IF_DEQUEUE(ifq, m);
386 if (m == NULL)
387 break;
388
389 ni = (struct ieee80211_node*)m->m_pkthdr.rcvif;
390 KASSERT(ni != NULL, ("frame w/o node"));
391 ieee80211_free_node(ni);
392 m->m_pkthdr.rcvif = NULL;
393
394 m_freem(m);
395 }
396 }
397
398
399 void
ieee80211_flush_ifq(struct ifqueue * ifq,struct ieee80211vap * vap)400 ieee80211_flush_ifq(struct ifqueue* ifq, struct ieee80211vap* vap)
401 {
402 struct ieee80211_node* ni;
403 struct mbuf* m;
404 struct mbuf** mprev;
405
406 IF_LOCK(ifq);
407 mprev = &ifq->ifq_head;
408 while ((m = *mprev) != NULL) {
409 ni = (struct ieee80211_node*)m->m_pkthdr.rcvif;
410 if (ni != NULL && ni->ni_vap == vap) {
411 *mprev = m->m_nextpkt;
412 // remove from list
413 ifq->ifq_len--;
414
415 m_freem(m);
416 ieee80211_free_node(ni);
417 // reclaim ref
418 } else
419 mprev = &m->m_nextpkt;
420 }
421 // recalculate tail ptr
422 m = ifq->ifq_head;
423 for (; m != NULL && m->m_nextpkt != NULL; m = m->m_nextpkt);
424 ifq->ifq_tail = m;
425 IF_UNLOCK(ifq);
426 }
427
428
429 #ifndef __NO_STRICT_ALIGNMENT
430 /*
431 * Re-align the payload in the mbuf. This is mainly used (right now)
432 * to handle IP header alignment requirements on certain architectures.
433 */
434 extern "C" struct mbuf *
ieee80211_realign(struct ieee80211vap * vap,struct mbuf * m,size_t align)435 ieee80211_realign(struct ieee80211vap *vap, struct mbuf *m, size_t align)
436 {
437 int pktlen, space;
438 struct mbuf *n;
439
440 pktlen = m->m_pkthdr.len;
441 space = pktlen + align;
442 if (space < MINCLSIZE)
443 n = m_gethdr(M_NOWAIT, MT_DATA);
444 else {
445 n = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR,
446 space <= MCLBYTES ? MCLBYTES :
447 #if MJUMPAGESIZE != MCLBYTES
448 space <= MJUMPAGESIZE ? MJUMPAGESIZE :
449 #endif
450 space <= MJUM9BYTES ? MJUM9BYTES : MJUM16BYTES);
451 }
452 if (__predict_true(n != NULL)) {
453 m_move_pkthdr(n, m);
454 n->m_data = (caddr_t)(ALIGN(n->m_data + align) - align);
455 m_copydata(m, 0, pktlen, mtod(n, caddr_t));
456 n->m_len = pktlen;
457 } else {
458 IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY,
459 mtod(m, const struct ieee80211_frame *), NULL,
460 "%s", "no mbuf to realign");
461 vap->iv_stats.is_rx_badalign++;
462 }
463 m_freem(m);
464 return n;
465 }
466 #endif /* !__NO_STRICT_ALIGNMENT */
467
468
469 int
ieee80211_add_callback(struct mbuf * m,void (* func)(struct ieee80211_node *,void *,int),void * arg)470 ieee80211_add_callback(struct mbuf* m,
471 void (*func)(struct ieee80211_node*, void*, int), void* arg)
472 {
473 struct m_tag* mtag;
474 struct ieee80211_cb* cb;
475
476 mtag = m_tag_alloc(MTAG_ABI_NET80211, NET80211_TAG_CALLBACK,
477 sizeof(struct ieee80211_cb), M_NOWAIT);
478 if (mtag == NULL)
479 return 0;
480
481 cb = (struct ieee80211_cb*)(mtag+1);
482 cb->func = func;
483 cb->arg = arg;
484 m_tag_prepend(m, mtag);
485 m->m_flags |= M_TXCB;
486 return 1;
487 }
488
489
490 void
ieee80211_process_callback(struct ieee80211_node * ni,struct mbuf * m,int status)491 ieee80211_process_callback(struct ieee80211_node* ni, struct mbuf* m,
492 int status)
493 {
494 struct m_tag* mtag;
495
496 mtag = m_tag_locate(m, MTAG_ABI_NET80211, NET80211_TAG_CALLBACK, NULL);
497 if (mtag != NULL) {
498 struct ieee80211_cb* cb = (struct ieee80211_cb*)(mtag+1);
499 cb->func(ni, cb->arg, status);
500 }
501 }
502
503
504 int
ieee80211_add_xmit_params(struct mbuf * m,const struct ieee80211_bpf_params * params)505 ieee80211_add_xmit_params(struct mbuf *m,
506 const struct ieee80211_bpf_params *params)
507 {
508 struct m_tag *mtag;
509 struct ieee80211_tx_params *tx;
510
511 mtag = m_tag_alloc(MTAG_ABI_NET80211, NET80211_TAG_XMIT_PARAMS,
512 sizeof(struct ieee80211_tx_params), M_NOWAIT);
513 if (mtag == NULL)
514 return (0);
515
516 tx = (struct ieee80211_tx_params *)(mtag+1);
517 memcpy(&tx->params, params, sizeof(struct ieee80211_bpf_params));
518 m_tag_prepend(m, mtag);
519 return (1);
520 }
521
522
523 int
ieee80211_get_xmit_params(struct mbuf * m,struct ieee80211_bpf_params * params)524 ieee80211_get_xmit_params(struct mbuf *m,
525 struct ieee80211_bpf_params *params)
526 {
527 struct m_tag *mtag;
528 struct ieee80211_tx_params *tx;
529
530 mtag = m_tag_locate(m, MTAG_ABI_NET80211, NET80211_TAG_XMIT_PARAMS,
531 NULL);
532 if (mtag == NULL)
533 return (-1);
534 tx = (struct ieee80211_tx_params *)(mtag + 1);
535 memcpy(params, &tx->params, sizeof(struct ieee80211_bpf_params));
536 return (0);
537 }
538
539
540 /*
541 * Add RX parameters to the given mbuf.
542 *
543 * Returns 1 if OK, 0 on error.
544 */
545 int
ieee80211_add_rx_params(struct mbuf * m,const struct ieee80211_rx_stats * rxs)546 ieee80211_add_rx_params(struct mbuf *m, const struct ieee80211_rx_stats *rxs)
547 {
548 struct m_tag *mtag;
549 struct ieee80211_rx_params *rx;
550
551 mtag = m_tag_alloc(MTAG_ABI_NET80211, NET80211_TAG_RECV_PARAMS,
552 sizeof(struct ieee80211_rx_stats), M_NOWAIT);
553 if (mtag == NULL)
554 return (0);
555
556 rx = (struct ieee80211_rx_params *)(mtag + 1);
557 memcpy(&rx->params, rxs, sizeof(*rxs));
558 m_tag_prepend(m, mtag);
559 return (1);
560 }
561
562
563 int
ieee80211_get_rx_params(struct mbuf * m,struct ieee80211_rx_stats * rxs)564 ieee80211_get_rx_params(struct mbuf *m, struct ieee80211_rx_stats *rxs)
565 {
566 struct m_tag *mtag;
567 struct ieee80211_rx_params *rx;
568
569 mtag = m_tag_locate(m, MTAG_ABI_NET80211, NET80211_TAG_RECV_PARAMS,
570 NULL);
571 if (mtag == NULL)
572 return (-1);
573 rx = (struct ieee80211_rx_params *)(mtag + 1);
574 memcpy(rxs, &rx->params, sizeof(*rxs));
575 return (0);
576 }
577
578
579 const struct ieee80211_rx_stats *
ieee80211_get_rx_params_ptr(struct mbuf * m)580 ieee80211_get_rx_params_ptr(struct mbuf *m)
581 {
582 struct m_tag *mtag;
583 struct ieee80211_rx_params *rx;
584
585 mtag = m_tag_locate(m, MTAG_ABI_NET80211, NET80211_TAG_RECV_PARAMS,
586 NULL);
587 if (mtag == NULL)
588 return (NULL);
589 rx = (struct ieee80211_rx_params *)(mtag + 1);
590 return (&rx->params);
591 }
592
593
594 /*
595 * Add TOA parameters to the given mbuf.
596 */
597 int
ieee80211_add_toa_params(struct mbuf * m,const struct ieee80211_toa_params * p)598 ieee80211_add_toa_params(struct mbuf *m, const struct ieee80211_toa_params *p)
599 {
600 struct m_tag *mtag;
601 struct ieee80211_toa_params *rp;
602
603 mtag = m_tag_alloc(MTAG_ABI_NET80211, NET80211_TAG_TOA_PARAMS,
604 sizeof(struct ieee80211_toa_params), M_NOWAIT);
605 if (mtag == NULL)
606 return (0);
607
608 rp = (struct ieee80211_toa_params *)(mtag + 1);
609 memcpy(rp, p, sizeof(*rp));
610 m_tag_prepend(m, mtag);
611 return (1);
612 }
613
614
615 int
ieee80211_get_toa_params(struct mbuf * m,struct ieee80211_toa_params * p)616 ieee80211_get_toa_params(struct mbuf *m, struct ieee80211_toa_params *p)
617 {
618 struct m_tag *mtag;
619 struct ieee80211_toa_params *rp;
620
621 mtag = m_tag_locate(m, MTAG_ABI_NET80211, NET80211_TAG_TOA_PARAMS,
622 NULL);
623 if (mtag == NULL)
624 return (0);
625 rp = (struct ieee80211_toa_params *)(mtag + 1);
626 if (p != NULL)
627 memcpy(p, rp, sizeof(*p));
628 return (1);
629 }
630
631
632 /*
633 * Transmit a frame to the parent interface.
634 */
635 int
ieee80211_parent_xmitpkt(struct ieee80211com * ic,struct mbuf * m)636 ieee80211_parent_xmitpkt(struct ieee80211com *ic, struct mbuf *m)
637 {
638 int error;
639
640 /*
641 * Assert the IC TX lock is held - this enforces the
642 * processing -> queuing order is maintained
643 */
644 IEEE80211_TX_LOCK_ASSERT(ic);
645 error = ic->ic_transmit(ic, m);
646 if (error) {
647 struct ieee80211_node *ni;
648
649 ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
650
651 /* XXX number of fragments */
652 if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, 1);
653 ieee80211_free_node(ni);
654 ieee80211_free_mbuf(m);
655 }
656 return (error);
657 }
658
659
660 /*
661 * Fetch the VAP name.
662 *
663 * This returns a const char pointer suitable for debugging,
664 * but don't expect it to stick around for much longer.
665 */
666 const char *
ieee80211_get_vap_ifname(struct ieee80211vap * vap)667 ieee80211_get_vap_ifname(struct ieee80211vap *vap)
668 {
669 if (vap->iv_ifp == NULL)
670 return "(none)";
671 return vap->iv_ifp->if_xname;
672 }
673
674 #ifdef DEBUGNET
675 static void
ieee80211_debugnet_init(struct ifnet * ifp,int * nrxr,int * ncl,int * clsize)676 ieee80211_debugnet_init(struct ifnet *ifp, int *nrxr, int *ncl, int *clsize)
677 {
678 struct ieee80211vap *vap;
679 struct ieee80211com *ic;
680
681 vap = if_getsoftc(ifp);
682 ic = vap->iv_ic;
683
684 IEEE80211_LOCK(ic);
685 ic->ic_debugnet_meth->dn8_init(ic, nrxr, ncl, clsize);
686 IEEE80211_UNLOCK(ic);
687 }
688
689 static void
ieee80211_debugnet_event(struct ifnet * ifp,enum debugnet_ev ev)690 ieee80211_debugnet_event(struct ifnet *ifp, enum debugnet_ev ev)
691 {
692 struct ieee80211vap *vap;
693 struct ieee80211com *ic;
694
695 vap = if_getsoftc(ifp);
696 ic = vap->iv_ic;
697
698 IEEE80211_LOCK(ic);
699 ic->ic_debugnet_meth->dn8_event(ic, ev);
700 IEEE80211_UNLOCK(ic);
701 }
702
703 static int
ieee80211_debugnet_transmit(struct ifnet * ifp,struct mbuf * m)704 ieee80211_debugnet_transmit(struct ifnet *ifp, struct mbuf *m)
705 {
706 return (ieee80211_vap_transmit(ifp, m));
707 }
708
709 static int
ieee80211_debugnet_poll(struct ifnet * ifp,int count)710 ieee80211_debugnet_poll(struct ifnet *ifp, int count)
711 {
712 struct ieee80211vap *vap;
713 struct ieee80211com *ic;
714
715 vap = if_getsoftc(ifp);
716 ic = vap->iv_ic;
717
718 return (ic->ic_debugnet_meth->dn8_poll(ic, count));
719 }
720 #endif
721
722 /*
723 * Transmit a frame to the VAP interface.
724 */
725 int
ieee80211_vap_xmitpkt(struct ieee80211vap * vap,struct mbuf * m)726 ieee80211_vap_xmitpkt(struct ieee80211vap *vap, struct mbuf *m)
727 {
728 struct ifnet *ifp = vap->iv_ifp;
729
730 /*
731 * When transmitting via the VAP, we shouldn't hold
732 * any IC TX lock as the VAP TX path will acquire it.
733 */
734 IEEE80211_TX_UNLOCK_ASSERT(vap->iv_ic);
735
736 return (ifp->if_transmit(ifp, m));
737
738 }
739
740
741 void
ieee80211_sysctl_vattach(struct ieee80211vap * vap)742 ieee80211_sysctl_vattach(struct ieee80211vap* vap)
743 {
744 vap->iv_debug = IEEE80211_MSG_XRATE
745 | IEEE80211_MSG_NODE
746 | IEEE80211_MSG_ASSOC
747 | IEEE80211_MSG_AUTH
748 | IEEE80211_MSG_STATE
749 | IEEE80211_MSG_WME
750 | IEEE80211_MSG_DOTH
751 | IEEE80211_MSG_INACT
752 | IEEE80211_MSG_ROAM;
753 }
754
755
756 void
ieee80211_sysctl_vdetach(struct ieee80211vap * vap)757 ieee80211_sysctl_vdetach(struct ieee80211vap* vap)
758 {
759 dprintf("%s not implemented, yet.\n", __func__);
760 }
761
762
763 void
ieee80211_vap_destroy(struct ieee80211vap * vap)764 ieee80211_vap_destroy(struct ieee80211vap* vap)
765 {
766 struct ieee80211com* ic = vap->iv_ic;
767
768 ic->ic_vap_delete(vap);
769 dprintf("%s: done.\n", __func__);
770 }
771
772
773 void
ieee80211_load_module(const char * modname)774 ieee80211_load_module(const char* modname)
775 {
776 #if 0
777 dprintf("%s not implemented, yet: modname %s\n", __func__, modname);
778 #endif
779 }
780
781
782 void
ieee80211_notify_node_join(struct ieee80211_node * ni,int newassoc)783 ieee80211_notify_node_join(struct ieee80211_node* ni, int newassoc)
784 {
785 struct ieee80211vap* vap = ni->ni_vap;
786 struct ifnet* ifp = vap->iv_ifp;
787
788 TRACE("%s\n", __FUNCTION__);
789
790 if (ni == vap->iv_bss)
791 if_link_state_change(ifp, LINK_STATE_UP);
792
793 if (sNotificationModule != NULL) {
794 char messageBuffer[512];
795 KMessage message;
796 message.SetTo(messageBuffer, sizeof(messageBuffer), B_NETWORK_MONITOR);
797 message.AddInt32("opcode", B_NETWORK_WLAN_JOINED);
798 message.AddString("interface", ifp->device_name);
799 // TODO: add data about the node
800
801 sNotificationModule->send_notification(&message);
802 }
803 }
804
805
806 void
ieee80211_notify_node_leave(struct ieee80211_node * ni)807 ieee80211_notify_node_leave(struct ieee80211_node* ni)
808 {
809 struct ieee80211vap* vap = ni->ni_vap;
810 struct ifnet* ifp = vap->iv_ifp;
811
812 if (ni == vap->iv_bss)
813 if_link_state_change(ifp, LINK_STATE_DOWN);
814
815 TRACE("%s\n", __FUNCTION__);
816
817 if (sNotificationModule != NULL) {
818 char messageBuffer[512];
819 KMessage message;
820 message.SetTo(messageBuffer, sizeof(messageBuffer), B_NETWORK_MONITOR);
821 message.AddInt32("opcode", B_NETWORK_WLAN_LEFT);
822 message.AddString("interface", ifp->device_name);
823 // TODO: add data about the node
824
825 sNotificationModule->send_notification(&message);
826 }
827 }
828
829
830 void
ieee80211_notify_scan_done(struct ieee80211vap * vap)831 ieee80211_notify_scan_done(struct ieee80211vap* vap)
832 {
833 release_sem_etc(vap->iv_ifp->scan_done_sem, 1,
834 B_DO_NOT_RESCHEDULE | B_RELEASE_ALL);
835
836 TRACE("%s\n", __FUNCTION__);
837
838 if (sNotificationModule != NULL) {
839 char messageBuffer[512];
840 KMessage message;
841 message.SetTo(messageBuffer, sizeof(messageBuffer), B_NETWORK_MONITOR);
842 message.AddInt32("opcode", B_NETWORK_WLAN_SCANNED);
843 message.AddString("interface", vap->iv_ifp->device_name);
844
845 sNotificationModule->send_notification(&message);
846 }
847 }
848
849
850 void
ieee80211_notify_replay_failure(struct ieee80211vap * vap,const struct ieee80211_frame * wh,const struct ieee80211_key * k,u_int64_t rsc,int tid)851 ieee80211_notify_replay_failure(struct ieee80211vap* vap,
852 const struct ieee80211_frame* wh, const struct ieee80211_key* k,
853 u_int64_t rsc, int tid)
854 {
855 dprintf("%s not implemented, yet.\n", __func__);
856 }
857
858
859 void
ieee80211_notify_michael_failure(struct ieee80211vap * vap,const struct ieee80211_frame * wh,u_int keyix)860 ieee80211_notify_michael_failure(struct ieee80211vap* vap,
861 const struct ieee80211_frame* wh, u_int keyix)
862 {
863 dprintf("%s not implemented, yet.\n", __func__);
864 }
865
866
867 void
ieee80211_notify_wds_discover(struct ieee80211_node * ni)868 ieee80211_notify_wds_discover(struct ieee80211_node* ni)
869 {
870 dprintf("%s not implemented, yet.\n", __func__);
871 }
872
873
874 void
ieee80211_notify_csa(struct ieee80211com * ic,const struct ieee80211_channel * c,int mode,int count)875 ieee80211_notify_csa(struct ieee80211com* ic,
876 const struct ieee80211_channel* c, int mode, int count)
877 {
878 dprintf("%s not implemented, yet.\n", __func__);
879 }
880
881
882 void
ieee80211_notify_radar(struct ieee80211com * ic,const struct ieee80211_channel * c)883 ieee80211_notify_radar(struct ieee80211com* ic,
884 const struct ieee80211_channel* c)
885 {
886 dprintf("%s not implemented, yet.\n", __func__);
887 }
888
889
890 void
ieee80211_notify_cac(struct ieee80211com * ic,const struct ieee80211_channel * c,enum ieee80211_notify_cac_event type)891 ieee80211_notify_cac(struct ieee80211com* ic,
892 const struct ieee80211_channel* c, enum ieee80211_notify_cac_event type)
893 {
894 dprintf("%s not implemented, yet.\n", __func__);
895 }
896
897
898 void
ieee80211_notify_node_deauth(struct ieee80211_node * ni)899 ieee80211_notify_node_deauth(struct ieee80211_node* ni)
900 {
901 dprintf("%s not implemented, yet.\n", __func__);
902 }
903
904
905 void
ieee80211_notify_node_auth(struct ieee80211_node * ni)906 ieee80211_notify_node_auth(struct ieee80211_node* ni)
907 {
908 dprintf("%s not implemented, yet.\n", __func__);
909 }
910
911
912 void
ieee80211_notify_country(struct ieee80211vap * vap,const uint8_t bssid[IEEE80211_ADDR_LEN],const uint8_t cc[2])913 ieee80211_notify_country(struct ieee80211vap* vap,
914 const uint8_t bssid[IEEE80211_ADDR_LEN], const uint8_t cc[2])
915 {
916 dprintf("%s not implemented, yet.\n", __func__);
917 }
918
919
920 void
ieee80211_notify_radio(struct ieee80211com * ic,int state)921 ieee80211_notify_radio(struct ieee80211com* ic, int state)
922 {
923 dprintf("%s not implemented, yet.\n", __func__);
924 }
925
926
927 extern "C" void
ieee80211_notify_ifnet_change(struct ieee80211vap * vap,int if_flags_mask)928 ieee80211_notify_ifnet_change(struct ieee80211vap *vap, int if_flags_mask)
929 {
930 dprintf("%s not implemented, yet.\n", __func__);
931 }
932
933
934 void
ieee80211_sysctl_attach(struct ieee80211com * ic)935 ieee80211_sysctl_attach(struct ieee80211com* ic)
936 {
937 dprintf("%s not implemented, yet.\n", __func__);
938 }
939
940
941 void
ieee80211_sysctl_detach(struct ieee80211com * ic)942 ieee80211_sysctl_detach(struct ieee80211com* ic)
943 {
944 dprintf("%s not implemented, yet.\n", __func__);
945 }
946