[BACK]Return to ieee80211_node.c CVS log [TXT][DIR] Up to [local] / sys / net80211

Annotation of sys/net80211/ieee80211_node.c, Revision 1.1.1.1

1.1       nbrk        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);

CVSweb