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