The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/wtap/if_wtap.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    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 }

Cache object: 30e3e6497bbebbd3fccdf3650fb5e120


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.