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 case SIOCSIFFLAGS: 261 case SIOCSIFMEDIA: 262 case SIOCGIFMEDIA: 263 case SIOCSIFMTU: 264 // Requests that make it here always come from the kernel 265 return ifp->if_ioctl(ifp, op, (caddr_t)arg); 266 } 267 268 return B_BAD_VALUE; 269 } 270 271 272 void 273 get_random_bytes(void* p, size_t n) 274 { 275 uint8_t* dp = (uint8_t*)p; 276 277 while (n > 0) { 278 uint32_t v = arc4random(); 279 size_t nb = n > sizeof(uint32_t) ? sizeof(uint32_t) : n; 280 bcopy(&v, dp, n > sizeof(uint32_t) ? sizeof(uint32_t) : n); 281 dp += sizeof(uint32_t), n -= nb; 282 } 283 } 284 285 286 struct mbuf * 287 ieee80211_getmgtframe(uint8_t **frm, int headroom, int pktlen) 288 { 289 struct mbuf *m; 290 u_int len; 291 292 /* 293 * NB: we know the mbuf routines will align the data area 294 * so we don't need to do anything special. 295 */ 296 len = roundup2(headroom + pktlen, 4); 297 KASSERT(len <= MCLBYTES, ("802.11 mgt frame too large: %u", len)); 298 if (len < MINCLSIZE) { 299 m = m_gethdr(M_NOWAIT, MT_DATA); 300 /* 301 * Align the data in case additional headers are added. 302 * This should only happen when a WEP header is added 303 * which only happens for shared key authentication mgt 304 * frames which all fit in MHLEN. 305 */ 306 if (m != NULL) 307 M_ALIGN(m, len); 308 } else { 309 m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); 310 if (m != NULL) 311 MC_ALIGN(m, len); 312 } 313 if (m != NULL) { 314 m->m_data += headroom; 315 *frm = (uint8_t*)m->m_data; 316 } 317 return m; 318 } 319 320 321 int 322 ieee80211_com_vincref(struct ieee80211vap *vap) 323 { 324 uint32_t ostate; 325 326 ostate = atomic_fetchadd_32(&vap->iv_com_state, IEEE80211_COM_REF_ADD); 327 328 if (ostate & IEEE80211_COM_DETACHED) { 329 atomic_subtract_32(&vap->iv_com_state, IEEE80211_COM_REF_ADD); 330 return (ENETDOWN); 331 } 332 333 if (_IEEE80211_MASKSHIFT(ostate, IEEE80211_COM_REF) == 334 IEEE80211_COM_REF_MAX) { 335 atomic_subtract_32(&vap->iv_com_state, IEEE80211_COM_REF_ADD); 336 return (EOVERFLOW); 337 } 338 339 return (0); 340 } 341 342 343 void 344 ieee80211_com_vdecref(struct ieee80211vap *vap) 345 { 346 uint32_t ostate; 347 348 ostate = atomic_fetchadd_32(&vap->iv_com_state, -IEEE80211_COM_REF_ADD); 349 350 KASSERT(_IEEE80211_MASKSHIFT(ostate, IEEE80211_COM_REF) != 0, 351 ("com reference counter underflow")); 352 353 (void) ostate; 354 } 355 356 357 void 358 ieee80211_com_vdetach(struct ieee80211vap *vap) 359 { 360 int sleep_time; 361 362 sleep_time = msecs_to_ticks(250); 363 atomic_set_32(&vap->iv_com_state, IEEE80211_COM_DETACHED); 364 while (_IEEE80211_MASKSHIFT(atomic_load_32(&vap->iv_com_state), 365 IEEE80211_COM_REF) != 0) 366 pause("comref", sleep_time); 367 } 368 369 370 /* 371 * Decrements the reference-counter and 372 * tests whether it became zero. If so, sets it to one. 373 * 374 * @return 1 reference-counter became zero 375 * @return 0 reference-counter didn't became zero 376 */ 377 int 378 ieee80211_node_dectestref(struct ieee80211_node* ni) 379 { 380 atomic_subtract_int(&ni->ni_refcnt, 1); 381 return atomic_cmpset_int(&ni->ni_refcnt, 0, 1); 382 } 383 384 385 void 386 ieee80211_drain_ifq(struct ifqueue* ifq) 387 { 388 struct ieee80211_node* ni; 389 struct mbuf* m; 390 391 for (;;) { 392 IF_DEQUEUE(ifq, m); 393 if (m == NULL) 394 break; 395 396 ni = (struct ieee80211_node*)m->m_pkthdr.rcvif; 397 KASSERT(ni != NULL, ("frame w/o node")); 398 ieee80211_free_node(ni); 399 m->m_pkthdr.rcvif = NULL; 400 401 m_freem(m); 402 } 403 } 404 405 406 void 407 ieee80211_flush_ifq(struct ifqueue* ifq, struct ieee80211vap* vap) 408 { 409 struct ieee80211_node* ni; 410 struct mbuf* m; 411 struct mbuf** mprev; 412 413 IF_LOCK(ifq); 414 mprev = &ifq->ifq_head; 415 while ((m = *mprev) != NULL) { 416 ni = (struct ieee80211_node*)m->m_pkthdr.rcvif; 417 if (ni != NULL && ni->ni_vap == vap) { 418 *mprev = m->m_nextpkt; 419 // remove from list 420 ifq->ifq_len--; 421 422 m_freem(m); 423 ieee80211_free_node(ni); 424 // reclaim ref 425 } else 426 mprev = &m->m_nextpkt; 427 } 428 // recalculate tail ptr 429 m = ifq->ifq_head; 430 for (; m != NULL && m->m_nextpkt != NULL; m = m->m_nextpkt); 431 ifq->ifq_tail = m; 432 IF_UNLOCK(ifq); 433 } 434 435 436 #ifndef __NO_STRICT_ALIGNMENT 437 /* 438 * Re-align the payload in the mbuf. This is mainly used (right now) 439 * to handle IP header alignment requirements on certain architectures. 440 */ 441 extern "C" struct mbuf * 442 ieee80211_realign(struct ieee80211vap *vap, struct mbuf *m, size_t align) 443 { 444 int pktlen, space; 445 struct mbuf *n; 446 447 pktlen = m->m_pkthdr.len; 448 space = pktlen + align; 449 if (space < MINCLSIZE) 450 n = m_gethdr(M_NOWAIT, MT_DATA); 451 else { 452 n = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, 453 space <= MCLBYTES ? MCLBYTES : 454 #if MJUMPAGESIZE != MCLBYTES 455 space <= MJUMPAGESIZE ? MJUMPAGESIZE : 456 #endif 457 space <= MJUM9BYTES ? MJUM9BYTES : MJUM16BYTES); 458 } 459 if (__predict_true(n != NULL)) { 460 m_move_pkthdr(n, m); 461 n->m_data = (caddr_t)(ALIGN(n->m_data + align) - align); 462 m_copydata(m, 0, pktlen, mtod(n, caddr_t)); 463 n->m_len = pktlen; 464 } else { 465 IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY, 466 mtod(m, const struct ieee80211_frame *), NULL, 467 "%s", "no mbuf to realign"); 468 vap->iv_stats.is_rx_badalign++; 469 } 470 m_freem(m); 471 return n; 472 } 473 #endif /* !__NO_STRICT_ALIGNMENT */ 474 475 476 int 477 ieee80211_add_callback(struct mbuf* m, 478 void (*func)(struct ieee80211_node*, void*, int), void* arg) 479 { 480 struct m_tag* mtag; 481 struct ieee80211_cb* cb; 482 483 mtag = m_tag_alloc(MTAG_ABI_NET80211, NET80211_TAG_CALLBACK, 484 sizeof(struct ieee80211_cb), M_NOWAIT); 485 if (mtag == NULL) 486 return 0; 487 488 cb = (struct ieee80211_cb*)(mtag+1); 489 cb->func = func; 490 cb->arg = arg; 491 m_tag_prepend(m, mtag); 492 m->m_flags |= M_TXCB; 493 return 1; 494 } 495 496 497 void 498 ieee80211_process_callback(struct ieee80211_node* ni, struct mbuf* m, 499 int status) 500 { 501 struct m_tag* mtag; 502 503 mtag = m_tag_locate(m, MTAG_ABI_NET80211, NET80211_TAG_CALLBACK, NULL); 504 if (mtag != NULL) { 505 struct ieee80211_cb* cb = (struct ieee80211_cb*)(mtag+1); 506 cb->func(ni, cb->arg, status); 507 } 508 } 509 510 511 int 512 ieee80211_add_xmit_params(struct mbuf *m, 513 const struct ieee80211_bpf_params *params) 514 { 515 struct m_tag *mtag; 516 struct ieee80211_tx_params *tx; 517 518 mtag = m_tag_alloc(MTAG_ABI_NET80211, NET80211_TAG_XMIT_PARAMS, 519 sizeof(struct ieee80211_tx_params), M_NOWAIT); 520 if (mtag == NULL) 521 return (0); 522 523 tx = (struct ieee80211_tx_params *)(mtag+1); 524 memcpy(&tx->params, params, sizeof(struct ieee80211_bpf_params)); 525 m_tag_prepend(m, mtag); 526 return (1); 527 } 528 529 530 int 531 ieee80211_get_xmit_params(struct mbuf *m, 532 struct ieee80211_bpf_params *params) 533 { 534 struct m_tag *mtag; 535 struct ieee80211_tx_params *tx; 536 537 mtag = m_tag_locate(m, MTAG_ABI_NET80211, NET80211_TAG_XMIT_PARAMS, 538 NULL); 539 if (mtag == NULL) 540 return (-1); 541 tx = (struct ieee80211_tx_params *)(mtag + 1); 542 memcpy(params, &tx->params, sizeof(struct ieee80211_bpf_params)); 543 return (0); 544 } 545 546 547 /* 548 * Add RX parameters to the given mbuf. 549 * 550 * Returns 1 if OK, 0 on error. 551 */ 552 int 553 ieee80211_add_rx_params(struct mbuf *m, const struct ieee80211_rx_stats *rxs) 554 { 555 struct m_tag *mtag; 556 struct ieee80211_rx_params *rx; 557 558 mtag = m_tag_alloc(MTAG_ABI_NET80211, NET80211_TAG_RECV_PARAMS, 559 sizeof(struct ieee80211_rx_stats), M_NOWAIT); 560 if (mtag == NULL) 561 return (0); 562 563 rx = (struct ieee80211_rx_params *)(mtag + 1); 564 memcpy(&rx->params, rxs, sizeof(*rxs)); 565 m_tag_prepend(m, mtag); 566 return (1); 567 } 568 569 570 int 571 ieee80211_get_rx_params(struct mbuf *m, struct ieee80211_rx_stats *rxs) 572 { 573 struct m_tag *mtag; 574 struct ieee80211_rx_params *rx; 575 576 mtag = m_tag_locate(m, MTAG_ABI_NET80211, NET80211_TAG_RECV_PARAMS, 577 NULL); 578 if (mtag == NULL) 579 return (-1); 580 rx = (struct ieee80211_rx_params *)(mtag + 1); 581 memcpy(rxs, &rx->params, sizeof(*rxs)); 582 return (0); 583 } 584 585 586 const struct ieee80211_rx_stats * 587 ieee80211_get_rx_params_ptr(struct mbuf *m) 588 { 589 struct m_tag *mtag; 590 struct ieee80211_rx_params *rx; 591 592 mtag = m_tag_locate(m, MTAG_ABI_NET80211, NET80211_TAG_RECV_PARAMS, 593 NULL); 594 if (mtag == NULL) 595 return (NULL); 596 rx = (struct ieee80211_rx_params *)(mtag + 1); 597 return (&rx->params); 598 } 599 600 601 /* 602 * Add TOA parameters to the given mbuf. 603 */ 604 int 605 ieee80211_add_toa_params(struct mbuf *m, const struct ieee80211_toa_params *p) 606 { 607 struct m_tag *mtag; 608 struct ieee80211_toa_params *rp; 609 610 mtag = m_tag_alloc(MTAG_ABI_NET80211, NET80211_TAG_TOA_PARAMS, 611 sizeof(struct ieee80211_toa_params), M_NOWAIT); 612 if (mtag == NULL) 613 return (0); 614 615 rp = (struct ieee80211_toa_params *)(mtag + 1); 616 memcpy(rp, p, sizeof(*rp)); 617 m_tag_prepend(m, mtag); 618 return (1); 619 } 620 621 622 int 623 ieee80211_get_toa_params(struct mbuf *m, struct ieee80211_toa_params *p) 624 { 625 struct m_tag *mtag; 626 struct ieee80211_toa_params *rp; 627 628 mtag = m_tag_locate(m, MTAG_ABI_NET80211, NET80211_TAG_TOA_PARAMS, 629 NULL); 630 if (mtag == NULL) 631 return (0); 632 rp = (struct ieee80211_toa_params *)(mtag + 1); 633 if (p != NULL) 634 memcpy(p, rp, sizeof(*p)); 635 return (1); 636 } 637 638 639 /* 640 * Transmit a frame to the parent interface. 641 */ 642 int 643 ieee80211_parent_xmitpkt(struct ieee80211com *ic, struct mbuf *m) 644 { 645 int error; 646 647 /* 648 * Assert the IC TX lock is held - this enforces the 649 * processing -> queuing order is maintained 650 */ 651 IEEE80211_TX_LOCK_ASSERT(ic); 652 error = ic->ic_transmit(ic, m); 653 if (error) { 654 struct ieee80211_node *ni; 655 656 ni = (struct ieee80211_node *)m->m_pkthdr.rcvif; 657 658 /* XXX number of fragments */ 659 if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, 1); 660 ieee80211_free_node(ni); 661 ieee80211_free_mbuf(m); 662 } 663 return (error); 664 } 665 666 667 /* 668 * Fetch the VAP name. 669 * 670 * This returns a const char pointer suitable for debugging, 671 * but don't expect it to stick around for much longer. 672 */ 673 const char * 674 ieee80211_get_vap_ifname(struct ieee80211vap *vap) 675 { 676 if (vap->iv_ifp == NULL) 677 return "(none)"; 678 return vap->iv_ifp->if_xname; 679 } 680 681 #ifdef DEBUGNET 682 static void 683 ieee80211_debugnet_init(struct ifnet *ifp, int *nrxr, int *ncl, int *clsize) 684 { 685 struct ieee80211vap *vap; 686 struct ieee80211com *ic; 687 688 vap = if_getsoftc(ifp); 689 ic = vap->iv_ic; 690 691 IEEE80211_LOCK(ic); 692 ic->ic_debugnet_meth->dn8_init(ic, nrxr, ncl, clsize); 693 IEEE80211_UNLOCK(ic); 694 } 695 696 static void 697 ieee80211_debugnet_event(struct ifnet *ifp, enum debugnet_ev ev) 698 { 699 struct ieee80211vap *vap; 700 struct ieee80211com *ic; 701 702 vap = if_getsoftc(ifp); 703 ic = vap->iv_ic; 704 705 IEEE80211_LOCK(ic); 706 ic->ic_debugnet_meth->dn8_event(ic, ev); 707 IEEE80211_UNLOCK(ic); 708 } 709 710 static int 711 ieee80211_debugnet_transmit(struct ifnet *ifp, struct mbuf *m) 712 { 713 return (ieee80211_vap_transmit(ifp, m)); 714 } 715 716 static int 717 ieee80211_debugnet_poll(struct ifnet *ifp, int count) 718 { 719 struct ieee80211vap *vap; 720 struct ieee80211com *ic; 721 722 vap = if_getsoftc(ifp); 723 ic = vap->iv_ic; 724 725 return (ic->ic_debugnet_meth->dn8_poll(ic, count)); 726 } 727 #endif 728 729 /* 730 * Transmit a frame to the VAP interface. 731 */ 732 int 733 ieee80211_vap_xmitpkt(struct ieee80211vap *vap, struct mbuf *m) 734 { 735 struct ifnet *ifp = vap->iv_ifp; 736 737 /* 738 * When transmitting via the VAP, we shouldn't hold 739 * any IC TX lock as the VAP TX path will acquire it. 740 */ 741 IEEE80211_TX_UNLOCK_ASSERT(vap->iv_ic); 742 743 return (ifp->if_transmit(ifp, m)); 744 745 } 746 747 748 void 749 ieee80211_sysctl_vattach(struct ieee80211vap* vap) 750 { 751 vap->iv_debug = IEEE80211_MSG_XRATE 752 | IEEE80211_MSG_NODE 753 | IEEE80211_MSG_ASSOC 754 | IEEE80211_MSG_AUTH 755 | IEEE80211_MSG_STATE 756 | IEEE80211_MSG_WME 757 | IEEE80211_MSG_DOTH 758 | IEEE80211_MSG_INACT 759 | IEEE80211_MSG_ROAM; 760 } 761 762 763 void 764 ieee80211_sysctl_vdetach(struct ieee80211vap* vap) 765 { 766 dprintf("%s not implemented, yet.\n", __func__); 767 } 768 769 770 void 771 ieee80211_vap_destroy(struct ieee80211vap* vap) 772 { 773 struct ieee80211com* ic = vap->iv_ic; 774 775 ic->ic_vap_delete(vap); 776 dprintf("%s: done.\n", __func__); 777 } 778 779 780 void 781 ieee80211_load_module(const char* modname) 782 { 783 #if 0 784 dprintf("%s not implemented, yet: modname %s\n", __func__, modname); 785 #endif 786 } 787 788 789 void 790 ieee80211_notify_node_join(struct ieee80211_node* ni, int newassoc) 791 { 792 struct ieee80211vap* vap = ni->ni_vap; 793 struct ifnet* ifp = vap->iv_ifp; 794 795 TRACE("%s\n", __FUNCTION__); 796 797 if (ni == vap->iv_bss) 798 if_link_state_change(ifp, LINK_STATE_UP); 799 800 if (sNotificationModule != NULL) { 801 char messageBuffer[512]; 802 KMessage message; 803 message.SetTo(messageBuffer, sizeof(messageBuffer), B_NETWORK_MONITOR); 804 message.AddInt32("opcode", B_NETWORK_WLAN_JOINED); 805 message.AddString("interface", ifp->device_name); 806 // TODO: add data about the node 807 808 sNotificationModule->send_notification(&message); 809 } 810 } 811 812 813 void 814 ieee80211_notify_node_leave(struct ieee80211_node* ni) 815 { 816 struct ieee80211vap* vap = ni->ni_vap; 817 struct ifnet* ifp = vap->iv_ifp; 818 819 if (ni == vap->iv_bss) 820 if_link_state_change(ifp, LINK_STATE_DOWN); 821 822 TRACE("%s\n", __FUNCTION__); 823 824 if (sNotificationModule != NULL) { 825 char messageBuffer[512]; 826 KMessage message; 827 message.SetTo(messageBuffer, sizeof(messageBuffer), B_NETWORK_MONITOR); 828 message.AddInt32("opcode", B_NETWORK_WLAN_LEFT); 829 message.AddString("interface", ifp->device_name); 830 // TODO: add data about the node 831 832 sNotificationModule->send_notification(&message); 833 } 834 } 835 836 837 void 838 ieee80211_notify_scan_done(struct ieee80211vap* vap) 839 { 840 release_sem_etc(vap->iv_ifp->scan_done_sem, 1, 841 B_DO_NOT_RESCHEDULE | B_RELEASE_ALL); 842 843 TRACE("%s\n", __FUNCTION__); 844 845 if (sNotificationModule != NULL) { 846 char messageBuffer[512]; 847 KMessage message; 848 message.SetTo(messageBuffer, sizeof(messageBuffer), B_NETWORK_MONITOR); 849 message.AddInt32("opcode", B_NETWORK_WLAN_SCANNED); 850 message.AddString("interface", vap->iv_ifp->device_name); 851 852 sNotificationModule->send_notification(&message); 853 } 854 } 855 856 857 void 858 ieee80211_notify_replay_failure(struct ieee80211vap* vap, 859 const struct ieee80211_frame* wh, const struct ieee80211_key* k, 860 u_int64_t rsc, int tid) 861 { 862 dprintf("%s not implemented, yet.\n", __func__); 863 } 864 865 866 void 867 ieee80211_notify_michael_failure(struct ieee80211vap* vap, 868 const struct ieee80211_frame* wh, u_int keyix) 869 { 870 dprintf("%s not implemented, yet.\n", __func__); 871 } 872 873 874 void 875 ieee80211_notify_wds_discover(struct ieee80211_node* ni) 876 { 877 dprintf("%s not implemented, yet.\n", __func__); 878 } 879 880 881 void 882 ieee80211_notify_csa(struct ieee80211com* ic, 883 const struct ieee80211_channel* c, int mode, int count) 884 { 885 dprintf("%s not implemented, yet.\n", __func__); 886 } 887 888 889 void 890 ieee80211_notify_radar(struct ieee80211com* ic, 891 const struct ieee80211_channel* c) 892 { 893 dprintf("%s not implemented, yet.\n", __func__); 894 } 895 896 897 void 898 ieee80211_notify_cac(struct ieee80211com* ic, 899 const struct ieee80211_channel* c, enum ieee80211_notify_cac_event type) 900 { 901 dprintf("%s not implemented, yet.\n", __func__); 902 } 903 904 905 void 906 ieee80211_notify_node_deauth(struct ieee80211_node* ni) 907 { 908 dprintf("%s not implemented, yet.\n", __func__); 909 } 910 911 912 void 913 ieee80211_notify_node_auth(struct ieee80211_node* ni) 914 { 915 dprintf("%s not implemented, yet.\n", __func__); 916 } 917 918 919 void 920 ieee80211_notify_country(struct ieee80211vap* vap, 921 const uint8_t bssid[IEEE80211_ADDR_LEN], const uint8_t cc[2]) 922 { 923 dprintf("%s not implemented, yet.\n", __func__); 924 } 925 926 927 void 928 ieee80211_notify_radio(struct ieee80211com* ic, int state) 929 { 930 dprintf("%s not implemented, yet.\n", __func__); 931 } 932 933 934 void 935 ieee80211_notify_ifnet_change(struct ieee80211vap *vap) 936 { 937 dprintf("%s not implemented, yet.\n", __func__); 938 } 939 940 941 void 942 ieee80211_sysctl_attach(struct ieee80211com* ic) 943 { 944 dprintf("%s not implemented, yet.\n", __func__); 945 } 946 947 948 void 949 ieee80211_sysctl_detach(struct ieee80211com* ic) 950 { 951 dprintf("%s not implemented, yet.\n", __func__); 952 } 953