root/net80211/ieee80211_node.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ieee80211_node_attach
  2. ieee80211_alloc_node_helper
  3. ieee80211_node_lateattach
  4. ieee80211_node_detach
  5. ieee80211_reset_scan
  6. ieee80211_begin_scan
  7. ieee80211_next_scan
  8. ieee80211_create_ibss
  9. ieee80211_match_bss
  10. ieee80211_end_scan
  11. ieee80211_get_rate
  12. ieee80211_node_alloc
  13. ieee80211_node_cleanup
  14. ieee80211_node_free
  15. ieee80211_node_copy
  16. ieee80211_node_getrssi
  17. ieee80211_setup_node
  18. ieee80211_alloc_node
  19. ieee80211_dup_bss
  20. ieee80211_find_node
  21. ieee80211_find_txnode
  22. ieee80211_needs_rxnode
  23. ieee80211_find_rxnode
  24. ieee80211_find_node_for_beacon
  25. ieee80211_free_node
  26. ieee80211_release_node
  27. ieee80211_free_allnodes
  28. ieee80211_clean_nodes
  29. ieee80211_iterate_nodes
  30. ieee80211_iserp_sta
  31. ieee80211_node_join_11g
  32. ieee80211_node_join
  33. ieee80211_node_leave_11g
  34. ieee80211_node_leave
  35. ieee80211_set_tim
  36. ieee80211_node_cmp

    1 /*      $OpenBSD: ieee80211_node.c,v 1.28 2007/07/06 18:18:43 damien Exp $      */
    2 /*      $NetBSD: ieee80211_node.c,v 1.14 2004/05/09 09:18:47 dyoung Exp $       */
    3 
    4 /*-
    5  * Copyright (c) 2001 Atsushi Onoe
    6  * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting
    7  * All rights reserved.
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice, this list of conditions and the following disclaimer.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *    notice, this list of conditions and the following disclaimer in the
   16  *    documentation and/or other materials provided with the distribution.
   17  * 3. The name of the author may not be used to endorse or promote products
   18  *    derived from this software without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   30  */
   31 
   32 #include "bpfilter.h"
   33 #include "bridge.h"
   34 
   35 #include <sys/param.h>
   36 #include <sys/systm.h>
   37 #include <sys/mbuf.h>
   38 #include <sys/malloc.h>
   39 #include <sys/kernel.h>
   40 #include <sys/socket.h>
   41 #include <sys/sockio.h>
   42 #include <sys/endian.h>
   43 #include <sys/errno.h>
   44 #include <sys/proc.h>
   45 #include <sys/sysctl.h>
   46 #include <sys/tree.h>
   47 
   48 #include <net/if.h>
   49 #include <net/if_dl.h>
   50 #include <net/if_media.h>
   51 #include <net/if_arp.h>
   52 #include <net/if_llc.h>
   53 
   54 #if NBPFILTER > 0
   55 #include <net/bpf.h>
   56 #endif
   57 
   58 #ifdef INET
   59 #include <netinet/in.h>
   60 #include <netinet/if_ether.h>
   61 #endif
   62 
   63 #if NBRIDGE > 0
   64 #include <net/if_bridge.h>
   65 #endif
   66 
   67 #include <net80211/ieee80211_var.h>
   68 
   69 #include <dev/rndvar.h>
   70 
   71 struct ieee80211_node *ieee80211_node_alloc(struct ieee80211com *);
   72 void ieee80211_node_free(struct ieee80211com *, struct ieee80211_node *);
   73 void ieee80211_node_copy(struct ieee80211com *, struct ieee80211_node *,
   74     const struct ieee80211_node *);
   75 u_int8_t ieee80211_node_getrssi(struct ieee80211com *,
   76     const struct ieee80211_node *);
   77 void ieee80211_setup_node(struct ieee80211com *, struct ieee80211_node *,
   78     const u_int8_t *);
   79 void ieee80211_free_node(struct ieee80211com *, struct ieee80211_node *);
   80 struct ieee80211_node *ieee80211_alloc_node_helper(struct ieee80211com *);
   81 void ieee80211_node_cleanup(struct ieee80211com *, struct ieee80211_node *);
   82 void ieee80211_node_join_11g(struct ieee80211com *, struct ieee80211_node *);
   83 void ieee80211_node_leave_11g(struct ieee80211com *, struct ieee80211_node *);
   84 void ieee80211_set_tim(struct ieee80211com *, int, int);
   85 
   86 #define M_80211_NODE    M_DEVBUF
   87 
   88 void
   89 ieee80211_node_attach(struct ifnet *ifp)
   90 {
   91         struct ieee80211com *ic = (void *)ifp;
   92         int size;
   93 
   94         RB_INIT(&ic->ic_tree);
   95         ic->ic_node_alloc = ieee80211_node_alloc;
   96         ic->ic_node_free = ieee80211_node_free;
   97         ic->ic_node_copy = ieee80211_node_copy;
   98         ic->ic_node_getrssi = ieee80211_node_getrssi;
   99         ic->ic_scangen = 1;
  100         ic->ic_max_nnodes = ieee80211_cache_size;
  101 
  102         if (ic->ic_max_aid == 0)
  103                 ic->ic_max_aid = IEEE80211_AID_DEF;
  104         else if (ic->ic_max_aid > IEEE80211_AID_MAX)
  105                 ic->ic_max_aid = IEEE80211_AID_MAX;
  106         size = howmany(ic->ic_max_aid, 32) * sizeof(u_int32_t);
  107         MALLOC(ic->ic_aid_bitmap, u_int32_t *, size, M_DEVBUF, M_NOWAIT);
  108         if (ic->ic_aid_bitmap == NULL) {
  109                 /* XXX no way to recover */
  110                 printf("%s: no memory for AID bitmap!\n", __func__);
  111                 ic->ic_max_aid = 0;
  112         } else
  113                 memset(ic->ic_aid_bitmap, 0, size);
  114 
  115         if (ic->ic_caps & (IEEE80211_C_HOSTAP | IEEE80211_C_IBSS)) {
  116                 ic->ic_tim_len = howmany(ic->ic_max_aid, 8);
  117                 MALLOC(ic->ic_tim_bitmap, u_int8_t *, ic->ic_tim_len, M_DEVBUF,
  118                     M_NOWAIT);
  119                 if (ic->ic_tim_bitmap == NULL) {
  120                         printf("%s: no memory for TIM bitmap!\n", __func__);
  121                         ic->ic_tim_len = 0;
  122                 } else {
  123                         memset(ic->ic_tim_bitmap, 0, ic->ic_tim_len);
  124                         ic->ic_set_tim = ieee80211_set_tim;
  125                 }
  126         }
  127 }
  128 
  129 struct ieee80211_node *
  130 ieee80211_alloc_node_helper(struct ieee80211com *ic)
  131 {
  132         struct ieee80211_node *ni;
  133         if (ic->ic_nnodes >= ic->ic_max_nnodes)
  134                 ieee80211_clean_nodes(ic);
  135         if (ic->ic_nnodes >= ic->ic_max_nnodes)
  136                 return NULL;
  137         ni = (*ic->ic_node_alloc)(ic);
  138         if (ni != NULL)
  139                 ic->ic_nnodes++;
  140         return ni;
  141 }
  142 
  143 void
  144 ieee80211_node_lateattach(struct ifnet *ifp)
  145 {
  146         struct ieee80211com *ic = (void *)ifp;
  147         struct ieee80211_node *ni;
  148 
  149         ni = ieee80211_alloc_node_helper(ic);
  150         if (ni == NULL)
  151                 panic("unable to setup inital BSS node");
  152         ni->ni_chan = IEEE80211_CHAN_ANYC;
  153         ic->ic_bss = ieee80211_ref_node(ni);
  154         ic->ic_txpower = IEEE80211_TXPOWER_MAX;
  155 }
  156 
  157 void
  158 ieee80211_node_detach(struct ifnet *ifp)
  159 {
  160         struct ieee80211com *ic = (void *)ifp;
  161 
  162         if (ic->ic_bss != NULL) {
  163                 (*ic->ic_node_free)(ic, ic->ic_bss);
  164                 ic->ic_bss = NULL;
  165         }
  166         ieee80211_free_allnodes(ic);
  167         if (ic->ic_aid_bitmap != NULL)
  168                 FREE(ic->ic_aid_bitmap, M_DEVBUF);
  169         if (ic->ic_tim_bitmap != NULL)
  170                 FREE(ic->ic_tim_bitmap, M_DEVBUF);
  171 }
  172 
  173 /*
  174  * AP scanning support.
  175  */
  176 
  177 /*
  178  * Initialize the active channel set based on the set
  179  * of available channels and the current PHY mode.
  180  */
  181 void
  182 ieee80211_reset_scan(struct ifnet *ifp)
  183 {
  184         struct ieee80211com *ic = (void *)ifp;
  185 
  186         memcpy(ic->ic_chan_scan, ic->ic_chan_active,
  187                 sizeof(ic->ic_chan_active));
  188         /* NB: hack, setup so next_scan starts with the first channel */
  189         if (ic->ic_bss != NULL && ic->ic_bss->ni_chan == IEEE80211_CHAN_ANYC)
  190                 ic->ic_bss->ni_chan = &ic->ic_channels[IEEE80211_CHAN_MAX];
  191 }
  192 
  193 /*
  194  * Begin an active scan.
  195  */
  196 void
  197 ieee80211_begin_scan(struct ifnet *ifp)
  198 {
  199         struct ieee80211com *ic = (void *)ifp;
  200 
  201         if (ic->ic_scan_lock & IEEE80211_SCAN_LOCKED)
  202                 return;
  203         ic->ic_scan_lock |= IEEE80211_SCAN_LOCKED;
  204 
  205         /*
  206          * In all but hostap mode scanning starts off in
  207          * an active mode before switching to passive.
  208          */
  209         if (ic->ic_opmode != IEEE80211_M_HOSTAP) {
  210                 ic->ic_flags |= IEEE80211_F_ASCAN;
  211                 ic->ic_stats.is_scan_active++;
  212         } else
  213                 ic->ic_stats.is_scan_passive++;
  214         if (ifp->if_flags & IFF_DEBUG)
  215                 printf("%s: begin %s scan\n", ifp->if_xname,
  216                         (ic->ic_flags & IEEE80211_F_ASCAN) ?
  217                                 "active" : "passive");
  218 
  219         /*
  220          * Flush any previously seen AP's. Note that the latter 
  221          * assumes we don't act as both an AP and a station,
  222          * otherwise we'll potentially flush state of stations
  223          * associated with us.
  224          */
  225         ieee80211_free_allnodes(ic);
  226 
  227         /*
  228          * Reset the current mode. Setting the current mode will also
  229          * reset scan state.
  230          */
  231         if (IFM_MODE(ic->ic_media.ifm_cur->ifm_media) == IFM_AUTO)
  232                 ic->ic_curmode = IEEE80211_MODE_AUTO;
  233         ieee80211_setmode(ic, ic->ic_curmode);
  234 
  235         ic->ic_scan_count = 0;
  236 
  237         /* Scan the next channel. */
  238         ieee80211_next_scan(ifp);
  239 }
  240 
  241 /*
  242  * Switch to the next channel marked for scanning.
  243  */
  244 void
  245 ieee80211_next_scan(struct ifnet *ifp)
  246 {
  247         struct ieee80211com *ic = (void *)ifp;
  248         struct ieee80211_channel *chan;
  249 
  250         chan = ic->ic_bss->ni_chan;
  251         for (;;) {
  252                 if (++chan > &ic->ic_channels[IEEE80211_CHAN_MAX])
  253                         chan = &ic->ic_channels[0];
  254                 if (isset(ic->ic_chan_scan, ieee80211_chan2ieee(ic, chan))) {
  255                         /*
  256                          * Ignore channels marked passive-only
  257                          * during an active scan.
  258                          */
  259                         if ((ic->ic_flags & IEEE80211_F_ASCAN) == 0 ||
  260                             (chan->ic_flags & IEEE80211_CHAN_PASSIVE) == 0)
  261                                 break;
  262                 }
  263                 if (chan == ic->ic_bss->ni_chan) {
  264                         ieee80211_end_scan(ifp);
  265                         return;
  266                 }
  267         }
  268         clrbit(ic->ic_chan_scan, ieee80211_chan2ieee(ic, chan));
  269         IEEE80211_DPRINTF(("%s: chan %d->%d\n", __func__,
  270             ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan),
  271             ieee80211_chan2ieee(ic, chan)));
  272         ic->ic_bss->ni_chan = chan;
  273         ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
  274 }
  275 
  276 void
  277 ieee80211_create_ibss(struct ieee80211com* ic, struct ieee80211_channel *chan)
  278 {
  279         struct ieee80211_node *ni;
  280         struct ifnet *ifp = &ic->ic_if;
  281 
  282         ni = ic->ic_bss;
  283         if (ifp->if_flags & IFF_DEBUG)
  284                 printf("%s: creating ibss\n", ifp->if_xname);
  285         ic->ic_flags |= IEEE80211_F_SIBSS;
  286         ni->ni_chan = chan;
  287         ni->ni_rates = ic->ic_sup_rates[ieee80211_chan2mode(ic, ni->ni_chan)];
  288         IEEE80211_ADDR_COPY(ni->ni_macaddr, ic->ic_myaddr);
  289         IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_myaddr);
  290         if (ic->ic_opmode == IEEE80211_M_IBSS) {
  291                 if ((ic->ic_flags & IEEE80211_F_DESBSSID) != 0)
  292                         IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_des_bssid);
  293                 else
  294                         ni->ni_bssid[0] |= 0x02;        /* local bit for IBSS */
  295         }
  296         ni->ni_esslen = ic->ic_des_esslen;
  297         memcpy(ni->ni_essid, ic->ic_des_essid, ni->ni_esslen);
  298         ni->ni_rssi = 0;
  299         ni->ni_rstamp = 0;
  300         memset(ni->ni_tstamp, 0, sizeof(ni->ni_tstamp));
  301         ni->ni_intval = ic->ic_lintval;
  302         ni->ni_capinfo = IEEE80211_CAPINFO_IBSS;
  303         if (ic->ic_flags & IEEE80211_F_WEPON)
  304                 ni->ni_capinfo |= IEEE80211_CAPINFO_PRIVACY;
  305         if (ic->ic_phytype == IEEE80211_T_FH) {
  306                 ni->ni_fhdwell = 200;   /* XXX */
  307                 ni->ni_fhindex = 1;
  308         }
  309         ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
  310 }
  311 
  312 int
  313 ieee80211_match_bss(struct ieee80211com *ic, struct ieee80211_node *ni)
  314 {
  315         u_int8_t rate;
  316         int fail;
  317 
  318         fail = 0;
  319         if (isclr(ic->ic_chan_active, ieee80211_chan2ieee(ic, ni->ni_chan)))
  320                 fail |= 0x01;
  321         if (ic->ic_des_chan != IEEE80211_CHAN_ANYC &&
  322             ni->ni_chan != ic->ic_des_chan)
  323                 fail |= 0x01;
  324         if (ic->ic_opmode == IEEE80211_M_IBSS) {
  325                 if ((ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) == 0)
  326                         fail |= 0x02;
  327         } else {
  328                 if ((ni->ni_capinfo & IEEE80211_CAPINFO_ESS) == 0)
  329                         fail |= 0x02;
  330         }
  331         if (ic->ic_flags & IEEE80211_F_WEPON) {
  332                 if ((ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) == 0)
  333                         fail |= 0x04;
  334         } else {
  335                 /* XXX does this mean privacy is supported or required? */
  336                 if (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY)
  337                         fail |= 0x04;
  338         }
  339         rate = ieee80211_fix_rate(ic, ni, IEEE80211_F_DONEGO);
  340         if (rate & IEEE80211_RATE_BASIC)
  341                 fail |= 0x08;
  342         if (ic->ic_des_esslen != 0 &&
  343             (ni->ni_esslen != ic->ic_des_esslen ||
  344              memcmp(ni->ni_essid, ic->ic_des_essid, ic->ic_des_esslen) != 0))
  345                 fail |= 0x10;
  346         if ((ic->ic_flags & IEEE80211_F_DESBSSID) &&
  347             !IEEE80211_ADDR_EQ(ic->ic_des_bssid, ni->ni_bssid))
  348                 fail |= 0x20;
  349 #ifdef IEEE80211_DEBUG
  350         if (ic->ic_if.if_flags & IFF_DEBUG) {
  351                 printf(" %c %s", fail ? '-' : '+',
  352                     ether_sprintf(ni->ni_macaddr));
  353                 printf(" %s%c", ether_sprintf(ni->ni_bssid),
  354                     fail & 0x20 ? '!' : ' ');
  355                 printf(" %3d%c", ieee80211_chan2ieee(ic, ni->ni_chan),
  356                         fail & 0x01 ? '!' : ' ');
  357                 printf(" %+4d", ni->ni_rssi);
  358                 printf(" %2dM%c", (rate & IEEE80211_RATE_VAL) / 2,
  359                     fail & 0x08 ? '!' : ' ');
  360                 printf(" %4s%c",
  361                     (ni->ni_capinfo & IEEE80211_CAPINFO_ESS) ? "ess" :
  362                     (ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) ? "ibss" :
  363                     "????",
  364                     fail & 0x02 ? '!' : ' ');
  365                 printf(" %3s%c ",
  366                     (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) ?
  367                     "wep" : "no",
  368                     fail & 0x04 ? '!' : ' ');
  369                 ieee80211_print_essid(ni->ni_essid, ni->ni_esslen);
  370                 printf("%s\n", fail & 0x10 ? "!" : "");
  371         }
  372 #endif
  373         return fail;
  374 }
  375 
  376 /*
  377  * Complete a scan of potential channels.
  378  */
  379 void
  380 ieee80211_end_scan(struct ifnet *ifp)
  381 {
  382         struct ieee80211com *ic = (void *)ifp;
  383         struct ieee80211_node *ni, *nextbs, *selbs;
  384         int i, fail;
  385 
  386         if (ifp->if_flags & IFF_DEBUG)
  387                 printf("%s: end %s scan\n", ifp->if_xname,
  388                         (ic->ic_flags & IEEE80211_F_ASCAN) ?
  389                                 "active" : "passive");
  390 
  391         if (ic->ic_scan_count)
  392                 ic->ic_flags &= ~IEEE80211_F_ASCAN;
  393 
  394         ni = RB_MIN(ieee80211_tree, &ic->ic_tree);
  395 
  396         if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
  397                 /* XXX off stack? */
  398                 u_char occupied[howmany(IEEE80211_CHAN_MAX, NBBY)];
  399                 /*
  400                  * The passive scan to look for existing AP's completed,
  401                  * select a channel to camp on.  Identify the channels
  402                  * that already have one or more AP's and try to locate
  403                  * an unnoccupied one.  If that fails, pick a random
  404                  * channel from the active set.
  405                  */
  406                 RB_FOREACH(ni, ieee80211_tree, &ic->ic_tree)
  407                         setbit(occupied, ieee80211_chan2ieee(ic, ni->ni_chan));
  408                 for (i = 0; i < IEEE80211_CHAN_MAX; i++)
  409                         if (isset(ic->ic_chan_active, i) && isclr(occupied, i))
  410                                 break;
  411                 if (i == IEEE80211_CHAN_MAX) {
  412                         fail = arc4random() & 3;        /* random 0-3 */
  413                         for (i = 0; i < IEEE80211_CHAN_MAX; i++)
  414                                 if (isset(ic->ic_chan_active, i) && fail-- == 0)
  415                                         break;
  416                 }
  417                 ieee80211_create_ibss(ic, &ic->ic_channels[i]);
  418                 goto wakeup;
  419         }
  420         if (ni == NULL) {
  421                 IEEE80211_DPRINTF(("%s: no scan candidate\n", __func__));
  422  notfound:
  423                 if (ic->ic_opmode == IEEE80211_M_IBSS &&
  424                     (ic->ic_flags & IEEE80211_F_IBSSON) &&
  425                     ic->ic_des_esslen != 0) {
  426                         ieee80211_create_ibss(ic, ic->ic_ibss_chan);
  427                         goto wakeup;
  428                 }
  429 
  430                 /*
  431                  * Scan the next mode if nothing has been found. This
  432                  * is necessary if the device supports different
  433                  * incompatible modes in the same channel range, like
  434                  * like 11b and "pure" 11G mode. This will loop
  435                  * forever except for user-initiated scans.
  436                  */
  437                 if (ieee80211_next_mode(ifp) == IEEE80211_MODE_AUTO) {
  438                         if (ic->ic_scan_lock & IEEE80211_SCAN_REQUEST &&
  439                             ic->ic_scan_lock & IEEE80211_SCAN_RESUME) {
  440                                 ic->ic_scan_lock = IEEE80211_SCAN_LOCKED;
  441                                 /* Return from an user-initiated scan */
  442                                 wakeup(&ic->ic_scan_lock);
  443                         } else if (ic->ic_scan_lock & IEEE80211_SCAN_REQUEST)
  444                                 goto wakeup;
  445                         ic->ic_scan_count++;
  446                 }
  447 
  448                 /*
  449                  * Reset the list of channels to scan and start again.
  450                  */
  451                 ieee80211_next_scan(ifp);
  452                 return;
  453         }
  454         selbs = NULL;
  455 
  456         for (; ni != NULL; ni = nextbs) {
  457                 nextbs = RB_NEXT(ieee80211_tree, &ic->ic_tree, ni);
  458                 if (ni->ni_fails) {
  459                         /*
  460                          * The configuration of the access points may change
  461                          * during my scan.  So delete the entry for the AP
  462                          * and retry to associate if there is another beacon.
  463                          */
  464                         if (ni->ni_fails++ > 2)
  465                                 ieee80211_free_node(ic, ni);
  466                         continue;
  467                 }
  468                 if (ieee80211_match_bss(ic, ni) == 0) {
  469                         if (selbs == NULL)
  470                                 selbs = ni;
  471                         else if (ni->ni_rssi > selbs->ni_rssi)
  472                                 selbs = ni;
  473                 }
  474         }
  475         if (selbs == NULL)
  476                 goto notfound;
  477         (*ic->ic_node_copy)(ic, ic->ic_bss, selbs);
  478 
  479         /*
  480          * Set the erp state (mostly the slot time) to deal with
  481          * the auto-select case; this should be redundant if the
  482          * mode is locked.
  483          */
  484         ic->ic_curmode = ieee80211_chan2mode(ic, selbs->ni_chan);
  485         ieee80211_reset_erp(ic);
  486 
  487         ieee80211_node_newstate(selbs, IEEE80211_STA_BSS);
  488         if (ic->ic_opmode == IEEE80211_M_IBSS) {
  489                 ieee80211_fix_rate(ic, ic->ic_bss, IEEE80211_F_DOFRATE |
  490                     IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
  491                 if (ic->ic_bss->ni_rates.rs_nrates == 0)
  492                         goto notfound;
  493                 ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
  494         } else {
  495                 ieee80211_new_state(ic, IEEE80211_S_AUTH, -1);
  496         }
  497 
  498  wakeup:
  499         if (ic->ic_scan_lock & IEEE80211_SCAN_REQUEST) {
  500                 /* Return from an user-initiated scan */
  501                 wakeup(&ic->ic_scan_lock);
  502         }
  503 
  504         ic->ic_scan_lock = IEEE80211_SCAN_UNLOCKED;
  505 }
  506 
  507 int
  508 ieee80211_get_rate(struct ieee80211com *ic)
  509 {
  510         u_int8_t (*rates)[IEEE80211_RATE_MAXSIZE];
  511         int rate;
  512 
  513         rates = &ic->ic_bss->ni_rates.rs_rates;
  514 
  515         if (ic->ic_fixed_rate != -1)
  516                 rate = (*rates)[ic->ic_fixed_rate];
  517         else if (ic->ic_state == IEEE80211_S_RUN)
  518                 rate = (*rates)[ic->ic_bss->ni_txrate];
  519         else
  520                 rate = 0;
  521 
  522         return rate & IEEE80211_RATE_VAL;
  523 }
  524 
  525 struct ieee80211_node *
  526 ieee80211_node_alloc(struct ieee80211com *ic)
  527 {
  528         struct ieee80211_node *ni;
  529         MALLOC(ni, struct ieee80211_node *, sizeof(struct ieee80211_node),
  530             M_80211_NODE, M_NOWAIT);
  531         if (ni != NULL)
  532                 memset(ni, 0, sizeof(struct ieee80211_node));
  533         return ni;
  534 }
  535 
  536 void
  537 ieee80211_node_cleanup(struct ieee80211com *ic, struct ieee80211_node *ni)
  538 {
  539 }
  540 
  541 void
  542 ieee80211_node_free(struct ieee80211com *ic, struct ieee80211_node *ni)
  543 {
  544         ieee80211_node_cleanup(ic, ni);
  545         FREE(ni, M_80211_NODE);
  546 }
  547 
  548 void
  549 ieee80211_node_copy(struct ieee80211com *ic,
  550         struct ieee80211_node *dst, const struct ieee80211_node *src)
  551 {
  552         ieee80211_node_cleanup(ic, dst);
  553         *dst = *src;
  554 }
  555 
  556 u_int8_t
  557 ieee80211_node_getrssi(struct ieee80211com *ic,
  558     const struct ieee80211_node *ni)
  559 {
  560         return ni->ni_rssi;
  561 }
  562 
  563 void
  564 ieee80211_setup_node(struct ieee80211com *ic,
  565         struct ieee80211_node *ni, const u_int8_t *macaddr)
  566 {
  567         int s;
  568 
  569         IEEE80211_DPRINTF(("%s %s\n", __func__,
  570             ether_sprintf((u_int8_t *)macaddr)));
  571         IEEE80211_ADDR_COPY(ni->ni_macaddr, macaddr);
  572         ieee80211_node_newstate(ni, IEEE80211_STA_CACHE);
  573 
  574         /* 
  575          * Note we don't enable the inactive timer when acting
  576          * as a station.  Nodes created in this mode represent
  577          * AP's identified while scanning.  If we time them out
  578          * then several things happen: we can't return the data
  579          * to users to show the list of AP's we encountered, and
  580          * more importantly, we'll incorrectly deauthenticate
  581          * ourself because the inactivity timer will kick us off.
  582          */
  583         s = splnet();
  584         if (ic->ic_opmode != IEEE80211_M_STA &&
  585             RB_EMPTY(&ic->ic_tree))
  586                 ic->ic_inact_timer = IEEE80211_INACT_WAIT;
  587         RB_INSERT(ieee80211_tree, &ic->ic_tree, ni);
  588         splx(s);
  589 }
  590 
  591 struct ieee80211_node *
  592 ieee80211_alloc_node(struct ieee80211com *ic, const u_int8_t *macaddr)
  593 {
  594         struct ieee80211_node *ni = ieee80211_alloc_node_helper(ic);
  595         if (ni != NULL)
  596                 ieee80211_setup_node(ic, ni, macaddr);
  597         else
  598                 ic->ic_stats.is_rx_nodealloc++;
  599         return ni;
  600 }
  601 
  602 struct ieee80211_node *
  603 ieee80211_dup_bss(struct ieee80211com *ic, const u_int8_t *macaddr)
  604 {
  605         struct ieee80211_node *ni = ieee80211_alloc_node_helper(ic);
  606         if (ni != NULL) {
  607                 ieee80211_setup_node(ic, ni, macaddr);
  608                 /*
  609                  * Inherit from ic_bss.
  610                  */
  611                 IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_bss->ni_bssid);
  612                 ni->ni_chan = ic->ic_bss->ni_chan;
  613         } else
  614                 ic->ic_stats.is_rx_nodealloc++;
  615         return ni;
  616 }
  617 
  618 struct ieee80211_node *
  619 ieee80211_find_node(struct ieee80211com *ic, const u_int8_t *macaddr)
  620 {
  621         struct ieee80211_node ni;
  622 
  623         IEEE80211_ADDR_COPY(ni.ni_macaddr, macaddr);
  624         return (RB_FIND(ieee80211_tree, &ic->ic_tree, &ni));
  625 }
  626 
  627 /*
  628  * Return a reference to the appropriate node for sending
  629  * a data frame.  This handles node discovery in adhoc networks.
  630  *
  631  * Drivers will call this, so increase the reference count before
  632  * returning the node.
  633  */
  634 struct ieee80211_node *
  635 ieee80211_find_txnode(struct ieee80211com *ic, const u_int8_t *macaddr)
  636 {
  637         struct ieee80211_node *ni;
  638         int s;
  639 
  640         /*
  641          * The destination address should be in the node table
  642          * unless we are operating in station mode or this is a
  643          * multicast/broadcast frame.
  644          */
  645         if (ic->ic_opmode == IEEE80211_M_STA || IEEE80211_IS_MULTICAST(macaddr))
  646                 return ieee80211_ref_node(ic->ic_bss);
  647 
  648         s = splnet();
  649         ni = ieee80211_find_node(ic, macaddr);
  650         splx(s);
  651         if (ni == NULL) {
  652                 if (ic->ic_opmode != IEEE80211_M_IBSS &&
  653                     ic->ic_opmode != IEEE80211_M_AHDEMO)
  654                         return NULL;
  655 
  656                 /*
  657                  * Fake up a node; this handles node discovery in
  658                  * adhoc mode.  Note that for the driver's benefit
  659                  * we we treat this like an association so the driver
  660                  * has an opportunity to setup its private state.
  661                  *
  662                  * XXX need better way to handle this; issue probe
  663                  *     request so we can deduce rate set, etc.
  664                  */
  665                 if ((ni = ieee80211_dup_bss(ic, macaddr)) == NULL)
  666                         return NULL;
  667                 /* XXX no rate negotiation; just dup */
  668                 ni->ni_rates = ic->ic_bss->ni_rates;
  669                 if (ic->ic_newassoc)
  670                         (*ic->ic_newassoc)(ic, ni, 1);
  671         }
  672         return ieee80211_ref_node(ni);
  673 }
  674 
  675 /*
  676  * It is usually desirable to process a Rx packet using its sender's
  677  * node-record instead of the BSS record.
  678  *
  679  * - AP mode: keep a node-record for every authenticated/associated
  680  *   station *in the BSS*. For future use, we also track neighboring
  681  *   APs, since they might belong to the same ESS.  APs in the same
  682  *   ESS may bridge packets to each other, forming a Wireless
  683  *   Distribution System (WDS).
  684  *
  685  * - IBSS mode: keep a node-record for every station *in the BSS*.
  686  *   Also track neighboring stations by their beacons/probe responses.
  687  *
  688  * - monitor mode: keep a node-record for every sender, regardless
  689  *   of BSS.
  690  *
  691  * - STA mode: the only available node-record is the BSS record,
  692  *   ic->ic_bss.
  693  *
  694  * Of all the 802.11 Control packets, only the node-records for
  695  * RTS packets node-record can be looked up.
  696  *
  697  * Return non-zero if the packet's node-record is kept, zero
  698  * otherwise.
  699  */
  700 static __inline int
  701 ieee80211_needs_rxnode(struct ieee80211com *ic,
  702     const struct ieee80211_frame *wh, const u_int8_t **bssid)
  703 {
  704         struct ieee80211_node *bss = ic->ic_bss;
  705         int monitor, rc = 0;
  706 
  707         monitor = (ic->ic_opmode == IEEE80211_M_MONITOR);
  708 
  709         *bssid = NULL;
  710 
  711         switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
  712         case IEEE80211_FC0_TYPE_CTL:
  713                 if (!monitor)
  714                         break;
  715                 return (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
  716                     IEEE80211_FC0_SUBTYPE_RTS;
  717         case IEEE80211_FC0_TYPE_MGT:
  718                 *bssid = wh->i_addr3;
  719                 switch (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) {
  720                 case IEEE80211_FC0_SUBTYPE_BEACON:
  721                 case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
  722                         rc = 1;
  723                         break;
  724                 default:
  725                         if (ic->ic_opmode == IEEE80211_M_STA)
  726                                 break;
  727                         rc = IEEE80211_ADDR_EQ(*bssid, bss->ni_bssid) ||
  728                              IEEE80211_ADDR_EQ(*bssid, etherbroadcastaddr);
  729                         break;
  730                 }
  731                 break;
  732         case IEEE80211_FC0_TYPE_DATA:
  733                 switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) {
  734                 case IEEE80211_FC1_DIR_NODS:
  735                         *bssid = wh->i_addr3;
  736                         if (ic->ic_opmode == IEEE80211_M_IBSS ||
  737                             ic->ic_opmode == IEEE80211_M_AHDEMO)
  738                                 rc = IEEE80211_ADDR_EQ(*bssid, bss->ni_bssid);
  739                         break;
  740                 case IEEE80211_FC1_DIR_TODS:
  741                         *bssid = wh->i_addr1;
  742                         if (ic->ic_opmode == IEEE80211_M_HOSTAP)
  743                                 rc = IEEE80211_ADDR_EQ(*bssid, bss->ni_bssid);
  744                         break;
  745                 case IEEE80211_FC1_DIR_FROMDS:
  746                 case IEEE80211_FC1_DIR_DSTODS:
  747                         *bssid = wh->i_addr2;
  748                         rc = (ic->ic_opmode == IEEE80211_M_HOSTAP);
  749                         break;
  750                 }
  751                 break;
  752         }
  753         return monitor || rc;
  754 }
  755 
  756 /* 
  757  * Drivers call this, so increase the reference count before returning
  758  * the node.
  759  */
  760 struct ieee80211_node *
  761 ieee80211_find_rxnode(struct ieee80211com *ic,
  762     const struct ieee80211_frame *wh)
  763 {
  764         static const u_int8_t zero[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
  765         struct ieee80211_node *ni;
  766         const u_int8_t *bssid;
  767         int s;
  768 
  769         if (!ieee80211_needs_rxnode(ic, wh, &bssid))
  770                 return ieee80211_ref_node(ic->ic_bss);
  771 
  772         s = splnet();
  773         ni = ieee80211_find_node(ic, wh->i_addr2);
  774         splx(s);
  775 
  776         if (ni != NULL)
  777                 return ieee80211_ref_node(ni);
  778         if (ic->ic_opmode == IEEE80211_M_HOSTAP)
  779                 return ieee80211_ref_node(ic->ic_bss);
  780 
  781         /* XXX see remarks in ieee80211_find_txnode */
  782         /* XXX no rate negotiation; just dup */
  783         if ((ni = ieee80211_dup_bss(ic, wh->i_addr2)) == NULL)
  784                 return ieee80211_ref_node(ic->ic_bss);
  785 
  786         IEEE80211_ADDR_COPY(ni->ni_bssid, (bssid != NULL) ? bssid : zero);
  787 
  788         ni->ni_rates = ic->ic_bss->ni_rates;
  789         if (ic->ic_newassoc)
  790                 (*ic->ic_newassoc)(ic, ni, 1);
  791 
  792         IEEE80211_DPRINTF(("%s: faked-up node %p for %s\n", __func__, ni,
  793             ether_sprintf((u_int8_t *)wh->i_addr2)));
  794 
  795         return ieee80211_ref_node(ni);
  796 }
  797 
  798 struct ieee80211_node *
  799 ieee80211_find_node_for_beacon(struct ieee80211com *ic,
  800     const u_int8_t *macaddr, const struct ieee80211_channel *chan,
  801     const char *ssid, u_int8_t rssi)
  802 {
  803         struct ieee80211_node *ni, *keep = NULL;
  804         int s, score = 0;
  805 
  806         if ((ni = ieee80211_find_node(ic, macaddr)) != NULL) {
  807                 s = splnet();
  808 
  809                 if (ni->ni_chan != chan && ni->ni_rssi >= rssi)
  810                         score++;
  811                 if (ssid[1] == 0 && ni->ni_esslen != 0)
  812                         score++;
  813                 if (score > 0)
  814                         keep = ni;
  815 
  816                 splx(s);
  817         }
  818 
  819         return (keep);
  820 }
  821 
  822 void
  823 ieee80211_free_node(struct ieee80211com *ic, struct ieee80211_node *ni)
  824 {
  825         if (ni == ic->ic_bss)
  826                 panic("freeing bss node");
  827 
  828         IEEE80211_DPRINTF(("%s %s\n", __func__, ether_sprintf(ni->ni_macaddr)));
  829         IEEE80211_AID_CLR(ni->ni_associd, ic->ic_aid_bitmap);
  830         RB_REMOVE(ieee80211_tree, &ic->ic_tree, ni);
  831         ic->ic_nnodes--;
  832         if (!IF_IS_EMPTY(&ni->ni_savedq)) {
  833                 IF_PURGE(&ni->ni_savedq);
  834                 if (ic->ic_set_tim != NULL)
  835                         (*ic->ic_set_tim)(ic, ni->ni_associd, 0);
  836         }
  837         if (RB_EMPTY(&ic->ic_tree))
  838                 ic->ic_inact_timer = 0;
  839         (*ic->ic_node_free)(ic, ni);
  840         /* TBD indicate to drivers that a new node can be allocated */
  841 }
  842 
  843 void
  844 ieee80211_release_node(struct ieee80211com *ic, struct ieee80211_node *ni)
  845 {
  846         int s;
  847 
  848         IEEE80211_DPRINTF(("%s %s refcnt %d\n", __func__,
  849             ether_sprintf(ni->ni_macaddr), ni->ni_refcnt));
  850         if (ieee80211_node_decref(ni) == 0 &&
  851             ni->ni_state == IEEE80211_STA_COLLECT) {
  852                 s = splnet();
  853                 ieee80211_free_node(ic, ni);
  854                 splx(s);
  855         }
  856 }
  857 
  858 void
  859 ieee80211_free_allnodes(struct ieee80211com *ic)
  860 {
  861         struct ieee80211_node *ni;
  862         int s;
  863 
  864         IEEE80211_DPRINTF(("%s\n", __func__));
  865         s = splnet();
  866         while ((ni = RB_MIN(ieee80211_tree, &ic->ic_tree)) != NULL)
  867                 ieee80211_free_node(ic, ni);
  868         splx(s);
  869 
  870         if (ic->ic_bss != NULL)
  871                 ieee80211_node_cleanup(ic, ic->ic_bss); /* for station mode */
  872 }
  873 
  874 /*
  875  * Timeout inactive nodes.
  876  */
  877 void
  878 ieee80211_clean_nodes(struct ieee80211com *ic)
  879 {
  880         struct ieee80211_node *ni, *next_ni;
  881         u_int gen = ic->ic_scangen++;           /* NB: ok 'cuz single-threaded*/
  882         int s;
  883 
  884         s = splnet();
  885         for (ni = RB_MIN(ieee80211_tree, &ic->ic_tree);
  886             ni != NULL; ni = next_ni) {
  887                 next_ni = RB_NEXT(ieee80211_tree, &ic->ic_tree, ni);
  888                 if (ic->ic_nnodes <= ic->ic_max_nnodes)
  889                         break;
  890                 if (ni->ni_scangen == gen)      /* previously handled */
  891                         continue;
  892                 ni->ni_scangen = gen;
  893                 if (ni->ni_refcnt > 0)
  894                         continue;
  895                 IEEE80211_DPRINTF(("station %s purged from LRU cache\n",
  896                     ether_sprintf(ni->ni_macaddr)));
  897                 /*
  898                  * Send a deauthenticate frame.
  899                  */
  900                 if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
  901                         splx(s);
  902                         IEEE80211_SEND_MGMT(ic, ni,
  903                             IEEE80211_FC0_SUBTYPE_DEAUTH,
  904                             IEEE80211_REASON_AUTH_EXPIRE);
  905                         s = splnet();
  906                         ieee80211_node_leave(ic, ni);
  907                 } else
  908                         ieee80211_free_node(ic, ni);
  909                 ic->ic_stats.is_node_timeout++;
  910         }
  911         splx(s);
  912 }
  913 
  914 void
  915 ieee80211_iterate_nodes(struct ieee80211com *ic, ieee80211_iter_func *f,
  916     void *arg)
  917 {
  918         struct ieee80211_node *ni;
  919         int s;
  920 
  921         s = splnet();
  922         RB_FOREACH(ni, ieee80211_tree, &ic->ic_tree)
  923                 (*f)(arg, ni);
  924         splx(s);
  925 }
  926 
  927 /*
  928  * Check if the specified node supports ERP.
  929  */
  930 int
  931 ieee80211_iserp_sta(const struct ieee80211_node *ni)
  932 {
  933 #define N(a)    (sizeof (a) / sizeof (a)[0])
  934         static const u_int8_t rates[] = { 2, 4, 11, 22, 12, 24, 48 };
  935         const struct ieee80211_rateset *rs = &ni->ni_rates;
  936         int i, j;
  937 
  938         /*
  939          * A STA supports ERP operation if it includes all the Clause 19
  940          * mandatory rates in its supported rate set.
  941          */
  942         for (i = 0; i < N(rates); i++) {
  943                 for (j = 0; j < rs->rs_nrates; j++) {
  944                         if ((rs->rs_rates[j] & IEEE80211_RATE_VAL) == rates[i])
  945                                 break;
  946                 }
  947                 if (j == rs->rs_nrates)
  948                         return 0;
  949         }
  950         return 1;
  951 #undef N
  952 }
  953 
  954 /*
  955  * Handle a station joining an 11g network.
  956  */
  957 void
  958 ieee80211_node_join_11g(struct ieee80211com *ic, struct ieee80211_node *ni)
  959 {
  960         if (!(ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME)) {
  961                 /*
  962                  * Joining STA doesn't support short slot time.  We must
  963                  * disable the use of short slot time for all other associated
  964                  * STAs and give the driver a chance to reconfigure the
  965                  * hardware.
  966                  */
  967                 if (++ic->ic_longslotsta == 1) {
  968                         if (ic->ic_caps & IEEE80211_C_SHSLOT)
  969                                 ieee80211_set_shortslottime(ic, 0);
  970                 }
  971                 IEEE80211_DPRINTF(("[%s] station needs long slot time, "
  972                     "count %d\n", ether_sprintf(ni->ni_macaddr),
  973                     ic->ic_longslotsta));
  974         }
  975 
  976         if (!ieee80211_iserp_sta(ni)) {
  977                 /*
  978                  * Joining STA is non-ERP.
  979                  */
  980                 ic->ic_nonerpsta++;
  981 
  982                 IEEE80211_DPRINTF(("[%s] station is non-ERP, %d non-ERP "
  983                     "stations associated\n", ether_sprintf(ni->ni_macaddr),
  984                     ic->ic_nonerpsta));
  985 
  986                 /* must enable the use of protection */
  987                 if (ic->ic_protmode != IEEE80211_PROT_NONE) {
  988                         IEEE80211_DPRINTF(("%s: enable use of protection\n",
  989                             __func__));
  990                         ic->ic_flags |= IEEE80211_F_USEPROT;
  991                 }
  992 
  993                 if (!(ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE))
  994                         ic->ic_flags &= ~IEEE80211_F_SHPREAMBLE;
  995         } else
  996                 ni->ni_flags |= IEEE80211_NODE_ERP;
  997 }
  998 
  999 void
 1000 ieee80211_node_join(struct ieee80211com *ic, struct ieee80211_node *ni,
 1001     int resp)
 1002 {
 1003         int newassoc;
 1004 
 1005         if (ni->ni_associd == 0) {
 1006                 u_int16_t aid;
 1007 
 1008                 /*
 1009                  * It would be clever to search the bitmap
 1010                  * more efficiently, but this will do for now.
 1011                  */
 1012                 for (aid = 1; aid < ic->ic_max_aid; aid++) {
 1013                         if (!IEEE80211_AID_ISSET(aid,
 1014                             ic->ic_aid_bitmap))
 1015                                 break;
 1016                 }
 1017                 if (aid >= ic->ic_max_aid) {
 1018                         IEEE80211_SEND_MGMT(ic, ni, resp,
 1019                             IEEE80211_REASON_ASSOC_TOOMANY);
 1020                         ieee80211_node_leave(ic, ni);
 1021                         return;
 1022                 }
 1023                 ni->ni_associd = aid | 0xc000;
 1024                 IEEE80211_AID_SET(ni->ni_associd, ic->ic_aid_bitmap);
 1025                 newassoc = 1;
 1026                 if (ic->ic_curmode == IEEE80211_MODE_11G)
 1027                         ieee80211_node_join_11g(ic, ni);
 1028         } else
 1029                 newassoc = 0;
 1030 
 1031         IEEE80211_DPRINTF(("station %s %s associated at aid %d\n",
 1032             ether_sprintf(ni->ni_macaddr),
 1033             (newassoc ? "newly" : "already"),
 1034             ni->ni_associd & ~0xc000));
 1035 
 1036         /* give driver a chance to setup state like ni_txrate */
 1037         if (ic->ic_newassoc)
 1038                 (*ic->ic_newassoc)(ic, ni, newassoc);
 1039         IEEE80211_SEND_MGMT(ic, ni, resp, IEEE80211_STATUS_SUCCESS);
 1040         ieee80211_node_newstate(ni, IEEE80211_STA_ASSOC);
 1041 
 1042 #if NBRIDGE > 0
 1043         /*
 1044          * If the parent interface belongs to a bridge, learn
 1045          * the node's address dynamically on this interface.
 1046          */
 1047         if (ic->ic_if.if_bridge != NULL)
 1048                 bridge_update(&ic->ic_if,
 1049                     (struct ether_addr *)ni->ni_macaddr, 0);
 1050 #endif
 1051 }
 1052 
 1053 /*
 1054  * Handle a station leaving an 11g network.
 1055  */
 1056 void
 1057 ieee80211_node_leave_11g(struct ieee80211com *ic, struct ieee80211_node *ni)
 1058 {
 1059         if (!(ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME)) {
 1060 #ifdef DIAGNOSTIC
 1061                 if (ic->ic_longslotsta == 0) {
 1062                         panic("bogus long slot station count %d",
 1063                             ic->ic_longslotsta);
 1064                 }
 1065 #endif
 1066                 /* leaving STA did not support short slot time */
 1067                 if (--ic->ic_longslotsta == 0) {
 1068                         /*
 1069                          * All associated STAs now support short slot time, so
 1070                          * enable this feature and give the driver a chance to
 1071                          * reconfigure the hardware. Notice that IBSS always
 1072                          * use a long slot time.
 1073                          */
 1074                         if ((ic->ic_caps & IEEE80211_C_SHSLOT) &&
 1075                             ic->ic_opmode != IEEE80211_M_IBSS)
 1076                                 ieee80211_set_shortslottime(ic, 1);
 1077                 }
 1078                 IEEE80211_DPRINTF(("[%s] long slot time station leaves, "
 1079                     "count now %d\n", ether_sprintf(ni->ni_macaddr),
 1080                     ic->ic_longslotsta));
 1081         }
 1082 
 1083         if (!(ni->ni_flags & IEEE80211_NODE_ERP)) {
 1084 #ifdef DIAGNOSTIC
 1085                 if (ic->ic_nonerpsta == 0) {
 1086                         panic("bogus non-ERP station count %d\n",
 1087                             ic->ic_nonerpsta);
 1088                 }
 1089 #endif
 1090                 /* leaving STA was non-ERP */
 1091                 if (--ic->ic_nonerpsta == 0) {
 1092                         /*
 1093                          * All associated STAs are now ERP capable, disable use
 1094                          * of protection and re-enable short preamble support.
 1095                          */
 1096                         ic->ic_flags &= ~IEEE80211_F_USEPROT;
 1097                         if (ic->ic_caps & IEEE80211_C_SHPREAMBLE)
 1098                                 ic->ic_flags |= IEEE80211_F_SHPREAMBLE;
 1099                 }
 1100                 IEEE80211_DPRINTF(("[%s] non-ERP station leaves, "
 1101                     "count now %d\n", ether_sprintf(ni->ni_macaddr),
 1102                     ic->ic_nonerpsta));
 1103         }
 1104 }
 1105 
 1106 /*
 1107  * Handle bookkeeping for station deauthentication/disassociation
 1108  * when operating as an ap.
 1109  */
 1110 void
 1111 ieee80211_node_leave(struct ieee80211com *ic, struct ieee80211_node *ni)
 1112 {
 1113         if (ic->ic_opmode != IEEE80211_M_HOSTAP)
 1114                 panic("not in ap mode, mode %u", ic->ic_opmode);
 1115         /*
 1116          * If node wasn't previously associated all
 1117          * we need to do is reclaim the reference.
 1118          */
 1119         if (ni->ni_associd == 0)
 1120                 return;
 1121         IEEE80211_AID_CLR(ni->ni_associd, ic->ic_aid_bitmap);
 1122         ni->ni_associd = 0;
 1123 
 1124         if (ic->ic_curmode == IEEE80211_MODE_11G)
 1125                 ieee80211_node_leave_11g(ic, ni);
 1126 
 1127         ieee80211_node_newstate(ni, IEEE80211_STA_COLLECT);
 1128 
 1129 #if NBRIDGE > 0
 1130         /*
 1131          * If the parent interface belongs to a bridge, delete
 1132          * any dynamically learned address for this node.
 1133          */
 1134         if (ic->ic_if.if_bridge != NULL)
 1135                 bridge_update(&ic->ic_if,
 1136                     (struct ether_addr *)ni->ni_macaddr, 1);
 1137 #endif
 1138 }
 1139 
 1140 void
 1141 ieee80211_set_tim(struct ieee80211com *ic, int aid, int set)
 1142 {
 1143         if (set)
 1144                 setbit(ic->ic_tim_bitmap, aid & ~0xc000);
 1145         else
 1146                 clrbit(ic->ic_tim_bitmap, aid & ~0xc000);
 1147 }
 1148 
 1149 /*
 1150  * Compare nodes in the tree by lladdr
 1151  */
 1152 int
 1153 ieee80211_node_cmp(const struct ieee80211_node *b1,
 1154     const struct ieee80211_node *b2)
 1155 {
 1156         return (memcmp(b1->ni_macaddr, b2->ni_macaddr, IEEE80211_ADDR_LEN));
 1157 }
 1158 
 1159 /*
 1160  * Generate red-black tree function logic
 1161  */
 1162 RB_GENERATE(ieee80211_tree, ieee80211_node, ni_node, ieee80211_node_cmp);

/* [<][>][^][v][top][bottom][index][help] */