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

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

1.1     ! nbrk        1: /*     $OpenBSD: ieee80211_output.c,v 1.55 2007/08/05 21:41:11 claudio Exp $   */
        !             2: /*     $NetBSD: ieee80211_output.c,v 1.13 2004/05/31 11:02:55 dyoung Exp $     */
        !             3:
        !             4: /*-
        !             5:  * Copyright (c) 2001 Atsushi Onoe
        !             6:  * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting
        !             7:  * Copyright (c) 2007 Damien Bergamini
        !             8:  * All rights reserved.
        !             9:  *
        !            10:  * Redistribution and use in source and binary forms, with or without
        !            11:  * modification, are permitted provided that the following conditions
        !            12:  * are met:
        !            13:  * 1. Redistributions of source code must retain the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer.
        !            15:  * 2. Redistributions in binary form must reproduce the above copyright
        !            16:  *    notice, this list of conditions and the following disclaimer in the
        !            17:  *    documentation and/or other materials provided with the distribution.
        !            18:  * 3. The name of the author may not be used to endorse or promote products
        !            19:  *    derived from this software without specific prior written permission.
        !            20:  *
        !            21:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            22:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            23:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            24:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
        !            25:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            26:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            27:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        !            28:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            29:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
        !            30:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            31:  */
        !            32:
        !            33: #include "bpfilter.h"
        !            34: #include "vlan.h"
        !            35:
        !            36: #include <sys/param.h>
        !            37: #include <sys/systm.h>
        !            38: #include <sys/mbuf.h>
        !            39: #include <sys/kernel.h>
        !            40: #include <sys/socket.h>
        !            41: #include <sys/sockio.h>
        !            42: #include <sys/endian.h>
        !            43: #include <sys/errno.h>
        !            44: #include <sys/proc.h>
        !            45: #include <sys/sysctl.h>
        !            46:
        !            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: #include <net/bpf.h>
        !            53:
        !            54: #ifdef INET
        !            55: #include <netinet/in.h>
        !            56: #include <netinet/if_ether.h>
        !            57: #include <netinet/in_systm.h>
        !            58: #include <netinet/ip.h>
        !            59: #endif
        !            60:
        !            61: #if NVLAN > 0
        !            62: #include <net/if_types.h>
        !            63: #include <net/if_vlan_var.h>
        !            64: #endif
        !            65:
        !            66: #include <net80211/ieee80211_var.h>
        !            67:
        !            68: #include <dev/rndvar.h>
        !            69:
        !            70: enum   ieee80211_edca_ac ieee80211_up_to_ac(struct ieee80211com *, int);
        !            71: int    ieee80211_classify(struct ieee80211com *, struct mbuf *);
        !            72: int    ieee80211_mgmt_output(struct ifnet *, struct ieee80211_node *,
        !            73:            struct mbuf *, int);
        !            74: u_int8_t *ieee80211_add_rsn_body(u_int8_t *, struct ieee80211com *,
        !            75:            const struct ieee80211_node *, int);
        !            76: struct mbuf *ieee80211_getmbuf(int, int, u_int);
        !            77: struct mbuf *ieee80211_get_probe_req(struct ieee80211com *,
        !            78:            struct ieee80211_node *);
        !            79: struct mbuf *ieee80211_get_probe_resp(struct ieee80211com *,
        !            80:            struct ieee80211_node *);
        !            81: struct mbuf *ieee80211_get_auth(struct ieee80211com *,
        !            82:            struct ieee80211_node *, u_int16_t, u_int16_t);
        !            83: struct mbuf *ieee80211_get_deauth(struct ieee80211com *,
        !            84:            struct ieee80211_node *, u_int16_t);
        !            85: struct mbuf *ieee80211_get_assoc_req(struct ieee80211com *,
        !            86:            struct ieee80211_node *, int);
        !            87: struct mbuf *ieee80211_get_assoc_resp(struct ieee80211com *,
        !            88:            struct ieee80211_node *, u_int16_t);
        !            89: struct mbuf *ieee80211_get_disassoc(struct ieee80211com *,
        !            90:            struct ieee80211_node *, u_int16_t);
        !            91: int    ieee80211_send_eapol_key(struct ieee80211com *, struct mbuf *,
        !            92:            struct ieee80211_node *);
        !            93: u_int8_t *ieee80211_add_gtk_kde(u_int8_t *, const struct ieee80211_key *);
        !            94: u_int8_t *ieee80211_add_pmkid_kde(u_int8_t *, const u_int8_t *);
        !            95: struct mbuf *ieee80211_get_eapol_key(int, int, u_int);
        !            96:
        !            97:
        !            98: /*
        !            99:  * IEEE 802.11 output routine. Normally this will directly call the
        !           100:  * Ethernet output routine because 802.11 encapsulation is called
        !           101:  * later by the driver. This function can be used to send raw frames
        !           102:  * if the mbuf has been tagged with a 802.11 data link type.
        !           103:  */
        !           104: int
        !           105: ieee80211_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
        !           106:     struct rtentry *rt)
        !           107: {
        !           108:        u_int dlt = 0;
        !           109:        int s, error = 0;
        !           110:        struct m_tag *mtag;
        !           111:
        !           112:        /* Interface has to be up and running */
        !           113:        if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) !=
        !           114:            (IFF_UP | IFF_RUNNING)) {
        !           115:                error = ENETDOWN;
        !           116:                goto bad;
        !           117:        }
        !           118:
        !           119:        /* Try to get the DLT from a mbuf tag */
        !           120:        if ((mtag = m_tag_find(m, PACKET_TAG_DLT, NULL)) != NULL) {
        !           121:                dlt = *(u_int *)(mtag + 1);
        !           122:
        !           123:                /* Fallback to ethernet for non-802.11 linktypes */
        !           124:                if (!(dlt == DLT_IEEE802_11 || dlt == DLT_IEEE802_11_RADIO))
        !           125:                        goto fallback;
        !           126:
        !           127:                /*
        !           128:                 * Queue message on interface without adding any
        !           129:                 * further headers, and start output if interface not
        !           130:                 * yet active.
        !           131:                 */
        !           132:                s = splnet();
        !           133:                IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error);
        !           134:                if (error) {
        !           135:                        /* mbuf is already freed */
        !           136:                        splx(s);
        !           137:                        printf("%s: failed to queue raw tx frame\n",
        !           138:                            ifp->if_xname);
        !           139:                        return (error);
        !           140:                }
        !           141:                ifp->if_obytes += m->m_pkthdr.len;
        !           142:                if (m->m_flags & M_MCAST)
        !           143:                        ifp->if_omcasts++;
        !           144:                if ((ifp->if_flags & IFF_OACTIVE) == 0)
        !           145:                        (*ifp->if_start)(ifp);
        !           146:                splx(s);
        !           147:
        !           148:                return (error);
        !           149:        }
        !           150:
        !           151:  fallback:
        !           152:        return (ether_output(ifp, m, dst, rt));
        !           153:
        !           154:  bad:
        !           155:        if (m)
        !           156:                m_freem(m);
        !           157:        return (error);
        !           158: }
        !           159:
        !           160: /*
        !           161:  * Send a management frame to the specified node.  The node pointer
        !           162:  * must have a reference as the pointer will be passed to the driver
        !           163:  * and potentially held for a long time.  If the frame is successfully
        !           164:  * dispatched to the driver, then it is responsible for freeing the
        !           165:  * reference (and potentially free'ing up any associated storage).
        !           166:  */
        !           167: int
        !           168: ieee80211_mgmt_output(struct ifnet *ifp, struct ieee80211_node *ni,
        !           169:     struct mbuf *m, int type)
        !           170: {
        !           171:        struct ieee80211com *ic = (void *)ifp;
        !           172:        struct ieee80211_frame *wh;
        !           173:
        !           174:        if (ni == NULL)
        !           175:                panic("null node");
        !           176:        ni->ni_inact = 0;
        !           177:
        !           178:        /*
        !           179:         * Yech, hack alert!  We want to pass the node down to the
        !           180:         * driver's start routine.  We could stick this in an m_tag
        !           181:         * and tack that on to the mbuf.  However that's rather
        !           182:         * expensive to do for every frame so instead we stuff it in
        !           183:         * the rcvif field since outbound frames do not (presently)
        !           184:         * use this.
        !           185:         */
        !           186:        M_PREPEND(m, sizeof(struct ieee80211_frame), M_DONTWAIT);
        !           187:        if (m == NULL)
        !           188:                return ENOMEM;
        !           189:        m->m_pkthdr.rcvif = (void *)ni;
        !           190:
        !           191:        wh = mtod(m, struct ieee80211_frame *);
        !           192:        wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT | type;
        !           193:        wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
        !           194:        *(u_int16_t *)&wh->i_dur[0] = 0;
        !           195:        *(u_int16_t *)&wh->i_seq[0] =
        !           196:            htole16(ni->ni_txseq << IEEE80211_SEQ_SEQ_SHIFT);
        !           197:        ni->ni_txseq++;
        !           198:        IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_macaddr);
        !           199:        IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_myaddr);
        !           200:        IEEE80211_ADDR_COPY(wh->i_addr3, ni->ni_bssid);
        !           201:
        !           202:        if (ifp->if_flags & IFF_DEBUG) {
        !           203:                /* avoid to print too many frames */
        !           204:                if (ic->ic_opmode == IEEE80211_M_IBSS ||
        !           205: #ifdef IEEE80211_DEBUG
        !           206:                    ieee80211_debug > 1 ||
        !           207: #endif
        !           208:                    (type & IEEE80211_FC0_SUBTYPE_MASK) !=
        !           209:                    IEEE80211_FC0_SUBTYPE_PROBE_RESP)
        !           210:                        printf("%s: sending %s to %s on channel %u mode %s\n",
        !           211:                            ifp->if_xname,
        !           212:                            ieee80211_mgt_subtype_name[
        !           213:                            (type & IEEE80211_FC0_SUBTYPE_MASK)
        !           214:                            >> IEEE80211_FC0_SUBTYPE_SHIFT],
        !           215:                            ether_sprintf(ni->ni_macaddr),
        !           216:                            ieee80211_chan2ieee(ic, ni->ni_chan),
        !           217:                            ieee80211_phymode_name[
        !           218:                            ieee80211_chan2mode(ic, ni->ni_chan)]);
        !           219:        }
        !           220:
        !           221:        IF_ENQUEUE(&ic->ic_mgtq, m);
        !           222:        ifp->if_timer = 1;
        !           223:        (*ifp->if_start)(ifp);
        !           224:        return 0;
        !           225: }
        !           226:
        !           227: /*-
        !           228:  * EDCA tables are computed using the following formulas:
        !           229:  *
        !           230:  * 1) EDCATable (non-AP QSTA)
        !           231:  *
        !           232:  * AC     CWmin           CWmax           AIFSN  TXOP limit(ms)
        !           233:  * -------------------------------------------------------------
        !           234:  * AC_BK  aCWmin          aCWmax          7      0
        !           235:  * AC_BE  aCWmin          aCWmax          3      0
        !           236:  * AC_VI  (aCWmin+1)/2-1   aCWmin         2      agn=3.008 b=6.016 others=0
        !           237:  * AC_VO  (aCWmin+1)/4-1   (aCWmin+1)/2-1  2     agn=1.504 b=3.264 others=0
        !           238:  *
        !           239:  * 2) QAPEDCATable (QAP)
        !           240:  *
        !           241:  * AC     CWmin           CWmax           AIFSN  TXOP limit(ms)
        !           242:  * -------------------------------------------------------------
        !           243:  * AC_BK  aCWmin          aCWmax          7      0
        !           244:  * AC_BE  aCWmin          4*(aCWmin+1)-1  3      0
        !           245:  * AC_VI  (aCWmin+1)/2-1   aCWmin         1      agn=3.008 b=6.016 others=0
        !           246:  * AC_VO  (aCWmin+1)/4-1   (aCWmin+1)/2-1  1     agn=1.504 b=3.264 others=0
        !           247:  *
        !           248:  * and the following aCWmin/aCWmax values:
        !           249:  *
        !           250:  * PHY         aCWmin  aCWmax
        !           251:  * ---------------------------
        !           252:  * 11A         15      1023
        !           253:  * 11B         31      1023
        !           254:  * 11G         15*     1023    (*) aCWmin(1)
        !           255:  * FH          15      1023
        !           256:  * Turbo A/G   7       1023    (Atheros proprietary mode)
        !           257:  */
        !           258: static const struct ieee80211_edca_ac_params
        !           259:     ieee80211_edca_table[IEEE80211_MODE_MAX][EDCA_NUM_AC] = {
        !           260:        [IEEE80211_MODE_FH] = {
        !           261:                [EDCA_AC_BK] = { 4, 10, 7,   0 },
        !           262:                [EDCA_AC_BE] = { 4, 10, 3,   0 },
        !           263:                [EDCA_AC_VI] = { 3,  4, 2,   0 },
        !           264:                [EDCA_AC_VO] = { 2,  3, 2,   0 }
        !           265:        },
        !           266:        [IEEE80211_MODE_11B] = {
        !           267:                [EDCA_AC_BK] = { 5, 10, 7,   0 },
        !           268:                [EDCA_AC_BE] = { 5, 10, 3,   0 },
        !           269:                [EDCA_AC_VI] = { 4,  5, 2, 188 },
        !           270:                [EDCA_AC_VO] = { 3,  4, 2, 102 }
        !           271:        },
        !           272:        [IEEE80211_MODE_11A] = {
        !           273:                [EDCA_AC_BK] = { 4, 10, 7,   0 },
        !           274:                [EDCA_AC_BE] = { 4, 10, 3,   0 },
        !           275:                [EDCA_AC_VI] = { 3,  4, 2,  94 },
        !           276:                [EDCA_AC_VO] = { 2,  3, 2,  47 }
        !           277:        },
        !           278:        [IEEE80211_MODE_11G] = {
        !           279:                [EDCA_AC_BK] = { 4, 10, 7,   0 },
        !           280:                [EDCA_AC_BE] = { 4, 10, 3,   0 },
        !           281:                [EDCA_AC_VI] = { 3,  4, 2,  94 },
        !           282:                [EDCA_AC_VO] = { 2,  3, 2,  47 }
        !           283:        },
        !           284:        [IEEE80211_MODE_TURBO] = {
        !           285:                [EDCA_AC_BK] = { 3, 10, 7,   0 },
        !           286:                [EDCA_AC_BE] = { 3, 10, 2,   0 },
        !           287:                [EDCA_AC_VI] = { 2,  3, 2,  94 },
        !           288:                [EDCA_AC_VO] = { 2,  2, 1,  47 }
        !           289:        }
        !           290: };
        !           291:
        !           292: static const struct ieee80211_edca_ac_params
        !           293:     ieee80211_qap_edca_table[IEEE80211_MODE_MAX][EDCA_NUM_AC] = {
        !           294:        [IEEE80211_MODE_FH] = {
        !           295:                [EDCA_AC_BK] = { 4, 10, 7,   0 },
        !           296:                [EDCA_AC_BE] = { 4,  6, 3,   0 },
        !           297:                [EDCA_AC_VI] = { 3,  4, 1,   0 },
        !           298:                [EDCA_AC_VO] = { 2,  3, 1,   0 }
        !           299:        },
        !           300:        [IEEE80211_MODE_11B] = {
        !           301:                [EDCA_AC_BK] = { 5, 10, 7,   0 },
        !           302:                [EDCA_AC_BE] = { 5,  7, 3,   0 },
        !           303:                [EDCA_AC_VI] = { 4,  5, 1, 188 },
        !           304:                [EDCA_AC_VO] = { 3,  4, 1, 102 }
        !           305:        },
        !           306:        [IEEE80211_MODE_11A] = {
        !           307:                [EDCA_AC_BK] = { 4, 10, 7,   0 },
        !           308:                [EDCA_AC_BE] = { 4,  6, 3,   0 },
        !           309:                [EDCA_AC_VI] = { 3,  4, 1,  94 },
        !           310:                [EDCA_AC_VO] = { 2,  3, 1,  47 }
        !           311:        },
        !           312:        [IEEE80211_MODE_11G] = {
        !           313:                [EDCA_AC_BK] = { 4, 10, 7,   0 },
        !           314:                [EDCA_AC_BE] = { 4,  6, 3,   0 },
        !           315:                [EDCA_AC_VI] = { 3,  4, 1,  94 },
        !           316:                [EDCA_AC_VO] = { 2,  3, 1,  47 }
        !           317:        },
        !           318:        [IEEE80211_MODE_TURBO] = {
        !           319:                [EDCA_AC_BK] = { 3, 10, 7,   0 },
        !           320:                [EDCA_AC_BE] = { 3,  5, 2,   0 },
        !           321:                [EDCA_AC_VI] = { 2,  3, 1,  94 },
        !           322:                [EDCA_AC_VO] = { 2,  2, 1,  47 }
        !           323:        }
        !           324: };
        !           325:
        !           326: /*
        !           327:  * Return the EDCA Access Category to be used for transmitting a frame with
        !           328:  * user-priority `up'.
        !           329:  */
        !           330: enum ieee80211_edca_ac
        !           331: ieee80211_up_to_ac(struct ieee80211com *ic, int up)
        !           332: {
        !           333:        /* IEEE Std 802.11e-2005, table 20i */
        !           334:        static const enum ieee80211_edca_ac up_to_ac[] = {
        !           335:                EDCA_AC_BE,     /* BE */
        !           336:                EDCA_AC_BK,     /* BK */
        !           337:                EDCA_AC_BK,     /* -- */
        !           338:                EDCA_AC_BE,     /* EE */
        !           339:                EDCA_AC_VI,     /* CL */
        !           340:                EDCA_AC_VI,     /* VI */
        !           341:                EDCA_AC_VO,     /* VO */
        !           342:                EDCA_AC_VO      /* NC */
        !           343:        };
        !           344:        enum ieee80211_edca_ac ac;
        !           345:
        !           346:        ac = (up <= 7) ? up_to_ac[up] : EDCA_AC_BE;
        !           347:
        !           348:        if (ic->ic_opmode == IEEE80211_M_HOSTAP)
        !           349:                return ac;
        !           350:
        !           351:        /*
        !           352:         * We do not support the admission control procedure defined in
        !           353:         * IEEE Std 802.11e-2005 section 9.9.3.1.2.  The spec says that
        !           354:         * non-AP QSTAs that don't support this procedure shall use EDCA
        !           355:         * parameters of a lower priority AC that does not require
        !           356:         * admission control.
        !           357:         */
        !           358:        while (ac != EDCA_AC_BK && ic->ic_edca_ac[ac].ac_acm) {
        !           359:                switch (ac) {
        !           360:                case EDCA_AC_BK:
        !           361:                        /* can't get there */
        !           362:                        break;
        !           363:                case EDCA_AC_BE:
        !           364:                        /* BE shouldn't require admission control */
        !           365:                        ac = EDCA_AC_BK;
        !           366:                        break;
        !           367:                case EDCA_AC_VI:
        !           368:                        ac = EDCA_AC_BE;
        !           369:                        break;
        !           370:                case EDCA_AC_VO:
        !           371:                        ac = EDCA_AC_VI;
        !           372:                        break;
        !           373:                }
        !           374:        }
        !           375:        return ac;
        !           376: }
        !           377:
        !           378: /*
        !           379:  * Get mbuf's user-priority: if mbuf is not VLAN tagged, select user-priority
        !           380:  * based on the DSCP (Differentiated Services Codepoint) field.
        !           381:  */
        !           382: int
        !           383: ieee80211_classify(struct ieee80211com *ic, struct mbuf *m)
        !           384: {
        !           385: #ifdef INET
        !           386:        const struct ether_header *eh;
        !           387: #endif
        !           388: #if NVLAN > 0
        !           389:        if ((m->m_flags & M_PROTO1) == M_PROTO1 && m->m_pkthdr.rcvif != NULL) {
        !           390:                const struct ifvlan *ifv = m->m_pkthdr.rcvif->if_softc;
        !           391:
        !           392:                /* use VLAN 802.1D user-priority */
        !           393:                if (ifv->ifv_prio <= 7)
        !           394:                        return ifv->ifv_prio;
        !           395:        }
        !           396: #endif
        !           397: #ifdef INET
        !           398:        eh = mtod(m, struct ether_header *);
        !           399:        if (eh->ether_type == htons(ETHERTYPE_IP)) {
        !           400:                const struct ip *ip = (const struct ip *)(eh + 1);
        !           401:                /*
        !           402:                 * Map Differentiated Services Codepoint field (see RFC2474).
        !           403:                 * Preserves backward compatibility with IP Precedence field.
        !           404:                 */
        !           405:                switch (ip->ip_tos & 0xfc) {
        !           406:                case IPTOS_PREC_PRIORITY:
        !           407:                        return 2;
        !           408:                case IPTOS_PREC_IMMEDIATE:
        !           409:                        return 1;
        !           410:                case IPTOS_PREC_FLASH:
        !           411:                        return 3;
        !           412:                case IPTOS_PREC_FLASHOVERRIDE:
        !           413:                        return 4;
        !           414:                case IPTOS_PREC_CRITIC_ECP:
        !           415:                        return 5;
        !           416:                case IPTOS_PREC_INTERNETCONTROL:
        !           417:                        return 6;
        !           418:                case IPTOS_PREC_NETCONTROL:
        !           419:                        return 7;
        !           420:                }
        !           421:        }
        !           422: #endif
        !           423:        return 0;       /* default to Best-Effort */
        !           424: }
        !           425:
        !           426: /*
        !           427:  * Encapsulate an outbound data frame.  The mbuf chain is updated and
        !           428:  * a reference to the destination node is returned.  If an error is
        !           429:  * encountered NULL is returned and the node reference will also be NULL.
        !           430:  *
        !           431:  * NB: The caller is responsible for free'ing a returned node reference.
        !           432:  *     The convention is ic_bss is not reference counted; the caller must
        !           433:  *     maintain that.
        !           434:  */
        !           435: struct mbuf *
        !           436: ieee80211_encap(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node **pni)
        !           437: {
        !           438:        struct ieee80211com *ic = (void *)ifp;
        !           439:        struct ether_header eh;
        !           440:        struct ieee80211_frame *wh;
        !           441:        struct ieee80211_node *ni = NULL;
        !           442:        struct llc *llc;
        !           443:        struct m_tag *mtag;
        !           444:        u_int8_t *addr;
        !           445:        u_int dlt, hdrlen;
        !           446:        int addqos, tid;
        !           447:
        !           448:        /* Handle raw frames if mbuf is tagged as 802.11 */
        !           449:        if ((mtag = m_tag_find(m, PACKET_TAG_DLT, NULL)) != NULL) {
        !           450:                dlt = *(u_int *)(mtag + 1);
        !           451:
        !           452:                if (!(dlt == DLT_IEEE802_11 || dlt == DLT_IEEE802_11_RADIO))
        !           453:                        goto fallback;
        !           454:
        !           455:                wh = mtod(m, struct ieee80211_frame *);
        !           456:
        !           457:                if (m->m_pkthdr.len < sizeof(struct ieee80211_frame_min))
        !           458:                        goto bad;
        !           459:
        !           460:                if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) !=
        !           461:                    IEEE80211_FC0_VERSION_0)
        !           462:                        goto bad;
        !           463:
        !           464:                switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) {
        !           465:                case IEEE80211_FC1_DIR_NODS:
        !           466:                case IEEE80211_FC1_DIR_FROMDS:
        !           467:                        addr = wh->i_addr1;
        !           468:                        break;
        !           469:                case IEEE80211_FC1_DIR_DSTODS:
        !           470:                case IEEE80211_FC1_DIR_TODS:
        !           471:                        addr = wh->i_addr3;
        !           472:                        break;
        !           473:                default:
        !           474:                        goto bad;
        !           475:                }
        !           476:
        !           477:                ni = ieee80211_find_txnode(ic, addr);
        !           478:                if (ni == NULL)
        !           479:                        ni = ieee80211_ref_node(ic->ic_bss);
        !           480:                if (ni == NULL) {
        !           481:                        printf("%s: no node for dst %s, "
        !           482:                            "discard raw tx frame\n", ifp->if_xname,
        !           483:                            ether_sprintf(addr));
        !           484:                        ic->ic_stats.is_tx_nonode++;
        !           485:                        goto bad;
        !           486:                }
        !           487:                ni->ni_inact = 0;
        !           488:
        !           489:                *pni = ni;
        !           490:                return (m);
        !           491:        }
        !           492:
        !           493:  fallback:
        !           494:        if (m->m_len < sizeof(struct ether_header)) {
        !           495:                m = m_pullup(m, sizeof(struct ether_header));
        !           496:                if (m == NULL) {
        !           497:                        ic->ic_stats.is_tx_nombuf++;
        !           498:                        goto bad;
        !           499:                }
        !           500:        }
        !           501:        memcpy(&eh, mtod(m, caddr_t), sizeof(struct ether_header));
        !           502:
        !           503:        ni = ieee80211_find_txnode(ic, eh.ether_dhost);
        !           504:        if (ni == NULL) {
        !           505:                IEEE80211_DPRINTF(("%s: no node for dst %s, discard frame\n",
        !           506:                    __func__, ether_sprintf(eh.ether_dhost)));
        !           507:                ic->ic_stats.is_tx_nonode++;
        !           508:                goto bad;
        !           509:        }
        !           510: #if 0
        !           511:        if (!ni->ni_port_valid && eh.ether_type != htons(ETHERTYPE_PAE)) {
        !           512:                IEEE80211_DPRINTF(("%s: port not valid: %s\n",
        !           513:                    __func__, ether_sprintf(eh.ether_dhost)));
        !           514:                ic->ic_stats.is_tx_noauth++;
        !           515:                goto bad;
        !           516:        }
        !           517: #endif
        !           518:        ni->ni_inact = 0;
        !           519:
        !           520:        if ((ic->ic_flags & IEEE80211_F_QOS) &&
        !           521:            (ni->ni_flags & IEEE80211_NODE_QOS) &&
        !           522:            /* do not QoS-encapsulate EAPOL frames */
        !           523:            eh.ether_type != htons(ETHERTYPE_PAE)) {
        !           524:                tid = ieee80211_classify(ic, m);
        !           525:                hdrlen = sizeof(struct ieee80211_qosframe);
        !           526:                addqos = 1;
        !           527:        } else {
        !           528:                hdrlen = sizeof(struct ieee80211_frame);
        !           529:                addqos = 0;
        !           530:        }
        !           531:        m_adj(m, sizeof(struct ether_header) - sizeof(struct llc));
        !           532:        llc = mtod(m, struct llc *);
        !           533:        llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
        !           534:        llc->llc_control = LLC_UI;
        !           535:        llc->llc_snap.org_code[0] = 0;
        !           536:        llc->llc_snap.org_code[1] = 0;
        !           537:        llc->llc_snap.org_code[2] = 0;
        !           538:        llc->llc_snap.ether_type = eh.ether_type;
        !           539:        M_PREPEND(m, hdrlen, M_DONTWAIT);
        !           540:        if (m == NULL) {
        !           541:                ic->ic_stats.is_tx_nombuf++;
        !           542:                goto bad;
        !           543:        }
        !           544:        wh = mtod(m, struct ieee80211_frame *);
        !           545:        wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_DATA;
        !           546:        *(u_int16_t *)&wh->i_dur[0] = 0;
        !           547:        if (addqos) {
        !           548:                struct ieee80211_qosframe *qwh =
        !           549:                    (struct ieee80211_qosframe *)wh;
        !           550:                qwh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_QOS;
        !           551:                qwh->i_qos[0] = tid & IEEE80211_QOS_TID;
        !           552:                qwh->i_qos[1] = 0;      /* no TXOP requested */
        !           553:                *(u_int16_t *)&qwh->i_seq[0] =
        !           554:                    htole16(ni->ni_qos_txseqs[tid] << IEEE80211_SEQ_SEQ_SHIFT);
        !           555:                ni->ni_qos_txseqs[tid]++;
        !           556:        } else {
        !           557:                *(u_int16_t *)&wh->i_seq[0] =
        !           558:                    htole16(ni->ni_txseq << IEEE80211_SEQ_SEQ_SHIFT);
        !           559:                ni->ni_txseq++;
        !           560:        }
        !           561:        switch (ic->ic_opmode) {
        !           562:        case IEEE80211_M_STA:
        !           563:                wh->i_fc[1] = IEEE80211_FC1_DIR_TODS;
        !           564:                IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_bssid);
        !           565:                IEEE80211_ADDR_COPY(wh->i_addr2, eh.ether_shost);
        !           566:                IEEE80211_ADDR_COPY(wh->i_addr3, eh.ether_dhost);
        !           567:                break;
        !           568:        case IEEE80211_M_IBSS:
        !           569:        case IEEE80211_M_AHDEMO:
        !           570:                wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
        !           571:                IEEE80211_ADDR_COPY(wh->i_addr1, eh.ether_dhost);
        !           572:                IEEE80211_ADDR_COPY(wh->i_addr2, eh.ether_shost);
        !           573:                IEEE80211_ADDR_COPY(wh->i_addr3, ic->ic_bss->ni_bssid);
        !           574:                break;
        !           575:        case IEEE80211_M_HOSTAP:
        !           576:                wh->i_fc[1] = IEEE80211_FC1_DIR_FROMDS;
        !           577:                IEEE80211_ADDR_COPY(wh->i_addr1, eh.ether_dhost);
        !           578:                IEEE80211_ADDR_COPY(wh->i_addr2, ni->ni_bssid);
        !           579:                IEEE80211_ADDR_COPY(wh->i_addr3, eh.ether_shost);
        !           580:                break;
        !           581:        case IEEE80211_M_MONITOR:
        !           582:                goto bad;
        !           583:        }
        !           584:        if (ic->ic_flags & IEEE80211_F_WEPON)
        !           585:                wh->i_fc[1] |= IEEE80211_FC1_WEP;
        !           586:        *pni = ni;
        !           587:        return m;
        !           588: bad:
        !           589:        if (m != NULL)
        !           590:                m_freem(m);
        !           591:        if (ni != NULL)
        !           592:                ieee80211_release_node(ic, ni);
        !           593:        *pni = NULL;
        !           594:        return NULL;
        !           595: }
        !           596:
        !           597: /* unaligned little endian access */
        !           598: #define LE_WRITE_2(p, v) do {                  \
        !           599:        ((u_int8_t *)(p))[0] = (v) & 0xff;      \
        !           600:        ((u_int8_t *)(p))[1] = (v) >> 8;        \
        !           601: } while (0)
        !           602:
        !           603: /*
        !           604:  * Add a Capability Information field to a frame (see 7.3.1.4).
        !           605:  */
        !           606: u_int8_t *
        !           607: ieee80211_add_capinfo(u_int8_t *frm, struct ieee80211com *ic,
        !           608:     const struct ieee80211_node *ni)
        !           609: {
        !           610:        u_int16_t capinfo;
        !           611:
        !           612:        if (ic->ic_opmode == IEEE80211_M_IBSS)
        !           613:                capinfo = IEEE80211_CAPINFO_IBSS;
        !           614:        else if (ic->ic_opmode == IEEE80211_M_HOSTAP)
        !           615:                capinfo = IEEE80211_CAPINFO_ESS;
        !           616:        else
        !           617:                capinfo = 0;
        !           618:        if (ic->ic_flags & IEEE80211_F_WEPON)
        !           619:                capinfo |= IEEE80211_CAPINFO_PRIVACY;
        !           620:        /* NB: some 11a AP's reject the request when short preamble is set */
        !           621:        if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
        !           622:            IEEE80211_IS_CHAN_2GHZ(ni->ni_chan))
        !           623:                capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE;
        !           624:        if (ic->ic_flags & IEEE80211_F_SHSLOT)
        !           625:                capinfo |= IEEE80211_CAPINFO_SHORT_SLOTTIME;
        !           626:        LE_WRITE_2(frm, capinfo);
        !           627:        return frm + 2;
        !           628: }
        !           629:
        !           630: /*
        !           631:  * Add an SSID element to a frame (see 7.3.2.1).
        !           632:  */
        !           633: u_int8_t *
        !           634: ieee80211_add_ssid(u_int8_t *frm, const u_int8_t *ssid, u_int len)
        !           635: {
        !           636:        *frm++ = IEEE80211_ELEMID_SSID;
        !           637:        *frm++ = len;
        !           638:        memcpy(frm, ssid, len);
        !           639:        return frm + len;
        !           640: }
        !           641:
        !           642: /*
        !           643:  * Add a supported rates element to a frame (see 7.3.2.2).
        !           644:  */
        !           645: u_int8_t *
        !           646: ieee80211_add_rates(u_int8_t *frm, const struct ieee80211_rateset *rs)
        !           647: {
        !           648:        int nrates;
        !           649:
        !           650:        *frm++ = IEEE80211_ELEMID_RATES;
        !           651:        nrates = min(rs->rs_nrates, IEEE80211_RATE_SIZE);
        !           652:        *frm++ = nrates;
        !           653:        memcpy(frm, rs->rs_rates, nrates);
        !           654:        return frm + nrates;
        !           655: }
        !           656:
        !           657: /*
        !           658:  * Add a FH Parameter Set element to a frame (see 7.3.2.3).
        !           659:  */
        !           660: u_int8_t *
        !           661: ieee80211_add_fh_params(u_int8_t *frm, struct ieee80211com *ic,
        !           662:     const struct ieee80211_node *ni)
        !           663: {
        !           664:        u_int chan = ieee80211_chan2ieee(ic, ni->ni_chan);
        !           665:
        !           666:        *frm++ = IEEE80211_ELEMID_FHPARMS;
        !           667:        *frm++ = 5;
        !           668:        LE_WRITE_2(frm, ni->ni_fhdwell); frm += 2;
        !           669:        *frm++ = IEEE80211_FH_CHANSET(chan);
        !           670:        *frm++ = IEEE80211_FH_CHANPAT(chan);
        !           671:        *frm++ = ni->ni_fhindex;
        !           672:        return frm;
        !           673: }
        !           674:
        !           675: /*
        !           676:  * Add a DS Parameter Set element to a frame (see 7.3.2.4).
        !           677:  */
        !           678: u_int8_t *
        !           679: ieee80211_add_ds_params(u_int8_t *frm, struct ieee80211com *ic,
        !           680:     const struct ieee80211_node *ni)
        !           681: {
        !           682:        *frm++ = IEEE80211_ELEMID_DSPARMS;
        !           683:        *frm++ = 1;
        !           684:        *frm++ = ieee80211_chan2ieee(ic, ni->ni_chan);
        !           685:        return frm;
        !           686: }
        !           687:
        !           688: /*
        !           689:  * Add a TIM element to a frame (see 7.3.2.6 and Annex L).
        !           690:  */
        !           691: u_int8_t *
        !           692: ieee80211_add_tim(u_int8_t *frm, struct ieee80211com *ic)
        !           693: {
        !           694:        u_int i, offset = 0, len;
        !           695:
        !           696:        /* find first non-zero octet in the virtual bit map */
        !           697:        for (i = 0; i < ic->ic_tim_len && ic->ic_tim_bitmap[i] == 0; i++);
        !           698:
        !           699:        /* clear the lsb as it is reserved for the broadcast indication bit */
        !           700:        if (i < ic->ic_tim_len)
        !           701:                offset = i & ~1;
        !           702:
        !           703:        /* find last non-zero octet in the virtual bit map */
        !           704:        for (i = ic->ic_tim_len - 1; i > 0 && ic->ic_tim_bitmap[i] == 0; i--);
        !           705:
        !           706:        len = i - offset + 1;
        !           707:
        !           708:        *frm++ = IEEE80211_ELEMID_TIM;
        !           709:        *frm++ = len + 3;               /* length */
        !           710:        *frm++ = ic->ic_dtim_count;     /* DTIM count */
        !           711:        *frm++ = ic->ic_dtim_period;    /* DTIM period */
        !           712:
        !           713:        /* Bitmap Control */
        !           714:        *frm = offset;
        !           715:        /* set broadcast/multicast indication bit if necessary */
        !           716:        if (ic->ic_dtim_count == 0 && ic->ic_tim_mcast)
        !           717:                *frm |= 0x01;
        !           718:        frm++;
        !           719:
        !           720:        /* Partial Virtual Bitmap */
        !           721:        memcpy(frm, &ic->ic_tim_bitmap[offset], len);
        !           722:        return frm + len;
        !           723: }
        !           724:
        !           725: /*
        !           726:  * Add an IBSS Parameter Set element to a frame (see 7.3.2.7).
        !           727:  */
        !           728: u_int8_t *
        !           729: ieee80211_add_ibss_params(u_int8_t *frm, const struct ieee80211_node *ni)
        !           730: {
        !           731:        *frm++ = IEEE80211_ELEMID_IBSSPARMS;
        !           732:        *frm++ = 2;
        !           733:        LE_WRITE_2(frm, 0);     /* TODO: ATIM window */
        !           734:        return frm + 2;
        !           735: }
        !           736:
        !           737: /*
        !           738:  * Add an EDCA Parameter Set element to a frame (see 7.3.2.29).
        !           739:  */
        !           740: u_int8_t *
        !           741: ieee80211_add_edca_params(u_int8_t *frm, struct ieee80211com *ic)
        !           742: {
        !           743:        const struct ieee80211_edca_ac_params *edca;
        !           744:        int aci;
        !           745:
        !           746:        *frm++ = IEEE80211_ELEMID_EDCAPARMS;
        !           747:        *frm++ = 18;    /* length */
        !           748:        *frm++ = 0;     /* QoS Info */
        !           749:        *frm++ = 0;     /* reserved */
        !           750:
        !           751:        /* setup AC Parameter Records */
        !           752:        edca = ieee80211_qap_edca_table[ic->ic_curmode];
        !           753:        for (aci = 0; aci < EDCA_NUM_AC; aci++) {
        !           754:                const struct ieee80211_edca_ac_params *ac = &edca[aci];
        !           755:
        !           756:                *frm++ = (aci << 5) | ((ac->ac_acm & 0x1) << 4) |
        !           757:                         (ac->ac_aifsn & 0xf);
        !           758:                *frm++ = (ac->ac_ecwmax << 4) |
        !           759:                         (ac->ac_ecwmin & 0xf);
        !           760:                LE_WRITE_2(frm, ac->ac_txoplimit); frm += 2;
        !           761:        }
        !           762:        return frm;
        !           763: }
        !           764:
        !           765: /*
        !           766:  * Add an ERP element to a frame (see 7.3.2.13).
        !           767:  */
        !           768: u_int8_t *
        !           769: ieee80211_add_erp(u_int8_t *frm, struct ieee80211com *ic)
        !           770: {
        !           771:        u_int8_t erp;
        !           772:
        !           773:        *frm++ = IEEE80211_ELEMID_ERP;
        !           774:        *frm++ = 1;
        !           775:        erp = 0;
        !           776:        /*
        !           777:         * The NonERP_Present bit shall be set to 1 when a NonERP STA
        !           778:         * is associated with the BSS.
        !           779:         */
        !           780:        if (ic->ic_nonerpsta != 0)
        !           781:                erp |= IEEE80211_ERP_NON_ERP_PRESENT;
        !           782:        /*
        !           783:         * If one or more NonERP STAs are associated in the BSS, the
        !           784:         * Use_Protection bit shall be set to 1 in transmitted ERP
        !           785:         * Information Elements.
        !           786:         */
        !           787:        if (ic->ic_flags & IEEE80211_F_USEPROT)
        !           788:                erp |= IEEE80211_ERP_USE_PROTECTION;
        !           789:        /*
        !           790:         * The Barker_Preamble_Mode bit shall be set to 1 by the ERP
        !           791:         * Information Element sender if one or more associated NonERP
        !           792:         * STAs are not short preamble capable.
        !           793:         */
        !           794:        if (!(ic->ic_flags & IEEE80211_F_SHPREAMBLE))
        !           795:                erp |= IEEE80211_ERP_BARKER_MODE;
        !           796:        *frm++ = erp;
        !           797:        return frm;
        !           798: }
        !           799:
        !           800: /*
        !           801:  * Add a QoS Capability element to a frame (see 7.3.2.35).
        !           802:  */
        !           803: u_int8_t *
        !           804: ieee80211_add_qos_capability(u_int8_t *frm, struct ieee80211com *ic)
        !           805: {
        !           806:        *frm++ = IEEE80211_ELEMID_QOS_CAP;
        !           807:        *frm++ = 1;
        !           808:        *frm++ = 0;     /* QoS Info */
        !           809:        return frm;
        !           810: }
        !           811:
        !           812: /*
        !           813:  * Add an RSN element to a frame (see 7.3.2.25).
        !           814:  */
        !           815: u_int8_t *
        !           816: ieee80211_add_rsn_body(u_int8_t *frm, struct ieee80211com *ic,
        !           817:     const struct ieee80211_node *ni, int wpa1)
        !           818: {
        !           819:        const u_int8_t *oui = wpa1 ? MICROSOFT_OUI : IEEE80211_OUI;
        !           820:        u_int8_t *pcount;
        !           821:        u_int16_t count;
        !           822:
        !           823:        /* write Version field */
        !           824:        LE_WRITE_2(frm, 1); frm += 2;
        !           825:
        !           826:        /* write Group Cipher Suite field (see Table 20da) */
        !           827:        memcpy(frm, oui, 3); frm += 3;
        !           828:        switch (ni->ni_group_cipher) {
        !           829:        case IEEE80211_CIPHER_USEGROUP:
        !           830:                /* can't get there */
        !           831:                panic("invalid group cipher!");
        !           832:                break;
        !           833:        case IEEE80211_CIPHER_WEP40:
        !           834:                *frm++ = 1;
        !           835:                break;
        !           836:        case IEEE80211_CIPHER_TKIP:
        !           837:                *frm++ = 2;
        !           838:                break;
        !           839:        case IEEE80211_CIPHER_CCMP:
        !           840:                *frm++ = 4;
        !           841:                break;
        !           842:        case IEEE80211_CIPHER_WEP104:
        !           843:                *frm++ = 5;
        !           844:                break;
        !           845:        }
        !           846:
        !           847:        pcount = frm; frm += 2;
        !           848:        count = 0;
        !           849:        /* write Pairwise Cipher Suite List */
        !           850:        if (ni->ni_pairwise_cipherset & IEEE80211_CIPHER_USEGROUP) {
        !           851:                memcpy(frm, oui, 3); frm += 3;
        !           852:                *frm++ = 0;
        !           853:                count++;
        !           854:        }
        !           855:        if (ni->ni_pairwise_cipherset & IEEE80211_CIPHER_TKIP) {
        !           856:                memcpy(frm, oui, 3); frm += 3;
        !           857:                *frm++ = 2;
        !           858:                count++;
        !           859:        }
        !           860:        if (ni->ni_pairwise_cipherset & IEEE80211_CIPHER_CCMP) {
        !           861:                memcpy(frm, oui, 3); frm += 3;
        !           862:                *frm++ = 4;
        !           863:                count++;
        !           864:        }
        !           865:        /* write Pairwise Cipher Suite Count field */
        !           866:        LE_WRITE_2(pcount, count);
        !           867:
        !           868:        pcount = frm; frm += 2;
        !           869:        count = 0;
        !           870:        /* write AKM Suite List (see Table 20dc) */
        !           871:        if (ni->ni_akmset & IEEE80211_AKM_IEEE8021X) {
        !           872:                memcpy(frm, oui, 3); frm += 3;
        !           873:                *frm++ = 1;
        !           874:                count++;
        !           875:        }
        !           876:        if (ni->ni_akmset & IEEE80211_AKM_PSK) {
        !           877:                memcpy(frm, oui, 3); frm += 3;
        !           878:                *frm++ = 2;
        !           879:                count++;
        !           880:        }
        !           881:        /* write AKM Suite List Count field */
        !           882:        LE_WRITE_2(pcount, count);
        !           883:
        !           884:        /* write RSN Capabilities field */
        !           885:        LE_WRITE_2(frm, ni->ni_rsncaps); frm += 2;
        !           886:
        !           887:        /* no PMKID List for now */
        !           888:
        !           889:        return frm;
        !           890: }
        !           891:
        !           892: u_int8_t *
        !           893: ieee80211_add_rsn(u_int8_t *frm, struct ieee80211com *ic,
        !           894:     const struct ieee80211_node *ni)
        !           895: {
        !           896:        u_int8_t *plen;
        !           897:
        !           898:        *frm++ = IEEE80211_ELEMID_RSN;
        !           899:        plen = frm++;   /* length filled in later */
        !           900:        frm = ieee80211_add_rsn_body(frm, ic, ni, 0);
        !           901:
        !           902:        /* write length field */
        !           903:        *plen = frm - plen - 1;
        !           904:        return frm;
        !           905: }
        !           906:
        !           907: /*
        !           908:  * Add a vendor specific WPA1 element to a frame.
        !           909:  * This is required for compatibility with Wi-Fi Alliance WPA1/WPA1+WPA2.
        !           910:  */
        !           911: u_int8_t *
        !           912: ieee80211_add_wpa1(u_int8_t *frm, struct ieee80211com *ic,
        !           913:     const struct ieee80211_node *ni)
        !           914: {
        !           915:        u_int8_t *plen;
        !           916:
        !           917:        *frm++ = IEEE80211_ELEMID_VENDOR;
        !           918:        plen = frm++;   /* length filled in later */
        !           919:        memcpy(frm, MICROSOFT_OUI, 3); frm += 3;
        !           920:        *frm++ = 1;     /* WPA1 */
        !           921:        frm = ieee80211_add_rsn_body(frm, ic, ni, 1);
        !           922:
        !           923:        /* write length field */
        !           924:        *plen = frm - plen - 1;
        !           925:        return frm;
        !           926: }
        !           927:
        !           928: /*
        !           929:  * Add an extended supported rates element to a frame (see 7.3.2.14).
        !           930:  */
        !           931: u_int8_t *
        !           932: ieee80211_add_xrates(u_int8_t *frm, const struct ieee80211_rateset *rs)
        !           933: {
        !           934:        int nrates;
        !           935:
        !           936:        KASSERT(rs->rs_nrates > IEEE80211_RATE_SIZE);
        !           937:
        !           938:        *frm++ = IEEE80211_ELEMID_XRATES;
        !           939:        nrates = rs->rs_nrates - IEEE80211_RATE_SIZE;
        !           940:        *frm++ = nrates;
        !           941:        memcpy(frm, rs->rs_rates + IEEE80211_RATE_SIZE, nrates);
        !           942:        return frm + nrates;
        !           943: }
        !           944:
        !           945: struct mbuf *
        !           946: ieee80211_getmbuf(int flags, int type, u_int pktlen)
        !           947: {
        !           948:        struct mbuf *m;
        !           949:
        !           950:        /* account for 802.11 header */
        !           951:        pktlen += sizeof(struct ieee80211_frame);
        !           952:
        !           953:        if (pktlen > MCLBYTES)
        !           954:                panic("802.11 packet too large: %u", pktlen);
        !           955:        MGETHDR(m, flags, type);
        !           956:        if (m != NULL && pktlen > MHLEN) {
        !           957:                MCLGET(m, flags);
        !           958:                if (!(m->m_flags & M_EXT))
        !           959:                        m = m_free(m);
        !           960:        }
        !           961:        return m;
        !           962: }
        !           963:
        !           964: /*-
        !           965:  * Probe request frame format:
        !           966:  * [tlv] SSID
        !           967:  * [tlv] Supported rates
        !           968:  * [tlv] Extended Supported Rates (802.11g)
        !           969:  */
        !           970: struct mbuf *
        !           971: ieee80211_get_probe_req(struct ieee80211com *ic, struct ieee80211_node *ni)
        !           972: {
        !           973:        const struct ieee80211_rateset *rs =
        !           974:            &ic->ic_sup_rates[ieee80211_chan2mode(ic, ni->ni_chan)];
        !           975:        struct mbuf *m;
        !           976:        u_int8_t *frm;
        !           977:
        !           978:        m = ieee80211_getmbuf(M_DONTWAIT, MT_DATA,
        !           979:            2 + ic->ic_des_esslen +
        !           980:            2 + min(rs->rs_nrates, IEEE80211_RATE_SIZE) +
        !           981:            ((rs->rs_nrates > IEEE80211_RATE_SIZE) ?
        !           982:                2 + rs->rs_nrates - IEEE80211_RATE_SIZE : 0));
        !           983:        if (m == NULL)
        !           984:                return NULL;
        !           985:
        !           986:        m->m_data += sizeof(struct ieee80211_frame);
        !           987:
        !           988:        frm = mtod(m, u_int8_t *);
        !           989:        frm = ieee80211_add_ssid(frm, ic->ic_des_essid, ic->ic_des_esslen);
        !           990:        frm = ieee80211_add_rates(frm, rs);
        !           991:        if (rs->rs_nrates > IEEE80211_RATE_SIZE)
        !           992:                frm = ieee80211_add_xrates(frm, rs);
        !           993:
        !           994:        m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);
        !           995:
        !           996:        return m;
        !           997: }
        !           998:
        !           999: /*-
        !          1000:  * Probe response frame format:
        !          1001:  * [8]    Timestamp
        !          1002:  * [2]    Beacon interval
        !          1003:  * [2]    Capability
        !          1004:  * [tlv]  Service Set Identifier (SSID)
        !          1005:  * [tlv]  Supported rates
        !          1006:  * [tlv*] Frequency-Hopping (FH) Parameter Set
        !          1007:  * [tlv*] DS Parameter Set (802.11g)
        !          1008:  * [tlv]  ERP Information (802.11g)
        !          1009:  * [tlv]  Extended Supported Rates (802.11g)
        !          1010:  * [tlv]  RSN (802.11i)
        !          1011:  * [tlv]  EDCA Parameter Set (802.11e)
        !          1012:  */
        !          1013: struct mbuf *
        !          1014: ieee80211_get_probe_resp(struct ieee80211com *ic, struct ieee80211_node *ni)
        !          1015: {
        !          1016:        const struct ieee80211_rateset *rs = &ic->ic_bss->ni_rates;
        !          1017:        struct mbuf *m;
        !          1018:        u_int8_t *frm;
        !          1019:
        !          1020:        m = ieee80211_getmbuf(M_DONTWAIT, MT_DATA,
        !          1021:            8 + 2 + 2 +
        !          1022:            2 + ni->ni_esslen +
        !          1023:            2 + min(rs->rs_nrates, IEEE80211_RATE_SIZE) +
        !          1024:            2 + ((ic->ic_phytype == IEEE80211_T_FH) ? 5 : 1) +
        !          1025:            ((ic->ic_opmode == IEEE80211_M_IBSS) ? 2 + 2 : 0) +
        !          1026:            ((ic->ic_curmode == IEEE80211_MODE_11G) ? 2 + 1 : 0) +
        !          1027:            ((rs->rs_nrates > IEEE80211_RATE_SIZE) ?
        !          1028:                2 + rs->rs_nrates - IEEE80211_RATE_SIZE : 0) +
        !          1029:            ((ic->ic_flags & IEEE80211_F_RSN) ? 2 + 44 : 0) +
        !          1030:            ((ic->ic_flags & IEEE80211_F_QOS) ? 2 + 18 : 0) +
        !          1031:            ((ic->ic_flags & IEEE80211_F_WPA1) ? 2 + 48 : 0));
        !          1032:        if (m == NULL)
        !          1033:                return NULL;
        !          1034:
        !          1035:        m->m_data += sizeof(struct ieee80211_frame);
        !          1036:
        !          1037:        frm = mtod(m, u_int8_t *);
        !          1038:        memset(frm, 0, 8); frm += 8;    /* timestamp is set by hardware */
        !          1039:        LE_WRITE_2(frm, ic->ic_bss->ni_intval); frm += 2;
        !          1040:        frm = ieee80211_add_capinfo(frm, ic, ni);
        !          1041:        frm = ieee80211_add_ssid(frm, ic->ic_bss->ni_essid,
        !          1042:            ic->ic_bss->ni_esslen);
        !          1043:        frm = ieee80211_add_rates(frm, rs);
        !          1044:        if (ic->ic_phytype == IEEE80211_T_FH)
        !          1045:                frm = ieee80211_add_fh_params(frm, ic, ni);
        !          1046:        else
        !          1047:                frm = ieee80211_add_ds_params(frm, ic, ni);
        !          1048:        if (ic->ic_opmode == IEEE80211_M_IBSS)
        !          1049:                frm = ieee80211_add_ibss_params(frm, ni);
        !          1050:        if (ic->ic_curmode == IEEE80211_MODE_11G)
        !          1051:                frm = ieee80211_add_erp(frm, ic);
        !          1052:        if (rs->rs_nrates > IEEE80211_RATE_SIZE)
        !          1053:                frm = ieee80211_add_xrates(frm, rs);
        !          1054:        if (ic->ic_flags & IEEE80211_F_RSN)
        !          1055:                frm = ieee80211_add_rsn(frm, ic, ic->ic_bss);
        !          1056:        if (ic->ic_flags & IEEE80211_F_QOS)
        !          1057:                frm = ieee80211_add_edca_params(frm, ic);
        !          1058:        if (ic->ic_flags & IEEE80211_F_WPA1)
        !          1059:                frm = ieee80211_add_wpa1(frm, ic, ic->ic_bss);
        !          1060:
        !          1061:        m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);
        !          1062:
        !          1063:        return m;
        !          1064: }
        !          1065:
        !          1066: /*-
        !          1067:  * Authentication frame format:
        !          1068:  * [2] Authentication algorithm number
        !          1069:  * [2] Authentication transaction sequence number
        !          1070:  * [2] Status code
        !          1071:  */
        !          1072: struct mbuf *
        !          1073: ieee80211_get_auth(struct ieee80211com *ic, struct ieee80211_node *ni,
        !          1074:     u_int16_t status, u_int16_t seq)
        !          1075: {
        !          1076:        struct mbuf *m;
        !          1077:        u_int8_t *frm;
        !          1078:
        !          1079:        MGETHDR(m, M_DONTWAIT, MT_DATA);
        !          1080:        if (m == NULL)
        !          1081:                return NULL;
        !          1082:        MH_ALIGN(m, 2 * 3);
        !          1083:        m->m_pkthdr.len = m->m_len = 2 * 3;
        !          1084:
        !          1085:        frm = mtod(m, u_int8_t *);
        !          1086:        LE_WRITE_2(frm, IEEE80211_AUTH_ALG_OPEN); frm += 2;
        !          1087:        LE_WRITE_2(frm, seq); frm += 2;
        !          1088:        LE_WRITE_2(frm, status);
        !          1089:
        !          1090:        return m;
        !          1091: }
        !          1092:
        !          1093: /*-
        !          1094:  * Deauthentication frame format:
        !          1095:  * [2] Reason code
        !          1096:  */
        !          1097: struct mbuf *
        !          1098: ieee80211_get_deauth(struct ieee80211com *ic, struct ieee80211_node *ni,
        !          1099:     u_int16_t reason)
        !          1100: {
        !          1101:        struct mbuf *m;
        !          1102:
        !          1103:        MGETHDR(m, M_DONTWAIT, MT_DATA);
        !          1104:        if (m == NULL)
        !          1105:                return NULL;
        !          1106:        MH_ALIGN(m, 2);
        !          1107:
        !          1108:        m->m_pkthdr.len = m->m_len = 2;
        !          1109:        *mtod(m, u_int16_t *) = htole16(reason);
        !          1110:
        !          1111:        return m;
        !          1112: }
        !          1113:
        !          1114: /*-
        !          1115:  * (Re)Association request frame format:
        !          1116:  * [2]   Capability information
        !          1117:  * [2]   Listen interval
        !          1118:  * [6*]  Current AP address (Reassociation only)
        !          1119:  * [tlv] SSID
        !          1120:  * [tlv] Supported rates
        !          1121:  * [tlv] Extended Supported Rates (802.11g)
        !          1122:  * [tlv] RSN (802.11i)
        !          1123:  * [tlv] QoS Capability (802.11e)
        !          1124:  */
        !          1125: struct mbuf *
        !          1126: ieee80211_get_assoc_req(struct ieee80211com *ic, struct ieee80211_node *ni,
        !          1127:     int reassoc)
        !          1128: {
        !          1129:        const struct ieee80211_rateset *rs = &ni->ni_rates;
        !          1130:        struct mbuf *m;
        !          1131:        u_int8_t *frm;
        !          1132:        u_int16_t capinfo;
        !          1133:
        !          1134:        m = ieee80211_getmbuf(M_DONTWAIT, MT_DATA,
        !          1135:            2 + 2 +
        !          1136:            ((reassoc == IEEE80211_FC0_SUBTYPE_REASSOC_REQ) ?
        !          1137:                IEEE80211_ADDR_LEN : 0) +
        !          1138:            2 + ni->ni_esslen +
        !          1139:            2 + min(rs->rs_nrates, IEEE80211_RATE_SIZE) +
        !          1140:            ((rs->rs_nrates > IEEE80211_RATE_SIZE) ?
        !          1141:                2 + rs->rs_nrates - IEEE80211_RATE_SIZE : 0) +
        !          1142:            ((ic->ic_flags & IEEE80211_F_RSN) ? 2 + 44 : 0) +
        !          1143:            ((ic->ic_flags & IEEE80211_F_QOS) ? 2 + 1 : 0) +
        !          1144:            ((ic->ic_flags & IEEE80211_F_WPA1) ? 2 + 48 : 0));
        !          1145:        if (m == NULL)
        !          1146:                return NULL;
        !          1147:
        !          1148:        m->m_data += sizeof(struct ieee80211_frame);
        !          1149:
        !          1150:        frm = mtod(m, u_int8_t *);
        !          1151:        capinfo = IEEE80211_CAPINFO_ESS;
        !          1152:        if (ic->ic_flags & IEEE80211_F_WEPON)
        !          1153:                capinfo |= IEEE80211_CAPINFO_PRIVACY;
        !          1154:        if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
        !          1155:            IEEE80211_IS_CHAN_2GHZ(ni->ni_chan))
        !          1156:                capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE;
        !          1157:        if ((ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME) &&
        !          1158:            (ic->ic_flags & IEEE80211_F_SHSLOT))
        !          1159:                capinfo |= IEEE80211_CAPINFO_SHORT_SLOTTIME;
        !          1160:        LE_WRITE_2(frm, capinfo); frm += 2;
        !          1161:        LE_WRITE_2(frm, ic->ic_lintval); frm += 2;
        !          1162:        if (reassoc == IEEE80211_FC0_SUBTYPE_REASSOC_REQ) {
        !          1163:                IEEE80211_ADDR_COPY(frm, ic->ic_bss->ni_bssid);
        !          1164:                frm += IEEE80211_ADDR_LEN;
        !          1165:        }
        !          1166:        frm = ieee80211_add_ssid(frm, ni->ni_essid, ni->ni_esslen);
        !          1167:        frm = ieee80211_add_rates(frm, rs);
        !          1168:        if (rs->rs_nrates > IEEE80211_RATE_SIZE)
        !          1169:                frm = ieee80211_add_xrates(frm, rs);
        !          1170:        if (ic->ic_flags & IEEE80211_F_RSN)
        !          1171:                frm = ieee80211_add_rsn(frm, ic, ic->ic_bss);
        !          1172:        if ((ic->ic_flags & IEEE80211_F_QOS) &&
        !          1173:            (ni->ni_flags & IEEE80211_NODE_QOS))
        !          1174:                frm = ieee80211_add_qos_capability(frm, ic);
        !          1175:        if (ic->ic_flags & IEEE80211_F_WPA1)
        !          1176:                frm = ieee80211_add_wpa1(frm, ic, ic->ic_bss);
        !          1177:
        !          1178:        m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);
        !          1179:
        !          1180:        return m;
        !          1181: }
        !          1182:
        !          1183: /*-
        !          1184:  * (Re)Association response frame format:
        !          1185:  * [2]   Capability information
        !          1186:  * [2]   Status code
        !          1187:  * [2]   Association ID (AID)
        !          1188:  * [tlv] Supported rates
        !          1189:  * [tlv] Extended Supported Rates (802.11g)
        !          1190:  * [tlv] EDCA Parameter Set (802.11e)
        !          1191:  */
        !          1192: struct mbuf *
        !          1193: ieee80211_get_assoc_resp(struct ieee80211com *ic, struct ieee80211_node *ni,
        !          1194:     u_int16_t status)
        !          1195: {
        !          1196:        const struct ieee80211_rateset *rs = &ni->ni_rates;
        !          1197:        struct mbuf *m;
        !          1198:        u_int8_t *frm;
        !          1199:
        !          1200:        m = ieee80211_getmbuf(M_DONTWAIT, MT_DATA,
        !          1201:            2 + 2 + 2 +
        !          1202:            2 + min(rs->rs_nrates, IEEE80211_RATE_SIZE) +
        !          1203:            ((rs->rs_nrates > IEEE80211_RATE_SIZE) ?
        !          1204:                2 + rs->rs_nrates - IEEE80211_RATE_SIZE : 0) +
        !          1205:            ((ic->ic_flags & IEEE80211_F_QOS) ? 2 + 18 : 0));
        !          1206:        if (m == NULL)
        !          1207:                return NULL;
        !          1208:
        !          1209:        m->m_data += sizeof(struct ieee80211_frame);
        !          1210:
        !          1211:        frm = mtod(m, u_int8_t *);
        !          1212:        frm = ieee80211_add_capinfo(frm, ic, ni);
        !          1213:        LE_WRITE_2(frm, status); frm += 2;
        !          1214:        if (status == IEEE80211_STATUS_SUCCESS)
        !          1215:                LE_WRITE_2(frm, ni->ni_associd);
        !          1216:        else
        !          1217:                LE_WRITE_2(frm, 0);
        !          1218:        frm += 2;
        !          1219:        frm = ieee80211_add_rates(frm, rs);
        !          1220:        if (rs->rs_nrates > IEEE80211_RATE_SIZE)
        !          1221:                frm = ieee80211_add_xrates(frm, rs);
        !          1222:        if ((ic->ic_flags & IEEE80211_F_QOS) &&
        !          1223:            (ni->ni_flags & IEEE80211_NODE_QOS))
        !          1224:                frm = ieee80211_add_edca_params(frm, ic);
        !          1225:
        !          1226:        m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);
        !          1227:
        !          1228:        return m;
        !          1229: }
        !          1230:
        !          1231: /*-
        !          1232:  * Disassociation frame format:
        !          1233:  * [2] Reason code
        !          1234:  */
        !          1235: struct mbuf *
        !          1236: ieee80211_get_disassoc(struct ieee80211com *ic, struct ieee80211_node *ni,
        !          1237:     u_int16_t reason)
        !          1238: {
        !          1239:        struct mbuf *m;
        !          1240:
        !          1241:        MGETHDR(m, M_DONTWAIT, MT_DATA);
        !          1242:        if (m == NULL)
        !          1243:                return NULL;
        !          1244:        MH_ALIGN(m, 2);
        !          1245:
        !          1246:        m->m_pkthdr.len = m->m_len = 2;
        !          1247:        *mtod(m, u_int16_t *) = htole16(reason);
        !          1248:
        !          1249:        return m;
        !          1250: }
        !          1251:
        !          1252: /*
        !          1253:  * Send a management frame.  The node is for the destination (or ic_bss
        !          1254:  * when in station mode).  Nodes other than ic_bss have their reference
        !          1255:  * count bumped to reflect our use for an indeterminant time.
        !          1256:  */
        !          1257: int
        !          1258: ieee80211_send_mgmt(struct ieee80211com *ic, struct ieee80211_node *ni,
        !          1259:     int type, int arg)
        !          1260: {
        !          1261: #define        senderr(_x, _v) do { ic->ic_stats._v++; ret = _x; goto bad; } while (0)
        !          1262:        struct ifnet *ifp = &ic->ic_if;
        !          1263:        struct mbuf *m;
        !          1264:        int ret, timer;
        !          1265:
        !          1266:        if (ni == NULL)
        !          1267:                panic("null node");
        !          1268:
        !          1269:        /*
        !          1270:         * Hold a reference on the node so it doesn't go away until after
        !          1271:         * the xmit is complete all the way in the driver.  On error we
        !          1272:         * will remove our reference.
        !          1273:         */
        !          1274:        ieee80211_ref_node(ni);
        !          1275:        timer = 0;
        !          1276:        switch (type) {
        !          1277:        case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
        !          1278:                if ((m = ieee80211_get_probe_req(ic, ni)) == NULL)
        !          1279:                        senderr(ENOMEM, is_tx_nombuf);
        !          1280:
        !          1281:                timer = IEEE80211_TRANS_WAIT;
        !          1282:                break;
        !          1283:
        !          1284:        case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
        !          1285:                if ((m = ieee80211_get_probe_resp(ic, ni)) == NULL)
        !          1286:                        senderr(ENOMEM, is_tx_nombuf);
        !          1287:                break;
        !          1288:
        !          1289:        case IEEE80211_FC0_SUBTYPE_AUTH:
        !          1290:                m = ieee80211_get_auth(ic, ni, arg >> 16, arg & 0xffff);
        !          1291:                if (m == NULL)
        !          1292:                        senderr(ENOMEM, is_tx_nombuf);
        !          1293:
        !          1294:                if (ic->ic_opmode == IEEE80211_M_STA)
        !          1295:                        timer = IEEE80211_TRANS_WAIT;
        !          1296:                break;
        !          1297:
        !          1298:        case IEEE80211_FC0_SUBTYPE_DEAUTH:
        !          1299:                if ((m = ieee80211_get_deauth(ic, ni, arg)) == NULL)
        !          1300:                        senderr(ENOMEM, is_tx_nombuf);
        !          1301:
        !          1302:                if (ifp->if_flags & IFF_DEBUG) {
        !          1303:                        printf("%s: station %s deauthenticate (reason %d)\n",
        !          1304:                            ifp->if_xname, ether_sprintf(ni->ni_macaddr), arg);
        !          1305:                }
        !          1306:                break;
        !          1307:
        !          1308:        case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
        !          1309:        case IEEE80211_FC0_SUBTYPE_REASSOC_REQ:
        !          1310:                if ((m = ieee80211_get_assoc_req(ic, ni, type)) == NULL)
        !          1311:                        senderr(ENOMEM, is_tx_nombuf);
        !          1312:
        !          1313:                timer = IEEE80211_TRANS_WAIT;
        !          1314:                break;
        !          1315:
        !          1316:        case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
        !          1317:        case IEEE80211_FC0_SUBTYPE_REASSOC_RESP:
        !          1318:                if ((m = ieee80211_get_assoc_resp(ic, ni, arg)) == NULL)
        !          1319:                        senderr(ENOMEM, is_tx_nombuf);
        !          1320:                break;
        !          1321:
        !          1322:        case IEEE80211_FC0_SUBTYPE_DISASSOC:
        !          1323:                if ((m = ieee80211_get_disassoc(ic, ni, arg)) == NULL)
        !          1324:                        senderr(ENOMEM, is_tx_nombuf);
        !          1325:
        !          1326:                if (ifp->if_flags & IFF_DEBUG) {
        !          1327:                        printf("%s: station %s disassociate (reason %d)\n",
        !          1328:                            ifp->if_xname, ether_sprintf(ni->ni_macaddr), arg);
        !          1329:                }
        !          1330:                break;
        !          1331:
        !          1332:        default:
        !          1333:                IEEE80211_DPRINTF(("%s: invalid mgmt frame type %u\n",
        !          1334:                    __func__, type));
        !          1335:                senderr(EINVAL, is_tx_unknownmgt);
        !          1336:                /* NOTREACHED */
        !          1337:        }
        !          1338:
        !          1339:        ret = ieee80211_mgmt_output(ifp, ni, m, type);
        !          1340:        if (ret == 0) {
        !          1341:                if (timer)
        !          1342:                        ic->ic_mgt_timer = timer;
        !          1343:        } else {
        !          1344: bad:
        !          1345:                ieee80211_release_node(ic, ni);
        !          1346:        }
        !          1347:        return ret;
        !          1348: #undef senderr
        !          1349: }
        !          1350:
        !          1351: /*
        !          1352:  * Build a RTS (Request To Send) control frame (see 7.2.1.1).
        !          1353:  */
        !          1354: struct mbuf *
        !          1355: ieee80211_get_rts(struct ieee80211com *ic, const struct ieee80211_frame *wh,
        !          1356:     u_int16_t dur)
        !          1357: {
        !          1358:        struct ieee80211_frame_rts *rts;
        !          1359:        struct mbuf *m;
        !          1360:
        !          1361:        MGETHDR(m, M_DONTWAIT, MT_DATA);
        !          1362:        if (m == NULL)
        !          1363:                return NULL;
        !          1364:
        !          1365:        m->m_pkthdr.len = m->m_len = sizeof (struct ieee80211_frame_rts);
        !          1366:
        !          1367:        rts = mtod(m, struct ieee80211_frame_rts *);
        !          1368:        rts->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_CTL |
        !          1369:            IEEE80211_FC0_SUBTYPE_RTS;
        !          1370:        rts->i_fc[1] = IEEE80211_FC1_DIR_NODS;
        !          1371:        *(u_int16_t *)rts->i_dur = htole16(dur);
        !          1372:        IEEE80211_ADDR_COPY(rts->i_ra, wh->i_addr1);
        !          1373:        IEEE80211_ADDR_COPY(rts->i_ta, wh->i_addr2);
        !          1374:
        !          1375:        return m;
        !          1376: }
        !          1377:
        !          1378: /*
        !          1379:  * Build a CTS-to-self (Clear To Send) control frame (see 7.2.1.2).
        !          1380:  */
        !          1381: struct mbuf *
        !          1382: ieee80211_get_cts_to_self(struct ieee80211com *ic, u_int16_t dur)
        !          1383: {
        !          1384:        struct ieee80211_frame_cts *cts;
        !          1385:        struct mbuf *m;
        !          1386:
        !          1387:        MGETHDR(m, M_DONTWAIT, MT_DATA);
        !          1388:        if (m == NULL)
        !          1389:                return NULL;
        !          1390:
        !          1391:        m->m_pkthdr.len = m->m_len = sizeof (struct ieee80211_frame_cts);
        !          1392:
        !          1393:        cts = mtod(m, struct ieee80211_frame_cts *);
        !          1394:        cts->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_CTL |
        !          1395:            IEEE80211_FC0_SUBTYPE_CTS;
        !          1396:        cts->i_fc[1] = IEEE80211_FC1_DIR_NODS;
        !          1397:        *(u_int16_t *)cts->i_dur = htole16(dur);
        !          1398:        IEEE80211_ADDR_COPY(cts->i_ra, ic->ic_myaddr);
        !          1399:
        !          1400:        return m;
        !          1401: }
        !          1402:
        !          1403: /*-
        !          1404:  * Beacon frame format:
        !          1405:  * [8]    Timestamp
        !          1406:  * [2]    Beacon interval
        !          1407:  * [2]    Capability
        !          1408:  * [tlv]  Service Set Identifier (SSID)
        !          1409:  * [tlv]  Supported rates
        !          1410:  * [tlv*] Frequency-Hopping (FH) Parameter Set
        !          1411:  * [tlv*] DS Parameter Set (802.11g)
        !          1412:  * [tlv*] IBSS Parameter Set
        !          1413:  * [tlv]  Traffic Indication Map (TIM)
        !          1414:  * [tlv]  ERP Information (802.11g)
        !          1415:  * [tlv]  Extended Supported Rates (802.11g)
        !          1416:  * [tlv]  RSN (802.11i)
        !          1417:  * [tlv]  EDCA Parameter Set (802.11e)
        !          1418:  */
        !          1419: struct mbuf *
        !          1420: ieee80211_beacon_alloc(struct ieee80211com *ic, struct ieee80211_node *ni)
        !          1421: {
        !          1422:        const struct ieee80211_rateset *rs = &ni->ni_rates;
        !          1423:        struct ieee80211_frame *wh;
        !          1424:        struct mbuf *m;
        !          1425:        u_int8_t *frm;
        !          1426:
        !          1427:        m = ieee80211_getmbuf(M_DONTWAIT, MT_DATA,
        !          1428:            8 + 2 + 2 +
        !          1429:            2 + ((ic->ic_flags & IEEE80211_F_HIDENWID) ? 0 : ni->ni_esslen) +
        !          1430:            2 + min(rs->rs_nrates, IEEE80211_RATE_SIZE) +
        !          1431:            2 + ((ic->ic_phytype == IEEE80211_T_FH) ? 5 : 1) +
        !          1432:            2 + ((ic->ic_opmode == IEEE80211_M_IBSS) ? 2 : 254) +
        !          1433:            ((ic->ic_curmode == IEEE80211_MODE_11G) ? 2 + 1 : 0) +
        !          1434:            ((rs->rs_nrates > IEEE80211_RATE_SIZE) ?
        !          1435:                2 + rs->rs_nrates - IEEE80211_RATE_SIZE : 0) +
        !          1436:            ((ic->ic_flags & IEEE80211_F_RSN) ? 2 + 44 : 0) +
        !          1437:            ((ic->ic_flags & IEEE80211_F_QOS) ? 2 + 18 : 0) +
        !          1438:            ((ic->ic_flags & IEEE80211_F_WPA1) ? 2 + 48 : 0));
        !          1439:        if (m == NULL)
        !          1440:                return NULL;
        !          1441:
        !          1442:        wh = mtod(m, struct ieee80211_frame *);
        !          1443:        wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT |
        !          1444:            IEEE80211_FC0_SUBTYPE_BEACON;
        !          1445:        wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
        !          1446:        *(u_int16_t *)wh->i_dur = 0;
        !          1447:        IEEE80211_ADDR_COPY(wh->i_addr1, etherbroadcastaddr);
        !          1448:        IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_myaddr);
        !          1449:        IEEE80211_ADDR_COPY(wh->i_addr3, ni->ni_bssid);
        !          1450:        *(u_int16_t *)wh->i_seq = 0;
        !          1451:
        !          1452:        frm = (u_int8_t *)&wh[1];
        !          1453:        memset(frm, 0, 8); frm += 8;    /* timestamp is set by hardware */
        !          1454:        LE_WRITE_2(frm, ni->ni_intval); frm += 2;
        !          1455:        frm = ieee80211_add_capinfo(frm, ic, ni);
        !          1456:        if (ic->ic_flags & IEEE80211_F_HIDENWID)
        !          1457:                frm = ieee80211_add_ssid(frm, NULL, 0);
        !          1458:        else
        !          1459:                frm = ieee80211_add_ssid(frm, ni->ni_essid, ni->ni_esslen);
        !          1460:        frm = ieee80211_add_rates(frm, rs);
        !          1461:        if (ic->ic_phytype == IEEE80211_T_FH)
        !          1462:                frm = ieee80211_add_fh_params(frm, ic, ni);
        !          1463:        else
        !          1464:                frm = ieee80211_add_ds_params(frm, ic, ni);
        !          1465:        if (ic->ic_opmode == IEEE80211_M_IBSS)
        !          1466:                frm = ieee80211_add_ibss_params(frm, ni);
        !          1467:        else
        !          1468:                frm = ieee80211_add_tim(frm, ic);
        !          1469:        if (ic->ic_curmode == IEEE80211_MODE_11G)
        !          1470:                frm = ieee80211_add_erp(frm, ic);
        !          1471:        if (rs->rs_nrates > IEEE80211_RATE_SIZE)
        !          1472:                frm = ieee80211_add_xrates(frm, rs);
        !          1473:        if (ic->ic_flags & IEEE80211_F_RSN)
        !          1474:                frm = ieee80211_add_rsn(frm, ic, ni);
        !          1475:        if (ic->ic_flags & IEEE80211_F_QOS)
        !          1476:                frm = ieee80211_add_edca_params(frm, ic);
        !          1477:        if (ic->ic_flags & IEEE80211_F_WPA1)
        !          1478:                frm = ieee80211_add_wpa1(frm, ic, ni);
        !          1479:
        !          1480:        m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);
        !          1481:        m->m_pkthdr.rcvif = (void *)ni;
        !          1482:
        !          1483:        return m;
        !          1484: }
        !          1485:
        !          1486: /* unaligned big endian access */
        !          1487: #define BE_READ_2(p)                           \
        !          1488:        ((u_int16_t)(p)[0] << 8 | (u_int16_t)(p)[1])
        !          1489:
        !          1490: #define BE_WRITE_2(p, v) do {                  \
        !          1491:        (p)[0] = (v) >>  8; (p)[1] = (v);       \
        !          1492: } while (0)
        !          1493:
        !          1494: #define BE_WRITE_8(p, v) do {                  \
        !          1495:        (p)[0] = (v) >> 56; (p)[1] = (v) >> 48; \
        !          1496:        (p)[2] = (v) >> 40; (p)[3] = (v) >> 32; \
        !          1497:        (p)[4] = (v) >> 24; (p)[5] = (v) >> 16; \
        !          1498:        (p)[6] = (v) >>  8; (p)[7] = (v);       \
        !          1499: } while (0)
        !          1500:
        !          1501: /* unaligned little endian access */
        !          1502: #define LE_WRITE_8(p, v) do {                  \
        !          1503:        (p)[7] = (v) >> 56; (p)[6] = (v) >> 48; \
        !          1504:        (p)[5] = (v) >> 40; (p)[4] = (v) >> 32; \
        !          1505:        (p)[3] = (v) >> 24; (p)[2] = (v) >> 16; \
        !          1506:        (p)[1] = (v) >>  8; (p)[0] = (v);       \
        !          1507: } while (0)
        !          1508:
        !          1509: int
        !          1510: ieee80211_send_eapol_key(struct ieee80211com *ic, struct mbuf *m,
        !          1511:     struct ieee80211_node *ni)
        !          1512: {
        !          1513:        struct ifnet *ifp = &ic->ic_if;
        !          1514:        struct ether_header *eh;
        !          1515:        struct ieee80211_eapol_key *key;
        !          1516:        u_int16_t len, info;
        !          1517:        int s, error;
        !          1518:
        !          1519:        M_PREPEND(m, sizeof(struct ether_header), M_DONTWAIT);
        !          1520:        if (m == NULL)
        !          1521:                return ENOMEM;
        !          1522:        eh = mtod(m, struct ether_header *);
        !          1523:        eh->ether_type = htons(ETHERTYPE_PAE);
        !          1524:        IEEE80211_ADDR_COPY(eh->ether_shost, ic->ic_myaddr);
        !          1525:        IEEE80211_ADDR_COPY(eh->ether_dhost, ni->ni_macaddr);
        !          1526:
        !          1527:        key = (struct ieee80211_eapol_key *)&eh[1];
        !          1528:        key->version = EAPOL_VERSION;
        !          1529:        key->type = EAPOL_KEY;
        !          1530:        key->desc = ni->ni_eapol_desc;
        !          1531:
        !          1532:        info = BE_READ_2(key->info);
        !          1533:        /* use V2 descriptor only when pairwise cipher is CCMP */
        !          1534:        info |= (ni->ni_pairwise_cipher != IEEE80211_CIPHER_CCMP) ?
        !          1535:            EAPOL_KEY_DESC_V1 : EAPOL_KEY_DESC_V2;
        !          1536:        BE_WRITE_2(key->info, info);
        !          1537:
        !          1538:        len = m->m_len - sizeof(struct ether_header);
        !          1539:        BE_WRITE_2(key->paylen, len - sizeof(*key));
        !          1540:        BE_WRITE_2(key->len, len - 4);
        !          1541:
        !          1542:        KASSERT((info & (EAPOL_KEY_ENCRYPTED | EAPOL_KEY_KEYMIC)) == 0 ||
        !          1543:            ni->ni_ptk_ok);
        !          1544:
        !          1545:        if (info & EAPOL_KEY_ENCRYPTED)
        !          1546:                ieee80211_eapol_key_encrypt(ic, key, ni->ni_ptk.kek);
        !          1547:
        !          1548:        if (info & EAPOL_KEY_KEYMIC)
        !          1549:                ieee80211_eapol_key_mic(key, ni->ni_ptk.kck);
        !          1550:
        !          1551:        s = splnet();
        !          1552:        IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error);
        !          1553:        if (error) {
        !          1554:                splx(s);
        !          1555:                return error;
        !          1556:        }
        !          1557:        ifp->if_obytes += m->m_pkthdr.len;
        !          1558:        if ((ifp->if_flags & IFF_OACTIVE) == 0)
        !          1559:                (*ifp->if_start)(ifp);
        !          1560:        splx(s);
        !          1561:
        !          1562:        return 0;
        !          1563: }
        !          1564:
        !          1565: /*
        !          1566:  * Add a GTK KDE to an EAPOL-Key frame (see Figure 144).
        !          1567:  */
        !          1568: u_int8_t *
        !          1569: ieee80211_add_gtk_kde(u_int8_t *frm, const struct ieee80211_key *k)
        !          1570: {
        !          1571:        KASSERT(k->k_flags & IEEE80211_KEY_GROUP);
        !          1572:
        !          1573:        *frm++ = IEEE80211_ELEMID_VENDOR;
        !          1574:        *frm++ = 6 + k->k_len;
        !          1575:        memcpy(frm, IEEE80211_OUI, 3); frm += 3;
        !          1576:        *frm++ = IEEE80211_KDE_GTK;
        !          1577:        *frm = k->k_id & 3;
        !          1578:        if (k->k_flags & IEEE80211_KEY_TX)
        !          1579:                *frm |= 1 << 2; /* set the Tx bit */
        !          1580:        frm++;
        !          1581:        *frm++ = 0;     /* reserved */
        !          1582:        memcpy(frm, k->k_key, k->k_len);
        !          1583:        return frm + k->k_len;
        !          1584: }
        !          1585:
        !          1586: /*
        !          1587:  * Add a PMKID KDE to an EAPOL-Key frame (see Figure 146).
        !          1588:  */
        !          1589: u_int8_t *
        !          1590: ieee80211_add_pmkid_kde(u_int8_t *frm, const u_int8_t *pmkid)
        !          1591: {
        !          1592:        *frm++ = IEEE80211_ELEMID_VENDOR;
        !          1593:        *frm++ = 20;
        !          1594:        memcpy(frm, IEEE80211_OUI, 3); frm += 3;
        !          1595:        *frm++ = IEEE80211_KDE_PMKID;
        !          1596:        memcpy(frm, pmkid, IEEE80211_PMKID_LEN);
        !          1597:        return frm + IEEE80211_PMKID_LEN;
        !          1598: }
        !          1599:
        !          1600: struct mbuf *
        !          1601: ieee80211_get_eapol_key(int flags, int type, u_int pktlen)
        !          1602: {
        !          1603:        struct mbuf *m;
        !          1604:
        !          1605:        pktlen += sizeof(struct ether_header) +
        !          1606:            sizeof(struct ieee80211_eapol_key);
        !          1607:
        !          1608:        if (pktlen > MCLBYTES)
        !          1609:                panic("EAPOL-Key frame too large: %u", pktlen);
        !          1610:        MGETHDR(m, flags, type);
        !          1611:        if (m != NULL && pktlen > MHLEN) {
        !          1612:                MCLGET(m, flags);
        !          1613:                if (!(m->m_flags & M_EXT))
        !          1614:                        m = m_free(m);
        !          1615:        }
        !          1616:        m->m_data += sizeof(struct ether_header);
        !          1617:        return m;
        !          1618: }
        !          1619:
        !          1620: /*
        !          1621:  * 4-Way Handshake Message 1 is sent by the authenticator to the supplicant
        !          1622:  * (see 8.5.3.1).
        !          1623:  */
        !          1624: int
        !          1625: ieee80211_send_4way_msg1(struct ieee80211com *ic, struct ieee80211_node *ni)
        !          1626: {
        !          1627:        struct ieee80211_eapol_key *key;
        !          1628:        struct mbuf *m;
        !          1629:        u_int16_t info, keylen;
        !          1630:        u_int8_t *pmkid;
        !          1631:        u_int8_t *frm;
        !          1632:
        !          1633:        m = ieee80211_get_eapol_key(M_DONTWAIT, MT_DATA,
        !          1634:            (ni->ni_eapol_desc == EAPOL_KEY_DESC_IEEE80211) ? 2 + 20 : 0);
        !          1635:        if (m == NULL)
        !          1636:                return ENOMEM;
        !          1637:        key = mtod(m, struct ieee80211_eapol_key *);
        !          1638:        memset(key, 0, sizeof(*key));
        !          1639:
        !          1640:        info = EAPOL_KEY_PAIRWISE | EAPOL_KEY_KEYACK;
        !          1641:        BE_WRITE_2(key->info, info);
        !          1642:
        !          1643:        /* generate a new nonce ANonce */
        !          1644:        get_random_bytes(ni->ni_nonce, EAPOL_KEY_NONCE_LEN);
        !          1645:        memcpy(key->nonce, ni->ni_nonce, EAPOL_KEY_NONCE_LEN);
        !          1646:
        !          1647:        keylen = ieee80211_cipher_keylen(ni->ni_pairwise_cipher);
        !          1648:        BE_WRITE_2(key->keylen, keylen);
        !          1649:
        !          1650:        frm = (u_int8_t *)&key[1];
        !          1651:        /* WPA1 does not have PMKID KDE */
        !          1652:        if (ni->ni_eapol_desc == EAPOL_KEY_DESC_IEEE80211) {
        !          1653:                /* XXX retrieve PMKID from the PMKSA cache */
        !          1654:                frm = ieee80211_add_pmkid_kde(frm, pmkid);
        !          1655:        }
        !          1656:
        !          1657:        m->m_pkthdr.len = m->m_len = frm - (u_int8_t *)key;
        !          1658:
        !          1659:        if (ic->ic_if.if_flags & IFF_DEBUG)
        !          1660:                printf("%s: sending msg %d/%d of the %s handshake to %s\n",
        !          1661:                    ic->ic_if.if_xname, 1, 4, "4-way",
        !          1662:                    ether_sprintf(ni->ni_macaddr));
        !          1663:
        !          1664:        return ieee80211_send_eapol_key(ic, m, ni);
        !          1665: }
        !          1666:
        !          1667: /*
        !          1668:  * 4-Way Handshake Message 2 is sent by the supplicant to the authenticator
        !          1669:  * (see 8.5.3.2).
        !          1670:  */
        !          1671: int
        !          1672: ieee80211_send_4way_msg2(struct ieee80211com *ic, struct ieee80211_node *ni,
        !          1673:     const u_int8_t *snonce)
        !          1674: {
        !          1675:        struct ieee80211_eapol_key *key;
        !          1676:        struct mbuf *m;
        !          1677:        u_int16_t info;
        !          1678:        u_int8_t *frm;
        !          1679:
        !          1680:        m = ieee80211_get_eapol_key(M_DONTWAIT, MT_DATA,
        !          1681:            2 + 48);
        !          1682:        if (m == NULL)
        !          1683:                return ENOMEM;
        !          1684:        key = mtod(m, struct ieee80211_eapol_key *);
        !          1685:        memset(key, 0, sizeof(*key));
        !          1686:
        !          1687:        info = EAPOL_KEY_PAIRWISE | EAPOL_KEY_KEYMIC;
        !          1688:        BE_WRITE_2(key->info, info);
        !          1689:
        !          1690:        /* copy key replay counter from authenticator */
        !          1691:        BE_WRITE_8(key->replaycnt, ni->ni_replaycnt);
        !          1692:
        !          1693:        /* copy the supplicant's nonce (SNonce) */
        !          1694:        memcpy(key->nonce, snonce, EAPOL_KEY_NONCE_LEN);
        !          1695:
        !          1696:        frm = (u_int8_t *)&key[1];
        !          1697:        /* add the WPA/RSN IE used in the (Re)Association Request */
        !          1698:        if (ni->ni_eapol_desc == EAPOL_KEY_DESC_WPA1) {
        !          1699:                u_int16_t keylen;
        !          1700:                frm = ieee80211_add_wpa1(frm, ic, ni);
        !          1701:                /* WPA1 sets the key length field here */
        !          1702:                keylen = ieee80211_cipher_keylen(ni->ni_pairwise_cipher);
        !          1703:                BE_WRITE_2(key->keylen, keylen);
        !          1704:        } else  /* RSN */
        !          1705:                frm = ieee80211_add_rsn(frm, ic, ni);
        !          1706:
        !          1707:        m->m_pkthdr.len = m->m_len = frm - (u_int8_t *)key;
        !          1708:
        !          1709:        if (ic->ic_if.if_flags & IFF_DEBUG)
        !          1710:                printf("%s: sending msg %d/%d of the %s handshake to %s\n",
        !          1711:                    ic->ic_if.if_xname, 2, 4, "4-way",
        !          1712:                    ether_sprintf(ni->ni_macaddr));
        !          1713:
        !          1714:        return ieee80211_send_eapol_key(ic, m, ni);
        !          1715: }
        !          1716:
        !          1717: /*
        !          1718:  * 4-Way Handshake Message 3 is sent by the authenticator to the supplicant
        !          1719:  * (see 8.5.3.3).
        !          1720:  */
        !          1721: int
        !          1722: ieee80211_send_4way_msg3(struct ieee80211com *ic, struct ieee80211_node *ni)
        !          1723: {
        !          1724:        struct ieee80211_eapol_key *key;
        !          1725:        struct ieee80211_key *gtk;
        !          1726:        struct mbuf *m;
        !          1727:        u_int16_t info, keylen;
        !          1728:        u_int8_t *frm;
        !          1729:
        !          1730:        m = ieee80211_get_eapol_key(M_DONTWAIT, MT_DATA,
        !          1731:            2 + 48 +
        !          1732:            ((ni->ni_eapol_desc == EAPOL_KEY_DESC_IEEE80211) ?
        !          1733:                2 + 6 + gtk->k_len : 0) +
        !          1734:            8);
        !          1735:        if (m == NULL)
        !          1736:                return ENOMEM;
        !          1737:        key = mtod(m, struct ieee80211_eapol_key *);
        !          1738:        memset(key, 0, sizeof(*key));
        !          1739:
        !          1740:        info = EAPOL_KEY_PAIRWISE | EAPOL_KEY_INSTALL | EAPOL_KEY_KEYACK |
        !          1741:            EAPOL_KEY_KEYMIC | EAPOL_KEY_SECURE;
        !          1742:
        !          1743:        BE_WRITE_8(key->replaycnt, ni->ni_replaycnt);
        !          1744:        /* use same nonce as in Message 1 */
        !          1745:        memcpy(key->nonce, ni->ni_nonce, EAPOL_KEY_NONCE_LEN);
        !          1746:
        !          1747:        keylen = ieee80211_cipher_keylen(ni->ni_pairwise_cipher);
        !          1748:        BE_WRITE_2(key->keylen, keylen);
        !          1749:
        !          1750:        frm = (u_int8_t *)&key[1];
        !          1751:        /* add the WPA/RSN IE included in Beacon/Probe Response */
        !          1752:        if (ni->ni_eapol_desc == EAPOL_KEY_DESC_IEEE80211) {
        !          1753:                frm = ieee80211_add_rsn(frm, ic, ic->ic_bss);
        !          1754:                /* RSN: encapsulate the GTK and ask for encryption */
        !          1755:                frm = ieee80211_add_gtk_kde(frm, gtk);
        !          1756:                LE_WRITE_8(key->rsc, gtk->k_rsc);
        !          1757:                info |= EAPOL_KEY_ENCRYPTED;
        !          1758:        } else  /* WPA1 */
        !          1759:                frm = ieee80211_add_wpa1(frm, ic, ic->ic_bss);
        !          1760:
        !          1761:        /* write the key info field */
        !          1762:        BE_WRITE_2(key->info, info);
        !          1763:
        !          1764:        m->m_pkthdr.len = m->m_len = frm - (u_int8_t *)key;
        !          1765:
        !          1766:        if (ic->ic_if.if_flags & IFF_DEBUG)
        !          1767:                printf("%s: sending msg %d/%d of the %s handshake to %s\n",
        !          1768:                    ic->ic_if.if_xname, 3, 4, "4-way",
        !          1769:                    ether_sprintf(ni->ni_macaddr));
        !          1770:
        !          1771:        return ieee80211_send_eapol_key(ic, m, ni);
        !          1772: }
        !          1773:
        !          1774: /*
        !          1775:  * 4-Way Handshake Message 4 is sent by the supplicant to the authenticator
        !          1776:  * (see 8.5.3.4).
        !          1777:  */
        !          1778: int
        !          1779: ieee80211_send_4way_msg4(struct ieee80211com *ic, struct ieee80211_node *ni)
        !          1780: {
        !          1781:        struct ieee80211_eapol_key *key;
        !          1782:        struct mbuf *m;
        !          1783:        u_int16_t info;
        !          1784:
        !          1785:        m = ieee80211_get_eapol_key(M_DONTWAIT, MT_DATA, 0);
        !          1786:        if (m == NULL)
        !          1787:                return ENOMEM;
        !          1788:        key = mtod(m, struct ieee80211_eapol_key *);
        !          1789:        memset(key, 0, sizeof(*key));
        !          1790:
        !          1791:        info = EAPOL_KEY_PAIRWISE | EAPOL_KEY_KEYMIC | EAPOL_KEY_SECURE;
        !          1792:        BE_WRITE_2(key->info, info);
        !          1793:
        !          1794:        /* copy key replay counter from authenticator */
        !          1795:        BE_WRITE_8(key->replaycnt, ni->ni_replaycnt);
        !          1796:
        !          1797:        if (ni->ni_eapol_desc == EAPOL_KEY_DESC_WPA1) {
        !          1798:                u_int16_t keylen;
        !          1799:                /* WPA1 sets the key length field here */
        !          1800:                keylen = ieee80211_cipher_keylen(ni->ni_pairwise_cipher);
        !          1801:                BE_WRITE_2(key->keylen, keylen);
        !          1802:        }
        !          1803:
        !          1804:        /* empty key data field */
        !          1805:        m->m_pkthdr.len = m->m_len = sizeof(*key);
        !          1806:
        !          1807:        if (ic->ic_if.if_flags & IFF_DEBUG)
        !          1808:                printf("%s: sending msg %d/%d of the %s handshake to %s\n",
        !          1809:                    ic->ic_if.if_xname, 4, 4, "4-way",
        !          1810:                    ether_sprintf(ni->ni_macaddr));
        !          1811:
        !          1812:        return ieee80211_send_eapol_key(ic, m, ni);
        !          1813: }
        !          1814:
        !          1815: /*
        !          1816:  * Group Key Handshake Message 1 is sent by the authenticator to the
        !          1817:  * supplicant (see 8.5.4.1).
        !          1818:  */
        !          1819: int
        !          1820: ieee80211_send_group_msg1(struct ieee80211com *ic, struct ieee80211_node *ni)
        !          1821: {
        !          1822:        struct ieee80211_eapol_key *key;
        !          1823:        struct ieee80211_key *gtk;
        !          1824:        struct mbuf *m;
        !          1825:        u_int16_t info;
        !          1826:        u_int8_t *frm;
        !          1827:
        !          1828:        m = ieee80211_get_eapol_key(M_DONTWAIT, MT_DATA,
        !          1829:            ((ni->ni_eapol_desc == EAPOL_KEY_DESC_WPA1) ?
        !          1830:                gtk->k_len : 2 + 6 + gtk->k_len) +
        !          1831:            8);
        !          1832:        if (m == NULL)
        !          1833:                return ENOMEM;
        !          1834:        key = mtod(m, struct ieee80211_eapol_key *);
        !          1835:        memset(key, 0, sizeof(*key));
        !          1836:
        !          1837:        info = EAPOL_KEY_KEYACK | EAPOL_KEY_KEYMIC | EAPOL_KEY_SECURE |
        !          1838:            EAPOL_KEY_ENCRYPTED;
        !          1839:
        !          1840:        BE_WRITE_8(key->replaycnt, ni->ni_replaycnt);
        !          1841:
        !          1842:        frm = (u_int8_t *)&key[1];
        !          1843:        if (ni->ni_eapol_desc == EAPOL_KEY_DESC_WPA1) {
        !          1844:                /* WPA1 does not have GTK KDE */
        !          1845:                BE_WRITE_2(key->keylen, gtk->k_len);
        !          1846:                memcpy(frm, gtk->k_key, gtk->k_len);
        !          1847:                frm += gtk->k_len;
        !          1848:                info |= gtk->k_id << EAPOL_KEY_WPA_KID_SHIFT;
        !          1849:                if (gtk->k_flags & IEEE80211_KEY_TX)
        !          1850:                        info |= EAPOL_KEY_WPA_TX;
        !          1851:        } else  /* RSN */
        !          1852:                frm = ieee80211_add_gtk_kde(frm, gtk);
        !          1853:
        !          1854:        LE_WRITE_8(key->rsc, gtk->k_rsc);
        !          1855:
        !          1856:        /* write the key info field */
        !          1857:        BE_WRITE_2(key->info, info);
        !          1858:
        !          1859:        m->m_pkthdr.len = m->m_len = frm - (u_int8_t *)key;
        !          1860:
        !          1861:        if (ic->ic_if.if_flags & IFF_DEBUG)
        !          1862:                printf("%s: sending msg %d/%d of the %s handshake to %s\n",
        !          1863:                    ic->ic_if.if_xname, 1, 2, "group key",
        !          1864:                    ether_sprintf(ni->ni_macaddr));
        !          1865:
        !          1866:        return ieee80211_send_eapol_key(ic, m, ni);
        !          1867: }
        !          1868:
        !          1869: /*
        !          1870:  * Group Key Handshake Message 2 is sent by the supplicant to the
        !          1871:  * authenticator (see 8.5.4.2).
        !          1872:  */
        !          1873: int
        !          1874: ieee80211_send_group_msg2(struct ieee80211com *ic, struct ieee80211_node *ni,
        !          1875:     const struct ieee80211_key *gtk)
        !          1876: {
        !          1877:        struct ieee80211_eapol_key *key;
        !          1878:        u_int16_t info;
        !          1879:        struct mbuf *m;
        !          1880:
        !          1881:        m = ieee80211_get_eapol_key(M_DONTWAIT, MT_DATA, 0);
        !          1882:        if (m == NULL)
        !          1883:                return ENOMEM;
        !          1884:        key = mtod(m, struct ieee80211_eapol_key *);
        !          1885:        memset(key, 0, sizeof(*key));
        !          1886:
        !          1887:        info = EAPOL_KEY_KEYMIC | EAPOL_KEY_SECURE;
        !          1888:
        !          1889:        /* copy key replay counter from authenticator */
        !          1890:        BE_WRITE_8(key->replaycnt, ni->ni_replaycnt);
        !          1891:
        !          1892:        if (ni->ni_eapol_desc == EAPOL_KEY_DESC_WPA1) {
        !          1893:                /* WPA1 sets the key length and key id fields here */
        !          1894:                BE_WRITE_2(key->keylen, gtk->k_len);
        !          1895:                info |= (gtk->k_id & 3) << EAPOL_KEY_WPA_KID_SHIFT;
        !          1896:        }
        !          1897:
        !          1898:        /* write the key info field */
        !          1899:        BE_WRITE_2(key->info, info);
        !          1900:
        !          1901:        /* empty key data field */
        !          1902:        m->m_pkthdr.len = m->m_len = sizeof(*key);
        !          1903:
        !          1904:        if (ic->ic_if.if_flags & IFF_DEBUG)
        !          1905:                printf("%s: sending msg %d/%d of the %s handshake to %s\n",
        !          1906:                    ic->ic_if.if_xname, 2, 2, "group key",
        !          1907:                    ether_sprintf(ni->ni_macaddr));
        !          1908:
        !          1909:        return ieee80211_send_eapol_key(ic, m, ni);
        !          1910: }
        !          1911:
        !          1912: /*
        !          1913:  * EAPOL-Key Request frames are sent by the supplicant to request that the
        !          1914:  * authenticator initiate either a 4-Way Handshake or Group Key Handshake
        !          1915:  * and to report a MIC failure in a TKIP MSDU.
        !          1916:  */
        !          1917: int
        !          1918: ieee80211_send_eapol_key_req(struct ieee80211com *ic,
        !          1919:     struct ieee80211_node *ni, u_int16_t info, u_int64_t tsc)
        !          1920: {
        !          1921:        struct ieee80211_eapol_key *key;
        !          1922:        struct mbuf *m;
        !          1923:
        !          1924:        m = ieee80211_get_eapol_key(M_DONTWAIT, MT_DATA, 0);
        !          1925:        if (m == NULL)
        !          1926:                return ENOMEM;
        !          1927:        key = mtod(m, struct ieee80211_eapol_key *);
        !          1928:        memset(key, 0, sizeof(*key));
        !          1929:
        !          1930:        BE_WRITE_2(key->info, info);
        !          1931:
        !          1932:        /* in case of TKIP MIC failure, fill the RSC field */
        !          1933:        if (info & EAPOL_KEY_ERROR)
        !          1934:                LE_WRITE_8(key->rsc, tsc);
        !          1935:
        !          1936:        /* use our separate key replay counter for key requests */
        !          1937:        BE_WRITE_8(key->replaycnt, ic->ic_keyreplaycnt);
        !          1938:        ic->ic_keyreplaycnt++;
        !          1939:
        !          1940:        if (ic->ic_if.if_flags & IFF_DEBUG)
        !          1941:                printf("%s: sending EAPOL-Key request to %s\n",
        !          1942:                    ic->ic_if.if_xname, ether_sprintf(ni->ni_macaddr));
        !          1943:
        !          1944:        return ieee80211_send_eapol_key(ic, m, ni);
        !          1945: }
        !          1946:
        !          1947: void
        !          1948: ieee80211_pwrsave(struct ieee80211com *ic, struct ieee80211_node *ni,
        !          1949:     struct mbuf *m)
        !          1950: {
        !          1951:        /* store the new packet on our queue, changing the TIM if necessary */
        !          1952:        if (IF_IS_EMPTY(&ni->ni_savedq))
        !          1953:                (*ic->ic_set_tim)(ic, ni->ni_associd, 1);
        !          1954:
        !          1955:        if (ni->ni_savedq.ifq_len >= IEEE80211_PS_MAX_QUEUE) {
        !          1956:                IF_DROP(&ni->ni_savedq);
        !          1957:                m_freem(m);
        !          1958:                if (ic->ic_if.if_flags & IFF_DEBUG)
        !          1959:                        printf("%s: station %s power save queue overflow"
        !          1960:                            " of size %d drops %d\n",
        !          1961:                            ic->ic_if.if_xname,
        !          1962:                            ether_sprintf(ni->ni_macaddr),
        !          1963:                            IEEE80211_PS_MAX_QUEUE,
        !          1964:                            ni->ni_savedq.ifq_drops);
        !          1965:        } else {
        !          1966:                /*
        !          1967:                 * Similar to ieee80211_mgmt_output, store the node in
        !          1968:                 * the rcvif field.
        !          1969:                 */
        !          1970:                IF_ENQUEUE(&ni->ni_savedq, m);
        !          1971:                m->m_pkthdr.rcvif = (void *)ni;
        !          1972:        }
        !          1973: }

CVSweb