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