1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2010-2011 Monthadar Al Jaberi, TerraNet AB 5 * All rights reserved. 6 * 7 * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer, 15 * without modification. 16 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 17 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 18 * redistribution must be conditioned upon including a substantially 19 * similar Disclaimer requirement for further binary redistribution. 20 * 21 * NO WARRANTY 22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 25 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 26 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 27 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 30 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 32 * THE POSSIBILITY OF SUCH DAMAGES. 33 */ 34 #include "if_wtapvar.h" 35 #include <sys/uio.h> /* uio struct */ 36 #include <net/if_var.h> 37 38 #include "if_medium.h" 39 #include "wtap_hal/hal.h" 40 41 /* 42 * This _requires_ vimage to be useful. 43 */ 44 #ifndef VIMAGE 45 #error if_wtap requires VIMAGE. 46 #endif /* VIMAGE */ 47 48 /* device for IOCTL and read/write for debuggin purposes */ 49 /* Function prototypes */ 50 static d_open_t wtap_node_open; 51 static d_close_t wtap_node_close; 52 static d_write_t wtap_node_write; 53 static d_ioctl_t wtap_node_ioctl; 54 55 static struct cdevsw wtap_cdevsw = { 56 .d_version = D_VERSION, 57 .d_flags = 0, 58 .d_open = wtap_node_open, 59 .d_close = wtap_node_close, 60 .d_write = wtap_node_write, 61 .d_ioctl = wtap_node_ioctl, 62 .d_name = "wtapnode", 63 }; 64 65 static int 66 wtap_node_open(struct cdev *dev, int oflags, int devtype, struct thread *p) 67 { 68 69 int err = 0; 70 uprintf("Opened device \"echo\" successfully.\n"); 71 return(err); 72 } 73 74 static int 75 wtap_node_close(struct cdev *dev, int fflag, int devtype, struct thread *p) 76 { 77 78 uprintf("Closing device \"echo.\"\n"); 79 return(0); 80 } 81 82 static int 83 wtap_node_write(struct cdev *dev, struct uio *uio, int ioflag) 84 { 85 int err = 0; 86 struct mbuf *m; 87 struct wtap_softc *sc; 88 uint8_t buf[1024]; 89 struct epoch_tracker et; 90 int buf_len; 91 92 uprintf("write device %s \"echo.\"\n", devtoname(dev)); 93 buf_len = MIN(uio->uio_iov->iov_len, 1024); 94 err = copyin(uio->uio_iov->iov_base, buf, buf_len); 95 96 if (err != 0) { 97 uprintf("Write failed: bad address!\n"); 98 return (err); 99 } 100 101 MGETHDR(m, M_NOWAIT, MT_DATA); 102 m_copyback(m, 0, buf_len, buf); 103 104 NET_EPOCH_ENTER(et); 105 106 sc = (struct wtap_softc *)dev->si_drv1; 107 printf("wtap id = %d\n", sc->id); 108 wtap_inject(sc, m); 109 110 NET_EPOCH_EXIT(et); 111 112 return(err); 113 } 114 115 int 116 wtap_node_ioctl(struct cdev *dev, u_long cmd, caddr_t data, 117 int fflag, struct thread *td) 118 { 119 int error = 0; 120 121 switch(cmd) { 122 default: 123 DWTAP_PRINTF("Unknown WTAP IOCTL\n"); 124 error = EINVAL; 125 } 126 return error; 127 } 128 129 static int wtap_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, 130 const struct ieee80211_bpf_params *params); 131 132 static int 133 wtap_medium_enqueue(struct wtap_vap *avp, struct mbuf *m) 134 { 135 136 return medium_transmit(avp->av_md, avp->id, m); 137 } 138 139 /* 140 * Intercept management frames to collect beacon rssi data 141 * and to do ibss merges. 142 */ 143 static void 144 wtap_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m, 145 int subtype, const struct ieee80211_rx_stats *stats, int rssi, int nf) 146 { 147 struct ieee80211vap *vap = ni->ni_vap; 148 struct wtap_softc *sc = vap->iv_ic->ic_softc; 149 #if 0 150 DWTAP_PRINTF("[%d] %s\n", myath_id(ni), __func__); 151 #endif 152 /* 153 * Call up first so subsequent work can use information 154 * potentially stored in the node (e.g. for ibss merge). 155 */ 156 WTAP_VAP(vap)->av_recv_mgmt(ni, m, subtype, stats, rssi, nf); 157 158 switch (subtype) { 159 case IEEE80211_FC0_SUBTYPE_BEACON: 160 case IEEE80211_FC0_SUBTYPE_PROBE_RESP: 161 if (vap->iv_opmode == IEEE80211_M_IBSS && 162 vap->iv_state == IEEE80211_S_RUN && 163 ieee80211_ibss_merge_check(ni)) { 164 uint64_t tsf = wtap_hal_get_tsf(sc->hal); 165 166 /* 167 * Handle ibss merge as needed; check the tsf on the 168 * frame before attempting the merge. The 802.11 spec 169 * says the station should change it's bssid to match 170 * the oldest station with the same ssid, where oldest 171 * is determined by the tsf. Note that hardware 172 * reconfiguration happens through callback to 173 * ath_newstate as the state machine will go from 174 * RUN -> RUN when this happens. 175 */ 176 if (le64toh(ni->ni_tstamp.tsf) >= tsf) 177 (void) ieee80211_ibss_merge(ni); 178 } 179 break; 180 } 181 } 182 183 static int 184 wtap_reset_vap(struct ieee80211vap *vap, u_long cmd) 185 { 186 187 DWTAP_PRINTF("%s\n", __func__); 188 return 0; 189 } 190 191 static void 192 wtap_beacon_update(struct ieee80211vap *vap, int item) 193 { 194 struct ieee80211_beacon_offsets *bo = &vap->iv_bcn_off; 195 196 DWTAP_PRINTF("%s\n", __func__); 197 setbit(bo->bo_flags, item); 198 } 199 200 /* 201 * Allocate and setup an initial beacon frame. 202 */ 203 static int 204 wtap_beacon_alloc(struct wtap_softc *sc, struct ieee80211_node *ni) 205 { 206 struct ieee80211vap *vap = ni->ni_vap; 207 struct wtap_vap *avp = WTAP_VAP(vap); 208 209 DWTAP_PRINTF("[%s] %s\n", ether_sprintf(ni->ni_macaddr), __func__); 210 211 /* 212 * NB: the beacon data buffer must be 32-bit aligned; 213 * we assume the mbuf routines will return us something 214 * with this alignment (perhaps should assert). 215 */ 216 avp->beacon = ieee80211_beacon_alloc(ni); 217 if (avp->beacon == NULL) { 218 printf("%s: cannot get mbuf\n", __func__); 219 return ENOMEM; 220 } 221 avp->bf_node = ieee80211_ref_node(ni); 222 223 return 0; 224 } 225 226 static void 227 wtap_beacon_config(struct wtap_softc *sc, struct ieee80211vap *vap) 228 { 229 DWTAP_PRINTF("%s\n", __func__); 230 } 231 232 static void 233 wtap_beacon_intrp(void *arg) 234 { 235 struct wtap_vap *avp = arg; 236 struct ieee80211vap *vap = arg; 237 struct wtap_softc *sc = vap->iv_ic->ic_softc; 238 struct ieee80211_frame *wh; 239 struct mbuf *m; 240 uint64_t tsf; 241 242 if (vap->iv_state < IEEE80211_S_RUN) { 243 DWTAP_PRINTF("Skip beacon, not running, state %d", vap->iv_state); 244 return ; 245 } 246 DWTAP_PRINTF("[%d] beacon intrp\n", avp->id); //burst mode 247 /* 248 * Update dynamic beacon contents. If this returns 249 * non-zero then we need to remap the memory because 250 * the beacon frame changed size (probably because 251 * of the TIM bitmap). 252 */ 253 m = m_dup(avp->beacon, M_NOWAIT); 254 if (ieee80211_beacon_update(avp->bf_node, m, 0)) { 255 printf("%s, need to remap the memory because the beacon frame" 256 " changed size.\n",__func__); 257 } 258 259 /* Get TSF from HAL, and insert it into beacon frame */ 260 tsf = wtap_hal_get_tsf(sc->hal); 261 wh = mtod(m, struct ieee80211_frame *); 262 memcpy(&wh[1], &tsf, sizeof(tsf)); 263 264 if (ieee80211_radiotap_active_vap(vap)) 265 ieee80211_radiotap_tx(vap, m); 266 267 #if 0 268 medium_transmit(avp->av_md, avp->id, m); 269 #endif 270 wtap_medium_enqueue(avp, m); 271 callout_schedule(&avp->av_swba, avp->av_bcinterval); 272 } 273 274 static int 275 wtap_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) 276 { 277 struct ieee80211com *ic = vap->iv_ic; 278 struct wtap_softc *sc = ic->ic_softc; 279 struct wtap_vap *avp = WTAP_VAP(vap); 280 struct ieee80211_node *ni = NULL; 281 int error; 282 283 DWTAP_PRINTF("%s\n", __func__); 284 285 ni = ieee80211_ref_node(vap->iv_bss); 286 /* 287 * Invoke the parent method to do net80211 work. 288 */ 289 error = avp->av_newstate(vap, nstate, arg); 290 if (error != 0) 291 goto bad; 292 293 if (nstate == IEEE80211_S_RUN) { 294 /* NB: collect bss node again, it may have changed */ 295 ieee80211_free_node(ni); 296 ni = ieee80211_ref_node(vap->iv_bss); 297 switch (vap->iv_opmode) { 298 case IEEE80211_M_IBSS: 299 case IEEE80211_M_MBSS: 300 /* 301 * Stop any previous beacon callout. This may be 302 * necessary, for example, when an ibss merge 303 * causes reconfiguration; there will be a state 304 * transition from RUN->RUN that means we may 305 * be called with beacon transmission active. 306 */ 307 callout_stop(&avp->av_swba); 308 309 error = wtap_beacon_alloc(sc, ni); 310 if (error != 0) 311 goto bad; 312 313 /* 314 * If joining an adhoc network defer beacon timer 315 * configuration to the next beacon frame so we 316 * have a current TSF to use. Otherwise we're 317 * starting an ibss/bss so there's no need to delay; 318 * if this is the first vap moving to RUN state, then 319 * beacon state needs to be [re]configured. 320 */ 321 if (vap->iv_opmode == IEEE80211_M_IBSS && 322 ni->ni_tstamp.tsf != 0) 323 break; 324 325 wtap_beacon_config(sc, vap); 326 327 /* Start TSF timer from now, and start s/w beacon alert */ 328 wtap_hal_reset_tsf(sc->hal); 329 callout_reset(&avp->av_swba, avp->av_bcinterval, 330 wtap_beacon_intrp, vap); 331 break; 332 default: 333 goto bad; 334 } 335 } else if (nstate == IEEE80211_S_INIT) { 336 callout_stop(&avp->av_swba); 337 } 338 ieee80211_free_node(ni); 339 return 0; 340 bad: 341 printf("%s: bad\n", __func__); 342 ieee80211_free_node(ni); 343 return error; 344 } 345 346 static void 347 wtap_bmiss(struct ieee80211vap *vap) 348 { 349 struct wtap_vap *avp = (struct wtap_vap *)vap; 350 351 DWTAP_PRINTF("%s\n", __func__); 352 avp->av_bmiss(vap); 353 } 354 355 static struct ieee80211vap * 356 wtap_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], 357 int unit, enum ieee80211_opmode opmode, int flags, 358 const uint8_t bssid[IEEE80211_ADDR_LEN], 359 const uint8_t mac[IEEE80211_ADDR_LEN]) 360 { 361 struct wtap_softc *sc = ic->ic_softc; 362 struct ieee80211vap *vap; 363 struct wtap_vap *avp; 364 int error; 365 struct ieee80211_node *ni; 366 367 DWTAP_PRINTF("%s\n", __func__); 368 369 avp = malloc(sizeof(struct wtap_vap), M_80211_VAP, M_WAITOK | M_ZERO); 370 avp->id = sc->id; 371 avp->av_md = sc->sc_md; 372 avp->av_bcinterval = msecs_to_ticks(BEACON_INTRERVAL + 100*sc->id); 373 vap = (struct ieee80211vap *) avp; 374 error = ieee80211_vap_setup(ic, vap, name, unit, opmode, 375 flags | IEEE80211_CLONE_NOBEACONS, bssid); 376 if (error) { 377 free(avp, M_80211_VAP); 378 return (NULL); 379 } 380 381 /* override various methods */ 382 avp->av_recv_mgmt = vap->iv_recv_mgmt; 383 vap->iv_recv_mgmt = wtap_recv_mgmt; 384 vap->iv_reset = wtap_reset_vap; 385 vap->iv_update_beacon = wtap_beacon_update; 386 avp->av_newstate = vap->iv_newstate; 387 vap->iv_newstate = wtap_newstate; 388 avp->av_bmiss = vap->iv_bmiss; 389 vap->iv_bmiss = wtap_bmiss; 390 391 /* complete setup */ 392 ieee80211_vap_attach(vap, ieee80211_media_change, 393 ieee80211_media_status, mac); 394 avp->av_dev = make_dev(&wtap_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, 395 "%s", if_name(vap->iv_ifp)); 396 avp->av_dev->si_drv1 = sc; 397 callout_init(&avp->av_swba, 0); 398 399 /* TODO this is a hack to force it to choose the rate we want */ 400 ni = ieee80211_ref_node(vap->iv_bss); 401 ieee80211_node_set_txrate_ht_mcsrate(ni, 2); 402 ieee80211_free_node(ni); 403 return vap; 404 } 405 406 static void 407 wtap_vap_delete(struct ieee80211vap *vap) 408 { 409 struct wtap_vap *avp = WTAP_VAP(vap); 410 411 DWTAP_PRINTF("%s\n", __func__); 412 destroy_dev(avp->av_dev); 413 callout_stop(&avp->av_swba); 414 ieee80211_vap_detach(vap); 415 free(avp, M_80211_VAP); 416 } 417 418 static void 419 wtap_parent(struct ieee80211com *ic) 420 { 421 struct wtap_softc *sc = ic->ic_softc; 422 423 if (ic->ic_nrunning > 0) { 424 sc->up = 1; 425 ieee80211_start_all(ic); 426 } else 427 sc->up = 0; 428 } 429 430 static void 431 wtap_scan_start(struct ieee80211com *ic) 432 { 433 434 #if 0 435 DWTAP_PRINTF("%s\n", __func__); 436 #endif 437 } 438 439 static void 440 wtap_scan_end(struct ieee80211com *ic) 441 { 442 443 #if 0 444 DWTAP_PRINTF("%s\n", __func__); 445 #endif 446 } 447 448 static void 449 wtap_set_channel(struct ieee80211com *ic) 450 { 451 452 #if 0 453 DWTAP_PRINTF("%s\n", __func__); 454 #endif 455 } 456 457 static int 458 wtap_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, 459 const struct ieee80211_bpf_params *params) 460 { 461 #if 0 462 DWTAP_PRINTF("%s, %p\n", __func__, m); 463 #endif 464 struct ieee80211vap *vap = ni->ni_vap; 465 struct wtap_vap *avp = WTAP_VAP(vap); 466 467 if (ieee80211_radiotap_active_vap(vap)) { 468 ieee80211_radiotap_tx(vap, m); 469 } 470 if (m->m_flags & M_TXCB) 471 ieee80211_process_callback(ni, m, 0); 472 ieee80211_free_node(ni); 473 return wtap_medium_enqueue(avp, m); 474 } 475 476 void 477 wtap_inject(struct wtap_softc *sc, struct mbuf *m) 478 { 479 struct wtap_buf *bf = (struct wtap_buf *)malloc(sizeof(struct wtap_buf), 480 M_WTAP_RXBUF, M_NOWAIT | M_ZERO); 481 KASSERT(bf != NULL, ("could not allocated a new wtap_buf\n")); 482 bf->m = m; 483 484 mtx_lock(&sc->sc_mtx); 485 STAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list); 486 taskqueue_enqueue(sc->sc_tq, &sc->sc_rxtask); 487 mtx_unlock(&sc->sc_mtx); 488 } 489 490 static void 491 wtap_rx_proc(void *arg, int npending) 492 { 493 struct wtap_softc *sc = (struct wtap_softc *)arg; 494 struct ieee80211com *ic = &sc->sc_ic; 495 struct mbuf *m; 496 struct ieee80211_node *ni; 497 struct wtap_buf *bf; 498 499 #if 0 500 DWTAP_PRINTF("%s\n", __func__); 501 #endif 502 503 for(;;) { 504 mtx_lock(&sc->sc_mtx); 505 bf = STAILQ_FIRST(&sc->sc_rxbuf); 506 if (bf == NULL) { 507 mtx_unlock(&sc->sc_mtx); 508 return; 509 } 510 STAILQ_REMOVE_HEAD(&sc->sc_rxbuf, bf_list); 511 mtx_unlock(&sc->sc_mtx); 512 KASSERT(bf != NULL, ("wtap_buf is NULL\n")); 513 m = bf->m; 514 DWTAP_PRINTF("[%d] receiving m=%p\n", sc->id, bf->m); 515 if (m == NULL) { /* NB: shouldn't happen */ 516 ic_printf(ic, "%s: no mbuf!\n", __func__); 517 free(bf, M_WTAP_RXBUF); 518 return; 519 } 520 521 /* 522 * It's weird to do this, but sometimes wtap will 523 * receive AMPDU packets (like ping(8)) even when 524 * the ic does not supports 11n HT. 525 */ 526 m->m_flags &= ~M_AMPDU; 527 #if 0 528 ieee80211_dump_pkt(ic, mtod(m, caddr_t), 0,0,0); 529 #endif 530 531 /* 532 * Locate the node for sender, track state, and then 533 * pass the (referenced) node up to the 802.11 layer 534 * for its use. 535 */ 536 ni = ieee80211_find_rxnode_withkey(ic, 537 mtod(m, const struct ieee80211_frame_min *), 538 IEEE80211_KEYIX_NONE); 539 if (ni != NULL) { 540 /* 541 * Sending station is known, dispatch directly. 542 */ 543 ieee80211_input(ni, m, 1<<7, 10); 544 ieee80211_free_node(ni); 545 } else { 546 ieee80211_input_all(ic, m, 1<<7, 10); 547 } 548 549 /* The mbufs are freed by the Net80211 stack */ 550 free(bf, M_WTAP_RXBUF); 551 } 552 } 553 554 static void 555 wtap_newassoc(struct ieee80211_node *ni, int isnew) 556 { 557 558 DWTAP_PRINTF("%s\n", __func__); 559 } 560 561 /* 562 * Callback from the 802.11 layer to update WME parameters. 563 */ 564 static int 565 wtap_wme_update(struct ieee80211com *ic) 566 { 567 568 DWTAP_PRINTF("%s\n", __func__); 569 return 0; 570 } 571 572 static void 573 wtap_update_mcast(struct ieee80211com *ic) 574 { 575 576 DWTAP_PRINTF("%s\n", __func__); 577 } 578 579 static void 580 wtap_update_promisc(struct ieee80211com *ic) 581 { 582 583 DWTAP_PRINTF("%s\n", __func__); 584 } 585 586 static int 587 wtap_transmit(struct ieee80211com *ic, struct mbuf *m) 588 { 589 struct ieee80211_node *ni = 590 (struct ieee80211_node *) m->m_pkthdr.rcvif; 591 struct ieee80211vap *vap = ni->ni_vap; 592 struct wtap_vap *avp = WTAP_VAP(vap); 593 594 if(ni == NULL){ 595 printf("m->m_pkthdr.rcvif is NULL we can't radiotap_tx\n"); 596 }else{ 597 if (ieee80211_radiotap_active_vap(vap)) 598 ieee80211_radiotap_tx(vap, m); 599 } 600 if (m->m_flags & M_TXCB) 601 ieee80211_process_callback(ni, m, 0); 602 ieee80211_free_node(ni); 603 return wtap_medium_enqueue(avp, m); 604 } 605 606 static struct ieee80211_node * 607 wtap_node_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN]) 608 { 609 struct ieee80211_node *ni; 610 611 DWTAP_PRINTF("%s\n", __func__); 612 613 ni = malloc(sizeof(struct ieee80211_node), M_80211_NODE, 614 M_NOWAIT|M_ZERO); 615 if (ni == NULL) 616 return (NULL); 617 ieee80211_node_set_txrate_ht_mcsrate(ni, 2); 618 return ni; 619 } 620 621 static void 622 wtap_node_free(struct ieee80211_node *ni) 623 { 624 struct ieee80211com *ic = ni->ni_ic; 625 struct wtap_softc *sc = ic->ic_softc; 626 627 DWTAP_PRINTF("%s\n", __func__); 628 sc->sc_node_free(ni); 629 } 630 631 int32_t 632 wtap_attach(struct wtap_softc *sc, const uint8_t *macaddr) 633 { 634 struct ieee80211com *ic = &sc->sc_ic; 635 636 DWTAP_PRINTF("%s\n", __func__); 637 638 sc->up = 0; 639 STAILQ_INIT(&sc->sc_rxbuf); 640 sc->sc_tq = taskqueue_create("wtap_taskq", M_NOWAIT | M_ZERO, 641 taskqueue_thread_enqueue, &sc->sc_tq); 642 taskqueue_start_threads(&sc->sc_tq, 1, PI_SOFT, "%s taskQ", sc->name); 643 NET_TASK_INIT(&sc->sc_rxtask, 0, wtap_rx_proc, sc); 644 645 ic->ic_softc = sc; 646 ic->ic_name = sc->name; 647 ic->ic_phytype = IEEE80211_T_DS; 648 ic->ic_opmode = IEEE80211_M_MBSS; 649 ic->ic_caps = IEEE80211_C_MBSS | IEEE80211_C_IBSS; 650 651 ic->ic_max_keyix = 128; /* A value read from Atheros ATH_KEYMAX */ 652 653 ic->ic_regdomain.regdomain = SKU_ETSI; 654 ic->ic_regdomain.country = CTRY_SWEDEN; 655 ic->ic_regdomain.location = 1; /* Indoors */ 656 ic->ic_regdomain.isocc[0] = 'S'; 657 ic->ic_regdomain.isocc[1] = 'E'; 658 659 ic->ic_nchans = 1; 660 ic->ic_channels[0].ic_flags = IEEE80211_CHAN_B; 661 ic->ic_channels[0].ic_freq = 2412; 662 663 IEEE80211_ADDR_COPY(ic->ic_macaddr, macaddr); 664 ieee80211_ifattach(ic); 665 666 /* override default methods */ 667 ic->ic_newassoc = wtap_newassoc; 668 ic->ic_wme.wme_update = wtap_wme_update; 669 ic->ic_vap_create = wtap_vap_create; 670 ic->ic_vap_delete = wtap_vap_delete; 671 ic->ic_raw_xmit = wtap_raw_xmit; 672 ic->ic_update_mcast = wtap_update_mcast; 673 ic->ic_update_promisc = wtap_update_promisc; 674 ic->ic_transmit = wtap_transmit; 675 ic->ic_parent = wtap_parent; 676 677 sc->sc_node_alloc = ic->ic_node_alloc; 678 ic->ic_node_alloc = wtap_node_alloc; 679 sc->sc_node_free = ic->ic_node_free; 680 ic->ic_node_free = wtap_node_free; 681 682 ic->ic_scan_start = wtap_scan_start; 683 ic->ic_scan_end = wtap_scan_end; 684 ic->ic_set_channel = wtap_set_channel; 685 686 ieee80211_radiotap_attach(ic, 687 &sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th), 688 WTAP_TX_RADIOTAP_PRESENT, 689 &sc->sc_rx_th.wr_ihdr, sizeof(sc->sc_rx_th), 690 WTAP_RX_RADIOTAP_PRESENT); 691 692 /* Work here, we must find a way to populate the rate table */ 693 #if 0 694 if(ic->ic_rt == NULL){ 695 printf("no table for ic_curchan\n"); 696 ic->ic_rt = ieee80211_get_ratetable(&ic->ic_channels[0]); 697 } 698 printf("ic->ic_rt =%p\n", ic->ic_rt); 699 printf("rate count %d\n", ic->ic_rt->rateCount); 700 701 uint8_t code = ic->ic_rt->info[0].dot11Rate; 702 uint8_t cix = ic->ic_rt->info[0].ctlRateIndex; 703 uint8_t ctl_rate = ic->ic_rt->info[cix].dot11Rate; 704 printf("code=%d, cix=%d, ctl_rate=%d\n", code, cix, ctl_rate); 705 706 uint8_t rix0 = ic->ic_rt->rateCodeToIndex[130]; 707 uint8_t rix1 = ic->ic_rt->rateCodeToIndex[132]; 708 uint8_t rix2 = ic->ic_rt->rateCodeToIndex[139]; 709 uint8_t rix3 = ic->ic_rt->rateCodeToIndex[150]; 710 printf("rix0 %u,rix1 %u,rix2 %u,rix3 %u\n", rix0,rix1,rix2,rix3); 711 printf("lpAckDuration=%u\n", ic->ic_rt->info[0].lpAckDuration); 712 printf("rate=%d\n", ic->ic_rt->info[0].rateKbps); 713 #endif 714 return 0; 715 } 716 717 int32_t 718 wtap_detach(struct wtap_softc *sc) 719 { 720 struct ieee80211com *ic = &sc->sc_ic; 721 722 DWTAP_PRINTF("%s\n", __func__); 723 ieee80211_ageq_drain(&ic->ic_stageq); 724 ieee80211_ifdetach(ic); 725 return 0; 726 } 727 728 void 729 wtap_resume(struct wtap_softc *sc) 730 { 731 732 DWTAP_PRINTF("%s\n", __func__); 733 } 734 735 void 736 wtap_suspend(struct wtap_softc *sc) 737 { 738 739 DWTAP_PRINTF("%s\n", __func__); 740 } 741 742 void 743 wtap_shutdown(struct wtap_softc *sc) 744 { 745 746 DWTAP_PRINTF("%s\n", __func__); 747 } 748 749 void 750 wtap_intr(struct wtap_softc *sc) 751 { 752 753 DWTAP_PRINTF("%s\n", __func__); 754 } 755