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

Annotation of sys/net80211/ieee80211_proto.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: ieee80211_proto.c,v 1.20 2007/07/28 11:24:06 damien Exp $     */
        !             2: /*     $NetBSD: ieee80211_proto.c,v 1.8 2004/04/30 23:58:20 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: /*
        !            33:  * IEEE 802.11 protocol support.
        !            34:  */
        !            35:
        !            36: #include "bpfilter.h"
        !            37:
        !            38: #include <sys/param.h>
        !            39: #include <sys/systm.h>
        !            40: #include <sys/mbuf.h>
        !            41: #include <sys/kernel.h>
        !            42: #include <sys/socket.h>
        !            43: #include <sys/sockio.h>
        !            44: #include <sys/endian.h>
        !            45: #include <sys/errno.h>
        !            46: #include <sys/proc.h>
        !            47: #include <sys/sysctl.h>
        !            48:
        !            49: #include <net/if.h>
        !            50: #include <net/if_dl.h>
        !            51: #include <net/if_media.h>
        !            52: #include <net/if_arp.h>
        !            53: #include <net/if_llc.h>
        !            54:
        !            55: #if NBPFILTER > 0
        !            56: #include <net/bpf.h>
        !            57: #endif
        !            58:
        !            59: #ifdef INET
        !            60: #include <netinet/in.h>
        !            61: #include <netinet/if_ether.h>
        !            62: #endif
        !            63:
        !            64: #include <net80211/ieee80211_var.h>
        !            65:
        !            66: const char * const ieee80211_mgt_subtype_name[] = {
        !            67:        "assoc_req",    "assoc_resp",   "reassoc_req",  "reassoc_resp",
        !            68:        "probe_req",    "probe_resp",   "reserved#6",   "reserved#7",
        !            69:        "beacon",       "atim",         "disassoc",     "auth",
        !            70:        "deauth",       "action",       "action_noack", "reserved#15"
        !            71: };
        !            72: const char * const ieee80211_state_name[IEEE80211_S_MAX] = {
        !            73:        "INIT",         /* IEEE80211_S_INIT */
        !            74:        "SCAN",         /* IEEE80211_S_SCAN */
        !            75:        "AUTH",         /* IEEE80211_S_AUTH */
        !            76:        "ASSOC",        /* IEEE80211_S_ASSOC */
        !            77:        "RUN"           /* IEEE80211_S_RUN */
        !            78: };
        !            79: const char * const ieee80211_phymode_name[] = {
        !            80:        "auto",         /* IEEE80211_MODE_AUTO */
        !            81:        "11a",          /* IEEE80211_MODE_11A */
        !            82:        "11b",          /* IEEE80211_MODE_11B */
        !            83:        "11g",          /* IEEE80211_MODE_11G */
        !            84:        "fh",           /* IEEE80211_MODE_FH */
        !            85:        "turbo",        /* IEEE80211_MODE_TURBO */
        !            86: };
        !            87:
        !            88: int ieee80211_newstate(struct ieee80211com *, enum ieee80211_state, int);
        !            89:
        !            90: void
        !            91: ieee80211_proto_attach(struct ifnet *ifp)
        !            92: {
        !            93:        struct ieee80211com *ic = (void *)ifp;
        !            94:
        !            95:        ifp->if_hdrlen = sizeof(struct ieee80211_frame);
        !            96:
        !            97: #ifdef notdef
        !            98:        ic->ic_rtsthreshold = IEEE80211_RTS_DEFAULT;
        !            99: #else
        !           100:        ic->ic_rtsthreshold = IEEE80211_RTS_MAX;
        !           101: #endif
        !           102:        ic->ic_fragthreshold = 2346;            /* XXX not used yet */
        !           103:        ic->ic_fixed_rate = -1;                 /* no fixed rate */
        !           104:        ic->ic_protmode = IEEE80211_PROT_CTSONLY;
        !           105:
        !           106:        /* protocol state change handler */
        !           107:        ic->ic_newstate = ieee80211_newstate;
        !           108:
        !           109:        /* initialize management frame handlers */
        !           110:        ic->ic_recv_mgmt = ieee80211_recv_mgmt;
        !           111:        ic->ic_send_mgmt = ieee80211_send_mgmt;
        !           112:
        !           113:        /* initialize EAPOL frame handler */
        !           114:        ic->ic_recv_eapol = ieee80211_recv_eapol;
        !           115: }
        !           116:
        !           117: void
        !           118: ieee80211_proto_detach(struct ifnet *ifp)
        !           119: {
        !           120:        struct ieee80211com *ic = (void *)ifp;
        !           121:
        !           122:        IF_PURGE(&ic->ic_mgtq);
        !           123:        IF_PURGE(&ic->ic_pwrsaveq);
        !           124: }
        !           125:
        !           126: void
        !           127: ieee80211_print_essid(const u_int8_t *essid, int len)
        !           128: {
        !           129:        int i;
        !           130:        const u_int8_t *p;
        !           131:
        !           132:        if (len > IEEE80211_NWID_LEN)
        !           133:                len = IEEE80211_NWID_LEN;
        !           134:        /* determine printable or not */
        !           135:        for (i = 0, p = essid; i < len; i++, p++) {
        !           136:                if (*p < ' ' || *p > 0x7e)
        !           137:                        break;
        !           138:        }
        !           139:        if (i == len) {
        !           140:                printf("\"");
        !           141:                for (i = 0, p = essid; i < len; i++, p++)
        !           142:                        printf("%c", *p);
        !           143:                printf("\"");
        !           144:        } else {
        !           145:                printf("0x");
        !           146:                for (i = 0, p = essid; i < len; i++, p++)
        !           147:                        printf("%02x", *p);
        !           148:        }
        !           149: }
        !           150:
        !           151: void
        !           152: ieee80211_dump_pkt(const u_int8_t *buf, int len, int rate, int rssi)
        !           153: {
        !           154:        struct ieee80211_frame *wh;
        !           155:        int i;
        !           156:
        !           157:        wh = (struct ieee80211_frame *)buf;
        !           158:        switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) {
        !           159:        case IEEE80211_FC1_DIR_NODS:
        !           160:                printf("NODS %s", ether_sprintf(wh->i_addr2));
        !           161:                printf("->%s", ether_sprintf(wh->i_addr1));
        !           162:                printf("(%s)", ether_sprintf(wh->i_addr3));
        !           163:                break;
        !           164:        case IEEE80211_FC1_DIR_TODS:
        !           165:                printf("TODS %s", ether_sprintf(wh->i_addr2));
        !           166:                printf("->%s", ether_sprintf(wh->i_addr3));
        !           167:                printf("(%s)", ether_sprintf(wh->i_addr1));
        !           168:                break;
        !           169:        case IEEE80211_FC1_DIR_FROMDS:
        !           170:                printf("FRDS %s", ether_sprintf(wh->i_addr3));
        !           171:                printf("->%s", ether_sprintf(wh->i_addr1));
        !           172:                printf("(%s)", ether_sprintf(wh->i_addr2));
        !           173:                break;
        !           174:        case IEEE80211_FC1_DIR_DSTODS:
        !           175:                printf("DSDS %s", ether_sprintf((u_int8_t *)&wh[1]));
        !           176:                printf("->%s", ether_sprintf(wh->i_addr3));
        !           177:                printf("(%s", ether_sprintf(wh->i_addr2));
        !           178:                printf("->%s)", ether_sprintf(wh->i_addr1));
        !           179:                break;
        !           180:        }
        !           181:        switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
        !           182:        case IEEE80211_FC0_TYPE_DATA:
        !           183:                printf(" data");
        !           184:                break;
        !           185:        case IEEE80211_FC0_TYPE_MGT:
        !           186:                printf(" %s", ieee80211_mgt_subtype_name[
        !           187:                    (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK)
        !           188:                    >> IEEE80211_FC0_SUBTYPE_SHIFT]);
        !           189:                break;
        !           190:        default:
        !           191:                printf(" type#%d", wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK);
        !           192:                break;
        !           193:        }
        !           194:        if (wh->i_fc[1] & IEEE80211_FC1_WEP)
        !           195:                printf(" WEP");
        !           196:        if (rate >= 0)
        !           197:                printf(" %d%sM", rate / 2, (rate & 1) ? ".5" : "");
        !           198:        if (rssi >= 0)
        !           199:                printf(" +%d", rssi);
        !           200:        printf("\n");
        !           201:        if (len > 0) {
        !           202:                for (i = 0; i < len; i++) {
        !           203:                        if ((i & 1) == 0)
        !           204:                                printf(" ");
        !           205:                        printf("%02x", buf[i]);
        !           206:                }
        !           207:                printf("\n");
        !           208:        }
        !           209: }
        !           210:
        !           211: int
        !           212: ieee80211_fix_rate(struct ieee80211com *ic, struct ieee80211_node *ni,
        !           213:     int flags)
        !           214: {
        !           215: #define        RV(v)   ((v) & IEEE80211_RATE_VAL)
        !           216:        int i, j, ignore, error;
        !           217:        int okrate, badrate, fixedrate;
        !           218:        const struct ieee80211_rateset *srs;
        !           219:        struct ieee80211_rateset *nrs;
        !           220:        u_int8_t r;
        !           221:
        !           222:        /*
        !           223:         * If the fixed rate check was requested but no fixed rate has been
        !           224:         * defined then just remove the check.
        !           225:         */
        !           226:        if ((flags & IEEE80211_F_DOFRATE) && ic->ic_fixed_rate == -1)
        !           227:                flags &= ~IEEE80211_F_DOFRATE;
        !           228:
        !           229:        error = 0;
        !           230:        okrate = badrate = fixedrate = 0;
        !           231:        srs = &ic->ic_sup_rates[ieee80211_chan2mode(ic, ni->ni_chan)];
        !           232:        nrs = &ni->ni_rates;
        !           233:        for (i = 0; i < nrs->rs_nrates; ) {
        !           234:                ignore = 0;
        !           235:                if (flags & IEEE80211_F_DOSORT) {
        !           236:                        /*
        !           237:                         * Sort rates.
        !           238:                         */
        !           239:                        for (j = i + 1; j < nrs->rs_nrates; j++) {
        !           240:                                if (RV(nrs->rs_rates[i]) >
        !           241:                                    RV(nrs->rs_rates[j])) {
        !           242:                                        r = nrs->rs_rates[i];
        !           243:                                        nrs->rs_rates[i] = nrs->rs_rates[j];
        !           244:                                        nrs->rs_rates[j] = r;
        !           245:                                }
        !           246:                        }
        !           247:                }
        !           248:                r = nrs->rs_rates[i] & IEEE80211_RATE_VAL;
        !           249:                badrate = r;
        !           250:                if (flags & IEEE80211_F_DOFRATE) {
        !           251:                        /*
        !           252:                         * Check fixed rate is included.
        !           253:                         */
        !           254:                        if (r == RV(srs->rs_rates[ic->ic_fixed_rate]))
        !           255:                                fixedrate = r;
        !           256:                }
        !           257:                if (flags & IEEE80211_F_DONEGO) {
        !           258:                        /*
        !           259:                         * Check against supported rates.
        !           260:                         */
        !           261:                        for (j = 0; j < srs->rs_nrates; j++) {
        !           262:                                if (r == RV(srs->rs_rates[j])) {
        !           263:                                        /*
        !           264:                                         * Overwrite with the supported rate
        !           265:                                         * value so any basic rate bit is set.
        !           266:                                         * This insures that response we send
        !           267:                                         * to stations have the necessary basic
        !           268:                                         * rate bit set.
        !           269:                                         */
        !           270:                                        nrs->rs_rates[i] = srs->rs_rates[j];
        !           271:                                        break;
        !           272:                                }
        !           273:                        }
        !           274:                        if (j == srs->rs_nrates) {
        !           275:                                /*
        !           276:                                 * A rate in the node's rate set is not
        !           277:                                 * supported.  If this is a basic rate and we
        !           278:                                 * are operating as an AP then this is an error.
        !           279:                                 * Otherwise we just discard/ignore the rate.
        !           280:                                 * Note that this is important for 11b stations
        !           281:                                 * when they want to associate with an 11g AP.
        !           282:                                 */
        !           283:                                if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
        !           284:                                    (nrs->rs_rates[i] & IEEE80211_RATE_BASIC))
        !           285:                                        error++;
        !           286:                                ignore++;
        !           287:                        }
        !           288:                }
        !           289:                if (flags & IEEE80211_F_DODEL) {
        !           290:                        /*
        !           291:                         * Delete unacceptable rates.
        !           292:                         */
        !           293:                        if (ignore) {
        !           294:                                nrs->rs_nrates--;
        !           295:                                for (j = i; j < nrs->rs_nrates; j++)
        !           296:                                        nrs->rs_rates[j] = nrs->rs_rates[j + 1];
        !           297:                                nrs->rs_rates[j] = 0;
        !           298:                                continue;
        !           299:                        }
        !           300:                }
        !           301:                if (!ignore)
        !           302:                        okrate = nrs->rs_rates[i];
        !           303:                i++;
        !           304:        }
        !           305:        if (okrate == 0 || error != 0 ||
        !           306:            ((flags & IEEE80211_F_DOFRATE) && fixedrate == 0))
        !           307:                return badrate | IEEE80211_RATE_BASIC;
        !           308:        else
        !           309:                return RV(okrate);
        !           310: #undef RV
        !           311: }
        !           312:
        !           313: /*
        !           314:  * Reset 11g-related state.
        !           315:  */
        !           316: void
        !           317: ieee80211_reset_erp(struct ieee80211com *ic)
        !           318: {
        !           319:        ic->ic_flags &= ~IEEE80211_F_USEPROT;
        !           320:        ic->ic_nonerpsta = 0;
        !           321:        ic->ic_longslotsta = 0;
        !           322:
        !           323:        /*
        !           324:         * Enable short slot time iff:
        !           325:         * - we're operating in 802.11a or
        !           326:         * - we're operating in 802.11g and we're not in IBSS mode and
        !           327:         *   the device supports short slot time
        !           328:         */
        !           329:        ieee80211_set_shortslottime(ic,
        !           330:            ic->ic_curmode == IEEE80211_MODE_11A ||
        !           331:            (ic->ic_curmode == IEEE80211_MODE_11G &&
        !           332:             ic->ic_opmode == IEEE80211_M_HOSTAP &&
        !           333:             (ic->ic_caps & IEEE80211_C_SHSLOT)));
        !           334:
        !           335:        if (ic->ic_curmode == IEEE80211_MODE_11A ||
        !           336:            (ic->ic_caps & IEEE80211_C_SHPREAMBLE))
        !           337:                ic->ic_flags |= IEEE80211_F_SHPREAMBLE;
        !           338:        else
        !           339:                ic->ic_flags &= ~IEEE80211_F_SHPREAMBLE;
        !           340: }
        !           341:
        !           342: /*
        !           343:  * Set the short slot time state and notify the driver.
        !           344:  */
        !           345: void
        !           346: ieee80211_set_shortslottime(struct ieee80211com *ic, int on)
        !           347: {
        !           348:        if (on)
        !           349:                ic->ic_flags |= IEEE80211_F_SHSLOT;
        !           350:        else
        !           351:                ic->ic_flags &= ~IEEE80211_F_SHSLOT;
        !           352:
        !           353:        /* notify the driver */
        !           354:        if (ic->ic_updateslot != NULL)
        !           355:                ic->ic_updateslot(ic);
        !           356: }
        !           357:
        !           358: int
        !           359: ieee80211_newstate(struct ieee80211com *ic, enum ieee80211_state nstate,
        !           360:     int mgt)
        !           361: {
        !           362:        struct ifnet *ifp = &ic->ic_if;
        !           363:        struct ieee80211_node *ni;
        !           364:        enum ieee80211_state ostate;
        !           365:        u_int rate;
        !           366:        int s;
        !           367:
        !           368:        ostate = ic->ic_state;
        !           369:        IEEE80211_DPRINTF(("%s: %s -> %s\n", __func__,
        !           370:            ieee80211_state_name[ostate], ieee80211_state_name[nstate]));
        !           371:        ic->ic_state = nstate;                  /* state transition */
        !           372:        ni = ic->ic_bss;                        /* NB: no reference held */
        !           373:        switch (nstate) {
        !           374:        case IEEE80211_S_INIT:
        !           375:                switch (ostate) {
        !           376:                case IEEE80211_S_INIT:
        !           377:                        break;
        !           378:                case IEEE80211_S_RUN:
        !           379:                        switch (ic->ic_opmode) {
        !           380:                        case IEEE80211_M_STA:
        !           381:                                IEEE80211_SEND_MGMT(ic, ni,
        !           382:                                    IEEE80211_FC0_SUBTYPE_DISASSOC,
        !           383:                                    IEEE80211_REASON_ASSOC_LEAVE);
        !           384:                                break;
        !           385:                        case IEEE80211_M_HOSTAP:
        !           386:                                s = splnet();
        !           387:                                RB_FOREACH(ni, ieee80211_tree, &ic->ic_tree) {
        !           388:                                        if (ni->ni_associd == 0)
        !           389:                                                continue;
        !           390:                                        IEEE80211_SEND_MGMT(ic, ni,
        !           391:                                            IEEE80211_FC0_SUBTYPE_DISASSOC,
        !           392:                                            IEEE80211_REASON_ASSOC_LEAVE);
        !           393:                                }
        !           394:                                splx(s);
        !           395:                                break;
        !           396:                        default:
        !           397:                                break;
        !           398:                        }
        !           399:                        /* FALLTHROUGH */
        !           400:                case IEEE80211_S_ASSOC:
        !           401:                        switch (ic->ic_opmode) {
        !           402:                        case IEEE80211_M_STA:
        !           403:                                IEEE80211_SEND_MGMT(ic, ni,
        !           404:                                    IEEE80211_FC0_SUBTYPE_DEAUTH,
        !           405:                                    IEEE80211_REASON_AUTH_LEAVE);
        !           406:                                break;
        !           407:                        case IEEE80211_M_HOSTAP:
        !           408:                                s = splnet();
        !           409:                                RB_FOREACH(ni, ieee80211_tree, &ic->ic_tree) {
        !           410:                                        IEEE80211_SEND_MGMT(ic, ni,
        !           411:                                            IEEE80211_FC0_SUBTYPE_DEAUTH,
        !           412:                                            IEEE80211_REASON_AUTH_LEAVE);
        !           413:                                }
        !           414:                                splx(s);
        !           415:                                break;
        !           416:                        default:
        !           417:                                break;
        !           418:                        }
        !           419:                        /* FALLTHROUGH */
        !           420:                case IEEE80211_S_AUTH:
        !           421:                case IEEE80211_S_SCAN:
        !           422:                        ic->ic_mgt_timer = 0;
        !           423:                        IF_PURGE(&ic->ic_mgtq);
        !           424:                        IF_PURGE(&ic->ic_pwrsaveq);
        !           425:                        if (ic->ic_wep_ctx != NULL) {
        !           426:                                free(ic->ic_wep_ctx, M_DEVBUF);
        !           427:                                ic->ic_wep_ctx = NULL;
        !           428:                        }
        !           429:                        ieee80211_free_allnodes(ic);
        !           430:                        break;
        !           431:                }
        !           432:                break;
        !           433:        case IEEE80211_S_SCAN:
        !           434:                ic->ic_flags &= ~IEEE80211_F_SIBSS;
        !           435:                /* initialize bss for probe request */
        !           436:                IEEE80211_ADDR_COPY(ni->ni_macaddr, etherbroadcastaddr);
        !           437:                IEEE80211_ADDR_COPY(ni->ni_bssid, etherbroadcastaddr);
        !           438:                ni->ni_rates = ic->ic_sup_rates[
        !           439:                        ieee80211_chan2mode(ic, ni->ni_chan)];
        !           440:                ni->ni_associd = 0;
        !           441:                ni->ni_rstamp = 0;
        !           442:                switch (ostate) {
        !           443:                case IEEE80211_S_INIT:
        !           444:                        if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
        !           445:                            ic->ic_des_chan != IEEE80211_CHAN_ANYC) {
        !           446:                                /*
        !           447:                                 * AP operation and we already have a channel;
        !           448:                                 * bypass the scan and startup immediately.
        !           449:                                 */
        !           450:                                ieee80211_create_ibss(ic, ic->ic_des_chan);
        !           451:                        } else {
        !           452:                                ieee80211_begin_scan(ifp);
        !           453:                        }
        !           454:                        break;
        !           455:                case IEEE80211_S_SCAN:
        !           456:                        /* scan next */
        !           457:                        if (ic->ic_flags & IEEE80211_F_ASCAN) {
        !           458:                                IEEE80211_SEND_MGMT(ic, ni,
        !           459:                                    IEEE80211_FC0_SUBTYPE_PROBE_REQ, 0);
        !           460:                        }
        !           461:                        break;
        !           462:                case IEEE80211_S_RUN:
        !           463:                        /* beacon miss */
        !           464:                        if (ifp->if_flags & IFF_DEBUG) {
        !           465:                                /* XXX bssid clobbered above */
        !           466:                                printf("%s: no recent beacons from %s;"
        !           467:                                    " rescanning\n", ifp->if_xname,
        !           468:                                    ether_sprintf(ic->ic_bss->ni_bssid));
        !           469:                        }
        !           470:                        ieee80211_free_allnodes(ic);
        !           471:                        /* FALLTHROUGH */
        !           472:                case IEEE80211_S_AUTH:
        !           473:                case IEEE80211_S_ASSOC:
        !           474:                        /* timeout restart scan */
        !           475:                        ni = ieee80211_find_node(ic, ic->ic_bss->ni_macaddr);
        !           476:                        if (ni != NULL)
        !           477:                                ni->ni_fails++;
        !           478:                        ieee80211_begin_scan(ifp);
        !           479:                        break;
        !           480:                }
        !           481:                break;
        !           482:        case IEEE80211_S_AUTH:
        !           483:                switch (ostate) {
        !           484:                case IEEE80211_S_INIT:
        !           485:                        IEEE80211_DPRINTF(("%s: invalid transition\n",
        !           486:                                __func__));
        !           487:                        break;
        !           488:                case IEEE80211_S_SCAN:
        !           489:                        IEEE80211_SEND_MGMT(ic, ni,
        !           490:                            IEEE80211_FC0_SUBTYPE_AUTH, 1);
        !           491:                        break;
        !           492:                case IEEE80211_S_AUTH:
        !           493:                case IEEE80211_S_ASSOC:
        !           494:                        switch (mgt) {
        !           495:                        case IEEE80211_FC0_SUBTYPE_AUTH:
        !           496:                                /* ??? */
        !           497:                                IEEE80211_SEND_MGMT(ic, ni,
        !           498:                                    IEEE80211_FC0_SUBTYPE_AUTH, 2);
        !           499:                                break;
        !           500:                        case IEEE80211_FC0_SUBTYPE_DEAUTH:
        !           501:                                /* ignore and retry scan on timeout */
        !           502:                                break;
        !           503:                        }
        !           504:                        break;
        !           505:                case IEEE80211_S_RUN:
        !           506:                        switch (mgt) {
        !           507:                        case IEEE80211_FC0_SUBTYPE_AUTH:
        !           508:                                IEEE80211_SEND_MGMT(ic, ni,
        !           509:                                    IEEE80211_FC0_SUBTYPE_AUTH, 2);
        !           510:                                ic->ic_state = ostate;  /* stay RUN */
        !           511:                                break;
        !           512:                        case IEEE80211_FC0_SUBTYPE_DEAUTH:
        !           513:                                /* try to reauth */
        !           514:                                IEEE80211_SEND_MGMT(ic, ni,
        !           515:                                    IEEE80211_FC0_SUBTYPE_AUTH, 1);
        !           516:                                break;
        !           517:                        }
        !           518:                        break;
        !           519:                }
        !           520:                break;
        !           521:        case IEEE80211_S_ASSOC:
        !           522:                switch (ostate) {
        !           523:                case IEEE80211_S_INIT:
        !           524:                case IEEE80211_S_SCAN:
        !           525:                case IEEE80211_S_ASSOC:
        !           526:                        IEEE80211_DPRINTF(("%s: invalid transition\n",
        !           527:                                __func__));
        !           528:                        break;
        !           529:                case IEEE80211_S_AUTH:
        !           530:                        IEEE80211_SEND_MGMT(ic, ni,
        !           531:                            IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 0);
        !           532:                        break;
        !           533:                case IEEE80211_S_RUN:
        !           534:                        IEEE80211_SEND_MGMT(ic, ni,
        !           535:                            IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 1);
        !           536:                        break;
        !           537:                }
        !           538:                break;
        !           539:        case IEEE80211_S_RUN:
        !           540:                switch (ostate) {
        !           541:                case IEEE80211_S_INIT:
        !           542:                case IEEE80211_S_AUTH:
        !           543:                case IEEE80211_S_RUN:
        !           544:                        IEEE80211_DPRINTF(("%s: invalid transition\n",
        !           545:                                __func__));
        !           546:                        break;
        !           547:                case IEEE80211_S_SCAN:          /* adhoc/hostap mode */
        !           548:                case IEEE80211_S_ASSOC:         /* infra mode */
        !           549:                        if (ni->ni_txrate >= ni->ni_rates.rs_nrates)
        !           550:                                panic("%s: bogus xmit rate %u setup\n",
        !           551:                                    __func__, ni->ni_txrate);
        !           552:                        if (ifp->if_flags & IFF_DEBUG) {
        !           553:                                printf("%s: %s with %s ssid ",
        !           554:                                    ifp->if_xname,
        !           555:                                    ic->ic_opmode == IEEE80211_M_STA ?
        !           556:                                    "associated" : "synchronized",
        !           557:                                    ether_sprintf(ni->ni_bssid));
        !           558:                                ieee80211_print_essid(ic->ic_bss->ni_essid,
        !           559:                                    ni->ni_esslen);
        !           560:                                rate = ni->ni_rates.rs_rates[ni->ni_txrate] &
        !           561:                                    IEEE80211_RATE_VAL;
        !           562:                                printf(" channel %d start %u%sMb",
        !           563:                                    ieee80211_chan2ieee(ic, ni->ni_chan),
        !           564:                                    rate / 2, (rate & 1) ? ".5" : "");
        !           565:                                printf(" %s preamble %s slot time%s\n",
        !           566:                                    (ic->ic_flags & IEEE80211_F_SHPREAMBLE) ?
        !           567:                                        "short" : "long",
        !           568:                                    (ic->ic_flags & IEEE80211_F_SHSLOT) ?
        !           569:                                        "short" : "long",
        !           570:                                    (ic->ic_flags & IEEE80211_F_USEPROT) ?
        !           571:                                        " protection enabled" : "");
        !           572:                        }
        !           573:                        ic->ic_mgt_timer = 0;
        !           574:                        (*ifp->if_start)(ifp);
        !           575:                        break;
        !           576:                }
        !           577:                break;
        !           578:        }
        !           579:        return 0;
        !           580: }

CVSweb