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