1229970Sadrian/*- 2229970Sadrian * Copyright (c) 2010-2011 Monthadar Al Jaberi, TerraNet AB 3229970Sadrian * All rights reserved. 4229970Sadrian * 5229970Sadrian * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting 6229970Sadrian * All rights reserved. 7229970Sadrian * 8229970Sadrian * Redistribution and use in source and binary forms, with or without 9229970Sadrian * modification, are permitted provided that the following conditions 10229970Sadrian * are met: 11229970Sadrian * 1. Redistributions of source code must retain the above copyright 12229970Sadrian * notice, this list of conditions and the following disclaimer, 13229970Sadrian * without modification. 14229970Sadrian * 2. Redistributions in binary form must reproduce at minimum a disclaimer 15229970Sadrian * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 16229970Sadrian * redistribution must be conditioned upon including a substantially 17229970Sadrian * similar Disclaimer requirement for further binary redistribution. 18229970Sadrian * 19229970Sadrian * NO WARRANTY 20229970Sadrian * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21229970Sadrian * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22229970Sadrian * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 23229970Sadrian * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 24229970Sadrian * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 25229970Sadrian * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26229970Sadrian * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27229970Sadrian * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 28229970Sadrian * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29229970Sadrian * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30229970Sadrian * THE POSSIBILITY OF SUCH DAMAGES. 31229970Sadrian * 32229970Sadrian * $FreeBSD: stable/11/sys/dev/wtap/if_wtap.c 343823 2019-02-06 02:35:56Z avos $ 33229970Sadrian */ 34229970Sadrian#include "if_wtapvar.h" 35229970Sadrian#include <sys/uio.h> /* uio struct */ 36229970Sadrian#include <sys/jail.h> 37229970Sadrian#include <net/if_var.h> 38229970Sadrian#include <net/vnet.h> 39229970Sadrian 40229970Sadrian#include <net80211/ieee80211_ratectl.h> 41229970Sadrian#include "if_medium.h" 42229970Sadrian 43232763Sadrian/* 44232763Sadrian * This _requires_ vimage to be useful. 45232763Sadrian */ 46232763Sadrian#ifndef VIMAGE 47232763Sadrian#error if_wtap requires VIMAGE. 48232763Sadrian#endif /* VIMAGE */ 49232763Sadrian 50229970Sadrian/* device for IOCTL and read/write for debuggin purposes */ 51229970Sadrian/* Function prototypes */ 52229970Sadrianstatic d_open_t wtap_node_open; 53229970Sadrianstatic d_close_t wtap_node_close; 54229970Sadrianstatic d_write_t wtap_node_write; 55229970Sadrianstatic d_ioctl_t wtap_node_ioctl; 56229970Sadrian 57229970Sadrianstatic struct cdevsw wtap_cdevsw = { 58229970Sadrian .d_version = D_VERSION, 59229970Sadrian .d_flags = 0, 60229970Sadrian .d_open = wtap_node_open, 61229970Sadrian .d_close = wtap_node_close, 62229970Sadrian .d_write = wtap_node_write, 63229970Sadrian .d_ioctl = wtap_node_ioctl, 64229970Sadrian .d_name = "wtapnode", 65229970Sadrian}; 66229970Sadrian 67229970Sadrianstatic int 68229970Sadrianwtap_node_open(struct cdev *dev, int oflags, int devtype, struct thread *p) 69229970Sadrian{ 70229970Sadrian 71229970Sadrian int err = 0; 72229970Sadrian uprintf("Opened device \"echo\" successfully.\n"); 73229970Sadrian return(err); 74229970Sadrian} 75229970Sadrian 76229970Sadrianstatic int 77229970Sadrianwtap_node_close(struct cdev *dev, int fflag, int devtype, struct thread *p) 78229970Sadrian{ 79229970Sadrian 80229970Sadrian uprintf("Closing device \"echo.\"\n"); 81229970Sadrian return(0); 82229970Sadrian} 83229970Sadrian 84229970Sadrianstatic int 85229970Sadrianwtap_node_write(struct cdev *dev, struct uio *uio, int ioflag) 86229970Sadrian{ 87229970Sadrian int err = 0; 88229970Sadrian struct mbuf *m; 89229970Sadrian struct ifnet *ifp; 90229970Sadrian struct wtap_softc *sc; 91229970Sadrian uint8_t buf[1024]; 92229970Sadrian int buf_len; 93229970Sadrian 94231378Sed uprintf("write device %s \"echo.\"\n", devtoname(dev)); 95229970Sadrian buf_len = MIN(uio->uio_iov->iov_len, 1024); 96229970Sadrian err = copyin(uio->uio_iov->iov_base, buf, buf_len); 97229970Sadrian 98229970Sadrian if (err != 0) { 99229970Sadrian uprintf("Write failed: bad address!\n"); 100229970Sadrian return (err); 101229970Sadrian } 102229970Sadrian 103243857Sglebius MGETHDR(m, M_NOWAIT, MT_DATA); 104229970Sadrian m_copyback(m, 0, buf_len, buf); 105229970Sadrian 106229970Sadrian CURVNET_SET(TD_TO_VNET(curthread)); 107229970Sadrian IFNET_RLOCK_NOSLEEP(); 108229970Sadrian 109229970Sadrian TAILQ_FOREACH(ifp, &V_ifnet, if_link) { 110229970Sadrian printf("ifp->if_xname = %s\n", ifp->if_xname); 111231378Sed if(strcmp(devtoname(dev), ifp->if_xname) == 0){ 112229970Sadrian printf("found match, correspoding wtap = %s\n", 113229970Sadrian ifp->if_xname); 114229970Sadrian sc = (struct wtap_softc *)ifp->if_softc; 115229970Sadrian printf("wtap id = %d\n", sc->id); 116229970Sadrian wtap_inject(sc, m); 117229970Sadrian } 118229970Sadrian } 119229970Sadrian 120229970Sadrian IFNET_RUNLOCK_NOSLEEP(); 121229970Sadrian CURVNET_RESTORE(); 122229970Sadrian 123229970Sadrian return(err); 124229970Sadrian} 125229970Sadrian 126229970Sadrianint 127229970Sadrianwtap_node_ioctl(struct cdev *dev, u_long cmd, caddr_t data, 128229970Sadrian int fflag, struct thread *td) 129229970Sadrian{ 130229970Sadrian int error = 0; 131229970Sadrian 132229970Sadrian switch(cmd) { 133229970Sadrian default: 134298931Spfg DWTAP_PRINTF("Unknown WTAP IOCTL\n"); 135229970Sadrian error = EINVAL; 136229970Sadrian } 137229970Sadrian return error; 138229970Sadrian} 139229970Sadrian 140229970Sadrianstatic int wtap_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, 141229970Sadrian const struct ieee80211_bpf_params *params); 142229970Sadrian 143229970Sadrianstatic int 144229970Sadrianwtap_medium_enqueue(struct wtap_vap *avp, struct mbuf *m) 145229970Sadrian{ 146229970Sadrian 147229970Sadrian return medium_transmit(avp->av_md, avp->id, m); 148229970Sadrian} 149229970Sadrian 150229970Sadrianstatic int 151229970Sadrianwtap_media_change(struct ifnet *ifp) 152229970Sadrian{ 153229970Sadrian 154229970Sadrian DWTAP_PRINTF("%s\n", __func__); 155229970Sadrian int error = ieee80211_media_change(ifp); 156229970Sadrian /* NB: only the fixed rate can change and that doesn't need a reset */ 157229970Sadrian return (error == ENETRESET ? 0 : error); 158229970Sadrian} 159229970Sadrian 160229970Sadrian/* 161229970Sadrian * Intercept management frames to collect beacon rssi data 162229970Sadrian * and to do ibss merges. 163229970Sadrian */ 164229970Sadrianstatic void 165229970Sadrianwtap_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m, 166286363Sglebius int subtype, const struct ieee80211_rx_stats *stats, int rssi, int nf) 167229970Sadrian{ 168229970Sadrian struct ieee80211vap *vap = ni->ni_vap; 169229970Sadrian#if 0 170229970Sadrian DWTAP_PRINTF("[%d] %s\n", myath_id(ni), __func__); 171229970Sadrian#endif 172286363Sglebius WTAP_VAP(vap)->av_recv_mgmt(ni, m, subtype, stats, rssi, nf); 173229970Sadrian} 174229970Sadrian 175229970Sadrianstatic int 176229970Sadrianwtap_reset_vap(struct ieee80211vap *vap, u_long cmd) 177229970Sadrian{ 178229970Sadrian 179229970Sadrian DWTAP_PRINTF("%s\n", __func__); 180229970Sadrian return 0; 181229970Sadrian} 182229970Sadrian 183229970Sadrianstatic void 184229970Sadrianwtap_beacon_update(struct ieee80211vap *vap, int item) 185229970Sadrian{ 186288095Sadrian struct ieee80211_beacon_offsets *bo = &vap->iv_bcn_off; 187229970Sadrian 188229970Sadrian DWTAP_PRINTF("%s\n", __func__); 189229970Sadrian setbit(bo->bo_flags, item); 190229970Sadrian} 191229970Sadrian 192229970Sadrian/* 193229970Sadrian * Allocate and setup an initial beacon frame. 194229970Sadrian */ 195229970Sadrianstatic int 196229970Sadrianwtap_beacon_alloc(struct wtap_softc *sc, struct ieee80211_node *ni) 197229970Sadrian{ 198229970Sadrian struct ieee80211vap *vap = ni->ni_vap; 199229970Sadrian struct wtap_vap *avp = WTAP_VAP(vap); 200229970Sadrian 201229970Sadrian DWTAP_PRINTF("[%s] %s\n", ether_sprintf(ni->ni_macaddr), __func__); 202229970Sadrian 203229970Sadrian /* 204229970Sadrian * NB: the beacon data buffer must be 32-bit aligned; 205229970Sadrian * we assume the mbuf routines will return us something 206229970Sadrian * with this alignment (perhaps should assert). 207229970Sadrian */ 208288636Sadrian avp->beacon = ieee80211_beacon_alloc(ni); 209229970Sadrian if (avp->beacon == NULL) { 210229970Sadrian printf("%s: cannot get mbuf\n", __func__); 211229970Sadrian return ENOMEM; 212229970Sadrian } 213229970Sadrian callout_init(&avp->av_swba, 0); 214229970Sadrian avp->bf_node = ieee80211_ref_node(ni); 215229970Sadrian 216229970Sadrian return 0; 217229970Sadrian} 218229970Sadrian 219229970Sadrianstatic void 220229970Sadrianwtap_beacon_config(struct wtap_softc *sc, struct ieee80211vap *vap) 221229970Sadrian{ 222229970Sadrian 223229970Sadrian DWTAP_PRINTF("%s\n", __func__); 224229970Sadrian} 225229970Sadrian 226229970Sadrianstatic void 227229970Sadrianwtap_beacon_intrp(void *arg) 228229970Sadrian{ 229229970Sadrian struct wtap_vap *avp = arg; 230229970Sadrian struct ieee80211vap *vap = arg; 231229970Sadrian struct mbuf *m; 232229970Sadrian 233238938Smonthadar if (vap->iv_state < IEEE80211_S_RUN) { 234238938Smonthadar DWTAP_PRINTF("Skip beacon, not running, state %d", vap->iv_state); 235238938Smonthadar return ; 236238938Smonthadar } 237229970Sadrian DWTAP_PRINTF("[%d] beacon intrp\n", avp->id); //burst mode 238229970Sadrian /* 239229970Sadrian * Update dynamic beacon contents. If this returns 240229970Sadrian * non-zero then we need to remap the memory because 241229970Sadrian * the beacon frame changed size (probably because 242229970Sadrian * of the TIM bitmap). 243229970Sadrian */ 244243857Sglebius m = m_dup(avp->beacon, M_NOWAIT); 245288636Sadrian if (ieee80211_beacon_update(avp->bf_node, m, 0)) { 246229970Sadrian printf("%s, need to remap the memory because the beacon frame" 247229970Sadrian " changed size.\n",__func__); 248229970Sadrian } 249229970Sadrian 250229970Sadrian if (ieee80211_radiotap_active_vap(vap)) 251229970Sadrian ieee80211_radiotap_tx(vap, m); 252229970Sadrian 253229970Sadrian#if 0 254229970Sadrian medium_transmit(avp->av_md, avp->id, m); 255229970Sadrian#endif 256229970Sadrian wtap_medium_enqueue(avp, m); 257229970Sadrian callout_schedule(&avp->av_swba, avp->av_bcinterval); 258229970Sadrian} 259229970Sadrian 260229970Sadrianstatic int 261229970Sadrianwtap_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) 262229970Sadrian{ 263229970Sadrian struct ieee80211com *ic = vap->iv_ic; 264287197Sglebius struct wtap_softc *sc = ic->ic_softc; 265229970Sadrian struct wtap_vap *avp = WTAP_VAP(vap); 266229970Sadrian struct ieee80211_node *ni = NULL; 267229970Sadrian int error; 268229970Sadrian 269229970Sadrian DWTAP_PRINTF("%s\n", __func__); 270229970Sadrian 271239760Sadrian ni = ieee80211_ref_node(vap->iv_bss); 272229970Sadrian /* 273229970Sadrian * Invoke the parent method to do net80211 work. 274229970Sadrian */ 275229970Sadrian error = avp->av_newstate(vap, nstate, arg); 276229970Sadrian if (error != 0) 277229970Sadrian goto bad; 278229970Sadrian 279229970Sadrian if (nstate == IEEE80211_S_RUN) { 280229970Sadrian /* NB: collect bss node again, it may have changed */ 281239760Sadrian ieee80211_free_node(ni); 282239760Sadrian ni = ieee80211_ref_node(vap->iv_bss); 283229970Sadrian switch (vap->iv_opmode) { 284229970Sadrian case IEEE80211_M_MBSS: 285229970Sadrian error = wtap_beacon_alloc(sc, ni); 286229970Sadrian if (error != 0) 287229970Sadrian goto bad; 288229970Sadrian wtap_beacon_config(sc, vap); 289229970Sadrian callout_reset(&avp->av_swba, avp->av_bcinterval, 290229970Sadrian wtap_beacon_intrp, vap); 291229970Sadrian break; 292229970Sadrian default: 293229970Sadrian goto bad; 294229970Sadrian } 295238938Smonthadar } else if (nstate == IEEE80211_S_INIT) { 296238938Smonthadar callout_stop(&avp->av_swba); 297229970Sadrian } 298239760Sadrian ieee80211_free_node(ni); 299229970Sadrian return 0; 300229970Sadrianbad: 301229970Sadrian printf("%s: bad\n", __func__); 302239760Sadrian ieee80211_free_node(ni); 303229970Sadrian return error; 304229970Sadrian} 305229970Sadrian 306229970Sadrianstatic void 307229970Sadrianwtap_bmiss(struct ieee80211vap *vap) 308229970Sadrian{ 309229970Sadrian struct wtap_vap *avp = (struct wtap_vap *)vap; 310229970Sadrian 311229970Sadrian DWTAP_PRINTF("%s\n", __func__); 312229970Sadrian avp->av_bmiss(vap); 313229970Sadrian} 314229970Sadrian 315229970Sadrianstatic struct ieee80211vap * 316229970Sadrianwtap_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], 317229970Sadrian int unit, enum ieee80211_opmode opmode, int flags, 318229970Sadrian const uint8_t bssid[IEEE80211_ADDR_LEN], 319229970Sadrian const uint8_t mac[IEEE80211_ADDR_LEN]) 320229970Sadrian{ 321287197Sglebius struct wtap_softc *sc = ic->ic_softc; 322229970Sadrian struct ieee80211vap *vap; 323229970Sadrian struct wtap_vap *avp; 324229970Sadrian int error; 325239760Sadrian struct ieee80211_node *ni; 326229970Sadrian 327229970Sadrian DWTAP_PRINTF("%s\n", __func__); 328229970Sadrian 329287197Sglebius avp = malloc(sizeof(struct wtap_vap), M_80211_VAP, M_WAITOK | M_ZERO); 330229970Sadrian avp->id = sc->id; 331229970Sadrian avp->av_md = sc->sc_md; 332232978Sadrian avp->av_bcinterval = msecs_to_ticks(BEACON_INTRERVAL + 100*sc->id); 333229970Sadrian vap = (struct ieee80211vap *) avp; 334229970Sadrian error = ieee80211_vap_setup(ic, vap, name, unit, IEEE80211_M_MBSS, 335287197Sglebius flags | IEEE80211_CLONE_NOBEACONS, bssid); 336244389Smonthadar if (error) { 337244399Smonthadar free(avp, M_80211_VAP); 338244399Smonthadar return (NULL); 339244389Smonthadar } 340229970Sadrian 341229970Sadrian /* override various methods */ 342229970Sadrian avp->av_recv_mgmt = vap->iv_recv_mgmt; 343229970Sadrian vap->iv_recv_mgmt = wtap_recv_mgmt; 344229970Sadrian vap->iv_reset = wtap_reset_vap; 345229970Sadrian vap->iv_update_beacon = wtap_beacon_update; 346229970Sadrian avp->av_newstate = vap->iv_newstate; 347229970Sadrian vap->iv_newstate = wtap_newstate; 348229970Sadrian avp->av_bmiss = vap->iv_bmiss; 349229970Sadrian vap->iv_bmiss = wtap_bmiss; 350229970Sadrian 351229970Sadrian /* complete setup */ 352287197Sglebius ieee80211_vap_attach(vap, wtap_media_change, ieee80211_media_status, 353287197Sglebius mac); 354229970Sadrian avp->av_dev = make_dev(&wtap_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, 355287197Sglebius "%s", (const char *)sc->name); 356229970Sadrian 357229970Sadrian /* TODO this is a hack to force it to choose the rate we want */ 358239760Sadrian ni = ieee80211_ref_node(vap->iv_bss); 359239760Sadrian ni->ni_txrate = 130; 360239760Sadrian ieee80211_free_node(ni); 361229970Sadrian return vap; 362229970Sadrian} 363229970Sadrian 364229970Sadrianstatic void 365229970Sadrianwtap_vap_delete(struct ieee80211vap *vap) 366229970Sadrian{ 367229970Sadrian struct wtap_vap *avp = WTAP_VAP(vap); 368229970Sadrian 369229970Sadrian DWTAP_PRINTF("%s\n", __func__); 370229970Sadrian destroy_dev(avp->av_dev); 371229970Sadrian callout_stop(&avp->av_swba); 372229970Sadrian ieee80211_vap_detach(vap); 373343823Savos free(avp, M_80211_VAP); 374229970Sadrian} 375229970Sadrian 376229970Sadrianstatic void 377287197Sglebiuswtap_parent(struct ieee80211com *ic) 378229970Sadrian{ 379287197Sglebius struct wtap_softc *sc = ic->ic_softc; 380229970Sadrian 381287197Sglebius if (ic->ic_nrunning > 0) { 382287197Sglebius sc->up = 1; 383287197Sglebius ieee80211_start_all(ic); 384287197Sglebius } else 385287197Sglebius sc->up = 0; 386229970Sadrian} 387229970Sadrian 388229970Sadrianstatic void 389229970Sadrianwtap_scan_start(struct ieee80211com *ic) 390229970Sadrian{ 391229970Sadrian 392229970Sadrian#if 0 393229970Sadrian DWTAP_PRINTF("%s\n", __func__); 394229970Sadrian#endif 395229970Sadrian} 396229970Sadrian 397229970Sadrianstatic void 398229970Sadrianwtap_scan_end(struct ieee80211com *ic) 399229970Sadrian{ 400229970Sadrian 401229970Sadrian#if 0 402229970Sadrian DWTAP_PRINTF("%s\n", __func__); 403229970Sadrian#endif 404229970Sadrian} 405229970Sadrian 406229970Sadrianstatic void 407229970Sadrianwtap_set_channel(struct ieee80211com *ic) 408229970Sadrian{ 409229970Sadrian 410229970Sadrian#if 0 411229970Sadrian DWTAP_PRINTF("%s\n", __func__); 412229970Sadrian#endif 413229970Sadrian} 414229970Sadrian 415229970Sadrianstatic int 416229970Sadrianwtap_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, 417229970Sadrian const struct ieee80211_bpf_params *params) 418229970Sadrian{ 419229970Sadrian#if 0 420229970Sadrian DWTAP_PRINTF("%s, %p\n", __func__, m); 421229970Sadrian#endif 422229970Sadrian struct ieee80211vap *vap = ni->ni_vap; 423229970Sadrian struct wtap_vap *avp = WTAP_VAP(vap); 424229970Sadrian 425229970Sadrian if (ieee80211_radiotap_active_vap(vap)) { 426229970Sadrian ieee80211_radiotap_tx(vap, m); 427229970Sadrian } 428229970Sadrian if (m->m_flags & M_TXCB) 429229970Sadrian ieee80211_process_callback(ni, m, 0); 430229970Sadrian ieee80211_free_node(ni); 431229970Sadrian return wtap_medium_enqueue(avp, m); 432229970Sadrian} 433229970Sadrian 434229970Sadrianvoid 435229970Sadrianwtap_inject(struct wtap_softc *sc, struct mbuf *m) 436229970Sadrian{ 437229970Sadrian struct wtap_buf *bf = (struct wtap_buf *)malloc(sizeof(struct wtap_buf), 438229970Sadrian M_WTAP_RXBUF, M_NOWAIT | M_ZERO); 439229970Sadrian KASSERT(bf != NULL, ("could not allocated a new wtap_buf\n")); 440229970Sadrian bf->m = m; 441229970Sadrian 442229970Sadrian mtx_lock(&sc->sc_mtx); 443229970Sadrian STAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list); 444229970Sadrian taskqueue_enqueue(sc->sc_tq, &sc->sc_rxtask); 445229970Sadrian mtx_unlock(&sc->sc_mtx); 446229970Sadrian} 447229970Sadrian 448229970Sadrianvoid 449229970Sadrianwtap_rx_deliver(struct wtap_softc *sc, struct mbuf *m) 450229970Sadrian{ 451287197Sglebius struct ieee80211com *ic = &sc->sc_ic; 452229970Sadrian struct ieee80211_node *ni; 453229970Sadrian int type; 454229970Sadrian#if 0 455229970Sadrian DWTAP_PRINTF("%s\n", __func__); 456229970Sadrian#endif 457229970Sadrian 458229970Sadrian DWTAP_PRINTF("[%d] receiving m=%p\n", sc->id, m); 459229970Sadrian if (m == NULL) { /* NB: shouldn't happen */ 460287197Sglebius ic_printf(ic, "%s: no mbuf!\n", __func__); 461229970Sadrian } 462229970Sadrian 463229970Sadrian ieee80211_dump_pkt(ic, mtod(m, caddr_t), 0,0,0); 464229970Sadrian 465229970Sadrian /* 466229970Sadrian * Locate the node for sender, track state, and then 467229970Sadrian * pass the (referenced) node up to the 802.11 layer 468229970Sadrian * for its use. 469229970Sadrian */ 470229970Sadrian ni = ieee80211_find_rxnode_withkey(ic, 471229970Sadrian mtod(m, const struct ieee80211_frame_min *),IEEE80211_KEYIX_NONE); 472229970Sadrian if (ni != NULL) { 473229970Sadrian /* 474229970Sadrian * Sending station is known, dispatch directly. 475229970Sadrian */ 476229970Sadrian type = ieee80211_input(ni, m, 1<<7, 10); 477229970Sadrian ieee80211_free_node(ni); 478229970Sadrian } else { 479229970Sadrian type = ieee80211_input_all(ic, m, 1<<7, 10); 480229970Sadrian } 481229970Sadrian} 482229970Sadrian 483229970Sadrianstatic void 484229970Sadrianwtap_rx_proc(void *arg, int npending) 485229970Sadrian{ 486229970Sadrian struct wtap_softc *sc = (struct wtap_softc *)arg; 487287197Sglebius struct ieee80211com *ic = &sc->sc_ic; 488229970Sadrian struct mbuf *m; 489229970Sadrian struct ieee80211_node *ni; 490229970Sadrian int type; 491229970Sadrian struct wtap_buf *bf; 492229970Sadrian 493229970Sadrian#if 0 494229970Sadrian DWTAP_PRINTF("%s\n", __func__); 495229970Sadrian#endif 496229970Sadrian 497229970Sadrian for(;;) { 498229970Sadrian mtx_lock(&sc->sc_mtx); 499229970Sadrian bf = STAILQ_FIRST(&sc->sc_rxbuf); 500229970Sadrian if (bf == NULL) { 501229970Sadrian mtx_unlock(&sc->sc_mtx); 502229970Sadrian return; 503229970Sadrian } 504229970Sadrian STAILQ_REMOVE_HEAD(&sc->sc_rxbuf, bf_list); 505229970Sadrian mtx_unlock(&sc->sc_mtx); 506229970Sadrian KASSERT(bf != NULL, ("wtap_buf is NULL\n")); 507229970Sadrian m = bf->m; 508229970Sadrian DWTAP_PRINTF("[%d] receiving m=%p\n", sc->id, bf->m); 509229970Sadrian if (m == NULL) { /* NB: shouldn't happen */ 510287197Sglebius ic_printf(ic, "%s: no mbuf!\n", __func__); 511229970Sadrian free(bf, M_WTAP_RXBUF); 512229970Sadrian return; 513229970Sadrian } 514229970Sadrian#if 0 515229970Sadrian ieee80211_dump_pkt(ic, mtod(m, caddr_t), 0,0,0); 516229970Sadrian#endif 517229970Sadrian 518229970Sadrian /* 519229970Sadrian * Locate the node for sender, track state, and then 520229970Sadrian * pass the (referenced) node up to the 802.11 layer 521229970Sadrian * for its use. 522229970Sadrian */ 523229970Sadrian ni = ieee80211_find_rxnode_withkey(ic, 524229970Sadrian mtod(m, const struct ieee80211_frame_min *), 525229970Sadrian IEEE80211_KEYIX_NONE); 526229970Sadrian if (ni != NULL) { 527229970Sadrian /* 528229970Sadrian * Sending station is known, dispatch directly. 529229970Sadrian */ 530229970Sadrian type = ieee80211_input(ni, m, 1<<7, 10); 531229970Sadrian ieee80211_free_node(ni); 532229970Sadrian } else { 533229970Sadrian type = ieee80211_input_all(ic, m, 1<<7, 10); 534229970Sadrian } 535229970Sadrian 536229970Sadrian /* The mbufs are freed by the Net80211 stack */ 537229970Sadrian free(bf, M_WTAP_RXBUF); 538229970Sadrian } 539229970Sadrian} 540229970Sadrian 541229970Sadrianstatic void 542229970Sadrianwtap_newassoc(struct ieee80211_node *ni, int isnew) 543229970Sadrian{ 544229970Sadrian 545229970Sadrian DWTAP_PRINTF("%s\n", __func__); 546229970Sadrian} 547229970Sadrian 548229970Sadrian/* 549229970Sadrian * Callback from the 802.11 layer to update WME parameters. 550229970Sadrian */ 551229970Sadrianstatic int 552229970Sadrianwtap_wme_update(struct ieee80211com *ic) 553229970Sadrian{ 554229970Sadrian 555229970Sadrian DWTAP_PRINTF("%s\n", __func__); 556229970Sadrian return 0; 557229970Sadrian} 558229970Sadrian 559229970Sadrianstatic void 560283540Sglebiuswtap_update_mcast(struct ieee80211com *ic) 561229970Sadrian{ 562229970Sadrian 563229970Sadrian DWTAP_PRINTF("%s\n", __func__); 564229970Sadrian} 565229970Sadrian 566229970Sadrianstatic void 567283540Sglebiuswtap_update_promisc(struct ieee80211com *ic) 568229970Sadrian{ 569229970Sadrian 570229970Sadrian DWTAP_PRINTF("%s\n", __func__); 571229970Sadrian} 572229970Sadrian 573229970Sadrianstatic int 574287197Sglebiuswtap_transmit(struct ieee80211com *ic, struct mbuf *m) 575229970Sadrian{ 576229970Sadrian struct ieee80211_node *ni = 577229970Sadrian (struct ieee80211_node *) m->m_pkthdr.rcvif; 578229970Sadrian struct ieee80211vap *vap = ni->ni_vap; 579229970Sadrian struct wtap_vap *avp = WTAP_VAP(vap); 580229970Sadrian 581229970Sadrian if(ni == NULL){ 582229970Sadrian printf("m->m_pkthdr.rcvif is NULL we cant radiotap_tx\n"); 583229970Sadrian }else{ 584229970Sadrian if (ieee80211_radiotap_active_vap(vap)) 585229970Sadrian ieee80211_radiotap_tx(vap, m); 586229970Sadrian } 587229970Sadrian if (m->m_flags & M_TXCB) 588229970Sadrian ieee80211_process_callback(ni, m, 0); 589229970Sadrian ieee80211_free_node(ni); 590229970Sadrian return wtap_medium_enqueue(avp, m); 591229970Sadrian} 592229970Sadrian 593229970Sadrianstatic struct ieee80211_node * 594229970Sadrianwtap_node_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN]) 595229970Sadrian{ 596229970Sadrian struct ieee80211_node *ni; 597229970Sadrian 598229970Sadrian DWTAP_PRINTF("%s\n", __func__); 599229970Sadrian 600229970Sadrian ni = malloc(sizeof(struct ieee80211_node), M_80211_NODE, 601229970Sadrian M_NOWAIT|M_ZERO); 602343823Savos if (ni == NULL) 603343823Savos return (NULL); 604229970Sadrian 605229970Sadrian ni->ni_txrate = 130; 606229970Sadrian return ni; 607229970Sadrian} 608229970Sadrian 609229970Sadrianstatic void 610229970Sadrianwtap_node_free(struct ieee80211_node *ni) 611229970Sadrian{ 612229970Sadrian struct ieee80211com *ic = ni->ni_ic; 613287197Sglebius struct wtap_softc *sc = ic->ic_softc; 614229970Sadrian 615229970Sadrian DWTAP_PRINTF("%s\n", __func__); 616229970Sadrian sc->sc_node_free(ni); 617229970Sadrian} 618229970Sadrian 619229970Sadrianint32_t 620229970Sadrianwtap_attach(struct wtap_softc *sc, const uint8_t *macaddr) 621229970Sadrian{ 622287197Sglebius struct ieee80211com *ic = &sc->sc_ic; 623229970Sadrian 624229970Sadrian DWTAP_PRINTF("%s\n", __func__); 625229970Sadrian 626229970Sadrian sc->up = 0; 627229970Sadrian STAILQ_INIT(&sc->sc_rxbuf); 628287197Sglebius sc->sc_tq = taskqueue_create("wtap_taskq", M_NOWAIT | M_ZERO, 629229970Sadrian taskqueue_thread_enqueue, &sc->sc_tq); 630287197Sglebius taskqueue_start_threads(&sc->sc_tq, 1, PI_SOFT, "%s taskQ", sc->name); 631229970Sadrian TASK_INIT(&sc->sc_rxtask, 0, wtap_rx_proc, sc); 632229970Sadrian 633283537Sglebius ic->ic_softc = sc; 634283527Sglebius ic->ic_name = sc->name; 635229970Sadrian ic->ic_phytype = IEEE80211_T_DS; 636229970Sadrian ic->ic_opmode = IEEE80211_M_MBSS; 637229970Sadrian ic->ic_caps = IEEE80211_C_MBSS; 638229970Sadrian 639229970Sadrian ic->ic_max_keyix = 128; /* A value read from Atheros ATH_KEYMAX */ 640229970Sadrian 641229970Sadrian ic->ic_regdomain.regdomain = SKU_ETSI; 642229970Sadrian ic->ic_regdomain.country = CTRY_SWEDEN; 643229970Sadrian ic->ic_regdomain.location = 1; /* Indoors */ 644229970Sadrian ic->ic_regdomain.isocc[0] = 'S'; 645229970Sadrian ic->ic_regdomain.isocc[1] = 'E'; 646244400Smonthadar 647229970Sadrian ic->ic_nchans = 1; 648229970Sadrian ic->ic_channels[0].ic_flags = IEEE80211_CHAN_B; 649229970Sadrian ic->ic_channels[0].ic_freq = 2412; 650229970Sadrian 651287197Sglebius IEEE80211_ADDR_COPY(ic->ic_macaddr, macaddr); 652287197Sglebius ieee80211_ifattach(ic); 653229970Sadrian 654229970Sadrian /* override default methods */ 655229970Sadrian ic->ic_newassoc = wtap_newassoc; 656229970Sadrian ic->ic_wme.wme_update = wtap_wme_update; 657229970Sadrian ic->ic_vap_create = wtap_vap_create; 658229970Sadrian ic->ic_vap_delete = wtap_vap_delete; 659229970Sadrian ic->ic_raw_xmit = wtap_raw_xmit; 660229970Sadrian ic->ic_update_mcast = wtap_update_mcast; 661229970Sadrian ic->ic_update_promisc = wtap_update_promisc; 662287197Sglebius ic->ic_transmit = wtap_transmit; 663287197Sglebius ic->ic_parent = wtap_parent; 664229970Sadrian 665229970Sadrian sc->sc_node_alloc = ic->ic_node_alloc; 666229970Sadrian ic->ic_node_alloc = wtap_node_alloc; 667229970Sadrian sc->sc_node_free = ic->ic_node_free; 668229970Sadrian ic->ic_node_free = wtap_node_free; 669229970Sadrian 670229970Sadrian ic->ic_scan_start = wtap_scan_start; 671229970Sadrian ic->ic_scan_end = wtap_scan_end; 672229970Sadrian ic->ic_set_channel = wtap_set_channel; 673229970Sadrian 674229970Sadrian ieee80211_radiotap_attach(ic, 675229970Sadrian &sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th), 676229970Sadrian WTAP_TX_RADIOTAP_PRESENT, 677229970Sadrian &sc->sc_rx_th.wr_ihdr, sizeof(sc->sc_rx_th), 678229970Sadrian WTAP_RX_RADIOTAP_PRESENT); 679229970Sadrian 680229970Sadrian /* Work here, we must find a way to populate the rate table */ 681229970Sadrian#if 0 682229970Sadrian if(ic->ic_rt == NULL){ 683229970Sadrian printf("no table for ic_curchan\n"); 684229970Sadrian ic->ic_rt = ieee80211_get_ratetable(&ic->ic_channels[0]); 685229970Sadrian } 686229970Sadrian printf("ic->ic_rt =%p\n", ic->ic_rt); 687229970Sadrian printf("rate count %d\n", ic->ic_rt->rateCount); 688229970Sadrian 689229970Sadrian uint8_t code = ic->ic_rt->info[0].dot11Rate; 690229970Sadrian uint8_t cix = ic->ic_rt->info[0].ctlRateIndex; 691229970Sadrian uint8_t ctl_rate = ic->ic_rt->info[cix].dot11Rate; 692229970Sadrian printf("code=%d, cix=%d, ctl_rate=%d\n", code, cix, ctl_rate); 693229970Sadrian 694229970Sadrian uint8_t rix0 = ic->ic_rt->rateCodeToIndex[130]; 695229970Sadrian uint8_t rix1 = ic->ic_rt->rateCodeToIndex[132]; 696229970Sadrian uint8_t rix2 = ic->ic_rt->rateCodeToIndex[139]; 697229970Sadrian uint8_t rix3 = ic->ic_rt->rateCodeToIndex[150]; 698229970Sadrian printf("rix0 %u,rix1 %u,rix2 %u,rix3 %u\n", rix0,rix1,rix2,rix3); 699229970Sadrian printf("lpAckDuration=%u\n", ic->ic_rt->info[0].lpAckDuration); 700229970Sadrian printf("rate=%d\n", ic->ic_rt->info[0].rateKbps); 701229970Sadrian#endif 702229970Sadrian return 0; 703229970Sadrian} 704229970Sadrian 705229970Sadrianint32_t 706229970Sadrianwtap_detach(struct wtap_softc *sc) 707229970Sadrian{ 708287197Sglebius struct ieee80211com *ic = &sc->sc_ic; 709229970Sadrian 710229970Sadrian DWTAP_PRINTF("%s\n", __func__); 711229970Sadrian ieee80211_ageq_drain(&ic->ic_stageq); 712229970Sadrian ieee80211_ifdetach(ic); 713229970Sadrian return 0; 714229970Sadrian} 715229970Sadrian 716229970Sadrianvoid 717229970Sadrianwtap_resume(struct wtap_softc *sc) 718229970Sadrian{ 719229970Sadrian 720229970Sadrian DWTAP_PRINTF("%s\n", __func__); 721229970Sadrian} 722229970Sadrian 723229970Sadrianvoid 724229970Sadrianwtap_suspend(struct wtap_softc *sc) 725229970Sadrian{ 726229970Sadrian 727229970Sadrian DWTAP_PRINTF("%s\n", __func__); 728229970Sadrian} 729229970Sadrian 730229970Sadrianvoid 731229970Sadrianwtap_shutdown(struct wtap_softc *sc) 732229970Sadrian{ 733229970Sadrian 734229970Sadrian DWTAP_PRINTF("%s\n", __func__); 735229970Sadrian} 736229970Sadrian 737229970Sadrianvoid 738229970Sadrianwtap_intr(struct wtap_softc *sc) 739229970Sadrian{ 740229970Sadrian 741229970Sadrian DWTAP_PRINTF("%s\n", __func__); 742229970Sadrian} 743