[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

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