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

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

1.1     ! nbrk        1: /*     $NetBSD: ieee80211_input.c,v 1.24 2004/05/31 11:12:24 dyoung Exp $      */
        !             2: /*     $OpenBSD: ieee80211_input.c,v 1.63 2007/08/16 14:59:14 deraadt Exp $    */
        !             3: /*-
        !             4:  * Copyright (c) 2001 Atsushi Onoe
        !             5:  * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting
        !             6:  * Copyright (c) 2007 Damien Bergamini
        !             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:
        !            34: #include <sys/param.h>
        !            35: #include <sys/systm.h>
        !            36: #include <sys/mbuf.h>
        !            37: #include <sys/malloc.h>
        !            38: #include <sys/kernel.h>
        !            39: #include <sys/socket.h>
        !            40: #include <sys/sockio.h>
        !            41: #include <sys/endian.h>
        !            42: #include <sys/errno.h>
        !            43: #include <sys/proc.h>
        !            44: #include <sys/sysctl.h>
        !            45: #include <sys/endian.h>
        !            46:
        !            47: #include <net/if.h>
        !            48: #include <net/if_dl.h>
        !            49: #include <net/if_media.h>
        !            50: #include <net/if_arp.h>
        !            51: #include <net/if_llc.h>
        !            52:
        !            53: #if NBPFILTER > 0
        !            54: #include <net/bpf.h>
        !            55: #endif
        !            56:
        !            57: #ifdef INET
        !            58: #include <netinet/in.h>
        !            59: #include <netinet/if_ether.h>
        !            60: #endif
        !            61:
        !            62: #include <net80211/ieee80211_var.h>
        !            63:
        !            64: #include <dev/rndvar.h>
        !            65:
        !            66:
        !            67: int    ieee80211_setup_rates(struct ieee80211com *, struct ieee80211_node *,
        !            68:            const u_int8_t *, const u_int8_t *, int);
        !            69: void   ieee80211_auth_open(struct ieee80211com *,
        !            70:            const struct ieee80211_frame *, struct ieee80211_node *, int,
        !            71:            u_int32_t, u_int16_t, u_int16_t);
        !            72: int    ieee80211_parse_edca_params_body(struct ieee80211com *,
        !            73:            const u_int8_t *);
        !            74: int    ieee80211_parse_edca_params(struct ieee80211com *, const u_int8_t *);
        !            75: int    ieee80211_parse_wmm_params(struct ieee80211com *, const u_int8_t *);
        !            76: enum   ieee80211_cipher ieee80211_parse_rsn_cipher(const u_int8_t[]);
        !            77: enum   ieee80211_akm ieee80211_parse_rsn_akm(const u_int8_t[]);
        !            78: int    ieee80211_parse_rsn_body(struct ieee80211com *,
        !            79:            struct ieee80211_node *, const u_int8_t *, u_int);
        !            80: int    ieee80211_parse_rsn(struct ieee80211com *, struct ieee80211_node *,
        !            81:            const u_int8_t *);
        !            82: int    ieee80211_parse_wpa1(struct ieee80211com *, struct ieee80211_node *,
        !            83:            const u_int8_t *);
        !            84: void   ieee80211_recv_pspoll(struct ieee80211com *, struct mbuf *, int,
        !            85:            u_int32_t);
        !            86: int    ieee80211_do_slow_print(struct ieee80211com *, int *);
        !            87: void   ieee80211_recv_probe_resp(struct ieee80211com *, struct mbuf *,
        !            88:            struct ieee80211_node *, int, u_int32_t);
        !            89: void   ieee80211_recv_probe_req(struct ieee80211com *, struct mbuf *,
        !            90:            struct ieee80211_node *, int, u_int32_t);
        !            91: void   ieee80211_recv_auth(struct ieee80211com *, struct mbuf *,
        !            92:            struct ieee80211_node *, int, u_int32_t);
        !            93: void   ieee80211_recv_assoc_req(struct ieee80211com *, struct mbuf *,
        !            94:            struct ieee80211_node *, int, u_int32_t);
        !            95: void   ieee80211_recv_assoc_resp(struct ieee80211com *, struct mbuf *,
        !            96:            struct ieee80211_node *, int, u_int32_t);
        !            97: void   ieee80211_recv_deauth(struct ieee80211com *, struct mbuf *,
        !            98:            struct ieee80211_node *, int, u_int32_t);
        !            99: void   ieee80211_recv_disassoc(struct ieee80211com *, struct mbuf *,
        !           100:            struct ieee80211_node *, int, u_int32_t);
        !           101: void   ieee80211_recv_4way_msg1(struct ieee80211com *,
        !           102:            const struct ieee80211_eapol_key *, struct ieee80211_node *);
        !           103: void   ieee80211_recv_4way_msg2(struct ieee80211com *,
        !           104:            const struct ieee80211_eapol_key *, struct ieee80211_node *);
        !           105: void   ieee80211_recv_4way_msg3(struct ieee80211com *,
        !           106:            const struct ieee80211_eapol_key *, struct ieee80211_node *);
        !           107: void   ieee80211_recv_4way_msg4(struct ieee80211com *,
        !           108:            const struct ieee80211_eapol_key *, struct ieee80211_node *);
        !           109: void   ieee80211_recv_rsn_group_msg1(struct ieee80211com *,
        !           110:            const struct ieee80211_eapol_key *, struct ieee80211_node *);
        !           111: void   ieee80211_recv_wpa_group_msg1(struct ieee80211com *,
        !           112:            struct ieee80211_eapol_key *, struct ieee80211_node *);
        !           113: void   ieee80211_recv_group_msg2(struct ieee80211com *,
        !           114:            const struct ieee80211_eapol_key *, struct ieee80211_node *);
        !           115: void   ieee80211_recv_eapol_key_req(struct ieee80211com *,
        !           116:            const struct ieee80211_eapol_key *, struct ieee80211_node *);
        !           117:
        !           118: /*
        !           119:  * Process a received frame.  The node associated with the sender
        !           120:  * should be supplied.  If nothing was found in the node table then
        !           121:  * the caller is assumed to supply a reference to ic_bss instead.
        !           122:  * The RSSI and a timestamp are also supplied.  The RSSI data is used
        !           123:  * during AP scanning to select a AP to associate with; it can have
        !           124:  * any units so long as values have consistent units and higher values
        !           125:  * mean ``better signal''.  The receive timestamp is currently not used
        !           126:  * by the 802.11 layer.
        !           127:  */
        !           128: void
        !           129: ieee80211_input(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node *ni,
        !           130:        int rssi, u_int32_t rstamp)
        !           131: {
        !           132:        struct ieee80211com *ic = (void *)ifp;
        !           133:        struct ieee80211_frame *wh;
        !           134:        struct ether_header *eh;
        !           135:        struct mbuf *m1;
        !           136:        int error, hdrlen, len;
        !           137:        u_int8_t dir, type, subtype;
        !           138:        u_int16_t orxseq, nrxseq;
        !           139:
        !           140:        if (ni == NULL)
        !           141:                panic("null mode");
        !           142:
        !           143:        /* trim CRC here so WEP can find its own CRC at the end of packet. */
        !           144:        if (m->m_flags & M_HASFCS) {
        !           145:                m_adj(m, -IEEE80211_CRC_LEN);
        !           146:                m->m_flags &= ~M_HASFCS;
        !           147:        }
        !           148:
        !           149:        /*
        !           150:         * In monitor mode, send everything directly to bpf.
        !           151:         * XXX may want to include the CRC
        !           152:         */
        !           153:        if (ic->ic_opmode == IEEE80211_M_MONITOR)
        !           154:                goto out;
        !           155:
        !           156:        /* do not process frames w/o i_addr2 any further */
        !           157:        if (m->m_pkthdr.len < sizeof(struct ieee80211_frame_min)) {
        !           158:                IEEE80211_DPRINTF2(("%s: frame too short (1), len %u\n",
        !           159:                    __func__, m->m_pkthdr.len));
        !           160:                ic->ic_stats.is_rx_tooshort++;
        !           161:                goto out;
        !           162:        }
        !           163:
        !           164:        wh = mtod(m, struct ieee80211_frame *);
        !           165:        if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) !=
        !           166:            IEEE80211_FC0_VERSION_0) {
        !           167:                IEEE80211_DPRINTF(("%s: packet with wrong version: %x\n",
        !           168:                    __func__, wh->i_fc[0]));
        !           169:                ic->ic_stats.is_rx_badversion++;
        !           170:                goto err;
        !           171:        }
        !           172:
        !           173:        dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK;
        !           174:        type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
        !           175:
        !           176:        /*
        !           177:         * NB: We are not yet prepared to handle control frames,
        !           178:         *     but permitting drivers to send them to us allows
        !           179:         *     them to go through bpf tapping at the 802.11 layer.
        !           180:         */
        !           181:        if (m->m_pkthdr.len < sizeof(struct ieee80211_frame)) {
        !           182:                IEEE80211_DPRINTF2(("%s: frame too short (2), len %u\n",
        !           183:                    __func__, m->m_pkthdr.len));
        !           184:                ic->ic_stats.is_rx_tooshort++;
        !           185:                goto out;
        !           186:        }
        !           187:        if (ic->ic_state != IEEE80211_S_SCAN) {
        !           188:                ni->ni_rssi = rssi;
        !           189:                ni->ni_rstamp = rstamp;
        !           190:                if (type == IEEE80211_FC0_TYPE_DATA &&
        !           191:                    (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_QOS)) {
        !           192:                        struct ieee80211_qosframe *qwh =
        !           193:                            (struct ieee80211_qosframe *)wh;
        !           194:                        int tid = qwh->i_qos[0] & IEEE80211_QOS_TID;
        !           195:                        orxseq = ni->ni_qos_rxseqs[tid];
        !           196:                        nrxseq = ni->ni_qos_rxseqs[tid] =
        !           197:                            letoh16(*(u_int16_t *)qwh->i_seq) >>
        !           198:                                IEEE80211_SEQ_SEQ_SHIFT;
        !           199:                } else {
        !           200:                        orxseq = ni->ni_rxseq;
        !           201:                        nrxseq = ni->ni_rxseq =
        !           202:                            letoh16(*(u_int16_t *)wh->i_seq) >>
        !           203:                                IEEE80211_SEQ_SEQ_SHIFT;
        !           204:                }
        !           205:                /* TODO: fragment */
        !           206:                if ((wh->i_fc[1] & IEEE80211_FC1_RETRY) &&
        !           207:                    orxseq == nrxseq) {
        !           208:                        /* duplicate, silently discarded */
        !           209:                        ic->ic_stats.is_rx_dup++; /* XXX per-station stat */
        !           210:                        goto out;
        !           211:                }
        !           212:                ni->ni_inact = 0;
        !           213:        }
        !           214:
        !           215:        if (ic->ic_set_tim != NULL &&
        !           216:            (wh->i_fc[1] & IEEE80211_FC1_PWR_MGT) &&
        !           217:            ni->ni_pwrsave == 0) {
        !           218:                /* turn on power save mode */
        !           219:
        !           220:                if (ifp->if_flags & IFF_DEBUG)
        !           221:                        printf("%s: power save mode on for %s\n",
        !           222:                            ifp->if_xname, ether_sprintf(wh->i_addr2));
        !           223:
        !           224:                ni->ni_pwrsave = IEEE80211_PS_SLEEP;
        !           225:        }
        !           226:        if (ic->ic_set_tim != NULL &&
        !           227:            !(wh->i_fc[1] & IEEE80211_FC1_PWR_MGT) &&
        !           228:            ni->ni_pwrsave != 0) {
        !           229:                /* turn off power save mode, dequeue stored packets */
        !           230:
        !           231:                ni->ni_pwrsave = 0;
        !           232:                (*ic->ic_set_tim)(ic, ni->ni_associd, 0);
        !           233:
        !           234:                if (ifp->if_flags & IFF_DEBUG)
        !           235:                        printf("%s: power save mode off for %s\n",
        !           236:                            ifp->if_xname, ether_sprintf(wh->i_addr2));
        !           237:
        !           238:                while (!IF_IS_EMPTY(&ni->ni_savedq)) {
        !           239:                        struct mbuf *m;
        !           240:                        IF_DEQUEUE(&ni->ni_savedq, m);
        !           241:                        IF_ENQUEUE(&ic->ic_pwrsaveq, m);
        !           242:                        (*ifp->if_start)(ifp);
        !           243:                }
        !           244:        }
        !           245:
        !           246:        switch (type) {
        !           247:        case IEEE80211_FC0_TYPE_DATA:
        !           248:                switch (ic->ic_opmode) {
        !           249:                case IEEE80211_M_STA:
        !           250:                        if (dir != IEEE80211_FC1_DIR_FROMDS) {
        !           251:                                ic->ic_stats.is_rx_wrongdir++;
        !           252:                                goto out;
        !           253:                        }
        !           254:                        if (ic->ic_state != IEEE80211_S_SCAN &&
        !           255:                            !IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_bssid)) {
        !           256:                                /* Source address is not our BSS. */
        !           257:                                IEEE80211_DPRINTF(
        !           258:                                    ("%s: discard frame from SA %s\n",
        !           259:                                    __func__, ether_sprintf(wh->i_addr2)));
        !           260:                                ic->ic_stats.is_rx_wrongbss++;
        !           261:                                goto out;
        !           262:                        }
        !           263:                        if ((ifp->if_flags & IFF_SIMPLEX) &&
        !           264:                            IEEE80211_IS_MULTICAST(wh->i_addr1) &&
        !           265:                            IEEE80211_ADDR_EQ(wh->i_addr3, ic->ic_myaddr)) {
        !           266:                                /*
        !           267:                                 * In IEEE802.11 network, multicast packet
        !           268:                                 * sent from me is broadcasted from AP.
        !           269:                                 * It should be silently discarded for
        !           270:                                 * SIMPLEX interface.
        !           271:                                 */
        !           272:                                ic->ic_stats.is_rx_mcastecho++;
        !           273:                                goto out;
        !           274:                        }
        !           275:                        break;
        !           276:                case IEEE80211_M_IBSS:
        !           277:                case IEEE80211_M_AHDEMO:
        !           278:                        if (dir != IEEE80211_FC1_DIR_NODS) {
        !           279:                                ic->ic_stats.is_rx_wrongdir++;
        !           280:                                goto out;
        !           281:                        }
        !           282:                        if (ic->ic_state != IEEE80211_S_SCAN &&
        !           283:                            !IEEE80211_ADDR_EQ(wh->i_addr3,
        !           284:                                ic->ic_bss->ni_bssid) &&
        !           285:                            !IEEE80211_ADDR_EQ(wh->i_addr3,
        !           286:                                etherbroadcastaddr)) {
        !           287:                                /* Destination is not our BSS or broadcast. */
        !           288:                                IEEE80211_DPRINTF2(
        !           289:                                    ("%s: discard data frame to DA %s\n",
        !           290:                                    __func__, ether_sprintf(wh->i_addr3)));
        !           291:                                ic->ic_stats.is_rx_wrongbss++;
        !           292:                                goto out;
        !           293:                        }
        !           294:                        break;
        !           295:                case IEEE80211_M_HOSTAP:
        !           296:                        if (dir != IEEE80211_FC1_DIR_TODS) {
        !           297:                                ic->ic_stats.is_rx_wrongdir++;
        !           298:                                goto out;
        !           299:                        }
        !           300:                        if (ic->ic_state != IEEE80211_S_SCAN &&
        !           301:                            !IEEE80211_ADDR_EQ(wh->i_addr1,
        !           302:                                ic->ic_bss->ni_bssid) &&
        !           303:                            !IEEE80211_ADDR_EQ(wh->i_addr1,
        !           304:                                etherbroadcastaddr)) {
        !           305:                                /* BSS is not us or broadcast. */
        !           306:                                IEEE80211_DPRINTF2(
        !           307:                                    ("%s: discard data frame to BSS %s\n",
        !           308:                                    __func__, ether_sprintf(wh->i_addr1)));
        !           309:                                ic->ic_stats.is_rx_wrongbss++;
        !           310:                                goto out;
        !           311:                        }
        !           312:                        /* check if source STA is associated */
        !           313:                        if (ni == ic->ic_bss) {
        !           314:                                IEEE80211_DPRINTF(("%s: "
        !           315:                                    "data from unknown src %s\n", __func__,
        !           316:                                    ether_sprintf(wh->i_addr2)));
        !           317:                                /* NB: caller deals with reference */
        !           318:                                ni = ieee80211_dup_bss(ic, wh->i_addr2);
        !           319:                                if (ni != NULL) {
        !           320:                                        IEEE80211_SEND_MGMT(ic, ni,
        !           321:                                            IEEE80211_FC0_SUBTYPE_DEAUTH,
        !           322:                                            IEEE80211_REASON_NOT_AUTHED);
        !           323:                                }
        !           324:                                ic->ic_stats.is_rx_notassoc++;
        !           325:                                goto err;
        !           326:                        }
        !           327:                        if (ni->ni_associd == 0) {
        !           328:                                IEEE80211_DPRINTF(("%s: "
        !           329:                                    "data from unassoc src %s\n", __func__,
        !           330:                                    ether_sprintf(wh->i_addr2)));
        !           331:                                IEEE80211_SEND_MGMT(ic, ni,
        !           332:                                    IEEE80211_FC0_SUBTYPE_DISASSOC,
        !           333:                                    IEEE80211_REASON_NOT_ASSOCED);
        !           334:                                ic->ic_stats.is_rx_notassoc++;
        !           335:                                goto err;
        !           336:                        }
        !           337:                        break;
        !           338:                case IEEE80211_M_MONITOR:
        !           339:                        /* can't get there */
        !           340:                        goto out;
        !           341:                }
        !           342:                if (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_QOS)
        !           343:                        hdrlen = sizeof(struct ieee80211_qosframe);
        !           344:                else
        !           345:                        hdrlen = sizeof(struct ieee80211_frame);
        !           346:                if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
        !           347:                        if (ic->ic_flags & IEEE80211_F_WEPON) {
        !           348:                                m = ieee80211_wep_crypt(ifp, m, 0);
        !           349:                                if (m == NULL) {
        !           350:                                        ic->ic_stats.is_rx_wepfail++;
        !           351:                                        goto err;
        !           352:                                }
        !           353:                                wh = mtod(m, struct ieee80211_frame *);
        !           354:                        } else {
        !           355:                                ic->ic_stats.is_rx_nowep++;
        !           356:                                goto out;
        !           357:                        }
        !           358:                }
        !           359: #if NBPFILTER > 0
        !           360:                /* copy to listener after decrypt */
        !           361:                if (ic->ic_rawbpf)
        !           362:                        bpf_mtap(ic->ic_rawbpf, m, BPF_DIRECTION_IN);
        !           363: #endif
        !           364:                m = ieee80211_decap(ifp, m, hdrlen);
        !           365:                if (m == NULL) {
        !           366:                        IEEE80211_DPRINTF(("%s: "
        !           367:                            "decapsulation error for src %s\n",
        !           368:                            __func__, ether_sprintf(wh->i_addr2)));
        !           369:                        ic->ic_stats.is_rx_decap++;
        !           370:                        goto err;
        !           371:                }
        !           372:                eh = mtod(m, struct ether_header *);
        !           373: #if 0
        !           374:                if (!ni->ni_port_valid &&
        !           375:                    eh->ether_type != htons(ETHERTYPE_PAE)) {
        !           376:                        IEEE80211_DPRINTF(("%s: port not valid: %s\n",
        !           377:                            __func__, ether_sprintf(wh->i_addr2)));
        !           378:                        ic->ic_stats.is_rx_unauth++;
        !           379:                        goto err;
        !           380:                }
        !           381: #endif
        !           382:                ifp->if_ipackets++;
        !           383:
        !           384:                /* perform as a bridge within the AP */
        !           385:                m1 = NULL;
        !           386:                if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
        !           387:                    (ic->ic_flags & IEEE80211_F_NOBRIDGE) == 0) {
        !           388:                        if (ETHER_IS_MULTICAST(eh->ether_dhost)) {
        !           389:                                m1 = m_copym(m, 0, M_COPYALL, M_DONTWAIT);
        !           390:                                if (m1 == NULL)
        !           391:                                        ifp->if_oerrors++;
        !           392:                                else
        !           393:                                        m1->m_flags |= M_MCAST;
        !           394:                        } else {
        !           395:                                ni = ieee80211_find_node(ic, eh->ether_dhost);
        !           396:                                if (ni != NULL) {
        !           397:                                        if (ni->ni_associd != 0) {
        !           398:                                                m1 = m;
        !           399:                                                m = NULL;
        !           400:                                        }
        !           401:                                }
        !           402:                        }
        !           403:                        if (m1 != NULL) {
        !           404:                                len = m1->m_pkthdr.len;
        !           405:                                IFQ_ENQUEUE(&ifp->if_snd, m1, NULL, error);
        !           406:                                if (error)
        !           407:                                        ifp->if_oerrors++;
        !           408:                                else {
        !           409:                                        if (m != NULL)
        !           410:                                                ifp->if_omcasts++;
        !           411:                                        ifp->if_obytes += len;
        !           412:                                }
        !           413:                        }
        !           414:                }
        !           415:                if (m != NULL) {
        !           416: #if NBPFILTER > 0
        !           417:                        /*
        !           418:                         * If we forward packet into transmitter of the AP,
        !           419:                         * we don't need to duplicate for DLT_EN10MB.
        !           420:                         */
        !           421:                        if (ifp->if_bpf && m1 == NULL)
        !           422:                                bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
        !           423: #endif
        !           424:                        ether_input_mbuf(ifp, m);
        !           425:                }
        !           426:                return;
        !           427:
        !           428:        case IEEE80211_FC0_TYPE_MGT:
        !           429:                if (dir != IEEE80211_FC1_DIR_NODS) {
        !           430:                        ic->ic_stats.is_rx_wrongdir++;
        !           431:                        goto err;
        !           432:                }
        !           433:                if (ic->ic_opmode == IEEE80211_M_AHDEMO) {
        !           434:                        ic->ic_stats.is_rx_ahdemo_mgt++;
        !           435:                        goto out;
        !           436:                }
        !           437:                subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
        !           438:
        !           439:                /* drop frames without interest */
        !           440:                if (ic->ic_state == IEEE80211_S_SCAN) {
        !           441:                        if (subtype != IEEE80211_FC0_SUBTYPE_BEACON &&
        !           442:                            subtype != IEEE80211_FC0_SUBTYPE_PROBE_RESP) {
        !           443:                                ic->ic_stats.is_rx_mgtdiscard++;
        !           444:                                goto out;
        !           445:                        }
        !           446:                }
        !           447:
        !           448:                if (ifp->if_flags & IFF_DEBUG) {
        !           449:                        /* avoid to print too many frames */
        !           450:                        int doprint = 0;
        !           451:
        !           452:                        switch (subtype) {
        !           453:                        case IEEE80211_FC0_SUBTYPE_BEACON:
        !           454:                                if (ic->ic_state == IEEE80211_S_SCAN)
        !           455:                                        doprint = 1;
        !           456:                                break;
        !           457:                        case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
        !           458:                                if (ic->ic_opmode == IEEE80211_M_IBSS)
        !           459:                                        doprint = 1;
        !           460:                                break;
        !           461:                        default:
        !           462:                                doprint = 1;
        !           463:                                break;
        !           464:                        }
        !           465: #ifdef IEEE80211_DEBUG
        !           466:                        doprint += ieee80211_debug;
        !           467: #endif
        !           468:                        if (doprint)
        !           469:                                printf("%s: received %s from %s rssi %d mode %s\n",
        !           470:                                    ifp->if_xname,
        !           471:                                    ieee80211_mgt_subtype_name[subtype
        !           472:                                    >> IEEE80211_FC0_SUBTYPE_SHIFT],
        !           473:                                    ether_sprintf(wh->i_addr2), rssi,
        !           474:                                    ieee80211_phymode_name[ieee80211_chan2mode(ic,
        !           475:                                    ic->ic_bss->ni_chan)]);
        !           476:                }
        !           477: #if NBPFILTER > 0
        !           478:                if (ic->ic_rawbpf)
        !           479:                        bpf_mtap(ic->ic_rawbpf, m, BPF_DIRECTION_IN);
        !           480:                /*
        !           481:                 * Drop mbuf if it was filtered by bpf. Normally, this is
        !           482:                 * done in ether_input() but IEEE 802.11 management frames
        !           483:                 * are a special case.
        !           484:                 */
        !           485:                if (m->m_flags & M_FILDROP) {
        !           486:                        m_freem(m);
        !           487:                        return;
        !           488:                }
        !           489: #endif
        !           490:                (*ic->ic_recv_mgmt)(ic, m, ni, subtype, rssi, rstamp);
        !           491:                m_freem(m);
        !           492:                return;
        !           493:
        !           494:        case IEEE80211_FC0_TYPE_CTL:
        !           495:                ic->ic_stats.is_rx_ctl++;
        !           496:                if (ic->ic_opmode != IEEE80211_M_HOSTAP)
        !           497:                        goto out;
        !           498:                subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
        !           499:                if (subtype == IEEE80211_FC0_SUBTYPE_PS_POLL) {
        !           500:                        /* XXX statistic */
        !           501:                        /* Dump out a single packet from the host */
        !           502:                        if (ifp->if_flags & IFF_DEBUG)
        !           503:                                printf("%s: got power save probe from %s\n",
        !           504:                                    ifp->if_xname,
        !           505:                                    ether_sprintf(wh->i_addr2));
        !           506:                        ieee80211_recv_pspoll(ic, m, rssi, rstamp);
        !           507:                }
        !           508:                goto out;
        !           509:
        !           510:        default:
        !           511:                IEEE80211_DPRINTF(("%s: bad packet type %x\n", __func__, type));
        !           512:                /* should not come here */
        !           513:                break;
        !           514:        }
        !           515:  err:
        !           516:        ifp->if_ierrors++;
        !           517:  out:
        !           518:        if (m != NULL) {
        !           519: #if NBPFILTER > 0
        !           520:                if (ic->ic_rawbpf)
        !           521:                        bpf_mtap(ic->ic_rawbpf, m, BPF_DIRECTION_IN);
        !           522: #endif
        !           523:                m_freem(m);
        !           524:        }
        !           525: }
        !           526:
        !           527: struct mbuf *
        !           528: ieee80211_decap(struct ifnet *ifp, struct mbuf *m, int hdrlen)
        !           529: {
        !           530:        struct ieee80211_frame wh;
        !           531:        struct ether_header *eh;
        !           532:        struct llc *llc;
        !           533:
        !           534:        if (m->m_len < hdrlen + sizeof(*llc)) {
        !           535:                m = m_pullup(m, hdrlen + sizeof(*llc));
        !           536:                if (m == NULL)
        !           537:                        return NULL;
        !           538:        }
        !           539:        memcpy(&wh, mtod(m, caddr_t), sizeof(wh));
        !           540:        llc = (struct llc *)(mtod(m, caddr_t) + hdrlen);
        !           541:        if (llc->llc_dsap == LLC_SNAP_LSAP &&
        !           542:            llc->llc_ssap == LLC_SNAP_LSAP &&
        !           543:            llc->llc_control == LLC_UI &&
        !           544:            llc->llc_snap.org_code[0] == 0 &&
        !           545:            llc->llc_snap.org_code[1] == 0 &&
        !           546:            llc->llc_snap.org_code[2] == 0) {
        !           547:                m_adj(m, hdrlen + sizeof(struct llc) - sizeof(*eh));
        !           548:                llc = NULL;
        !           549:        } else {
        !           550:                m_adj(m, hdrlen - sizeof(*eh));
        !           551:        }
        !           552:        eh = mtod(m, struct ether_header *);
        !           553:        switch (wh.i_fc[1] & IEEE80211_FC1_DIR_MASK) {
        !           554:        case IEEE80211_FC1_DIR_NODS:
        !           555:                IEEE80211_ADDR_COPY(eh->ether_dhost, wh.i_addr1);
        !           556:                IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr2);
        !           557:                break;
        !           558:        case IEEE80211_FC1_DIR_TODS:
        !           559:                IEEE80211_ADDR_COPY(eh->ether_dhost, wh.i_addr3);
        !           560:                IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr2);
        !           561:                break;
        !           562:        case IEEE80211_FC1_DIR_FROMDS:
        !           563:                IEEE80211_ADDR_COPY(eh->ether_dhost, wh.i_addr1);
        !           564:                IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr3);
        !           565:                break;
        !           566:        case IEEE80211_FC1_DIR_DSTODS:
        !           567:                /* not yet supported */
        !           568:                IEEE80211_DPRINTF(("%s: discard DS to DS frame\n", __func__));
        !           569:                m_freem(m);
        !           570:                return NULL;
        !           571:        }
        !           572:        if (!ALIGNED_POINTER(mtod(m, caddr_t) + sizeof(*eh), u_int32_t)) {
        !           573:                struct mbuf *n, *n0, **np;
        !           574:                caddr_t newdata;
        !           575:                int off, pktlen;
        !           576:
        !           577:                n0 = NULL;
        !           578:                np = &n0;
        !           579:                off = 0;
        !           580:                pktlen = m->m_pkthdr.len;
        !           581:                while (pktlen > off) {
        !           582:                        if (n0 == NULL) {
        !           583:                                MGETHDR(n, M_DONTWAIT, MT_DATA);
        !           584:                                if (n == NULL) {
        !           585:                                        m_freem(m);
        !           586:                                        return NULL;
        !           587:                                }
        !           588:                                M_DUP_PKTHDR(n, m);
        !           589:                                n->m_len = MHLEN;
        !           590:                        } else {
        !           591:                                MGET(n, M_DONTWAIT, MT_DATA);
        !           592:                                if (n == NULL) {
        !           593:                                        m_freem(m);
        !           594:                                        m_freem(n0);
        !           595:                                        return NULL;
        !           596:                                }
        !           597:                                n->m_len = MLEN;
        !           598:                        }
        !           599:                        if (pktlen - off >= MINCLSIZE) {
        !           600:                                MCLGET(n, M_DONTWAIT);
        !           601:                                if (n->m_flags & M_EXT)
        !           602:                                        n->m_len = n->m_ext.ext_size;
        !           603:                        }
        !           604:                        if (n0 == NULL) {
        !           605:                                newdata =
        !           606:                                    (caddr_t)ALIGN(n->m_data + sizeof(*eh)) -
        !           607:                                    sizeof(*eh);
        !           608:                                n->m_len -= newdata - n->m_data;
        !           609:                                n->m_data = newdata;
        !           610:                        }
        !           611:                        if (n->m_len > pktlen - off)
        !           612:                                n->m_len = pktlen - off;
        !           613:                        m_copydata(m, off, n->m_len, mtod(n, caddr_t));
        !           614:                        off += n->m_len;
        !           615:                        *np = n;
        !           616:                        np = &n->m_next;
        !           617:                }
        !           618:                m_freem(m);
        !           619:                m = n0;
        !           620:        }
        !           621:        if (llc != NULL) {
        !           622:                eh = mtod(m, struct ether_header *);
        !           623:                eh->ether_type = htons(m->m_pkthdr.len - sizeof(*eh));
        !           624:        }
        !           625:        return m;
        !           626: }
        !           627:
        !           628: /*
        !           629:  * Install received rate set information in the node's state block.
        !           630:  */
        !           631: int
        !           632: ieee80211_setup_rates(struct ieee80211com *ic, struct ieee80211_node *ni,
        !           633:     const u_int8_t *rates, const u_int8_t *xrates, int flags)
        !           634: {
        !           635:        struct ieee80211_rateset *rs = &ni->ni_rates;
        !           636:
        !           637:        memset(rs, 0, sizeof(*rs));
        !           638:        rs->rs_nrates = rates[1];
        !           639:        memcpy(rs->rs_rates, rates + 2, rs->rs_nrates);
        !           640:        if (xrates != NULL) {
        !           641:                u_int8_t nxrates;
        !           642:                /*
        !           643:                 * Tack on 11g extended supported rate element.
        !           644:                 */
        !           645:                nxrates = xrates[1];
        !           646:                if (rs->rs_nrates + nxrates > IEEE80211_RATE_MAXSIZE) {
        !           647:                        nxrates = IEEE80211_RATE_MAXSIZE - rs->rs_nrates;
        !           648:                        IEEE80211_DPRINTF(("%s: extended rate set too large;"
        !           649:                                " only using %u of %u rates\n",
        !           650:                                __func__, nxrates, xrates[1]));
        !           651:                        ic->ic_stats.is_rx_rstoobig++;
        !           652:                }
        !           653:                memcpy(rs->rs_rates + rs->rs_nrates, xrates+2, nxrates);
        !           654:                rs->rs_nrates += nxrates;
        !           655:        }
        !           656:        return ieee80211_fix_rate(ic, ni, flags);
        !           657: }
        !           658:
        !           659: /* Verify the existence and length of __elem or get out. */
        !           660: #define IEEE80211_VERIFY_ELEMENT(__elem, __maxlen) do {                        \
        !           661:        if ((__elem) == NULL) {                                         \
        !           662:                IEEE80211_DPRINTF(("%s: no " #__elem "in %s frame\n",   \
        !           663:                        __func__, ieee80211_mgt_subtype_name[           \
        !           664:                                (wh->i_fc[0] &                          \
        !           665:                                    IEEE80211_FC0_SUBTYPE_MASK) >>      \
        !           666:                                IEEE80211_FC0_SUBTYPE_SHIFT]));         \
        !           667:                ic->ic_stats.is_rx_elem_missing++;                      \
        !           668:                return;                                                 \
        !           669:        }                                                               \
        !           670:        if ((__elem)[1] > (__maxlen)) {                                 \
        !           671:                IEEE80211_DPRINTF(("%s: bad " #__elem " len %d in %s "  \
        !           672:                        "frame from %s\n", __func__, (__elem)[1],       \
        !           673:                        ieee80211_mgt_subtype_name[(wh->i_fc[0] &       \
        !           674:                                IEEE80211_FC0_SUBTYPE_MASK) >>          \
        !           675:                            IEEE80211_FC0_SUBTYPE_SHIFT],               \
        !           676:                        ether_sprintf((u_int8_t *)wh->i_addr2)));       \
        !           677:                ic->ic_stats.is_rx_elem_toobig++;                       \
        !           678:                return;                                                 \
        !           679:        }                                                               \
        !           680: } while (0)
        !           681:
        !           682: #define        IEEE80211_VERIFY_LENGTH(_len, _minlen) do {                     \
        !           683:        if ((_len) < (_minlen)) {                                       \
        !           684:                IEEE80211_DPRINTF(("%s: %s frame too short from %s\n",  \
        !           685:                        __func__,                                       \
        !           686:                        ieee80211_mgt_subtype_name[(wh->i_fc[0] &       \
        !           687:                                IEEE80211_FC0_SUBTYPE_MASK) >>          \
        !           688:                            IEEE80211_FC0_SUBTYPE_SHIFT],               \
        !           689:                        ether_sprintf((u_int8_t *)wh->i_addr2)));       \
        !           690:                ic->ic_stats.is_rx_elem_toosmall++;                     \
        !           691:                return;                                                 \
        !           692:        }                                                               \
        !           693: } while (0)
        !           694:
        !           695: #ifdef IEEE80211_DEBUG
        !           696: void
        !           697: ieee80211_ssid_mismatch(struct ieee80211com *, const char *,
        !           698:     const u_int8_t[IEEE80211_ADDR_LEN], const u_int8_t *);
        !           699: void
        !           700: ieee80211_ssid_mismatch(struct ieee80211com *ic, const char *tag,
        !           701:     const u_int8_t mac[IEEE80211_ADDR_LEN], const u_int8_t *ssid)
        !           702: {
        !           703:        printf("[%s] %s req ssid mismatch: ",
        !           704:            ether_sprintf((u_int8_t *)mac), tag);
        !           705:        ieee80211_print_essid(ssid + 2, ssid[1]);
        !           706:        printf("\n");
        !           707: }
        !           708:
        !           709: #define IEEE80211_VERIFY_SSID(_ni, _ssid, _packet_type) do {           \
        !           710:        if ((_ssid)[1] != 0 &&                                          \
        !           711:            ((_ssid)[1] != (_ni)->ni_esslen ||                          \
        !           712:            memcmp((_ssid) + 2, (_ni)->ni_essid, (_ssid)[1]) != 0)) {   \
        !           713:                if (ieee80211_debug)                                    \
        !           714:                        ieee80211_ssid_mismatch(ic, _packet_type,       \
        !           715:                                wh->i_addr2, _ssid);                    \
        !           716:                ic->ic_stats.is_rx_ssidmismatch++;                      \
        !           717:                return;                                                 \
        !           718:        }                                                               \
        !           719: } while (0)
        !           720: #else /* !IEEE80211_DEBUG */
        !           721: #define IEEE80211_VERIFY_SSID(_ni, _ssid, _packet_type) do {           \
        !           722:        if ((_ssid)[1] != 0 &&                                          \
        !           723:            ((_ssid)[1] != (_ni)->ni_esslen ||                          \
        !           724:            memcmp((_ssid) + 2, (_ni)->ni_essid, (_ssid)[1]) != 0)) {   \
        !           725:                ic->ic_stats.is_rx_ssidmismatch++;                      \
        !           726:                return;                                                 \
        !           727:        }                                                               \
        !           728: } while (0)
        !           729: #endif /* !IEEE80211_DEBUG */
        !           730:
        !           731: void
        !           732: ieee80211_auth_open(struct ieee80211com *ic, const struct ieee80211_frame *wh,
        !           733:     struct ieee80211_node *ni, int rssi, u_int32_t rstamp, u_int16_t seq,
        !           734:     u_int16_t status)
        !           735: {
        !           736:        struct ifnet *ifp = &ic->ic_if;
        !           737:        switch (ic->ic_opmode) {
        !           738:        case IEEE80211_M_IBSS:
        !           739:                if (ic->ic_state != IEEE80211_S_RUN ||
        !           740:                    seq != IEEE80211_AUTH_OPEN_REQUEST) {
        !           741:                        IEEE80211_DPRINTF(("%s: discard auth from %s; "
        !           742:                            "state %u, seq %u\n", __func__,
        !           743:                            ether_sprintf((u_int8_t *)wh->i_addr2),
        !           744:                            ic->ic_state, seq));
        !           745:                        ic->ic_stats.is_rx_bad_auth++;
        !           746:                        return;
        !           747:                }
        !           748:                ieee80211_new_state(ic, IEEE80211_S_AUTH,
        !           749:                    wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
        !           750:                break;
        !           751:
        !           752:        case IEEE80211_M_AHDEMO:
        !           753:                /* should not come here */
        !           754:                break;
        !           755:
        !           756:        case IEEE80211_M_HOSTAP:
        !           757:                if (ic->ic_state != IEEE80211_S_RUN ||
        !           758:                    seq != IEEE80211_AUTH_OPEN_REQUEST) {
        !           759:                        IEEE80211_DPRINTF(("%s: discard auth from %s; "
        !           760:                            "state %u, seq %u\n", __func__,
        !           761:                            ether_sprintf((u_int8_t *)wh->i_addr2),
        !           762:                            ic->ic_state, seq));
        !           763:                        ic->ic_stats.is_rx_bad_auth++;
        !           764:                        return;
        !           765:                }
        !           766:                if (ni == ic->ic_bss) {
        !           767:                        ni = ieee80211_alloc_node(ic, wh->i_addr2);
        !           768:                        if (ni == NULL) {
        !           769:                                ic->ic_stats.is_rx_nodealloc++;
        !           770:                                return;
        !           771:                        }
        !           772:                        IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_bss->ni_bssid);
        !           773:                        ni->ni_rssi = rssi;
        !           774:                        ni->ni_rstamp = rstamp;
        !           775:                        ni->ni_chan = ic->ic_bss->ni_chan;
        !           776:                }
        !           777:                IEEE80211_SEND_MGMT(ic, ni,
        !           778:                        IEEE80211_FC0_SUBTYPE_AUTH, seq + 1);
        !           779:                if (ifp->if_flags & IFF_DEBUG)
        !           780:                        printf("%s: station %s %s authenticated (open)\n",
        !           781:                            ifp->if_xname,
        !           782:                            ether_sprintf((u_int8_t *)ni->ni_macaddr),
        !           783:                            ni->ni_state != IEEE80211_STA_CACHE ?
        !           784:                            "newly" : "already");
        !           785:                ieee80211_node_newstate(ni, IEEE80211_STA_AUTH);
        !           786:                break;
        !           787:
        !           788:        case IEEE80211_M_STA:
        !           789:                if (ic->ic_state != IEEE80211_S_AUTH ||
        !           790:                    seq != IEEE80211_AUTH_OPEN_RESPONSE) {
        !           791:                        ic->ic_stats.is_rx_bad_auth++;
        !           792:                        IEEE80211_DPRINTF(("%s: discard auth from %s; "
        !           793:                            "state %u, seq %u\n", __func__,
        !           794:                            ether_sprintf((u_int8_t *)wh->i_addr2),
        !           795:                            ic->ic_state, seq));
        !           796:                        return;
        !           797:                }
        !           798:                if (status != 0) {
        !           799:                        if (ifp->if_flags & IFF_DEBUG)
        !           800:                                printf("%s: open authentication failed "
        !           801:                                    "(reason %d) for %s\n", ifp->if_xname,
        !           802:                                    status,
        !           803:                                    ether_sprintf((u_int8_t *)wh->i_addr3));
        !           804:                        if (ni != ic->ic_bss)
        !           805:                                ni->ni_fails++;
        !           806:                        ic->ic_stats.is_rx_auth_fail++;
        !           807:                        return;
        !           808:                }
        !           809:                ieee80211_new_state(ic, IEEE80211_S_ASSOC,
        !           810:                    wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
        !           811:                break;
        !           812:        case IEEE80211_M_MONITOR:
        !           813:                break;
        !           814:        }
        !           815: }
        !           816:
        !           817: /* unaligned little endian access */
        !           818: #define LE_READ_2(p)                                   \
        !           819:        ((u_int16_t)                                    \
        !           820:         ((((const u_int8_t *)(p))[0]) |                \
        !           821:          (((const u_int8_t *)(p))[1] <<  8)))
        !           822: #define LE_READ_4(p)                                   \
        !           823:        ((u_int32_t)                                    \
        !           824:         ((((const u_int8_t *)(p))[0])       |          \
        !           825:          (((const u_int8_t *)(p))[1] <<  8) |          \
        !           826:          (((const u_int8_t *)(p))[2] << 16) |          \
        !           827:          (((const u_int8_t *)(p))[3] << 24)))
        !           828:
        !           829: /*
        !           830:  * Parse an EDCA Parameter Set element (see 7.3.2.27).
        !           831:  */
        !           832: int
        !           833: ieee80211_parse_edca_params_body(struct ieee80211com *ic, const u_int8_t *frm)
        !           834: {
        !           835:        u_int updtcount;
        !           836:        int aci;
        !           837:
        !           838:        /*
        !           839:         * Check if EDCA parameters have changed XXX if we miss more than
        !           840:         * 15 consecutive beacons, we might not detect changes to EDCA
        !           841:         * parameters due to wraparound of the 4-bit Update Count field.
        !           842:         */
        !           843:        updtcount = frm[0] & 0xf;
        !           844:        if (updtcount == ic->ic_edca_updtcount)
        !           845:                return 0;       /* no changes to EDCA parameters, ignore */
        !           846:        ic->ic_edca_updtcount = updtcount;
        !           847:
        !           848:        frm += 2;       /* skip QoS Info & Reserved fields */
        !           849:
        !           850:        /* parse AC Parameter Records */
        !           851:        for (aci = 0; aci < EDCA_NUM_AC; aci++) {
        !           852:                struct ieee80211_edca_ac_params *ac = &ic->ic_edca_ac[aci];
        !           853:
        !           854:                ac->ac_acm       = (frm[0] >> 4) & 0x1;
        !           855:                ac->ac_aifsn     = frm[0] & 0xf;
        !           856:                ac->ac_ecwmin    = frm[1] & 0xf;
        !           857:                ac->ac_ecwmax    = frm[1] >> 4;
        !           858:                ac->ac_txoplimit = LE_READ_2(frm + 2);
        !           859:                frm += 4;
        !           860:        }
        !           861:        /* give drivers a chance to update their settings */
        !           862:        if ((ic->ic_flags & IEEE80211_F_QOS) && ic->ic_updateedca != NULL)
        !           863:                (*ic->ic_updateedca)(ic);
        !           864:
        !           865:        return 0;
        !           866: }
        !           867:
        !           868: int
        !           869: ieee80211_parse_edca_params(struct ieee80211com *ic, const u_int8_t *frm)
        !           870: {
        !           871:        /* check IE length */
        !           872:        if (frm[1] < 18) {
        !           873:                IEEE80211_DPRINTF(("%s: invalid EDCA parameter set IE;"
        !           874:                    " length %u, expecting 18\n", __func__, frm[1]));
        !           875:                ic->ic_stats.is_rx_elem_toosmall++;
        !           876:                return IEEE80211_REASON_IE_INVALID;
        !           877:        }
        !           878:        return ieee80211_parse_edca_params_body(ic, frm + 2);
        !           879: }
        !           880:
        !           881: int
        !           882: ieee80211_parse_wmm_params(struct ieee80211com *ic, const u_int8_t *frm)
        !           883: {
        !           884:        /* check IE length */
        !           885:        if (frm[1] < 24) {
        !           886:                IEEE80211_DPRINTF(("%s: invalid WMM parameter set IE;"
        !           887:                    " length %u, expecting 24\n", __func__, frm[1]));
        !           888:                ic->ic_stats.is_rx_elem_toosmall++;
        !           889:                return IEEE80211_REASON_IE_INVALID;
        !           890:        }
        !           891:        return ieee80211_parse_edca_params_body(ic, frm + 8);
        !           892: }
        !           893:
        !           894: enum ieee80211_cipher
        !           895: ieee80211_parse_rsn_cipher(const u_int8_t selector[4])
        !           896: {
        !           897:        /* from IEEE Std 802.11i-2004 - Table 20da */
        !           898:        if (memcmp(selector, MICROSOFT_OUI, 3) == 0 ||  /* WPA1 */
        !           899:            memcmp(selector, IEEE80211_OUI, 3) == 0) {  /* RSN (aka WPA2) */
        !           900:                switch (selector[3]) {
        !           901:                case 0: /* use group cipher suite */
        !           902:                        return IEEE80211_CIPHER_USEGROUP;
        !           903:                case 1: /* WEP-40 */
        !           904:                        return IEEE80211_CIPHER_WEP40;
        !           905:                case 2: /* TKIP */
        !           906:                        return IEEE80211_CIPHER_TKIP;
        !           907:                case 4: /* CCMP (RSNA default) */
        !           908:                        return IEEE80211_CIPHER_CCMP;
        !           909:                case 5: /* WEP-104 */
        !           910:                        return IEEE80211_CIPHER_WEP104;
        !           911:                }
        !           912:        }
        !           913:        return IEEE80211_CIPHER_NONE;   /* ignore unknown ciphers */
        !           914: }
        !           915:
        !           916: enum ieee80211_akm
        !           917: ieee80211_parse_rsn_akm(const u_int8_t selector[4])
        !           918: {
        !           919:        /* from IEEE Std 802.11i-2004 - Table 20dc */
        !           920:        if (memcmp(selector, MICROSOFT_OUI, 3) == 0 ||  /* WPA1 */
        !           921:            memcmp(selector, IEEE80211_OUI, 3) == 0) {  /* RSN (aka WPA2) */
        !           922:                switch (selector[3]) {
        !           923:                case 1: /* IEEE 802.1X (RSNA default) */
        !           924:                        return IEEE80211_AKM_IEEE8021X;
        !           925:                case 2: /* PSK */
        !           926:                        return IEEE80211_AKM_PSK;
        !           927:                }
        !           928:        }
        !           929:        return IEEE80211_AKM_NONE;      /* ignore unknown AKMs */
        !           930: }
        !           931:
        !           932: /*
        !           933:  * Parse an RSN element (see 7.3.2.25).
        !           934:  */
        !           935: int
        !           936: ieee80211_parse_rsn_body(struct ieee80211com *ic, struct ieee80211_node *ni,
        !           937:     const u_int8_t *frm, u_int len)
        !           938: {
        !           939:        const u_int8_t *efrm;
        !           940:        u_int16_t m, n, s;
        !           941:        u_int16_t rsncaps;
        !           942:        enum ieee80211_cipher group_cipher;
        !           943:        u_int akmset, pairwise_cipherset;
        !           944:
        !           945:        efrm = frm + len;
        !           946:
        !           947:        /* check Version field */
        !           948:        if (LE_READ_2(frm) != 1)
        !           949:                return IEEE80211_REASON_RSN_IE_VER_UNSUP;
        !           950:        frm += 2;
        !           951:
        !           952:        /* all fields after the Version field are optional */
        !           953:
        !           954:        /* if Cipher Suite missing, default to CCMP */
        !           955:        ni->ni_group_cipher = IEEE80211_CIPHER_CCMP;
        !           956:        ni->ni_pairwise_cipherset = IEEE80211_CIPHER_CCMP;
        !           957:        /* if AKM Suite missing, default to 802.1X */
        !           958:        ni->ni_akmset = IEEE80211_AKM_IEEE8021X;
        !           959:
        !           960:        /* read Group Cipher Suite field */
        !           961:        if (frm + 4 > efrm)
        !           962:                return 0;
        !           963:        group_cipher = ieee80211_parse_rsn_cipher(frm);
        !           964:        if (group_cipher == IEEE80211_CIPHER_USEGROUP)
        !           965:                return IEEE80211_REASON_BAD_GROUP_CIPHER;
        !           966:        frm += 4;
        !           967:
        !           968:        /* read Pairwise Cipher Suite Count field */
        !           969:        if (frm + 2 > efrm)
        !           970:                return 0;
        !           971:        m = LE_READ_2(frm);
        !           972:        frm += 2;
        !           973:
        !           974:        /* read Pairwise Cipher Suite List */
        !           975:        if (frm + m * 4 > efrm)
        !           976:                return IEEE80211_REASON_IE_INVALID;
        !           977:        pairwise_cipherset = IEEE80211_CIPHER_NONE;
        !           978:        while (m-- > 0) {
        !           979:                pairwise_cipherset |= ieee80211_parse_rsn_cipher(frm);
        !           980:                frm += 4;
        !           981:        }
        !           982:        if (pairwise_cipherset & IEEE80211_CIPHER_USEGROUP) {
        !           983:                if (pairwise_cipherset != IEEE80211_CIPHER_USEGROUP)
        !           984:                        return IEEE80211_REASON_BAD_PAIRWISE_CIPHER;
        !           985:                if (group_cipher == IEEE80211_CIPHER_CCMP)
        !           986:                        return IEEE80211_REASON_BAD_PAIRWISE_CIPHER;
        !           987:        }
        !           988:
        !           989:        /* read AKM Suite List Count field */
        !           990:        if (frm + 2 > efrm)
        !           991:                return 0;
        !           992:        n = LE_READ_2(frm);
        !           993:        frm += 2;
        !           994:
        !           995:        /* read AKM Suite List */
        !           996:        if (frm + n * 4 > efrm)
        !           997:                return IEEE80211_REASON_IE_INVALID;
        !           998:        akmset = IEEE80211_AKM_NONE;
        !           999:        while (n-- > 0) {
        !          1000:                akmset |= ieee80211_parse_rsn_akm(frm);
        !          1001:                frm += 4;
        !          1002:        }
        !          1003:
        !          1004:        /* read RSN Capabilities field */
        !          1005:        if (frm + 2 > efrm)
        !          1006:                return 0;
        !          1007:        rsncaps = LE_READ_2(frm);
        !          1008:        frm += 2;
        !          1009:
        !          1010:        /* read PMKID Count field */
        !          1011:        if (frm + 2 > efrm)
        !          1012:                return 0;
        !          1013:        s = LE_READ_2(frm);
        !          1014:        frm += 2;
        !          1015:
        !          1016:        /* read PMKID List */
        !          1017:        if (frm + s * IEEE80211_PMKID_LEN > efrm)
        !          1018:                return IEEE80211_REASON_IE_INVALID;
        !          1019:        while (s-- > 0) {
        !          1020:                /* ignore PMKIDs for now */
        !          1021:                frm += IEEE80211_PMKID_LEN;
        !          1022:        }
        !          1023:
        !          1024:        ni->ni_group_cipher = group_cipher;
        !          1025:        ni->ni_pairwise_cipherset = pairwise_cipherset;
        !          1026:        ni->ni_akmset = akmset;
        !          1027:        ni->ni_rsncaps = rsncaps;
        !          1028:
        !          1029:        return 0;
        !          1030: }
        !          1031:
        !          1032: int
        !          1033: ieee80211_parse_rsn(struct ieee80211com *ic, struct ieee80211_node *ni,
        !          1034:     const u_int8_t *frm)
        !          1035: {
        !          1036:        /* check IE length */
        !          1037:        if (frm[1] < 2) {
        !          1038:                IEEE80211_DPRINTF(("%s: invalid RSN/WPA2 IE;"
        !          1039:                    " length %u, expecting at least 2\n", __func__, frm[1]));
        !          1040:                ic->ic_stats.is_rx_elem_toosmall++;
        !          1041:                return IEEE80211_REASON_IE_INVALID;
        !          1042:        }
        !          1043:        return ieee80211_parse_rsn_body(ic, ni, frm + 2, frm[1] - 2);
        !          1044: }
        !          1045:
        !          1046: int
        !          1047: ieee80211_parse_wpa1(struct ieee80211com *ic, struct ieee80211_node *ni,
        !          1048:     const u_int8_t *frm)
        !          1049: {
        !          1050:        /* check IE length */
        !          1051:        if (frm[1] < 6) {
        !          1052:                IEEE80211_DPRINTF(("%s: invalid WPA1 IE;"
        !          1053:                    " length %u, expecting at least 6\n", __func__, frm[1]));
        !          1054:                ic->ic_stats.is_rx_elem_toosmall++;
        !          1055:                return IEEE80211_REASON_IE_INVALID;
        !          1056:        }
        !          1057:        return ieee80211_parse_rsn_body(ic, ni, frm + 6, frm[1] - 4);
        !          1058: }
        !          1059:
        !          1060: /*-
        !          1061:  * Beacon/Probe response frame format:
        !          1062:  * [8]    Timestamp
        !          1063:  * [2]    Beacon interval
        !          1064:  * [2]    Capability
        !          1065:  * [tlv]  Service Set Identifier (SSID)
        !          1066:  * [tlv]  Supported rates
        !          1067:  * [tlv*] Frequency-Hopping (FH) Parameter Set
        !          1068:  * [tlv*] DS Parameter Set (802.11g)
        !          1069:  * [tlv]  ERP Information (802.11g)
        !          1070:  * [tlv]  Extended Supported Rates (802.11g)
        !          1071:  * [tlv]  RSN (802.11i)
        !          1072:  * [tlv]  EDCA Parameter Set (802.11e)
        !          1073:  * [tlv]  QoS Capability (Beacon only, 802.11e)
        !          1074:  */
        !          1075: void
        !          1076: ieee80211_recv_probe_resp(struct ieee80211com *ic, struct mbuf *m0,
        !          1077:     struct ieee80211_node *ni, int rssi, u_int32_t rstamp)
        !          1078: {
        !          1079: #define        ISPROBE(_wh)    (((_wh)->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == \
        !          1080:        IEEE80211_FC0_SUBTYPE_PROBE_RESP)
        !          1081:
        !          1082:        const struct ieee80211_frame *wh;
        !          1083:        const u_int8_t *frm, *efrm;
        !          1084:        const u_int8_t *tstamp, *ssid, *rates, *xrates, *edca, *wmm;
        !          1085:        const u_int8_t *rsn, *wpa;
        !          1086:        u_int16_t capinfo, bintval, fhdwell;
        !          1087:        u_int8_t chan, bchan, fhindex, erp;
        !          1088:        int is_new;
        !          1089:
        !          1090:        /*
        !          1091:         * We process beacon/probe response frames for:
        !          1092:         *    o station mode: to collect state
        !          1093:         *      updates such as 802.11g slot time and for passive
        !          1094:         *      scanning of APs
        !          1095:         *    o adhoc mode: to discover neighbors
        !          1096:         *    o hostap mode: for passive scanning of neighbor APs
        !          1097:         *    o when scanning
        !          1098:         * In other words, in all modes other than monitor (which
        !          1099:         * does not process incoming packets) and adhoc-demo (which
        !          1100:         * does not use management frames at all).
        !          1101:         */
        !          1102: #ifdef DIAGNOSTIC
        !          1103:        if (ic->ic_opmode != IEEE80211_M_STA &&
        !          1104:            ic->ic_opmode != IEEE80211_M_IBSS &&
        !          1105:            ic->ic_opmode != IEEE80211_M_HOSTAP &&
        !          1106:            ic->ic_state != IEEE80211_S_SCAN) {
        !          1107:                panic("%s: impossible operating mode", __func__);
        !          1108:        }
        !          1109: #endif
        !          1110:        wh = mtod(m0, struct ieee80211_frame *);
        !          1111:        frm = (const u_int8_t *)&wh[1];
        !          1112:        efrm = mtod(m0, u_int8_t *) + m0->m_len;
        !          1113:
        !          1114:        IEEE80211_VERIFY_LENGTH(efrm - frm, 12);
        !          1115:        tstamp  = frm; frm += 8;
        !          1116:        bintval = LE_READ_2(frm); frm += 2;
        !          1117:        capinfo = LE_READ_2(frm); frm += 2;
        !          1118:        ssid = rates = xrates = edca = wmm = rsn = wpa = NULL;
        !          1119:        bchan = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan);
        !          1120:        chan = bchan;
        !          1121:        fhdwell = 0;
        !          1122:        fhindex = 0;
        !          1123:        erp = 0;
        !          1124:        while (frm + 2 <= efrm) {
        !          1125:                if (frm + 2 + frm[1] > efrm) {
        !          1126:                        ic->ic_stats.is_rx_elem_toosmall++;
        !          1127:                        return;
        !          1128:                }
        !          1129:                switch (frm[0]) {
        !          1130:                case IEEE80211_ELEMID_SSID:
        !          1131:                        ssid = frm;
        !          1132:                        break;
        !          1133:                case IEEE80211_ELEMID_RATES:
        !          1134:                        rates = frm;
        !          1135:                        break;
        !          1136:                case IEEE80211_ELEMID_FHPARMS:
        !          1137:                        if (ic->ic_phytype != IEEE80211_T_FH)
        !          1138:                                break;
        !          1139:                        if (frm[1] < 5) {
        !          1140:                                ic->ic_stats.is_rx_elem_toosmall++;
        !          1141:                                break;
        !          1142:                        }
        !          1143:                        fhdwell = LE_READ_2(frm + 2);
        !          1144:                        chan = IEEE80211_FH_CHAN(frm[4], frm[5]);
        !          1145:                        fhindex = frm[6];
        !          1146:                        break;
        !          1147:                case IEEE80211_ELEMID_DSPARMS:
        !          1148:                        if (ic->ic_phytype == IEEE80211_T_FH)
        !          1149:                                break;
        !          1150:                        if (frm[1] < 1) {
        !          1151:                                ic->ic_stats.is_rx_elem_toosmall++;
        !          1152:                                break;
        !          1153:                        }
        !          1154:                        chan = frm[2];
        !          1155:                        break;
        !          1156:                case IEEE80211_ELEMID_TIM:
        !          1157:                        break;
        !          1158:                case IEEE80211_ELEMID_IBSSPARMS:
        !          1159:                        break;
        !          1160:                case IEEE80211_ELEMID_XRATES:
        !          1161:                        xrates = frm;
        !          1162:                        break;
        !          1163:                case IEEE80211_ELEMID_ERP:
        !          1164:                        if (frm[1] < 1) {
        !          1165:                                ic->ic_stats.is_rx_elem_toosmall++;
        !          1166:                                break;
        !          1167:                        }
        !          1168:                        erp = frm[2];
        !          1169:                        break;
        !          1170:                case IEEE80211_ELEMID_RSN:
        !          1171:                        rsn = frm;
        !          1172:                        break;
        !          1173:                case IEEE80211_ELEMID_EDCAPARMS:
        !          1174:                        edca = frm;
        !          1175:                        break;
        !          1176:                case IEEE80211_ELEMID_QOS_CAP:
        !          1177:                        break;
        !          1178:                case IEEE80211_ELEMID_VENDOR:
        !          1179:                        if (frm[1] < 4) {
        !          1180:                                ic->ic_stats.is_rx_elem_toosmall++;
        !          1181:                                break;
        !          1182:                        }
        !          1183:                        if (memcmp(frm + 2, MICROSOFT_OUI, 3) == 0) {
        !          1184:                                if (frm[5] == 1)
        !          1185:                                        wpa = frm;
        !          1186:                                else if (frm[1] >= 5 &&
        !          1187:                                    frm[5] == 2 && frm[6] == 1)
        !          1188:                                        wmm = frm;
        !          1189:                        }
        !          1190:                        break;
        !          1191:                default:
        !          1192:                        IEEE80211_DPRINTF2(("%s: element id %u/len %u "
        !          1193:                            "ignored\n", __func__, *frm, frm[1]));
        !          1194:                        ic->ic_stats.is_rx_elem_unknown++;
        !          1195:                        break;
        !          1196:                }
        !          1197:                frm += 2 + frm[1];
        !          1198:        }
        !          1199:        IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE);
        !          1200:        IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN);
        !          1201:
        !          1202:        if (
        !          1203: #if IEEE80211_CHAN_MAX < 255
        !          1204:            chan > IEEE80211_CHAN_MAX ||
        !          1205: #endif
        !          1206:            isclr(ic->ic_chan_active, chan)) {
        !          1207:                IEEE80211_DPRINTF(("%s: ignore %s with invalid channel "
        !          1208:                    "%u\n", __func__, ISPROBE(wh) ?
        !          1209:                    "probe response" : "beacon", chan));
        !          1210:                ic->ic_stats.is_rx_badchan++;
        !          1211:                return;
        !          1212:        }
        !          1213:        if (!(ic->ic_caps & IEEE80211_C_SCANALL) &&
        !          1214:            (chan != bchan && ic->ic_phytype != IEEE80211_T_FH)) {
        !          1215:                /*
        !          1216:                 * Frame was received on a channel different from the
        !          1217:                 * one indicated in the DS params element id;
        !          1218:                 * silently discard it.
        !          1219:                 *
        !          1220:                 * NB: this can happen due to signal leakage.
        !          1221:                 *     But we should take it for FH phy because
        !          1222:                 *     the rssi value should be correct even for
        !          1223:                 *     different hop pattern in FH.
        !          1224:                 */
        !          1225:                IEEE80211_DPRINTF(("%s: ignore %s on channel %u marked "
        !          1226:                    "for channel %u\n", __func__, ISPROBE(wh) ?
        !          1227:                    "probe response" : "beacon", bchan, chan));
        !          1228:                ic->ic_stats.is_rx_chanmismatch++;
        !          1229:                return;
        !          1230:        }
        !          1231:        /*
        !          1232:         * Use mac, channel and rssi so we collect only the
        !          1233:         * best potential AP with the equal bssid while scanning.
        !          1234:         * Collecting all potential APs may result in bloat of
        !          1235:         * the node tree. This call will return NULL if the node
        !          1236:         * for this APs does not exist or if the new node is the
        !          1237:         * potential better one.
        !          1238:         */
        !          1239:        if ((ni = ieee80211_find_node_for_beacon(ic, wh->i_addr2,
        !          1240:            &ic->ic_channels[chan], ssid, rssi)) != NULL)
        !          1241:                return;
        !          1242:
        !          1243: #ifdef IEEE80211_DEBUG
        !          1244:        if (ieee80211_debug &&
        !          1245:            (ni == NULL || ic->ic_state == IEEE80211_S_SCAN)) {
        !          1246:                printf("%s: %s%s on chan %u (bss chan %u) ",
        !          1247:                    __func__, (ni == NULL ? "new " : ""),
        !          1248:                    ISPROBE(wh) ? "probe response" : "beacon",
        !          1249:                    chan, bchan);
        !          1250:                ieee80211_print_essid(ssid + 2, ssid[1]);
        !          1251:                printf(" from %s\n", ether_sprintf((u_int8_t *)wh->i_addr2));
        !          1252:                printf("%s: caps 0x%x bintval %u erp 0x%x\n",
        !          1253:                        __func__, capinfo, bintval, erp);
        !          1254:        }
        !          1255: #endif
        !          1256:
        !          1257:        if ((ni = ieee80211_find_node(ic, wh->i_addr2)) == NULL) {
        !          1258:                ni = ieee80211_alloc_node(ic, wh->i_addr2);
        !          1259:                if (ni == NULL)
        !          1260:                        return;
        !          1261:                is_new = 1;
        !          1262:        } else
        !          1263:                is_new = 0;
        !          1264:
        !          1265:        /*
        !          1266:         * When operating in station mode, check for state updates
        !          1267:         * while we're associated. We consider only 11g stuff right
        !          1268:         * now.
        !          1269:         */
        !          1270:        if (ic->ic_opmode == IEEE80211_M_STA &&
        !          1271:            ic->ic_state == IEEE80211_S_ASSOC &&
        !          1272:            ni->ni_state == IEEE80211_STA_BSS) {
        !          1273:                /*
        !          1274:                 * Check if protection mode has changed since last
        !          1275:                 * beacon.
        !          1276:                 */
        !          1277:                if (ni->ni_erp != erp) {
        !          1278:                        IEEE80211_DPRINTF((
        !          1279:                            "[%s] erp change: was 0x%x, now 0x%x\n",
        !          1280:                            ether_sprintf((u_int8_t *)wh->i_addr2),
        !          1281:                            ni->ni_erp, erp));
        !          1282:                        if (ic->ic_curmode == IEEE80211_MODE_11G &&
        !          1283:                            (erp & IEEE80211_ERP_USE_PROTECTION))
        !          1284:                                ic->ic_flags |= IEEE80211_F_USEPROT;
        !          1285:                        else
        !          1286:                                ic->ic_flags &= ~IEEE80211_F_USEPROT;
        !          1287:                        ic->ic_bss->ni_erp = erp;
        !          1288:                }
        !          1289:                /*
        !          1290:                 * Check if AP short slot time setting has changed
        !          1291:                 * since last beacon and give the driver a chance to
        !          1292:                 * update the hardware.
        !          1293:                 */
        !          1294:                if ((ni->ni_capinfo ^ capinfo) &
        !          1295:                    IEEE80211_CAPINFO_SHORT_SLOTTIME) {
        !          1296:                        ieee80211_set_shortslottime(ic,
        !          1297:                            ic->ic_curmode == IEEE80211_MODE_11A ||
        !          1298:                            (capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME));
        !          1299:                }
        !          1300:        }
        !          1301:        if (ni->ni_flags & IEEE80211_NODE_QOS) {
        !          1302:                if (edca != NULL)
        !          1303:                        ieee80211_parse_edca_params(ic, edca);
        !          1304:                else if (wmm != NULL)
        !          1305:                        ieee80211_parse_wmm_params(ic, edca);
        !          1306:        }
        !          1307:        if (ssid[1] != 0 && ni->ni_esslen == 0) {
        !          1308:                /*
        !          1309:                 * Update ESSID at probe response to adopt hidden AP by
        !          1310:                 * Lucent/Cisco, which announces null ESSID in beacon.
        !          1311:                 */
        !          1312:                ni->ni_esslen = ssid[1];
        !          1313:                memset(ni->ni_essid, 0, sizeof(ni->ni_essid));
        !          1314:                memcpy(ni->ni_essid, ssid + 2, ssid[1]);
        !          1315:        }
        !          1316:        IEEE80211_ADDR_COPY(ni->ni_bssid, wh->i_addr3);
        !          1317:        ni->ni_rssi = rssi;
        !          1318:        ni->ni_rstamp = rstamp;
        !          1319:        memcpy(ni->ni_tstamp, tstamp, sizeof(ni->ni_tstamp));
        !          1320:        ni->ni_intval = bintval;
        !          1321:        ni->ni_capinfo = capinfo;
        !          1322:        /* XXX validate channel # */
        !          1323:        ni->ni_chan = &ic->ic_channels[chan];
        !          1324:        ni->ni_fhdwell = fhdwell;
        !          1325:        ni->ni_fhindex = fhindex;
        !          1326:        ni->ni_erp = erp;
        !          1327:        /* NB: must be after ni_chan is setup */
        !          1328:        ieee80211_setup_rates(ic, ni, rates, xrates, IEEE80211_F_DOSORT);
        !          1329:
        !          1330:        /*
        !          1331:         * When scanning we record results (nodes) with a zero
        !          1332:         * refcnt.  Otherwise we want to hold the reference for
        !          1333:         * ibss neighbors so the nodes don't get released prematurely.
        !          1334:         * Anything else can be discarded (XXX and should be handled
        !          1335:         * above so we don't do so much work).
        !          1336:         */
        !          1337:        if (ic->ic_opmode == IEEE80211_M_IBSS || (is_new && ISPROBE(wh))) {
        !          1338:                /*
        !          1339:                 * Fake an association so the driver can setup it's
        !          1340:                 * private state.  The rate set has been setup above;
        !          1341:                 * there is no handshake as in ap/station operation.
        !          1342:                 */
        !          1343:                if (ic->ic_newassoc)
        !          1344:                        (*ic->ic_newassoc)(ic, ni, 1);
        !          1345:        }
        !          1346: #undef ISPROBE
        !          1347: }
        !          1348:
        !          1349: /*-
        !          1350:  * Probe request frame format:
        !          1351:  * [tlv] SSID
        !          1352:  * [tlv] Supported rates
        !          1353:  * [tlv] Extended Supported Rates (802.11g)
        !          1354:  */
        !          1355: void
        !          1356: ieee80211_recv_probe_req(struct ieee80211com *ic, struct mbuf *m0,
        !          1357:     struct ieee80211_node *ni, int rssi, u_int32_t rstamp)
        !          1358: {
        !          1359:        const struct ieee80211_frame *wh;
        !          1360:        const u_int8_t *frm, *efrm;
        !          1361:        const u_int8_t *ssid, *rates, *xrates;
        !          1362:        u_int8_t rate;
        !          1363:
        !          1364:        if (ic->ic_opmode == IEEE80211_M_STA ||
        !          1365:            ic->ic_state != IEEE80211_S_RUN)
        !          1366:                return;
        !          1367:
        !          1368:        wh = mtod(m0, struct ieee80211_frame *);
        !          1369:        frm = (const u_int8_t *)&wh[1];
        !          1370:        efrm = mtod(m0, u_int8_t *) + m0->m_len;
        !          1371:
        !          1372:        ssid = rates = xrates = NULL;
        !          1373:        while (frm + 2 <= efrm) {
        !          1374:                if (frm + 2 + frm[1] > efrm) {
        !          1375:                        ic->ic_stats.is_rx_elem_toosmall++;
        !          1376:                        return;
        !          1377:                }
        !          1378:                switch (frm[0]) {
        !          1379:                case IEEE80211_ELEMID_SSID:
        !          1380:                        ssid = frm;
        !          1381:                        break;
        !          1382:                case IEEE80211_ELEMID_RATES:
        !          1383:                        rates = frm;
        !          1384:                        break;
        !          1385:                case IEEE80211_ELEMID_XRATES:
        !          1386:                        xrates = frm;
        !          1387:                        break;
        !          1388:                }
        !          1389:                frm += 2 + frm[1];
        !          1390:        }
        !          1391:        IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE);
        !          1392:        IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN);
        !          1393:        IEEE80211_VERIFY_SSID(ic->ic_bss, ssid, "probe");
        !          1394:        if ((ic->ic_flags & IEEE80211_F_HIDENWID) && ssid[1] == 0) {
        !          1395:                IEEE80211_DPRINTF(("%s: no ssid "
        !          1396:                    "with ssid suppression enabled", __func__));
        !          1397:                ic->ic_stats.is_rx_ssidmismatch++;
        !          1398:                return;
        !          1399:        }
        !          1400:
        !          1401:        if (ni == ic->ic_bss) {
        !          1402:                ni = ieee80211_dup_bss(ic, wh->i_addr2);
        !          1403:                if (ni == NULL)
        !          1404:                        return;
        !          1405:                IEEE80211_DPRINTF(("%s: new probe req from %s\n",
        !          1406:                    __func__, ether_sprintf((u_int8_t *)wh->i_addr2)));
        !          1407:        }
        !          1408:        ni->ni_rssi = rssi;
        !          1409:        ni->ni_rstamp = rstamp;
        !          1410:        rate = ieee80211_setup_rates(ic, ni, rates, xrates,
        !          1411:            IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE | IEEE80211_F_DONEGO |
        !          1412:            IEEE80211_F_DODEL);
        !          1413:        if (rate & IEEE80211_RATE_BASIC) {
        !          1414:                IEEE80211_DPRINTF(("%s: rate mismatch for %s\n",
        !          1415:                    __func__, ether_sprintf((u_int8_t *)wh->i_addr2)));
        !          1416:        } else {
        !          1417:                IEEE80211_SEND_MGMT(ic, ni,
        !          1418:                        IEEE80211_FC0_SUBTYPE_PROBE_RESP, 0);
        !          1419:        }
        !          1420: }
        !          1421:
        !          1422: /*-
        !          1423:  * Authentication frame format:
        !          1424:  * [2] Authentication algorithm number
        !          1425:  * [2] Authentication transaction sequence number
        !          1426:  * [2] Status code
        !          1427:  */
        !          1428: void
        !          1429: ieee80211_recv_auth(struct ieee80211com *ic, struct mbuf *m0,
        !          1430:     struct ieee80211_node *ni, int rssi, u_int32_t rstamp)
        !          1431: {
        !          1432:        const struct ieee80211_frame *wh;
        !          1433:        const u_int8_t *frm, *efrm;
        !          1434:        u_int16_t algo, seq, status;
        !          1435:
        !          1436:        wh = mtod(m0, struct ieee80211_frame *);
        !          1437:        frm = (const u_int8_t *)&wh[1];
        !          1438:        efrm = mtod(m0, u_int8_t *) + m0->m_len;
        !          1439:
        !          1440:        IEEE80211_VERIFY_LENGTH(efrm - frm, 6);
        !          1441:        algo   = LE_READ_2(frm); frm += 2;
        !          1442:        seq    = LE_READ_2(frm); frm += 2;
        !          1443:        status = LE_READ_2(frm); frm += 2;
        !          1444:        IEEE80211_DPRINTF(("%s: auth %d seq %d from %s\n",
        !          1445:            __func__, algo, seq, ether_sprintf((u_int8_t *)wh->i_addr2)));
        !          1446:
        !          1447:        if (algo == IEEE80211_AUTH_ALG_OPEN)
        !          1448:                ieee80211_auth_open(ic, wh, ni, rssi, rstamp, seq, status);
        !          1449:        else {
        !          1450:                IEEE80211_DPRINTF(("%s: unsupported authentication "
        !          1451:                    "algorithm %d from %s\n",
        !          1452:                    __func__, algo, ether_sprintf((u_int8_t *)wh->i_addr2)));
        !          1453:                ic->ic_stats.is_rx_auth_unsupported++;
        !          1454:                if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
        !          1455:                        /* XXX hack to workaround calling convention */
        !          1456:                        IEEE80211_SEND_MGMT(ic, ni,
        !          1457:                                IEEE80211_FC0_SUBTYPE_AUTH,
        !          1458:                                (seq+1) | (IEEE80211_STATUS_ALG<<16));
        !          1459:                }
        !          1460:        }
        !          1461: }
        !          1462:
        !          1463: /*-
        !          1464:  * (Re)Association request frame format:
        !          1465:  * [2]   Capability information
        !          1466:  * [2]   Listen interval
        !          1467:  * [6*]  Current AP address (Reassociation only)
        !          1468:  * [tlv] SSID
        !          1469:  * [tlv] Supported rates
        !          1470:  * [tlv] Extended Supported Rates (802.11g)
        !          1471:  * [tlv] RSN (802.11i)
        !          1472:  * [tlv] QoS Capability (802.11e)
        !          1473:  */
        !          1474: void
        !          1475: ieee80211_recv_assoc_req(struct ieee80211com *ic, struct mbuf *m0,
        !          1476:     struct ieee80211_node *ni, int rssi, u_int32_t rstamp)
        !          1477: {
        !          1478: #define ISREASSOC(_wh) (((_wh)->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == \
        !          1479:        IEEE80211_FC0_SUBTYPE_REASSOC_REQ)
        !          1480:
        !          1481:        const struct ieee80211_frame *wh;
        !          1482:        const u_int8_t *frm, *efrm;
        !          1483:        const u_int8_t *ssid, *rates, *xrates, *rsn, *wpa;
        !          1484:        u_int16_t capinfo, bintval;
        !          1485:        int reassoc, resp, reason = 0;
        !          1486:        u_int8_t rate;
        !          1487:
        !          1488:        if (ic->ic_opmode != IEEE80211_M_HOSTAP ||
        !          1489:            ic->ic_state != IEEE80211_S_RUN)
        !          1490:                return;
        !          1491:
        !          1492:        wh = mtod(m0, struct ieee80211_frame *);
        !          1493:        frm = (const u_int8_t *)&wh[1];
        !          1494:        efrm = mtod(m0, u_int8_t *) + m0->m_len;
        !          1495:
        !          1496:        if (ISREASSOC(wh)) {
        !          1497:                reassoc = 1;
        !          1498:                resp = IEEE80211_FC0_SUBTYPE_REASSOC_RESP;
        !          1499:        } else {
        !          1500:                reassoc = 0;
        !          1501:                resp = IEEE80211_FC0_SUBTYPE_ASSOC_RESP;
        !          1502:        }
        !          1503:
        !          1504:        IEEE80211_VERIFY_LENGTH(efrm - frm, (reassoc ? 10 : 4));
        !          1505:        if (!IEEE80211_ADDR_EQ(wh->i_addr3, ic->ic_bss->ni_bssid)) {
        !          1506:                IEEE80211_DPRINTF(("%s: ignore other bss from %s\n",
        !          1507:                    __func__, ether_sprintf((u_int8_t *)wh->i_addr2)));
        !          1508:                ic->ic_stats.is_rx_assoc_bss++;
        !          1509:                return;
        !          1510:        }
        !          1511:        capinfo = LE_READ_2(frm); frm += 2;
        !          1512:        bintval = LE_READ_2(frm); frm += 2;
        !          1513:        if (reassoc)
        !          1514:                frm += IEEE80211_ADDR_LEN;      /* skip current AP address */
        !          1515:        ssid = rates = xrates = rsn = wpa = NULL;
        !          1516:        while (frm + 2 <= efrm) {
        !          1517:                if (frm + 2 + frm[1] > efrm) {
        !          1518:                        ic->ic_stats.is_rx_elem_toosmall++;
        !          1519:                        return;
        !          1520:                }
        !          1521:                switch (frm[0]) {
        !          1522:                case IEEE80211_ELEMID_SSID:
        !          1523:                        ssid = frm;
        !          1524:                        break;
        !          1525:                case IEEE80211_ELEMID_RATES:
        !          1526:                        rates = frm;
        !          1527:                        break;
        !          1528:                case IEEE80211_ELEMID_XRATES:
        !          1529:                        xrates = frm;
        !          1530:                        break;
        !          1531:                case IEEE80211_ELEMID_RSN:
        !          1532:                        rsn = frm;
        !          1533:                        break;
        !          1534:                case IEEE80211_ELEMID_QOS_CAP:
        !          1535:                        break;
        !          1536:                case IEEE80211_ELEMID_VENDOR:
        !          1537:                        if (frm[1] < 4) {
        !          1538:                                ic->ic_stats.is_rx_elem_toosmall++;
        !          1539:                                break;
        !          1540:                        }
        !          1541:                        if (memcmp(frm + 2, MICROSOFT_OUI, 3) == 0) {
        !          1542:                                if (frm[5] == 1)
        !          1543:                                        wpa = frm;
        !          1544:                        }
        !          1545:                        break;
        !          1546:                }
        !          1547:                frm += 2 + frm[1];
        !          1548:        }
        !          1549:        IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE);
        !          1550:        IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN);
        !          1551:        IEEE80211_VERIFY_SSID(ic->ic_bss, ssid,
        !          1552:                reassoc ? "reassoc" : "assoc");
        !          1553:        if (ni->ni_state != IEEE80211_STA_AUTH &&
        !          1554:            ni->ni_state != IEEE80211_STA_ASSOC) {
        !          1555:                IEEE80211_DPRINTF(
        !          1556:                    ("%s: deny %sassoc from %s, not authenticated\n",
        !          1557:                    __func__, reassoc ? "re" : "",
        !          1558:                    ether_sprintf((u_int8_t *)wh->i_addr2)));
        !          1559:                ni = ieee80211_dup_bss(ic, wh->i_addr2);
        !          1560:                if (ni != NULL) {
        !          1561:                        IEEE80211_SEND_MGMT(ic, ni,
        !          1562:                            IEEE80211_FC0_SUBTYPE_DEAUTH,
        !          1563:                            IEEE80211_REASON_ASSOC_NOT_AUTHED);
        !          1564:                }
        !          1565:                ic->ic_stats.is_rx_assoc_notauth++;
        !          1566:                return;
        !          1567:        }
        !          1568:        if (rsn != NULL)
        !          1569:                reason = ieee80211_parse_rsn(ic, ni, rsn);
        !          1570:        else if (wpa != NULL)
        !          1571:                reason = ieee80211_parse_wpa1(ic, ni, wpa);
        !          1572:        if (reason != 0) {
        !          1573:                IEEE80211_DPRINTF(("%s: invalid RSN IE for %s\n",
        !          1574:                    __func__, ether_sprintf((u_int8_t *)wh->i_addr2)));
        !          1575:                IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DEAUTH,
        !          1576:                    reason);
        !          1577:                ieee80211_node_leave(ic, ni);
        !          1578:                ic->ic_stats.is_rx_assoc_badrsnie++;
        !          1579:                return;
        !          1580:        }
        !          1581:        if (!(capinfo & IEEE80211_CAPINFO_ESS)) {
        !          1582:                IEEE80211_DPRINTF(("%s: capinfo mismatch for %s\n",
        !          1583:                    __func__, ether_sprintf((u_int8_t *)wh->i_addr2)));
        !          1584:                IEEE80211_SEND_MGMT(ic, ni, resp, IEEE80211_STATUS_CAPINFO);
        !          1585:                ieee80211_node_leave(ic, ni);
        !          1586:                ic->ic_stats.is_rx_assoc_capmismatch++;
        !          1587:                return;
        !          1588:        }
        !          1589:        rate = ieee80211_setup_rates(ic, ni, rates, xrates,
        !          1590:            IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE | IEEE80211_F_DONEGO |
        !          1591:            IEEE80211_F_DODEL);
        !          1592:        if (rate & IEEE80211_RATE_BASIC) {
        !          1593:                IEEE80211_DPRINTF(("%s: rate mismatch for %s\n",
        !          1594:                    __func__, ether_sprintf((u_int8_t *)wh->i_addr2)));
        !          1595:                IEEE80211_SEND_MGMT(ic, ni, resp, IEEE80211_STATUS_BASIC_RATE);
        !          1596:                ieee80211_node_leave(ic, ni);
        !          1597:                ic->ic_stats.is_rx_assoc_norate++;
        !          1598:                return;
        !          1599:        }
        !          1600:        ni->ni_rssi = rssi;
        !          1601:        ni->ni_rstamp = rstamp;
        !          1602:        ni->ni_intval = bintval;
        !          1603:        ni->ni_capinfo = capinfo;
        !          1604:        ni->ni_chan = ic->ic_bss->ni_chan;
        !          1605:        ni->ni_fhdwell = ic->ic_bss->ni_fhdwell;
        !          1606:        ni->ni_fhindex = ic->ic_bss->ni_fhindex;
        !          1607:
        !          1608:        ieee80211_node_join(ic, ni, resp);
        !          1609: #undef ISREASSOC
        !          1610: }
        !          1611:
        !          1612: /*-
        !          1613:  * (Re)Association response frame format:
        !          1614:  * [2]   Capability information
        !          1615:  * [2]   Status code
        !          1616:  * [2]   Association ID (AID)
        !          1617:  * [tlv] Supported rates
        !          1618:  * [tlv] Extended Supported Rates (802.11g)
        !          1619:  * [tlv] EDCA Parameter Set (802.11e)
        !          1620:  */
        !          1621: void
        !          1622: ieee80211_recv_assoc_resp(struct ieee80211com *ic, struct mbuf *m0,
        !          1623:     struct ieee80211_node *ni, int rssi, u_int32_t rstamp)
        !          1624: {
        !          1625: #define ISREASSOC(_wh) (((_wh)->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == \
        !          1626:        IEEE80211_FC0_SUBTYPE_REASSOC_RESP)
        !          1627:
        !          1628:        struct ifnet *ifp = &ic->ic_if;
        !          1629:        const struct ieee80211_frame *wh;
        !          1630:        const u_int8_t *frm, *efrm;
        !          1631:        const u_int8_t *rates, *xrates, *edca, *wmm;
        !          1632:        u_int16_t capinfo, status, associd;
        !          1633:        u_int8_t rate;
        !          1634:
        !          1635:        if (ic->ic_opmode != IEEE80211_M_STA ||
        !          1636:            ic->ic_state != IEEE80211_S_ASSOC) {
        !          1637:                ic->ic_stats.is_rx_mgtdiscard++;
        !          1638:                return;
        !          1639:        }
        !          1640:
        !          1641:        wh = mtod(m0, struct ieee80211_frame *);
        !          1642:        frm = (const u_int8_t *)&wh[1];
        !          1643:        efrm = mtod(m0, u_int8_t *) + m0->m_len;
        !          1644:
        !          1645:        IEEE80211_VERIFY_LENGTH(efrm - frm, 6);
        !          1646:        ni = ic->ic_bss;
        !          1647:        capinfo = LE_READ_2(frm); frm += 2;
        !          1648:        status =  LE_READ_2(frm); frm += 2;
        !          1649:        if (status != 0) {
        !          1650:                if (ifp->if_flags & IFF_DEBUG)
        !          1651:                        printf("%s: %sassociation failed (reason %d)"
        !          1652:                            " for %s\n", ifp->if_xname,
        !          1653:                            ISREASSOC(wh) ?  "re" : "",
        !          1654:                            status, ether_sprintf((u_int8_t *)wh->i_addr3));
        !          1655:                if (ni != ic->ic_bss)
        !          1656:                        ni->ni_fails++;
        !          1657:                ic->ic_stats.is_rx_auth_fail++;
        !          1658:                return;
        !          1659:        }
        !          1660:        associd = LE_READ_2(frm); frm += 2;
        !          1661:
        !          1662:        rates = xrates = edca = wmm = NULL;
        !          1663:        while (frm + 2 <= efrm) {
        !          1664:                if (frm + 2 + frm[1] > efrm) {
        !          1665:                        ic->ic_stats.is_rx_elem_toosmall++;
        !          1666:                        return;
        !          1667:                }
        !          1668:                switch (frm[0]) {
        !          1669:                case IEEE80211_ELEMID_RATES:
        !          1670:                        rates = frm;
        !          1671:                        break;
        !          1672:                case IEEE80211_ELEMID_XRATES:
        !          1673:                        xrates = frm;
        !          1674:                        break;
        !          1675:                case IEEE80211_ELEMID_EDCAPARMS:
        !          1676:                        edca = frm;
        !          1677:                        break;
        !          1678:                case IEEE80211_ELEMID_VENDOR:
        !          1679:                        if (frm[1] < 4) {
        !          1680:                                ic->ic_stats.is_rx_elem_toosmall++;
        !          1681:                                break;
        !          1682:                        }
        !          1683:                        if (memcmp(frm + 2, MICROSOFT_OUI, 3) == 0) {
        !          1684:                                if (frm[1] >= 5 && frm[5] == 2 && frm[6] == 1)
        !          1685:                                        wmm = frm;
        !          1686:                        }
        !          1687:                        break;
        !          1688:                }
        !          1689:                frm += 2 + frm[1];
        !          1690:        }
        !          1691:
        !          1692:        IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE);
        !          1693:        rate = ieee80211_setup_rates(ic, ni, rates, xrates,
        !          1694:            IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE | IEEE80211_F_DONEGO |
        !          1695:            IEEE80211_F_DODEL);
        !          1696:        if (rate & IEEE80211_RATE_BASIC) {
        !          1697:                IEEE80211_DPRINTF(("%s: rate mismatch for %s\n",
        !          1698:                    __func__, ether_sprintf((u_int8_t *)wh->i_addr2)));
        !          1699:                ic->ic_stats.is_rx_assoc_norate++;
        !          1700:                return;
        !          1701:        }
        !          1702:        ni->ni_capinfo = capinfo;
        !          1703:        ni->ni_associd = associd;
        !          1704:        if (edca != NULL || wmm != NULL) {
        !          1705:                /* force update of EDCA parameters */
        !          1706:                ic->ic_edca_updtcount = -1;
        !          1707:
        !          1708:                if ((edca != NULL &&
        !          1709:                     ieee80211_parse_edca_params(ic, edca) == 0) ||
        !          1710:                    (wmm != NULL &&
        !          1711:                     ieee80211_parse_wmm_params(ic, wmm) == 0))
        !          1712:                        ni->ni_flags |= IEEE80211_NODE_QOS;
        !          1713:                else    /* for Reassociation */
        !          1714:                        ni->ni_flags &= ~IEEE80211_NODE_QOS;
        !          1715:        }
        !          1716:        /*
        !          1717:         * Configure state now that we are associated.
        !          1718:         */
        !          1719:        if (ic->ic_curmode == IEEE80211_MODE_11A ||
        !          1720:            (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE))
        !          1721:                ic->ic_flags |= IEEE80211_F_SHPREAMBLE;
        !          1722:        else
        !          1723:                ic->ic_flags &= ~IEEE80211_F_SHPREAMBLE;
        !          1724:
        !          1725:        ieee80211_set_shortslottime(ic,
        !          1726:            ic->ic_curmode == IEEE80211_MODE_11A ||
        !          1727:            (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME));
        !          1728:        /*
        !          1729:         * Honor ERP protection.
        !          1730:         */
        !          1731:        if (ic->ic_curmode == IEEE80211_MODE_11G &&
        !          1732:            (ni->ni_erp & IEEE80211_ERP_USE_PROTECTION))
        !          1733:                ic->ic_flags |= IEEE80211_F_USEPROT;
        !          1734:        else
        !          1735:                ic->ic_flags &= ~IEEE80211_F_USEPROT;
        !          1736:
        !          1737:        ieee80211_new_state(ic, IEEE80211_S_RUN,
        !          1738:                wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
        !          1739: #undef ISREASSOC
        !          1740: }
        !          1741:
        !          1742: /*-
        !          1743:  * Deauthentication frame format:
        !          1744:  * [2] Reason code
        !          1745:  */
        !          1746: void
        !          1747: ieee80211_recv_deauth(struct ieee80211com *ic, struct mbuf *m0,
        !          1748:     struct ieee80211_node *ni, int rssi, u_int32_t rstamp)
        !          1749: {
        !          1750:        struct ifnet *ifp = &ic->ic_if;
        !          1751:        const struct ieee80211_frame *wh;
        !          1752:        const u_int8_t *frm, *efrm;
        !          1753:        u_int16_t reason;
        !          1754:
        !          1755:        wh = mtod(m0, struct ieee80211_frame *);
        !          1756:        frm = (const u_int8_t *)&wh[1];
        !          1757:        efrm = mtod(m0, u_int8_t *) + m0->m_len;
        !          1758:
        !          1759:        IEEE80211_VERIFY_LENGTH(efrm - frm, 2);
        !          1760:        reason = LE_READ_2(frm);
        !          1761:        ic->ic_stats.is_rx_deauth++;
        !          1762:        switch (ic->ic_opmode) {
        !          1763:        case IEEE80211_M_STA:
        !          1764:                ieee80211_new_state(ic, IEEE80211_S_AUTH,
        !          1765:                    wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
        !          1766:                break;
        !          1767:        case IEEE80211_M_HOSTAP:
        !          1768:                if (ni != ic->ic_bss) {
        !          1769:                        if (ifp->if_flags & IFF_DEBUG)
        !          1770:                                printf("%s: station %s deauthenticated "
        !          1771:                                    "by peer (reason %d)\n",
        !          1772:                                    ifp->if_xname,
        !          1773:                                    ether_sprintf(ni->ni_macaddr),
        !          1774:                                    reason);
        !          1775:                        ieee80211_node_leave(ic, ni);
        !          1776:                }
        !          1777:                break;
        !          1778:        default:
        !          1779:                break;
        !          1780:        }
        !          1781: }
        !          1782:
        !          1783: /*-
        !          1784:  * Disassociation frame format:
        !          1785:  * [2] Reason code
        !          1786:  */
        !          1787: void
        !          1788: ieee80211_recv_disassoc(struct ieee80211com *ic, struct mbuf *m0,
        !          1789:     struct ieee80211_node *ni, int rssi, u_int32_t rstamp)
        !          1790: {
        !          1791:        struct ifnet *ifp = &ic->ic_if;
        !          1792:        const struct ieee80211_frame *wh;
        !          1793:        const u_int8_t *frm, *efrm;
        !          1794:        u_int16_t reason;
        !          1795:
        !          1796:        wh = mtod(m0, struct ieee80211_frame *);
        !          1797:        frm = (const u_int8_t *)&wh[1];
        !          1798:        efrm = mtod(m0, u_int8_t *) + m0->m_len;
        !          1799:
        !          1800:        IEEE80211_VERIFY_LENGTH(efrm - frm, 2);
        !          1801:        reason = LE_READ_2(frm);
        !          1802:        ic->ic_stats.is_rx_disassoc++;
        !          1803:        switch (ic->ic_opmode) {
        !          1804:        case IEEE80211_M_STA:
        !          1805:                ieee80211_new_state(ic, IEEE80211_S_ASSOC,
        !          1806:                    wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
        !          1807:                break;
        !          1808:        case IEEE80211_M_HOSTAP:
        !          1809:                if (ni != ic->ic_bss) {
        !          1810:                        if (ifp->if_flags & IFF_DEBUG)
        !          1811:                                printf("%s: station %s disassociated "
        !          1812:                                    "by peer (reason %d)\n",
        !          1813:                                    ifp->if_xname,
        !          1814:                                    ether_sprintf(ni->ni_macaddr),
        !          1815:                                    reason);
        !          1816:                        ieee80211_node_leave(ic, ni);
        !          1817:                }
        !          1818:                break;
        !          1819:        default:
        !          1820:                break;
        !          1821:        }
        !          1822: }
        !          1823:
        !          1824: void
        !          1825: ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
        !          1826:     struct ieee80211_node *ni, int subtype, int rssi, u_int32_t rstamp)
        !          1827: {
        !          1828:        switch (subtype) {
        !          1829:        case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
        !          1830:        case IEEE80211_FC0_SUBTYPE_BEACON:
        !          1831:                ieee80211_recv_probe_resp(ic, m0, ni, rssi, rstamp);
        !          1832:                break;
        !          1833:        case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
        !          1834:                ieee80211_recv_probe_req(ic, m0, ni, rssi, rstamp);
        !          1835:                break;
        !          1836:        case IEEE80211_FC0_SUBTYPE_AUTH:
        !          1837:                ieee80211_recv_auth(ic, m0, ni, rssi, rstamp);
        !          1838:                break;
        !          1839:        case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
        !          1840:        case IEEE80211_FC0_SUBTYPE_REASSOC_REQ:
        !          1841:                ieee80211_recv_assoc_req(ic, m0, ni, rssi, rstamp);
        !          1842:                break;
        !          1843:        case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
        !          1844:        case IEEE80211_FC0_SUBTYPE_REASSOC_RESP:
        !          1845:                ieee80211_recv_assoc_resp(ic, m0, ni, rssi, rstamp);
        !          1846:                break;
        !          1847:        case IEEE80211_FC0_SUBTYPE_DEAUTH:
        !          1848:                ieee80211_recv_deauth(ic, m0, ni, rssi, rstamp);
        !          1849:                break;
        !          1850:        case IEEE80211_FC0_SUBTYPE_DISASSOC:
        !          1851:                ieee80211_recv_disassoc(ic, m0, ni, rssi, rstamp);
        !          1852:                break;
        !          1853:        default:
        !          1854:                IEEE80211_DPRINTF(("%s: mgmt frame with subtype 0x%x not "
        !          1855:                    "handled\n", __func__, subtype));
        !          1856:                ic->ic_stats.is_rx_badsubtype++;
        !          1857:                break;
        !          1858:        }
        !          1859: }
        !          1860: #undef IEEE80211_VERIFY_LENGTH
        !          1861: #undef IEEE80211_VERIFY_ELEMENT
        !          1862: #undef IEEE80211_VERIFY_SSID
        !          1863:
        !          1864: /* unaligned big endian access */
        !          1865: #define BE_READ_2(p)                                           \
        !          1866:        ((u_int16_t)(p)[0] << 8 | (u_int16_t)(p)[1])
        !          1867:
        !          1868: #define BE_READ_8(p)                                           \
        !          1869:        ((u_int64_t)(p)[0] << 56 | (u_int64_t)(p)[1] << 48 |    \
        !          1870:         (u_int64_t)(p)[2] << 40 | (u_int64_t)(p)[3] << 32 |    \
        !          1871:         (u_int64_t)(p)[4] << 24 | (u_int64_t)(p)[5] << 16 |    \
        !          1872:         (u_int64_t)(p)[6] <<  8 | (u_int64_t)(p)[7])
        !          1873:
        !          1874: #define BE_WRITE_2(p, v) do {  \
        !          1875:        (p)[0] = (v) >> 8;      \
        !          1876:        (p)[1] = (v) & 0xff;    \
        !          1877: } while (0)
        !          1878:
        !          1879: /* unaligned little endian access */
        !          1880: #define LE_READ_8(p)                                           \
        !          1881:        ((u_int64_t)(p)[7] << 56 | (u_int64_t)(p)[6] << 48 |    \
        !          1882:         (u_int64_t)(p)[5] << 40 | (u_int64_t)(p)[4] << 32 |    \
        !          1883:         (u_int64_t)(p)[3] << 24 | (u_int64_t)(p)[2] << 16 |    \
        !          1884:         (u_int64_t)(p)[1] <<  8 | (u_int64_t)(p)[0])
        !          1885:
        !          1886: /*
        !          1887:  * 4-Way Handshake Message 1 is sent by the authenticator to the supplicant
        !          1888:  * (see 8.5.3.1).
        !          1889:  */
        !          1890: void
        !          1891: ieee80211_recv_4way_msg1(struct ieee80211com *ic,
        !          1892:     const struct ieee80211_eapol_key *key, struct ieee80211_node *ni)
        !          1893: {
        !          1894:        u_int8_t snonce[EAPOL_KEY_NONCE_LEN];
        !          1895:        const u_int8_t *frm, *efrm;
        !          1896:        const u_int8_t *pmkid;
        !          1897:        const u_int8_t *pmk;
        !          1898:        size_t pmk_len;
        !          1899:
        !          1900:        if (ic->ic_opmode != IEEE80211_M_STA &&
        !          1901:            ic->ic_opmode != IEEE80211_M_IBSS)
        !          1902:                return;
        !          1903:
        !          1904:        if (ni->ni_replaycnt_ok &&
        !          1905:            BE_READ_8(key->replaycnt) <= ni->ni_replaycnt)
        !          1906:                return;
        !          1907:
        !          1908:        /* save authenticator's nonce (ANonce) */
        !          1909:        memcpy(ni->ni_nonce, key->nonce, EAPOL_KEY_NONCE_LEN);
        !          1910:
        !          1911:        /* parse key data field (shall contain an encapsulated PMKID) */
        !          1912:        frm = (const u_int8_t *)&key[1];
        !          1913:        efrm = frm + BE_READ_2(key->paylen);
        !          1914:
        !          1915:        pmkid = NULL;
        !          1916:        while (frm + 2 <= efrm) {
        !          1917:                if (frm + 2 + frm[1] > efrm)
        !          1918:                        break;
        !          1919:                switch (frm[0]) {
        !          1920:                case IEEE80211_ELEMID_VENDOR:
        !          1921:                        if (frm[1] < 4)
        !          1922:                                break;
        !          1923:                        if (memcmp(&frm[2], IEEE80211_OUI, 3) == 0) {
        !          1924:                                switch (frm[5]) {
        !          1925:                                case IEEE80211_KDE_PMKID:
        !          1926:                                        pmkid = frm;
        !          1927:                                        break;
        !          1928:                                }
        !          1929:                        }
        !          1930:                        break;
        !          1931:                }
        !          1932:                frm += 2 + frm[1];
        !          1933:        }
        !          1934:        /* check that the PMKID KDE is valid */
        !          1935:        if (pmkid != NULL && pmkid[1] - 4 < 16)
        !          1936:                return;
        !          1937:
        !          1938:        /* update the last seen value of the key replay counter field */
        !          1939:        ni->ni_replaycnt = BE_READ_8(key->replaycnt);
        !          1940:        /* do not set ni_replaycnt_ok since the frame contains no MIC */
        !          1941:
        !          1942:        /* generate a new nonce (SNonce) */
        !          1943:        get_random_bytes(snonce, EAPOL_KEY_NONCE_LEN);
        !          1944:
        !          1945:        if (ni->ni_akm == IEEE80211_AKM_IEEE8021X) {
        !          1946:                /* XXX find the PMK in the PMKSA cache using the PMKID */
        !          1947:        } else {
        !          1948:                /* XXX the PMK is the PSK */
        !          1949:        }
        !          1950:
        !          1951:        /* derive PTK from PMK */
        !          1952:        ieee80211_derive_ptk(pmk, pmk_len, ni->ni_macaddr, ic->ic_myaddr,
        !          1953:            ni->ni_nonce, snonce, (u_int8_t *)&ni->ni_ptk, sizeof(ni->ni_ptk));
        !          1954:        ni->ni_ptk_ok = 1;
        !          1955:
        !          1956:        if (ic->ic_if.if_flags & IFF_DEBUG)
        !          1957:                printf("%s: received msg %d/%d of the %s handshake from %s\n",
        !          1958:                    ic->ic_if.if_xname, 1, 4, "4-way",
        !          1959:                    ether_sprintf(ni->ni_macaddr));
        !          1960:
        !          1961:        /* send message 2 to authenticator */
        !          1962:        ieee80211_send_4way_msg2(ic, ni, snonce);
        !          1963: }
        !          1964:
        !          1965: /*
        !          1966:  * 4-Way Handshake Message 2 is sent by the supplicant to the authenticator
        !          1967:  * (see 8.5.3.2).
        !          1968:  */
        !          1969: void
        !          1970: ieee80211_recv_4way_msg2(struct ieee80211com *ic,
        !          1971:     const struct ieee80211_eapol_key *key, struct ieee80211_node *ni)
        !          1972: {
        !          1973:        const u_int8_t *frm, *efrm;
        !          1974:        const u_int8_t *rsn;
        !          1975:        const u_int8_t *pmk;
        !          1976:        size_t pmk_len;
        !          1977:
        !          1978:        if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
        !          1979:            ic->ic_opmode != IEEE80211_M_IBSS)
        !          1980:                return;
        !          1981:
        !          1982:        if (BE_READ_8(key->replaycnt) != ni->ni_replaycnt)
        !          1983:                return;
        !          1984:
        !          1985:        /* derive PTK from PMK */
        !          1986:        ieee80211_derive_ptk(pmk, pmk_len, ic->ic_myaddr, ni->ni_macaddr,
        !          1987:            ni->ni_nonce, key->nonce, (u_int8_t *)&ni->ni_ptk,
        !          1988:            sizeof(ni->ni_ptk));
        !          1989:        ni->ni_ptk_ok = 1;
        !          1990:
        !          1991:        /* parse key data field (shall contain an RSN IE) */
        !          1992:        frm = (const u_int8_t *)&key[1];
        !          1993:        efrm = frm + BE_READ_2(key->paylen);
        !          1994:
        !          1995:        rsn = NULL;
        !          1996:        while (frm + 2 <= efrm) {
        !          1997:                if (frm + 2 + frm[1] > efrm)
        !          1998:                        break;
        !          1999:                switch (frm[0]) {
        !          2000:                case IEEE80211_ELEMID_RSN:
        !          2001:                        rsn = frm;
        !          2002:                        break;
        !          2003:                case IEEE80211_ELEMID_VENDOR:
        !          2004:                        if (frm[1] < 4)
        !          2005:                                break;
        !          2006:                        if (memcmp(&frm[2], MICROSOFT_OUI, 3) == 0) {
        !          2007:                                switch (frm[5]) {
        !          2008:                                case 1: /* WPA */
        !          2009:                                        rsn = frm;
        !          2010:                                        break;
        !          2011:                                }
        !          2012:                        }
        !          2013:                }
        !          2014:                frm += 2 + frm[1];
        !          2015:        }
        !          2016:        if (rsn == NULL)
        !          2017:                return;
        !          2018:
        !          2019:        /*
        !          2020:         * The RSN IE must match bit-wise with what the STA included in its
        !          2021:         * (Re)Association Request.
        !          2022:         */
        !          2023:        if (ni->ni_rsnie == NULL || rsn[1] != ni->ni_rsnie[1] ||
        !          2024:            memcmp(rsn, ni->ni_rsnie, 2 + rsn[1]) != 0)
        !          2025:                return;
        !          2026:
        !          2027:        if (ic->ic_if.if_flags & IFF_DEBUG)
        !          2028:                printf("%s: received msg %d/%d of the %s handshake from %s\n",
        !          2029:                    ic->ic_if.if_xname, 2, 4, "4-way",
        !          2030:                    ether_sprintf(ni->ni_macaddr));
        !          2031:
        !          2032:        /* send message 3 to supplicant */
        !          2033:        ieee80211_send_4way_msg3(ic, ni);
        !          2034: }
        !          2035:
        !          2036: /*
        !          2037:  * 4-Way Handshake Message 3 is sent by the authenticator to the supplicant
        !          2038:  * (see 8.5.3.3).
        !          2039:  */
        !          2040: void
        !          2041: ieee80211_recv_4way_msg3(struct ieee80211com *ic,
        !          2042:     const struct ieee80211_eapol_key *key, struct ieee80211_node *ni)
        !          2043: {
        !          2044:        struct ieee80211_key *k;
        !          2045:        const u_int8_t *frm, *efrm;
        !          2046:        const u_int8_t *rsn1, *rsn2, *gtk;
        !          2047:
        !          2048:        if (ic->ic_opmode != IEEE80211_M_STA &&
        !          2049:            ic->ic_opmode != IEEE80211_M_IBSS)
        !          2050:                return;
        !          2051:
        !          2052:        if (BE_READ_8(key->replaycnt) <= ni->ni_replaycnt)
        !          2053:                return;
        !          2054:
        !          2055:        /* check that ANonce matches the one received in message 1 */
        !          2056:        if (memcmp(key->nonce, ni->ni_nonce, EAPOL_KEY_NONCE_LEN) != 0)
        !          2057:                return;
        !          2058:
        !          2059:        /* parse key data field */
        !          2060:        frm = (const u_int8_t *)&key[1];
        !          2061:        efrm = frm + BE_READ_2(key->paylen);
        !          2062:
        !          2063:        rsn1 = rsn2 = gtk = NULL;
        !          2064:        while (frm + 2 <= efrm) {
        !          2065:                if (frm + 2 + frm[1] > efrm)
        !          2066:                        break;
        !          2067:                switch (frm[0]) {
        !          2068:                case IEEE80211_ELEMID_RSN:
        !          2069:                        if (rsn1 == NULL)
        !          2070:                                rsn1 = frm;
        !          2071:                        else if (rsn2 == NULL)
        !          2072:                                rsn2 = frm;
        !          2073:                        /* ignore if more than two RSN IEs */
        !          2074:                        break;
        !          2075:                case IEEE80211_ELEMID_VENDOR:
        !          2076:                        if (frm[1] < 4)
        !          2077:                                break;
        !          2078:                        if (memcmp(&frm[2], IEEE80211_OUI, 3) == 0) {
        !          2079:                                switch (frm[5]) {
        !          2080:                                case IEEE80211_KDE_GTK:
        !          2081:                                        gtk = frm;
        !          2082:                                        break;
        !          2083:                                }
        !          2084:                        } else if (memcmp(&frm[2], MICROSOFT_OUI, 3) == 0) {
        !          2085:                                switch (frm[5]) {
        !          2086:                                case 1: /* WPA */
        !          2087:                                        rsn1 = frm;
        !          2088:                                        break;
        !          2089:                                }
        !          2090:                        }
        !          2091:                        break;
        !          2092:                }
        !          2093:                frm += 2 + frm[1];
        !          2094:        }
        !          2095:        /* first WPA/RSN IE is mandatory */
        !          2096:        if (rsn1 == NULL)
        !          2097:                return;
        !          2098:        /* key data must be encrypted if GTK is included */
        !          2099:        if (gtk != NULL && !(BE_READ_2(key->info) & EAPOL_KEY_ENCRYPTED))
        !          2100:                return;
        !          2101:
        !          2102:        /*
        !          2103:         * Check that first RSN IE is identical to the one received in
        !          2104:         * the beacon or probe response frame.
        !          2105:         */
        !          2106:        if (ni->ni_rsnie == NULL || rsn1[1] != ni->ni_rsnie[1] ||
        !          2107:            memcmp(rsn1, ni->ni_rsnie, 2 + rsn1[1]) != 0)
        !          2108:                return;
        !          2109:
        !          2110:        /* update the last seen value of the key replay counter field */
        !          2111:        ni->ni_replaycnt = BE_READ_8(key->replaycnt);
        !          2112:        ni->ni_replaycnt_ok = 1;
        !          2113:
        !          2114:        /*
        !          2115:         * If a second RSN information element is present, use its pairwise
        !          2116:         * cipher suite or deauthenticate.
        !          2117:         */
        !          2118:        if (rsn2 != NULL) {
        !          2119:                /* XXX ieee80211_parse_rsn(rsn2); */
        !          2120:        }
        !          2121:
        !          2122:        /* install the PTK */
        !          2123:        k = &ni->ni_pairwise_key;
        !          2124:        memset(k, 0, sizeof(*k));
        !          2125:        k->k_cipher = ni->ni_pairwise_cipher;
        !          2126:        k->k_flags = IEEE80211_KEY_TX;
        !          2127:        k->k_len = BE_READ_2(key->keylen);
        !          2128:        /* check that key length matches pairwise cipher */
        !          2129:        if (k->k_len != ieee80211_cipher_keylen(k->k_cipher))
        !          2130:                return;
        !          2131:        memcpy(k->k_key, ni->ni_ptk.tk, k->k_len);
        !          2132:        if (ic->ic_set_key != NULL && (*ic->ic_set_key)(ic, ni, k) != 0)
        !          2133:                return;
        !          2134:
        !          2135:        if (gtk != NULL) {
        !          2136:                u_int8_t kid;
        !          2137:
        !          2138:                /* check that the GTK KDE is valid */
        !          2139:                if (gtk[1] - 4 < 2)
        !          2140:                        return;
        !          2141:
        !          2142:                /* install the GTK */
        !          2143:                kid = gtk[6] & 3;
        !          2144:                k = &ic->ic_nw_keys[kid];
        !          2145:                memset(k, 0, sizeof(*k));
        !          2146:                k->k_id = kid;
        !          2147:                k->k_cipher = ni->ni_group_cipher;
        !          2148:                k->k_flags = IEEE80211_KEY_GROUP;
        !          2149:                if (gtk[6] & (1 << 2))  /* Tx bit */
        !          2150:                        k->k_flags |= IEEE80211_KEY_TX;
        !          2151:                k->k_len = gtk[1] - 6;
        !          2152:                /* check that key length matches group cipher */
        !          2153:                if (k->k_len != ieee80211_cipher_keylen(k->k_cipher))
        !          2154:                        return; /* XXX PTK already installed! */
        !          2155:                memcpy(k->k_key, &gtk[8], k->k_len);
        !          2156:                k->k_rsc = LE_READ_8(key->rsc);
        !          2157:                if (ic->ic_set_key != NULL &&
        !          2158:                    (*ic->ic_set_key)(ic, ni, k) != 0)
        !          2159:                        return;
        !          2160:        }
        !          2161:
        !          2162:        /* mark the PAE port as valid */
        !          2163:        ni->ni_port_valid = 1;
        !          2164:
        !          2165:        if (ic->ic_if.if_flags & IFF_DEBUG)
        !          2166:                printf("%s: received msg %d/%d of the %s handshake from %s\n",
        !          2167:                    ic->ic_if.if_xname, 3, 4, "4-way",
        !          2168:                    ether_sprintf(ni->ni_macaddr));
        !          2169:
        !          2170:        /* send message 4 to authenticator */
        !          2171:        ieee80211_send_4way_msg4(ic, ni);
        !          2172: }
        !          2173:
        !          2174: /*
        !          2175:  * 4-Way Handshake Message 4 is sent by the supplicant to the authenticator
        !          2176:  * (see 8.5.3.4).
        !          2177:  */
        !          2178: void
        !          2179: ieee80211_recv_4way_msg4(struct ieee80211com *ic,
        !          2180:     const struct ieee80211_eapol_key *key, struct ieee80211_node *ni)
        !          2181: {
        !          2182:        struct ieee80211_key *k;
        !          2183:
        !          2184:        if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
        !          2185:            ic->ic_opmode != IEEE80211_M_IBSS)
        !          2186:                return;
        !          2187:
        !          2188:        if (BE_READ_8(key->replaycnt) != ni->ni_replaycnt)
        !          2189:                return;
        !          2190:
        !          2191:        /* empty key data field */
        !          2192:
        !          2193:        /* install the PTK */
        !          2194:        k = &ni->ni_pairwise_key;
        !          2195:        memset(k, 0, sizeof(*k));
        !          2196:        k->k_cipher = ni->ni_pairwise_cipher;
        !          2197:        k->k_flags = IEEE80211_KEY_TX;
        !          2198:        k->k_len = ieee80211_cipher_keylen(k->k_cipher);
        !          2199:        memcpy(k->k_key, ni->ni_ptk.tk, k->k_len);
        !          2200:        if (ic->ic_set_key != NULL && (*ic->ic_set_key)(ic, ni, k) != 0)
        !          2201:                return;
        !          2202:
        !          2203:        if (ic->ic_opmode == IEEE80211_M_IBSS) {
        !          2204:                if (++ni->ni_key_count == 2)
        !          2205:                        ni->ni_port_valid = 1;
        !          2206:        } else
        !          2207:                ni->ni_port_valid = 1;
        !          2208:
        !          2209:        /* increment the 64-bit Key Replay Counter */
        !          2210:        ni->ni_replaycnt++;
        !          2211:
        !          2212:        if (ic->ic_if.if_flags & IFF_DEBUG)
        !          2213:                printf("%s: received msg %d/%d of the %s handshake from %s\n",
        !          2214:                    ic->ic_if.if_xname, 4, 4, "4-way",
        !          2215:                    ether_sprintf(ni->ni_macaddr));
        !          2216: }
        !          2217:
        !          2218: /*
        !          2219:  * Group Key Handshake Message 1 is sent by the authenticator to the
        !          2220:  * supplicant (see 8.5.4.1).
        !          2221:  */
        !          2222: void
        !          2223: ieee80211_recv_rsn_group_msg1(struct ieee80211com *ic,
        !          2224:     const struct ieee80211_eapol_key *key, struct ieee80211_node *ni)
        !          2225: {
        !          2226:        struct ieee80211_key *k;
        !          2227:        const u_int8_t *frm, *efrm;
        !          2228:        const u_int8_t *gtk;
        !          2229:        u_int8_t kid;
        !          2230:
        !          2231:        if (ic->ic_opmode != IEEE80211_M_STA &&
        !          2232:            ic->ic_opmode != IEEE80211_M_IBSS)
        !          2233:                return;
        !          2234:
        !          2235:        if (BE_READ_8(key->replaycnt) <= ni->ni_replaycnt)
        !          2236:                return;
        !          2237:
        !          2238:        /* parse key data field (shall contain a GTK KDE) */
        !          2239:        frm = (const u_int8_t *)&key[1];
        !          2240:        efrm = frm + BE_READ_2(key->paylen);
        !          2241:
        !          2242:        gtk = NULL;
        !          2243:        while (frm + 2 <= efrm) {
        !          2244:                if (frm + 2 + frm[1] > efrm)
        !          2245:                        break;
        !          2246:                switch (frm[0]) {
        !          2247:                case IEEE80211_ELEMID_VENDOR:
        !          2248:                        if (frm[1] < 4)
        !          2249:                                break;
        !          2250:                        if (memcmp(&frm[2], IEEE80211_OUI, 3) == 0) {
        !          2251:                                switch (frm[5]) {
        !          2252:                                case IEEE80211_KDE_GTK:
        !          2253:                                        gtk = frm;
        !          2254:                                        break;
        !          2255:                                }
        !          2256:                        }
        !          2257:                        break;
        !          2258:                }
        !          2259:                frm += 2 + frm[1];
        !          2260:        }
        !          2261:        if (gtk == NULL || !(BE_READ_2(key->info) & EAPOL_KEY_ENCRYPTED))
        !          2262:                return;
        !          2263:
        !          2264:        /* check that the GTK KDE is valid */
        !          2265:        if (gtk[1] - 4 < 2)
        !          2266:                return;
        !          2267:
        !          2268:        /* install the GTK */
        !          2269:        kid = gtk[6] & 3;
        !          2270:        k = &ic->ic_nw_keys[kid];
        !          2271:        memset(k, 0, sizeof(*k));
        !          2272:        k->k_id = kid;
        !          2273:        k->k_cipher = ni->ni_group_cipher;
        !          2274:        k->k_flags = IEEE80211_KEY_GROUP;
        !          2275:        if (gtk[6] & (1 << 2))  /* Tx bit */
        !          2276:                k->k_flags |= IEEE80211_KEY_TX;
        !          2277:        k->k_len = gtk[1] - 6;
        !          2278:        /* check that key length matches group cipher */
        !          2279:        if (k->k_len != ieee80211_cipher_keylen(k->k_cipher))
        !          2280:                return;
        !          2281:        memcpy(k->k_key, &gtk[8], k->k_len);
        !          2282:        k->k_rsc = LE_READ_8(key->rsc);
        !          2283:        if (ic->ic_set_key != NULL && (*ic->ic_set_key)(ic, ni, k) != 0)
        !          2284:                return;
        !          2285:
        !          2286:        /* update the last seen value of the key replay counter field */
        !          2287:        ni->ni_replaycnt = BE_READ_8(key->replaycnt);
        !          2288:
        !          2289:        if (ic->ic_if.if_flags & IFF_DEBUG)
        !          2290:                printf("%s: received msg %d/%d of the %s handshake from %s\n",
        !          2291:                    ic->ic_if.if_xname, 1, 2, "group key",
        !          2292:                    ether_sprintf(ni->ni_macaddr));
        !          2293:
        !          2294:        /* send message 2 to authenticator */
        !          2295:        ieee80211_send_group_msg2(ic, ni, k);
        !          2296: }
        !          2297:
        !          2298: void
        !          2299: ieee80211_recv_wpa_group_msg1(struct ieee80211com *ic,
        !          2300:     struct ieee80211_eapol_key *key, struct ieee80211_node *ni)
        !          2301: {
        !          2302:        struct ieee80211_key *k;
        !          2303:        u_int16_t info;
        !          2304:        u_int8_t kid;
        !          2305:
        !          2306:        if (ic->ic_opmode != IEEE80211_M_STA &&
        !          2307:            ic->ic_opmode != IEEE80211_M_IBSS)
        !          2308:                return;
        !          2309:
        !          2310:        if (BE_READ_8(key->replaycnt) <= ni->ni_replaycnt)
        !          2311:                return;
        !          2312:
        !          2313:        /*
        !          2314:         * EAPOL-Key data field is encrypted even though WPA1 doesn't set
        !          2315:         * the ENCRYPTED bit in the info field.
        !          2316:         */
        !          2317:        if (!ni->ni_ptk_ok ||
        !          2318:            ieee80211_eapol_key_decrypt(key, ni->ni_ptk.kek) != 0)
        !          2319:                return;
        !          2320:
        !          2321:        info = BE_READ_2(key->info);
        !          2322:
        !          2323:        /* install the GTK */
        !          2324:        kid = (info >> EAPOL_KEY_WPA_KID_SHIFT) & 3;
        !          2325:        k = &ic->ic_nw_keys[kid];
        !          2326:        memset(k, 0, sizeof(*k));
        !          2327:        k->k_id = kid;
        !          2328:        k->k_cipher = ni->ni_group_cipher;
        !          2329:        k->k_flags = IEEE80211_KEY_GROUP;
        !          2330:        if (info & EAPOL_KEY_WPA_TX)
        !          2331:                k->k_flags |= IEEE80211_KEY_TX;
        !          2332:        k->k_len = BE_READ_2(key->keylen);
        !          2333:        /* check that key length matches group cipher */
        !          2334:        if (k->k_len != ieee80211_cipher_keylen(k->k_cipher))
        !          2335:                return;
        !          2336:        memcpy(k->k_key, (u_int8_t *)&key[1], k->k_len);
        !          2337:        k->k_rsc = LE_READ_8(key->rsc);
        !          2338:        if (ic->ic_set_key != NULL && (*ic->ic_set_key)(ic, ni, k) != 0)
        !          2339:                return;
        !          2340:
        !          2341:        /* update the last seen value of the key replay counter field */
        !          2342:        ni->ni_replaycnt = BE_READ_8(key->replaycnt);
        !          2343:
        !          2344:        if (ic->ic_if.if_flags & IFF_DEBUG)
        !          2345:                printf("%s: received msg %d/%d of the %s handshake from %s\n",
        !          2346:                    ic->ic_if.if_xname, 1, 2, "group key",
        !          2347:                    ether_sprintf(ni->ni_macaddr));
        !          2348:
        !          2349:        /* send message 2 to authenticator */
        !          2350:        ieee80211_send_group_msg2(ic, ni, k);
        !          2351: }
        !          2352:
        !          2353: /*
        !          2354:  * Group Key Handshake Message 2 is sent by the supplicant to the
        !          2355:  * authenticator (see 8.5.4.2).
        !          2356:  */
        !          2357: void
        !          2358: ieee80211_recv_group_msg2(struct ieee80211com *ic,
        !          2359:     const struct ieee80211_eapol_key *key, struct ieee80211_node *ni)
        !          2360: {
        !          2361:        if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
        !          2362:            ic->ic_opmode != IEEE80211_M_IBSS)
        !          2363:                return;
        !          2364:
        !          2365:        if (BE_READ_8(key->replaycnt) != ni->ni_replaycnt)
        !          2366:                return;
        !          2367:
        !          2368:        /* empty key data field */
        !          2369:
        !          2370: #ifdef notyet
        !          2371:        if (--ic->ic_keydone_sta == 0) {
        !          2372:                /* install GTK */
        !          2373:        }
        !          2374: #endif
        !          2375:        if (ic->ic_if.if_flags & IFF_DEBUG)
        !          2376:                printf("%s: received msg %d/%d of the %s handshake from %s\n",
        !          2377:                    ic->ic_if.if_xname, 2, 2, "group key",
        !          2378:                    ether_sprintf(ni->ni_macaddr));
        !          2379: }
        !          2380:
        !          2381: /*
        !          2382:  * EAPOL-Key Request frames are sent by the supplicant to request that the
        !          2383:  * authenticator initiate either a 4-Way Handshake or Group Key Handshake
        !          2384:  * and to report a MIC failure in a TKIP MSDU.
        !          2385:  */
        !          2386: void
        !          2387: ieee80211_recv_eapol_key_req(struct ieee80211com *ic,
        !          2388:     const struct ieee80211_eapol_key *key, struct ieee80211_node *ni)
        !          2389: {
        !          2390:        u_int16_t info;
        !          2391:
        !          2392:        if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
        !          2393:            ic->ic_opmode != IEEE80211_M_IBSS)
        !          2394:                return;
        !          2395:
        !          2396:        info = BE_READ_2(key->info);
        !          2397:
        !          2398:        if (info & EAPOL_KEY_ERROR) {
        !          2399:                /* TKIP MIC failure */
        !          2400:
        !          2401:        } else if (info & EAPOL_KEY_PAIRWISE) {
        !          2402:                /* initiate the 4-Way Handshake */
        !          2403:
        !          2404:        } else {
        !          2405:                /*
        !          2406:                 * Should change the GTK, initiate the 4-Way Handshake and
        !          2407:                 * then execute a Group Key Handshake with all supplicants.
        !          2408:                 */
        !          2409:        }
        !          2410: }
        !          2411:
        !          2412: #ifdef IEEE80211_DEBUG
        !          2413: static void
        !          2414: ieee80211_print_eapol_key(struct ieee80211com *ic,
        !          2415:     const struct ieee80211_eapol_key *key, const struct ieee80211_node *ni)
        !          2416: {
        !          2417:        int i;
        !          2418:        printf("%s: received EAPOL-Key frame from %s\n",
        !          2419:            ic->ic_if.if_xname, ether_sprintf((u_int8_t *)ni->ni_macaddr));
        !          2420:        printf("version=0x%02x type=0x%02x desc=0x%02x body length=%d "
        !          2421:            "data length=%d\n", key->version, key->type, key->desc,
        !          2422:            BE_READ_2(key->len), BE_READ_2(key->paylen));
        !          2423:        printf("info=%b\n", BE_READ_2(key->info),
        !          2424:            "\20\x03PAIRWISE\x06INSTALL\x07KEYACK\x08KEYMIC\x09SECURE"
        !          2425:            "\x0aERROR\x0bREQUEST\x0cENCRYPTED\x0dSMK");
        !          2426:        printf("Key Replay Counter=0x");
        !          2427:        for (i = 0; i < 8; i++)
        !          2428:                printf("%02x", key->replaycnt[i]);
        !          2429:        printf("\n");
        !          2430:        printf("Key Nonce=0x");
        !          2431:        for (i = 0; i < EAPOL_KEY_NONCE_LEN; i++)
        !          2432:                printf("%02x", key->nonce[i]);
        !          2433:        printf("\n");
        !          2434:        printf("Key IV=0x");
        !          2435:        for (i = 0; i < EAPOL_KEY_IV_LEN; i++)
        !          2436:                printf("%02x", key->iv[i]);
        !          2437:        printf("\n");
        !          2438:        printf("Key RSC=0x");
        !          2439:        for (i = 0; i < 8; i++)
        !          2440:                printf("%02x", key->rsc[i]);
        !          2441:        printf("\n");
        !          2442:        printf("Key MIC=0x");
        !          2443:        for (i = 0; i < EAPOL_KEY_MIC_LEN; i++)
        !          2444:                printf("%02x", key->mic[i]);
        !          2445:        printf("\n");
        !          2446: }
        !          2447: #endif
        !          2448:
        !          2449: /*
        !          2450:  * Process an incoming EAPOL frame.  Notice that we are only interested in
        !          2451:  * EAPOL-Key frames with an IEEE 802.11 or WPA1 descriptor type.
        !          2452:  */
        !          2453: void
        !          2454: ieee80211_recv_eapol(struct ieee80211com *ic, struct mbuf *m0,
        !          2455:     struct ieee80211_node *ni)
        !          2456: {
        !          2457:        struct ieee80211_eapol_key *key;
        !          2458:        u_int16_t info;
        !          2459:
        !          2460:        if (m0->m_len < sizeof(struct ether_header) + sizeof(*key))
        !          2461:                goto out;
        !          2462:
        !          2463:        m_adj(m0, sizeof(struct ether_header));
        !          2464:        key = mtod(m0, struct ieee80211_eapol_key *);
        !          2465:
        !          2466:        if (key->type != EAPOL_KEY || key->desc != ni->ni_eapol_desc)
        !          2467:                goto out;
        !          2468:
        !          2469:        /* check packet body length */
        !          2470:        if (m0->m_len < 4 + BE_READ_2(key->len))
        !          2471:                goto out;
        !          2472:
        !          2473:        /* check key data length */
        !          2474:        if (m0->m_len < sizeof(*key) + BE_READ_2(key->paylen))
        !          2475:                goto out;
        !          2476:
        !          2477: #ifdef IEEE80211_DEBUG
        !          2478:        if (ieee80211_debug > 0)
        !          2479:                ieee80211_print_eapol_key(ic, key, ni);
        !          2480: #endif
        !          2481:        info = BE_READ_2(key->info);
        !          2482:
        !          2483:        if (info & (EAPOL_KEY_KEYMIC | EAPOL_KEY_ENCRYPTED)) {
        !          2484:                /* check that we have a valid PTK or TPTK */
        !          2485:                if (!ni->ni_ptk_ok)
        !          2486:                        goto out;
        !          2487:
        !          2488:                if (ni->ni_pairwise_cipher == IEEE80211_CIPHER_CCMP &&
        !          2489:                    (info & EAPOL_KEY_VERSION_MASK) != EAPOL_KEY_DESC_V2)
        !          2490:                        goto out;
        !          2491:
        !          2492:                /* check Key MIC field using KCK */
        !          2493:                if ((info & EAPOL_KEY_KEYMIC) &&
        !          2494:                    ieee80211_eapol_key_check_mic(key, ni->ni_ptk.kck) != 0)
        !          2495:                        goto out;
        !          2496:
        !          2497:                /* decrypt Key Data field using KEK */
        !          2498:                if ((info & EAPOL_KEY_ENCRYPTED) &&
        !          2499:                    ieee80211_eapol_key_decrypt(key, ni->ni_ptk.kek) != 0)
        !          2500:                        goto out;
        !          2501:        }
        !          2502:
        !          2503:        /* determine message type (see 8.5.3.7) */
        !          2504:        if (info & EAPOL_KEY_REQUEST) {
        !          2505:                /* EAPOL-Key Request */
        !          2506:                ieee80211_recv_eapol_key_req(ic, key, ni);
        !          2507:
        !          2508:        } else if (info & EAPOL_KEY_PAIRWISE) {
        !          2509:                /* 4-Way Handshake */
        !          2510:                if (info & EAPOL_KEY_KEYMIC) {
        !          2511:                        if (!(info & EAPOL_KEY_KEYACK)) {
        !          2512:                                if (info & EAPOL_KEY_SECURE)
        !          2513:                                        ieee80211_recv_4way_msg4(ic, key, ni);
        !          2514:                                else
        !          2515:                                        ieee80211_recv_4way_msg2(ic, key, ni);
        !          2516:                        } else
        !          2517:                                ieee80211_recv_4way_msg3(ic, key, ni);
        !          2518:                } else
        !          2519:                        ieee80211_recv_4way_msg1(ic, key, ni);
        !          2520:        } else {
        !          2521:                /* Group Key Handshake */
        !          2522:                if (!(info & EAPOL_KEY_KEYMIC))
        !          2523:                        goto out;
        !          2524:                if (info & EAPOL_KEY_KEYACK) {
        !          2525:                        if (key->desc == EAPOL_KEY_DESC_WPA1)
        !          2526:                                ieee80211_recv_wpa_group_msg1(ic, key, ni);
        !          2527:                        else
        !          2528:                                ieee80211_recv_rsn_group_msg1(ic, key, ni);
        !          2529:                } else
        !          2530:                        ieee80211_recv_group_msg2(ic, key, ni);
        !          2531:        }
        !          2532:  out:
        !          2533:        m_freem(m0);
        !          2534: }
        !          2535:
        !          2536: void
        !          2537: ieee80211_recv_pspoll(struct ieee80211com *ic, struct mbuf *m0, int rssi,
        !          2538:     u_int32_t rstamp)
        !          2539: {
        !          2540:        struct ifnet *ifp = &ic->ic_if;
        !          2541:        struct ieee80211_frame *wh;
        !          2542:        struct ieee80211_node *ni;
        !          2543:        struct mbuf *m;
        !          2544:        u_int16_t aid;
        !          2545:
        !          2546:        if (ic->ic_set_tim == NULL)  /* no powersaving functionality */
        !          2547:                return;
        !          2548:
        !          2549:        wh = mtod(m0, struct ieee80211_frame *);
        !          2550:
        !          2551:        if ((ni = ieee80211_find_node(ic, wh->i_addr2)) == NULL) {
        !          2552:                if (ifp->if_flags & IFF_DEBUG)
        !          2553:                        printf("%s: station %s sent bogus power save poll\n",
        !          2554:                            ifp->if_xname, ether_sprintf(wh->i_addr2));
        !          2555:                return;
        !          2556:        }
        !          2557:
        !          2558:        memcpy(&aid, wh->i_dur, sizeof(wh->i_dur));
        !          2559:        if ((aid & 0xc000) != 0xc000) {
        !          2560:                if (ifp->if_flags & IFF_DEBUG)
        !          2561:                        printf("%s: station %s sent bogus aid %x\n",
        !          2562:                            ifp->if_xname, ether_sprintf(wh->i_addr2), aid);
        !          2563:                return;
        !          2564:        }
        !          2565:
        !          2566:        if (aid != ni->ni_associd) {
        !          2567:                if (ifp->if_flags & IFF_DEBUG)
        !          2568:                        printf("%s: station %s aid %x doesn't match pspoll "
        !          2569:                            "aid %x\n", ifp->if_xname,
        !          2570:                            ether_sprintf(wh->i_addr2), ni->ni_associd, aid);
        !          2571:                return;
        !          2572:        }
        !          2573:
        !          2574:        /* Okay, take the first queued packet and put it out... */
        !          2575:
        !          2576:        IF_DEQUEUE(&ni->ni_savedq, m);
        !          2577:        if (m == NULL) {
        !          2578:                if (ifp->if_flags & IFF_DEBUG)
        !          2579:                        printf("%s: station %s sent pspoll, "
        !          2580:                            "but no packets are saved\n",
        !          2581:                            ifp->if_xname, ether_sprintf(wh->i_addr2));
        !          2582:                return;
        !          2583:        }
        !          2584:        wh = mtod(m, struct ieee80211_frame *);
        !          2585:
        !          2586:        /*
        !          2587:         * If this is the last packet, turn off the TIM fields.
        !          2588:         * If there are more packets, set the more packets bit.
        !          2589:         */
        !          2590:
        !          2591:        if (IF_IS_EMPTY(&ni->ni_savedq))
        !          2592:                (*ic->ic_set_tim)(ic, ni->ni_associd, 0);
        !          2593:        else
        !          2594:                wh->i_fc[1] |= IEEE80211_FC1_MORE_DATA;
        !          2595:
        !          2596:        if (ifp->if_flags & IFF_DEBUG)
        !          2597:                printf("%s: enqueued power saving packet for station %s\n",
        !          2598:                    ifp->if_xname, ether_sprintf(ni->ni_macaddr));
        !          2599:
        !          2600:        IF_ENQUEUE(&ic->ic_pwrsaveq, m);
        !          2601:        (*ifp->if_start)(ifp);
        !          2602: }
        !          2603:
        !          2604: int
        !          2605: ieee80211_do_slow_print(struct ieee80211com *ic, int *did_print)
        !          2606: {
        !          2607:        static const struct timeval merge_print_intvl = {
        !          2608:                .tv_sec = 1, .tv_usec = 0
        !          2609:        };
        !          2610:        if ((ic->ic_if.if_flags & IFF_LINK0) == 0)
        !          2611:                return 0;
        !          2612:        if (!*did_print && (ic->ic_if.if_flags & IFF_DEBUG) == 0 &&
        !          2613:            !ratecheck(&ic->ic_last_merge_print, &merge_print_intvl))
        !          2614:                return 0;
        !          2615:
        !          2616:        *did_print = 1;
        !          2617:        return 1;
        !          2618: }
        !          2619:
        !          2620: /* ieee80211_ibss_merge helps merge 802.11 ad hoc networks.  The
        !          2621:  * convention, set by the Wireless Ethernet Compatibility Alliance
        !          2622:  * (WECA), is that an 802.11 station will change its BSSID to match
        !          2623:  * the "oldest" 802.11 ad hoc network, on the same channel, that
        !          2624:  * has the station's desired SSID.  The "oldest" 802.11 network
        !          2625:  * sends beacons with the greatest TSF timestamp.
        !          2626:  *
        !          2627:  * Return ENETRESET if the BSSID changed, 0 otherwise.
        !          2628:  *
        !          2629:  * XXX Perhaps we should compensate for the time that elapses
        !          2630:  * between the MAC receiving the beacon and the host processing it
        !          2631:  * in ieee80211_ibss_merge.
        !          2632:  */
        !          2633: int
        !          2634: ieee80211_ibss_merge(struct ieee80211com *ic, struct ieee80211_node *ni,
        !          2635:     u_int64_t local_tsft)
        !          2636: {
        !          2637:        u_int64_t beacon_tsft;
        !          2638:        int did_print = 0, sign;
        !          2639:        union {
        !          2640:                u_int64_t       word;
        !          2641:                u_int8_t        tstamp[8];
        !          2642:        } u;
        !          2643:
        !          2644:        /* ensure alignment */
        !          2645:        (void)memcpy(&u, &ni->ni_tstamp[0], sizeof(u));
        !          2646:        beacon_tsft = letoh64(u.word);
        !          2647:
        !          2648:        /* we are faster, let the other guy catch up */
        !          2649:        if (beacon_tsft < local_tsft)
        !          2650:                sign = -1;
        !          2651:        else
        !          2652:                sign = 1;
        !          2653:
        !          2654:        if (IEEE80211_ADDR_EQ(ni->ni_bssid, ic->ic_bss->ni_bssid)) {
        !          2655:                if (!ieee80211_do_slow_print(ic, &did_print))
        !          2656:                        return 0;
        !          2657:                printf("%s: tsft offset %s%llu\n", ic->ic_if.if_xname,
        !          2658:                    (sign < 0) ? "-" : "",
        !          2659:                    (sign < 0)
        !          2660:                        ? (local_tsft - beacon_tsft)
        !          2661:                        : (beacon_tsft - local_tsft));
        !          2662:                return 0;
        !          2663:        }
        !          2664:
        !          2665:        if (sign < 0)
        !          2666:                return 0;
        !          2667:
        !          2668:        if (ieee80211_match_bss(ic, ni) != 0)
        !          2669:                return 0;
        !          2670:
        !          2671:        if (ieee80211_do_slow_print(ic, &did_print)) {
        !          2672:                printf("%s: ieee80211_ibss_merge: bssid mismatch %s\n",
        !          2673:                    ic->ic_if.if_xname, ether_sprintf(ni->ni_bssid));
        !          2674:                printf("%s: my tsft %llu beacon tsft %llu\n",
        !          2675:                    ic->ic_if.if_xname, local_tsft, beacon_tsft);
        !          2676:                printf("%s: sync TSF with %s\n",
        !          2677:                    ic->ic_if.if_xname, ether_sprintf(ni->ni_macaddr));
        !          2678:        }
        !          2679:
        !          2680:        ic->ic_flags &= ~IEEE80211_F_SIBSS;
        !          2681:
        !          2682:        /* negotiate rates with new IBSS */
        !          2683:        ieee80211_fix_rate(ic, ni, IEEE80211_F_DOFRATE |
        !          2684:            IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
        !          2685:        if (ni->ni_rates.rs_nrates == 0) {
        !          2686:                if (ieee80211_do_slow_print(ic, &did_print)) {
        !          2687:                        printf("%s: rates mismatch, BSSID %s\n",
        !          2688:                            ic->ic_if.if_xname, ether_sprintf(ni->ni_bssid));
        !          2689:                }
        !          2690:                return 0;
        !          2691:        }
        !          2692:
        !          2693:        if (ieee80211_do_slow_print(ic, &did_print)) {
        !          2694:                printf("%s: sync BSSID %s -> ",
        !          2695:                    ic->ic_if.if_xname, ether_sprintf(ic->ic_bss->ni_bssid));
        !          2696:                printf("%s ", ether_sprintf(ni->ni_bssid));
        !          2697:                printf("(from %s)\n", ether_sprintf(ni->ni_macaddr));
        !          2698:        }
        !          2699:
        !          2700:        ieee80211_node_newstate(ni, IEEE80211_STA_BSS);
        !          2701:        (*ic->ic_node_copy)(ic, ic->ic_bss, ni);
        !          2702:
        !          2703:        return ENETRESET;
        !          2704: }

CVSweb