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 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 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 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 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 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* 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 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 140 uninit_wlan_stack(void) 141 { 142 if (sNotificationModule != NULL) 143 put_module(NET_NOTIFICATIONS_MODULE_NAME); 144 } 145 146 147 status_t 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 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 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 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 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 266 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 * 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 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 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 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 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 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 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 * 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 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 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 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 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 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 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 * 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 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 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 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 * 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 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 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 704 ieee80211_debugnet_transmit(struct ifnet *ifp, struct mbuf *m) 705 { 706 return (ieee80211_vap_transmit(ifp, m)); 707 } 708 709 static int 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 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 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 757 ieee80211_sysctl_vdetach(struct ieee80211vap* vap) 758 { 759 dprintf("%s not implemented, yet.\n", __func__); 760 } 761 762 763 void 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 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 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 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 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 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 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 868 ieee80211_notify_wds_discover(struct ieee80211_node* ni) 869 { 870 dprintf("%s not implemented, yet.\n", __func__); 871 } 872 873 874 void 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 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 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 899 ieee80211_notify_node_deauth(struct ieee80211_node* ni) 900 { 901 dprintf("%s not implemented, yet.\n", __func__); 902 } 903 904 905 void 906 ieee80211_notify_node_auth(struct ieee80211_node* ni) 907 { 908 dprintf("%s not implemented, yet.\n", __func__); 909 } 910 911 912 void 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 921 ieee80211_notify_radio(struct ieee80211com* ic, int state) 922 { 923 dprintf("%s not implemented, yet.\n", __func__); 924 } 925 926 927 void 928 ieee80211_notify_ifnet_change(struct ieee80211vap *vap) 929 { 930 dprintf("%s not implemented, yet.\n", __func__); 931 } 932 933 934 void 935 ieee80211_sysctl_attach(struct ieee80211com* ic) 936 { 937 dprintf("%s not implemented, yet.\n", __func__); 938 } 939 940 941 void 942 ieee80211_sysctl_detach(struct ieee80211com* ic) 943 { 944 dprintf("%s not implemented, yet.\n", __func__); 945 } 946