1/* 2 * Copyright 2009, Colin G��nther, coling@gmx.de. All rights reserved. 3 * Copyright 2018, 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 41extern "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) \ 74do { \ 75 (m)->m_data += (MCLBYTES - (len)) &~ (sizeof(long) - 1);\ 76} while (/* CONSTCOND */ 0) 77 78 79static 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 */ 86int 87ieee80211_priv_check_vap_getkey(u_long cmd __unused, 88 struct ieee80211vap *vap __unused, struct ifnet *ifp __unused) 89{ 90 return 0; 91} 92 93int 94ieee80211_priv_check_vap_manage(u_long cmd __unused, 95 struct ieee80211vap *vap __unused, struct ifnet *ifp __unused) 96{ 97 return 0; 98} 99 100int 101ieee80211_priv_check_vap_setmac(u_long cmd __unused, 102 struct ieee80211vap *vap __unused, struct ifnet *ifp __unused) 103{ 104 return 0; 105} 106 107int 108ieee80211_priv_check_create_vap(u_long cmd __unused, 109 struct ieee80211vap *vap __unused, struct ifnet *ifp __unused) 110{ 111 return 0; 112} 113 114 115static struct ifnet* 116get_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 129status_t 130init_wlan_stack(void) 131{ 132 get_module(NET_NOTIFICATIONS_MODULE_NAME, 133 (module_info**)&sNotificationModule); 134 135 return B_OK; 136} 137 138 139void 140uninit_wlan_stack(void) 141{ 142 if (sNotificationModule != NULL) 143 put_module(NET_NOTIFICATIONS_MODULE_NAME); 144} 145 146 147status_t 148start_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 179status_t 180stop_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 201status_t 202wlan_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 216status_t 217wlan_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 229status_t 230wlan_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 265void 266get_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 279struct mbuf * 280ieee80211_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 314int 315ieee80211_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 336void 337ieee80211_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 350void 351ieee80211_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 */ 370int 371ieee80211_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 378void 379ieee80211_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 399void 400ieee80211_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 */ 434extern "C" struct mbuf * 435ieee80211_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 469int 470ieee80211_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 490void 491ieee80211_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 504int 505ieee80211_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 523int 524ieee80211_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 */ 545int 546ieee80211_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 563int 564ieee80211_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 579const struct ieee80211_rx_stats * 580ieee80211_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 */ 597int 598ieee80211_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 615int 616ieee80211_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 */ 635int 636ieee80211_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 */ 666const char * 667ieee80211_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 675static void 676ieee80211_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 689static void 690ieee80211_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 703static int 704ieee80211_debugnet_transmit(struct ifnet *ifp, struct mbuf *m) 705{ 706 return (ieee80211_vap_transmit(ifp, m)); 707} 708 709static int 710ieee80211_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 */ 725int 726ieee80211_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 741void 742ieee80211_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 756void 757ieee80211_sysctl_vdetach(struct ieee80211vap* vap) 758{ 759 dprintf("%s not implemented, yet.\n", __func__); 760} 761 762 763void 764ieee80211_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 773void 774ieee80211_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 782void 783ieee80211_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 806void 807ieee80211_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 830void 831ieee80211_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 850void 851ieee80211_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 859void 860ieee80211_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 867void 868ieee80211_notify_wds_discover(struct ieee80211_node* ni) 869{ 870 dprintf("%s not implemented, yet.\n", __func__); 871} 872 873 874void 875ieee80211_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 882void 883ieee80211_notify_radar(struct ieee80211com* ic, 884 const struct ieee80211_channel* c) 885{ 886 dprintf("%s not implemented, yet.\n", __func__); 887} 888 889 890void 891ieee80211_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 898void 899ieee80211_notify_node_deauth(struct ieee80211_node* ni) 900{ 901 dprintf("%s not implemented, yet.\n", __func__); 902} 903 904 905void 906ieee80211_notify_node_auth(struct ieee80211_node* ni) 907{ 908 dprintf("%s not implemented, yet.\n", __func__); 909} 910 911 912void 913ieee80211_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 920void 921ieee80211_notify_radio(struct ieee80211com* ic, int state) 922{ 923 dprintf("%s not implemented, yet.\n", __func__); 924} 925 926 927void 928ieee80211_notify_ifnet_change(struct ieee80211vap *vap) 929{ 930 dprintf("%s not implemented, yet.\n", __func__); 931} 932 933 934void 935ieee80211_sysctl_attach(struct ieee80211com* ic) 936{ 937 dprintf("%s not implemented, yet.\n", __func__); 938} 939 940 941void 942ieee80211_sysctl_detach(struct ieee80211com* ic) 943{ 944 dprintf("%s not implemented, yet.\n", __func__); 945} 946