0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc/*
19d332fefbc61327bb6187d0eb818629f3b52c6ffei feng - Sun Microsystems - Beijing China * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Use is subject to license terms.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc/*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Copyright (c) 2001 Atsushi Onoe
19d332fefbc61327bb6187d0eb818629f3b52c6ffei feng - Sun Microsystems - Beijing China * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * All rights reserved.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Redistribution and use in source and binary forms, with or without
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * modification, are permitted provided that the following conditions
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * are met:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * 1. Redistributions of source code must retain the above copyright
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * notice, this list of conditions and the following disclaimer.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * 2. Redistributions in binary form must reproduce the above copyright
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * notice, this list of conditions and the following disclaimer in the
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * documentation and/or other materials provided with the distribution.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * 3. The name of the author may not be used to endorse or promote products
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * derived from this software without specific prior written permission.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Alternatively, this software may be distributed under the terms of the
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * GNU General Public License ("GPL") version 2 as published by the Free
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Software Foundation.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc/*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Process received frame
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include <sys/mac_provider.h>
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc#include <sys/byteorder.h>
ff3124eff995e6cd8ebd8c6543648e0670920034ff#include <sys/strsun.h>
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc#include "net80211_impl.h"
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcstatic mblk_t *ieee80211_defrag(ieee80211com_t *, ieee80211_node_t *,
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc mblk_t *, int);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc/*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Process a received frame. The node associated with the sender
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * should be supplied. If nothing was found in the node table then
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * the caller is assumed to supply a reference to ic_bss instead.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * The RSSI and a timestamp are also supplied. The RSSI data is used
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * during AP scanning to select a AP to associate with; it can have
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * any units so long as values have consistent units and higher values
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * mean ``better signal''. The receive timestamp is currently not used
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * by the 802.11 layer.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcint
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcieee80211_input(ieee80211com_t *ic, mblk_t *mp, struct ieee80211_node *in,
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc int32_t rssi, uint32_t rstamp)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc struct ieee80211_frame *wh;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc struct ieee80211_key *key;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc uint8_t *bssid;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc int hdrspace;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc int len;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc uint16_t rxseq;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc uint8_t dir;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc uint8_t type;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc uint8_t subtype;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc uint8_t tid;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang uint8_t qos;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang if (mp->b_flag & M_AMPDU) {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang /*
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * Fastpath for A-MPDU reorder q resubmission. Frames
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * w/ M_AMPDU marked have already passed through here
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * but were received out of order and been held on the
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * reorder queue. When resubmitted they are marked
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * with the M_AMPDU flag and we can bypass most of the
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * normal processing.
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang IEEE80211_LOCK(ic);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang wh = (struct ieee80211_frame *)mp->b_rptr;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang type = IEEE80211_FC0_TYPE_DATA;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang subtype = IEEE80211_FC0_SUBTYPE_QOS;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang hdrspace = ieee80211_hdrspace(ic, wh); /* optimize */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang /* clear driver/net80211 flags before passing up */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang mp->b_flag &= ~M_AMPDU;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang goto resubmit_ampdu;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ASSERT(in != NULL);
19d332fefbc61327bb6187d0eb818629f3b52c6ffei feng - Sun Microsystems - Beijing China in->in_inact = in->in_inact_reload;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc type = (uint8_t)-1; /* undefined */
ff3124eff995e6cd8ebd8c6543648e0670920034ff len = MBLKL(mp);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (len < sizeof (struct ieee80211_frame_min)) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_dbg(IEEE80211_MSG_ANY, "ieee80211_input: "
ff3124eff995e6cd8ebd8c6543648e0670920034ff "too short (1): len %u", len);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc goto out;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Bit of a cheat here, we use a pointer for a 3-address
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * frame format but don't reference fields past outside
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * ieee80211_frame_min w/o first validating the data is
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * present.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc wh = (struct ieee80211_frame *)mp->b_rptr;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) !=
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_FC0_VERSION_0) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_dbg(IEEE80211_MSG_ANY, "ieee80211_input: "
ff3124eff995e6cd8ebd8c6543648e0670920034ff "discard pkt with wrong version %x", wh->i_fc[0]);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc goto out;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_LOCK(ic);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (!(ic->ic_flags & IEEE80211_F_SCAN)) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc switch (ic->ic_opmode) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_M_STA:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc bssid = wh->i_addr2;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (!IEEE80211_ADDR_EQ(bssid, in->in_bssid))
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc goto out_exit_mutex;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_M_IBSS:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_M_AHDEMO:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (dir != IEEE80211_FC1_DIR_NODS) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc bssid = wh->i_addr1;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc } else if (type == IEEE80211_FC0_TYPE_CTL) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc bssid = wh->i_addr1;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc } else {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (len < sizeof (struct ieee80211_frame)) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_dbg(IEEE80211_MSG_ANY,
ff3124eff995e6cd8ebd8c6543648e0670920034ff "ieee80211_input: too short(2):"
ff3124eff995e6cd8ebd8c6543648e0670920034ff "len %u\n", len);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc goto out_exit_mutex;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc bssid = wh->i_addr3;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (type != IEEE80211_FC0_TYPE_DATA)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Data frame, validate the bssid.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (!IEEE80211_ADDR_EQ(bssid, ic->ic_bss->in_bssid) &&
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc !IEEE80211_ADDR_EQ(bssid, wifi_bcastaddr)) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /* not interested in */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_dbg(IEEE80211_MSG_INPUT,
ff3124eff995e6cd8ebd8c6543648e0670920034ff "ieee80211_input: not to bss %s\n",
ff3124eff995e6cd8ebd8c6543648e0670920034ff ieee80211_macaddr_sprintf(bssid));
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc goto out_exit_mutex;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * For adhoc mode we cons up a node when it doesn't
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * exist. This should probably done after an ACL check.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (in == ic->ic_bss &&
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_opmode != IEEE80211_M_HOSTAP &&
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc !IEEE80211_ADDR_EQ(wh->i_addr2, in->in_macaddr)) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Fake up a node for this newly
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * discovered member of the IBSS.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc in = ieee80211_fakeup_adhoc_node(&ic->ic_sta,
ff3124eff995e6cd8ebd8c6543648e0670920034ff wh->i_addr2);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (in == NULL) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /* NB: stat kept for alloc failure */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc goto out_exit_mutex;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc default:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc goto out_exit_mutex;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc in->in_rssi = (uint8_t)rssi;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc in->in_rstamp = rstamp;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (!(type & IEEE80211_FC0_TYPE_CTL)) {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang if (IEEE80211_QOS_HAS_SEQ(wh)) {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang tid = ((struct ieee80211_qosframe *)wh)->
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang i_qos[0] & IEEE80211_QOS_TID;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang if (TID_TO_WME_AC(tid) >= WME_AC_VI)
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang ic->ic_wme.wme_hipri_traffic++;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang tid++;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang } else {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang tid = IEEE80211_NONQOS_TID;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang }
b510adae7e8895b2bf58eda3537fd56df35302e4fei feng - Sun Microsystems - Beijing China rxseq = LE_16(*(uint16_t *)wh->i_seq);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang if ((in->in_flags & IEEE80211_NODE_HT) == 0 &&
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang (wh->i_fc[1] & IEEE80211_FC1_RETRY) &&
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc (rxseq - in->in_rxseqs[tid]) <= 0) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /* duplicate, discard */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_dbg(IEEE80211_MSG_INPUT,
ff3124eff995e6cd8ebd8c6543648e0670920034ff "ieee80211_input: duplicate",
ff3124eff995e6cd8ebd8c6543648e0670920034ff "seqno <%u,%u> fragno <%u,%u> tid %u",
ff3124eff995e6cd8ebd8c6543648e0670920034ff rxseq >> IEEE80211_SEQ_SEQ_SHIFT,
ff3124eff995e6cd8ebd8c6543648e0670920034ff in->in_rxseqs[tid] >>
ff3124eff995e6cd8ebd8c6543648e0670920034ff IEEE80211_SEQ_SEQ_SHIFT,
ff3124eff995e6cd8ebd8c6543648e0670920034ff rxseq & IEEE80211_SEQ_FRAG_MASK,
ff3124eff995e6cd8ebd8c6543648e0670920034ff in->in_rxseqs[tid] &
ff3124eff995e6cd8ebd8c6543648e0670920034ff IEEE80211_SEQ_FRAG_MASK,
ff3124eff995e6cd8ebd8c6543648e0670920034ff tid);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_stats.is_rx_dups++;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc goto out_exit_mutex;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc in->in_rxseqs[tid] = rxseq;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc switch (type) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_FC0_TYPE_DATA:
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang hdrspace = ieee80211_hdrspace(ic, wh);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (len < hdrspace) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_dbg(IEEE80211_MSG_ANY, "ieee80211_input: "
ff3124eff995e6cd8ebd8c6543648e0670920034ff "data too short: expecting %u", hdrspace);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc goto out_exit_mutex;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc switch (ic->ic_opmode) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_M_STA:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (dir != IEEE80211_FC1_DIR_FROMDS) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_dbg(IEEE80211_MSG_INPUT,
ff3124eff995e6cd8ebd8c6543648e0670920034ff "ieee80211_input: data ",
ff3124eff995e6cd8ebd8c6543648e0670920034ff "unknown dir 0x%x", dir);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc goto out_exit_mutex;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (IEEE80211_IS_MULTICAST(wh->i_addr1) &&
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_ADDR_EQ(wh->i_addr3, ic->ic_macaddr)) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * In IEEE802.11 network, multicast packet
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * sent from me is broadcasted from AP.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * It should be silently discarded for
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * SIMPLEX interface.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_dbg(IEEE80211_MSG_INPUT,
ff3124eff995e6cd8ebd8c6543648e0670920034ff "ieee80211_input: multicast echo\n");
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc goto out_exit_mutex;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_M_IBSS:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_M_AHDEMO:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (dir != IEEE80211_FC1_DIR_NODS) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_dbg(IEEE80211_MSG_INPUT,
ff3124eff995e6cd8ebd8c6543648e0670920034ff "ieee80211_input: unknown dir 0x%x",
ff3124eff995e6cd8ebd8c6543648e0670920034ff dir);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc goto out_exit_mutex;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc default:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_err("ieee80211_input: "
ff3124eff995e6cd8ebd8c6543648e0670920034ff "receive data, unknown opmode %u, skip\n",
ff3124eff995e6cd8ebd8c6543648e0670920034ff ic->ic_opmode);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc goto out_exit_mutex;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang /*
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * Handle A-MPDU re-ordering. The station must be
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * associated and negotiated HT. The frame must be
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * a QoS frame (not QoS null data) and not previously
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * processed for A-MPDU re-ordering. If the frame is
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * to be processed directly then ieee80211_ampdu_reorder
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * will return 0; otherwise it has consumed the mbuf
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * and we should do nothing more with it.
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang if ((in->in_flags & IEEE80211_NODE_HT) &&
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang (subtype == IEEE80211_FC0_SUBTYPE_QOS)) {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang IEEE80211_UNLOCK(ic);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang if (ieee80211_ampdu_reorder(in, mp) != 0) {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang mp = NULL; /* CONSUMED */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang goto out;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang }
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang IEEE80211_LOCK(ic);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang }
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang resubmit_ampdu:
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Handle privacy requirements.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if ((ic->ic_flags & IEEE80211_F_PRIVACY) == 0) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Discard encrypted frames when privacy off.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_dbg(IEEE80211_MSG_INPUT,
ff3124eff995e6cd8ebd8c6543648e0670920034ff "ieee80211_input: ""WEP PRIVACY off");
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_stats.is_wep_errors++;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc goto out_exit_mutex;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc key = ieee80211_crypto_decap(ic, mp, hdrspace);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (key == NULL) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /* NB: stats+msgs handled in crypto_decap */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_stats.is_wep_errors++;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc goto out_exit_mutex;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc wh = (struct ieee80211_frame *)mp->b_rptr;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc wh->i_fc[1] &= ~IEEE80211_FC1_WEP;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc } else {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc key = NULL;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang /*
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * Save QoS bits for use below--before we strip the header.
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang if (subtype == IEEE80211_FC0_SUBTYPE_QOS) {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang qos = (dir == IEEE80211_FC1_DIR_DSTODS) ?
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang ((struct ieee80211_qosframe_addr4 *)wh)->i_qos[0] :
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang ((struct ieee80211_qosframe *)wh)->i_qos[0];
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang } else {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang qos = 0;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang }
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Next up, any fragmentation
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc mp = ieee80211_defrag(ic, in, mp, hdrspace);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (mp == NULL) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /* Fragment dropped or frame not complete yet */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc goto out_exit_mutex;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc wh = NULL; /* no longer valid, catch any uses */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Next strip any MSDU crypto bits.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (key != NULL && !ieee80211_crypto_demic(ic, key, mp, 0)) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_dbg(IEEE80211_MSG_INPUT, "ieee80211_input: "
ff3124eff995e6cd8ebd8c6543648e0670920034ff "data demic error\n");
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc goto out_exit_mutex;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang if (qos & IEEE80211_QOS_AMSDU) {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang ieee80211_dbg(IEEE80211_MSG_INPUT | IEEE80211_MSG_HT,
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang "ieee80211_input: QOS_AMSDU (%x)\n", qos);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang mp = ieee80211_decap_amsdu(in, mp);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang if (mp == NULL) /* MSDU processed by HT */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang goto out_exit_mutex;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang }
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_stats.is_rx_frags++;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_stats.is_rx_bytes += len;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_UNLOCK(ic);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc mac_rx(ic->ic_mach, NULL, mp);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (IEEE80211_FC0_TYPE_DATA);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_FC0_TYPE_MGT:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (dir != IEEE80211_FC1_DIR_NODS)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc goto out_exit_mutex;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (len < sizeof (struct ieee80211_frame))
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc goto out_exit_mutex;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (subtype != IEEE80211_FC0_SUBTYPE_AUTH) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Only shared key auth frames with a challenge
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * should be encrypted, discard all others.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_dbg(IEEE80211_MSG_INPUT,
ff3124eff995e6cd8ebd8c6543648e0670920034ff "ieee80211_input: "
ff3124eff995e6cd8ebd8c6543648e0670920034ff "%s WEP set but not permitted",
ff3124eff995e6cd8ebd8c6543648e0670920034ff IEEE80211_SUBTYPE_NAME(subtype));
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_stats.is_wep_errors++;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc goto out_exit_mutex;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if ((ic->ic_flags & IEEE80211_F_PRIVACY) == 0) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Discard encrypted frames when privacy off.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_dbg(IEEE80211_MSG_INPUT,
ff3124eff995e6cd8ebd8c6543648e0670920034ff "ieee80211_input: "
ff3124eff995e6cd8ebd8c6543648e0670920034ff "mgt WEP set but PRIVACY off");
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_stats.is_wep_errors++;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc goto out_exit_mutex;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang hdrspace = ieee80211_hdrspace(ic, wh);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc key = ieee80211_crypto_decap(ic, mp, hdrspace);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (key == NULL) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /* NB: stats+msgs handled in crypto_decap */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc goto out_exit_mutex;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc wh = (struct ieee80211_frame *)mp->b_rptr;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc wh->i_fc[1] &= ~IEEE80211_FC1_WEP;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_UNLOCK(ic);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_recv_mgmt(ic, mp, in, subtype, rssi, rstamp);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc goto out;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_FC0_TYPE_CTL:
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang switch (subtype) {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang case IEEE80211_FC0_SUBTYPE_BAR:
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang ieee80211_recv_bar(in, mp);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang break;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang }
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang }
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang break;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc default:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_dbg(IEEE80211_MSG_ANY, "ieee80211_input: "
ff3124eff995e6cd8ebd8c6543648e0670920034ff "bad frame type 0x%x", type);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /* should not come here */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcout_exit_mutex:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_UNLOCK(ic);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcout:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (mp != NULL)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc freemsg(mp);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (type);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc}
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc/*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * This function reassemble fragments.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * More fragments bit in the frame control means the packet is fragmented.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * While the sequence control field consists of 4-bit fragment number
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * field and a 12-bit sequence number field.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc/* ARGSUSED */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcstatic mblk_t *
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcieee80211_defrag(ieee80211com_t *ic, struct ieee80211_node *in, mblk_t *mp,
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc int hdrspace)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc struct ieee80211_frame *wh = (struct ieee80211_frame *)mp->b_rptr;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc struct ieee80211_frame *lwh;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc mblk_t *mfrag;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc uint16_t rxseq;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc uint8_t fragno;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc uint8_t more_frag;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ASSERT(!IEEE80211_IS_MULTICAST(wh->i_addr1));
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc more_frag = wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc rxseq = LE_16(*(uint16_t *)wh->i_seq);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc fragno = rxseq & IEEE80211_SEQ_FRAG_MASK;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /* Quick way out, if there's nothing to defragment */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (!more_frag && fragno == 0 && in->in_rxfrag == NULL)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (mp);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Remove frag to insure it doesn't get reaped by timer.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (in->in_table == NULL) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Should never happen. If the node is orphaned (not in
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * the table) then input packets should not reach here.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Otherwise, a concurrent request that yanks the table
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * should be blocked by other interlocking and/or by first
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * shutting the driver down. Regardless, be defensive
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * here and just bail
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc freemsg(mp);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (NULL);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_NODE_LOCK(in->in_table);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc mfrag = in->in_rxfrag;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc in->in_rxfrag = NULL;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_NODE_UNLOCK(in->in_table);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Validate new fragment is in order and
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * related to the previous ones.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (mfrag != NULL) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc uint16_t last_rxseq;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc lwh = (struct ieee80211_frame *)mfrag->b_rptr;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc last_rxseq = LE_16(*(uint16_t *)lwh->i_seq);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Sequence control field contains 12-bit sequence no
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * and 4-bit fragment number. For fragemnts, the
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * sequence no is not changed.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * NB: check seq # and frag together
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (rxseq != last_rxseq + 1 ||
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc !IEEE80211_ADDR_EQ(wh->i_addr1, lwh->i_addr1) ||
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc !IEEE80211_ADDR_EQ(wh->i_addr2, lwh->i_addr2)) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Unrelated fragment or no space for it,
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * clear current fragments.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc freemsg(mfrag);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc mfrag = NULL;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (mfrag == NULL) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (fragno != 0) { /* !first fragment, discard */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc freemsg(mp);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (NULL);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc mfrag = mp;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc } else { /* concatenate */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc (void) adjmsg(mp, hdrspace);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc linkb(mfrag, mp);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /* track last seqnum and fragno */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc lwh = (struct ieee80211_frame *)mfrag->b_rptr;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *(uint16_t *)lwh->i_seq = *(uint16_t *)wh->i_seq;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (more_frag != 0) { /* more to come, save */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc in->in_rxfragstamp = ddi_get_lbolt();
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc in->in_rxfrag = mfrag;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc mfrag = NULL;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (mfrag);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc}
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc/*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Install received rate set information in the node's state block.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcint
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcieee80211_setup_rates(struct ieee80211_node *in, const uint8_t *rates,
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc const uint8_t *xrates, int flags)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc struct ieee80211_rateset *rs = &in->in_rates;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc bzero(rs, sizeof (*rs));
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc rs->ir_nrates = rates[1];
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /* skip 1 byte element ID and 1 byte length */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc bcopy(rates + 2, rs->ir_rates, rs->ir_nrates);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (xrates != NULL) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc uint8_t nxrates;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Tack on 11g extended supported rate element.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc nxrates = xrates[1];
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (rs->ir_nrates + nxrates > IEEE80211_RATE_MAXSIZE) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc nxrates = IEEE80211_RATE_MAXSIZE - rs->ir_nrates;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_dbg(IEEE80211_MSG_XRATE,
ff3124eff995e6cd8ebd8c6543648e0670920034ff "ieee80211_setup_rates: %s",
ff3124eff995e6cd8ebd8c6543648e0670920034ff "[%s] extended rate set too large;"
ff3124eff995e6cd8ebd8c6543648e0670920034ff " only using %u of %u rates\n",
ff3124eff995e6cd8ebd8c6543648e0670920034ff ieee80211_macaddr_sprintf(in->in_macaddr),
ff3124eff995e6cd8ebd8c6543648e0670920034ff nxrates, xrates[1]);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc bcopy(xrates + 2, rs->ir_rates + rs->ir_nrates, nxrates);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc rs->ir_nrates += nxrates;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang return (ieee80211_fix_rate(in, &in->in_rates, flags));
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc}
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc/*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Process open-system authentication response frame and start
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * association if the authentication request is accepted.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcstatic void
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcieee80211_auth_open(ieee80211com_t *ic, struct ieee80211_frame *wh,
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc struct ieee80211_node *in, uint16_t seq, uint16_t status)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_LOCK_ASSERT(ic);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (in->in_authmode == IEEE80211_AUTH_SHARED) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_dbg(IEEE80211_MSG_AUTH,
ff3124eff995e6cd8ebd8c6543648e0670920034ff "open auth: bad sta auth mode %u", in->in_authmode);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ic->ic_opmode == IEEE80211_M_STA) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ic->ic_state != IEEE80211_S_AUTH ||
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc seq != IEEE80211_AUTH_OPEN_RESPONSE) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_UNLOCK(ic);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (status != 0) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_dbg(IEEE80211_MSG_DEBUG | IEEE80211_MSG_AUTH,
ff3124eff995e6cd8ebd8c6543648e0670920034ff "open auth failed (reason %d)\n", status);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (in != ic->ic_bss)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc in->in_fails++;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_new_state(ic, IEEE80211_S_SCAN, 0);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc } else {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /* i_fc[0] - frame control's type & subtype field */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_new_state(ic, IEEE80211_S_ASSOC,
ff3124eff995e6cd8ebd8c6543648e0670920034ff wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_LOCK(ic);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc } else {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_dbg(IEEE80211_MSG_AUTH, "ieee80211_auth_open: "
ff3124eff995e6cd8ebd8c6543648e0670920034ff "bad operating mode %u", ic->ic_opmode);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc}
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc/*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Allocate challenge text for use by shared-key authentication
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Return B_TRUE on success, B_FALST otherwise.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcstatic boolean_t
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcieee80211_alloc_challenge(struct ieee80211_node *in)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (in->in_challenge == NULL) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc in->in_challenge = kmem_alloc(IEEE80211_CHALLENGE_LEN,
ff3124eff995e6cd8ebd8c6543648e0670920034ff KM_NOSLEEP);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (in->in_challenge == NULL) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_dbg(IEEE80211_MSG_DEBUG | IEEE80211_MSG_AUTH,
ff3124eff995e6cd8ebd8c6543648e0670920034ff "[%s] shared key challenge alloc failed\n",
ff3124eff995e6cd8ebd8c6543648e0670920034ff ieee80211_macaddr_sprintf(in->in_macaddr));
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (in->in_challenge != NULL);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc}
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc/*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Process shared-key authentication response frames. If authentication
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * succeeds, start association; otherwise, restart scan.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcstatic void
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcieee80211_auth_shared(ieee80211com_t *ic, struct ieee80211_frame *wh,
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc uint8_t *frm, uint8_t *efrm, struct ieee80211_node *in, uint16_t seq,
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc uint16_t status)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc uint8_t *challenge;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Pre-shared key authentication is evil; accept
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * it only if explicitly configured (it is supported
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * mainly for compatibility with clients like OS X).
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_LOCK_ASSERT(ic);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (in->in_authmode != IEEE80211_AUTH_AUTO &&
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc in->in_authmode != IEEE80211_AUTH_SHARED) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_dbg(IEEE80211_MSG_AUTH, "ieee80211_auth_shared: "
ff3124eff995e6cd8ebd8c6543648e0670920034ff "bad sta auth mode %u", in->in_authmode);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc goto bad;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc challenge = NULL;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (frm + 1 < efrm) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Challenge text information element
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * frm[0] - element ID
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * frm[1] - length
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * frm[2]... - challenge text
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
ff3124eff995e6cd8ebd8c6543648e0670920034ff if ((frm[1] + 2) > (_PTRDIFF(efrm, frm))) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_dbg(IEEE80211_MSG_AUTH,
ff3124eff995e6cd8ebd8c6543648e0670920034ff "ieee80211_auth_shared: ie %d%d too long\n",
ff3124eff995e6cd8ebd8c6543648e0670920034ff frm[0], (frm[1] + 2) - (_PTRDIFF(efrm, frm)));
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc goto bad;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (*frm == IEEE80211_ELEMID_CHALLENGE)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc challenge = frm;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc frm += frm[1] + 2;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc switch (seq) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_AUTH_SHARED_CHALLENGE:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_AUTH_SHARED_RESPONSE:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (challenge == NULL) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_dbg(IEEE80211_MSG_AUTH,
ff3124eff995e6cd8ebd8c6543648e0670920034ff "ieee80211_auth_shared: no challenge\n");
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc goto bad;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (challenge[1] != IEEE80211_CHALLENGE_LEN) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_dbg(IEEE80211_MSG_AUTH,
ff3124eff995e6cd8ebd8c6543648e0670920034ff "ieee80211_auth_shared: bad challenge len %d\n",
ff3124eff995e6cd8ebd8c6543648e0670920034ff challenge[1]);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc goto bad;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc default:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc switch (ic->ic_opmode) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_M_STA:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ic->ic_state != IEEE80211_S_AUTH)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc switch (seq) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_AUTH_SHARED_PASS:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (in->in_challenge != NULL) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc kmem_free(in->in_challenge,
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_CHALLENGE_LEN);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc in->in_challenge = NULL;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (status != 0) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_dbg(IEEE80211_MSG_DEBUG |
ff3124eff995e6cd8ebd8c6543648e0670920034ff IEEE80211_MSG_AUTH,
ff3124eff995e6cd8ebd8c6543648e0670920034ff "shared key auth failed (reason %d)\n",
ff3124eff995e6cd8ebd8c6543648e0670920034ff status);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (in != ic->ic_bss)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc in->in_fails++;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_UNLOCK(ic);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_new_state(ic, IEEE80211_S_ASSOC,
ff3124eff995e6cd8ebd8c6543648e0670920034ff wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_LOCK(ic);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_AUTH_SHARED_CHALLENGE:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (!ieee80211_alloc_challenge(in))
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc bcopy(&challenge[2], in->in_challenge, challenge[1]);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_UNLOCK(ic);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_SEND_MGMT(ic, in, IEEE80211_FC0_SUBTYPE_AUTH,
ff3124eff995e6cd8ebd8c6543648e0670920034ff seq + 1);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_LOCK(ic);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc default:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_dbg(IEEE80211_MSG_AUTH, "80211_auth_shared: "
ff3124eff995e6cd8ebd8c6543648e0670920034ff "shared key auth: bad seq %d", seq);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc default:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_dbg(IEEE80211_MSG_AUTH,
ff3124eff995e6cd8ebd8c6543648e0670920034ff "ieee80211_auth_shared: bad opmode %u\n",
ff3124eff995e6cd8ebd8c6543648e0670920034ff ic->ic_opmode);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcbad:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ic->ic_opmode == IEEE80211_M_STA) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Kick the state machine. This short-circuits
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * using the mgt frame timeout to trigger the
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * state transition.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ic->ic_state == IEEE80211_S_AUTH) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_UNLOCK(ic);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_new_state(ic, IEEE80211_S_SCAN, 0);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_LOCK(ic);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc}
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
a399b7655a1d835aa8606c2b29e4e777baac8635zfstatic int
a399b7655a1d835aa8606c2b29e4e777baac8635zfiswpaoui(const uint8_t *frm)
a399b7655a1d835aa8606c2b29e4e777baac8635zf{
b510adae7e8895b2bf58eda3537fd56df35302e4fei feng - Sun Microsystems - Beijing China uint32_t c;
b510adae7e8895b2bf58eda3537fd56df35302e4fei feng - Sun Microsystems - Beijing China bcopy(frm + 2, &c, 4);
b510adae7e8895b2bf58eda3537fd56df35302e4fei feng - Sun Microsystems - Beijing China return (frm[1] > 3 && LE_32(c) == ((WPA_OUI_TYPE << 24) | WPA_OUI));
a399b7655a1d835aa8606c2b29e4e777baac8635zf}
a399b7655a1d835aa8606c2b29e4e777baac8635zf
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang#define LE_READ_4(p) \
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang ((uint32_t) \
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang ((((uint8_t *)(p))[0]) | (((uint8_t *)(p))[1] << 8) | \
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang (((uint8_t *)(p))[2] << 16) | (((uint8_t *)(p))[3] << 24)))
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang#define LE_READ_2(p) \
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang ((uint16_t) \
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang (((uint8_t *)(p))[0]) | (((uint8_t *)(p))[1] << 8))
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fangstatic int
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fangiswmeoui(const uint8_t *frm)
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang{
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang return (frm[1] > 3 && LE_READ_4(frm+2) == ((WME_OUI_TYPE<<24)|WME_OUI));
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang}
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fangstatic int
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fangiswmeparam(const uint8_t *frm)
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang{
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang return (frm[1] > 5 &&
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang LE_READ_4(frm+2) == ((WME_OUI_TYPE<<24)|WME_OUI) &&
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang frm[6] == WME_PARAM_OUI_SUBTYPE);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang}
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fangstatic int
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fangiswmeinfo(const uint8_t *frm)
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang{
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang return (frm[1] > 5 &&
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang LE_READ_4(frm+2) == ((WME_OUI_TYPE<<24)|WME_OUI) &&
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang frm[6] == WME_INFO_OUI_SUBTYPE);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang}
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fangstatic int
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fangishtcapoui(const uint8_t *frm)
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang{
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang return (frm[1] > 3 &&
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang LE_READ_4(frm+2) == ((BCM_OUI_HTCAP<<24)|BCM_OUI));
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang}
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fangstatic int
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fangishtinfooui(const uint8_t *frm)
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang{
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang return (frm[1] > 3 &&
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang LE_READ_4(frm+2) == ((BCM_OUI_HTINFO<<24)|BCM_OUI));
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang}
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang/* ARGSUSED */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fangstatic int
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fangieee80211_parse_wmeparams(struct ieee80211com *ic, uint8_t *frm,
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang const struct ieee80211_frame *wh)
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang{
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang#define MS(_v, _f) (((_v) & _f) >> _f##_S)
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang struct ieee80211_wme_state *wme = &ic->ic_wme;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang uint_t len = frm[1];
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang uint8_t qosinfo;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang int i;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang if (len < sizeof (struct ieee80211_wme_param) - 2) {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang ieee80211_dbg(IEEE80211_MSG_ELEMID | IEEE80211_MSG_WME,
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang "WME too short, len %u", len);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang return (-1);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang }
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang qosinfo = frm[offsetof(struct ieee80211_wme_param, wme_qosInfo)];
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang qosinfo &= WME_QOSINFO_COUNT;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang /* do proper check for wraparound */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang if (qosinfo == wme->wme_wmeChanParams.cap_info)
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang return (0);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang frm += offsetof(struct ieee80211_wme_param, wme_acParams);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang for (i = 0; i < WME_NUM_AC; i++) {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang struct wmeParams *wmep =
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang &wme->wme_wmeChanParams.cap_wmeParams[i];
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang /* NB: ACI not used */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang wmep->wmep_acm = MS(frm[0], WME_PARAM_ACM);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang wmep->wmep_aifsn = MS(frm[0], WME_PARAM_AIFSN);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang wmep->wmep_logcwmin = MS(frm[1], WME_PARAM_LOGCWMIN);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang wmep->wmep_logcwmax = MS(frm[1], WME_PARAM_LOGCWMAX);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang wmep->wmep_txopLimit = LE_READ_2(frm+2);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang frm += 4;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang }
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang wme->wme_wmeChanParams.cap_info = qosinfo;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang return (1);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang#undef MS
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang}
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc/*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Process a beacon/probe response frame.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * When the device is in station mode, create a node and add it
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * to the node database for a new ESS or update node info if it's
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * already there.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcstatic void
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcieee80211_recv_beacon(ieee80211com_t *ic, mblk_t *mp, struct ieee80211_node *in,
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc int subtype, int rssi, uint32_t rstamp)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_impl_t *im = ic->ic_private;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc struct ieee80211_frame *wh;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc uint8_t *frm;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc uint8_t *efrm; /* end of frame body */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc struct ieee80211_scanparams scan;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc wh = (struct ieee80211_frame *)mp->b_rptr;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc frm = (uint8_t *)&wh[1];
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc efrm = (uint8_t *)mp->b_wptr;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
216e0daa70a0058c5dc883bc667cd6925015df0aQuaker Fang ic->ic_beaconmiss = 0; /* clear beacon miss counter */
216e0daa70a0058c5dc883bc667cd6925015df0aQuaker Fang
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * We process beacon/probe response frames:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * o when scanning, or
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * o station mode when associated (to collect state
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * updates such as 802.11g slot time), or
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * o adhoc mode (to discover neighbors)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Frames otherwise received are discarded.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (!((ic->ic_flags & IEEE80211_F_SCAN) ||
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc (ic->ic_opmode == IEEE80211_M_STA && in->in_associd != 0) ||
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_opmode == IEEE80211_M_IBSS)) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * beacon/probe response frame format
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [8] time stamp
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [2] beacon interval
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [2] capability information
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [tlv] ssid
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [tlv] supported rates
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [tlv] country information
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [tlv] parameter set (FH/DS)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [tlv] erp information
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [tlv] extended supported rates
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [tlv] WME
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [tlv] WPA or RSN
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * [tlv] HT capabilities
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * [tlv] HT information
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
ff3124eff995e6cd8ebd8c6543648e0670920034ff IEEE80211_VERIFY_LENGTH(_PTRDIFF(efrm, frm),
ff3124eff995e6cd8ebd8c6543648e0670920034ff IEEE80211_BEACON_ELEM_MIN, return);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc bzero(&scan, sizeof (scan));
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc scan.tstamp = frm;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc frm += 8;
b510adae7e8895b2bf58eda3537fd56df35302e4fei feng - Sun Microsystems - Beijing China scan.bintval = LE_16(*(uint16_t *)frm);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc frm += 2;
b510adae7e8895b2bf58eda3537fd56df35302e4fei feng - Sun Microsystems - Beijing China scan.capinfo = LE_16(*(uint16_t *)frm);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc frm += 2;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc scan.bchan = ieee80211_chan2ieee(ic, ic->ic_curchan);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc scan.chan = scan.bchan;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc while (frm < efrm) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /* Agere element in beacon */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if ((*frm == IEEE80211_ELEMID_AGERE1) ||
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc (*frm == IEEE80211_ELEMID_AGERE2)) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc frm = efrm;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
ff3124eff995e6cd8ebd8c6543648e0670920034ff IEEE80211_VERIFY_LENGTH(_PTRDIFF(efrm, frm), frm[1], return);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc switch (*frm) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_ELEMID_SSID:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc scan.ssid = frm;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_ELEMID_RATES:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc scan.rates = frm;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_ELEMID_COUNTRY:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc scan.country = frm;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_ELEMID_FHPARMS:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ic->ic_phytype == IEEE80211_T_FH) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc scan.fhdwell = LE_16(*(uint16_t *)(frm + 2));
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc scan.chan = IEEE80211_FH_CHAN(frm[4], frm[5]);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc scan.fhindex = frm[6];
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc scan.phytype = IEEE80211_T_FH;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_ELEMID_DSPARMS:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ic->ic_phytype != IEEE80211_T_FH) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc scan.chan = frm[2];
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc scan.phytype = IEEE80211_T_DS;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_ELEMID_TIM:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc scan.tim = frm;
ff3124eff995e6cd8ebd8c6543648e0670920034ff scan.timoff = _PTRDIFF(frm, mp->b_rptr);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_ELEMID_IBSSPARMS:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_ELEMID_XRATES:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc scan.xrates = frm;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_ELEMID_ERP:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (frm[1] != 1) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_dbg(IEEE80211_MSG_ELEMID,
ff3124eff995e6cd8ebd8c6543648e0670920034ff "ieee80211_recv_mgmt: ignore %s, "
ff3124eff995e6cd8ebd8c6543648e0670920034ff "invalid ERP element; "
ff3124eff995e6cd8ebd8c6543648e0670920034ff "length %u, expecting 1\n",
ff3124eff995e6cd8ebd8c6543648e0670920034ff IEEE80211_SUBTYPE_NAME(subtype),
ff3124eff995e6cd8ebd8c6543648e0670920034ff frm[1]);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc scan.erp = frm[2];
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc scan.phytype = IEEE80211_T_OFDM;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang case IEEE80211_ELEMID_HTCAP:
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang scan.htcap = frm;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_ELEMID_RSN:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc scan.wpa = frm;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang case IEEE80211_ELEMID_HTINFO:
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang scan.htinfo = frm;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang break;
a399b7655a1d835aa8606c2b29e4e777baac8635zf case IEEE80211_ELEMID_VENDOR:
a399b7655a1d835aa8606c2b29e4e777baac8635zf if (iswpaoui(frm))
a399b7655a1d835aa8606c2b29e4e777baac8635zf scan.wpa = frm; /* IEEE802.11i D3.0 */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang else if (iswmeparam(frm) || iswmeinfo(frm))
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang scan.wme = frm;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang else if (ic->ic_flags_ext & IEEE80211_FEXT_HTCOMPAT) {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang /*
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * Accept pre-draft HT ie's if the
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * standard ones have not been seen.
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang if (ishtcapoui(frm)) {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang if (scan.htcap == NULL)
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang scan.htcap = frm;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang } else if (ishtinfooui(frm)) {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang if (scan.htinfo == NULL)
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang scan.htinfo = frm;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang }
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang }
a399b7655a1d835aa8606c2b29e4e777baac8635zf break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc default:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_dbg(IEEE80211_MSG_ELEMID,
ff3124eff995e6cd8ebd8c6543648e0670920034ff "ieee80211_recv_mgmt: ignore %s,"
ff3124eff995e6cd8ebd8c6543648e0670920034ff "unhandled id %u, len %u, totallen %u",
ff3124eff995e6cd8ebd8c6543648e0670920034ff IEEE80211_SUBTYPE_NAME(subtype),
ff3124eff995e6cd8ebd8c6543648e0670920034ff *frm, frm[1],
ff3124eff995e6cd8ebd8c6543648e0670920034ff MBLKL(mp));
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /* frm[1] - component length */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc frm += IEEE80211_ELEM_LEN(frm[1]);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_VERIFY_ELEMENT(scan.rates, IEEE80211_RATE_MAXSIZE, return);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_VERIFY_ELEMENT(scan.ssid, IEEE80211_NWID_LEN, return);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ieee80211_isclr(ic->ic_chan_active, scan.chan)) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_dbg(IEEE80211_MSG_ELEMID | IEEE80211_MSG_INPUT,
ff3124eff995e6cd8ebd8c6543648e0670920034ff "ieee80211_recv_mgmt: ignore %s ,"
ff3124eff995e6cd8ebd8c6543648e0670920034ff "invalid channel %u\n",
ff3124eff995e6cd8ebd8c6543648e0670920034ff IEEE80211_SUBTYPE_NAME(subtype), scan.chan);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (scan.chan != scan.bchan &&
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_phytype != IEEE80211_T_FH) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Frame was received on a channel different from the
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * one indicated in the DS params element id;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * silently discard it.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * NB: this can happen due to signal leakage.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * But we should take it for FH phy because
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * the rssi value should be correct even for
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * different hop pattern in FH.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_dbg(IEEE80211_MSG_ELEMID,
ff3124eff995e6cd8ebd8c6543648e0670920034ff "ieee80211_recv_mgmt: ignore %s ,"
ff3124eff995e6cd8ebd8c6543648e0670920034ff "phytype %u channel %u marked for %u\n",
ff3124eff995e6cd8ebd8c6543648e0670920034ff IEEE80211_SUBTYPE_NAME(subtype),
ff3124eff995e6cd8ebd8c6543648e0670920034ff ic->ic_phytype, scan.bchan, scan.chan);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (!(IEEE80211_BINTVAL_MIN <= scan.bintval &&
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc scan.bintval <= IEEE80211_BINTVAL_MAX)) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_dbg(IEEE80211_MSG_ELEMID | IEEE80211_MSG_INPUT,
ff3124eff995e6cd8ebd8c6543648e0670920034ff "ieee80211_recv_mgmt: ignore %s ,"
ff3124eff995e6cd8ebd8c6543648e0670920034ff "bogus beacon interval %u\n",
ff3124eff995e6cd8ebd8c6543648e0670920034ff IEEE80211_SUBTYPE_NAME(subtype), scan.bintval);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang /*
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * Process HT ie's. This is complicated by our
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * accepting both the standard ie's and the pre-draft
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * vendor OUI ie's that some vendors still use/require.
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang if (scan.htcap != NULL) {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang IEEE80211_VERIFY_LENGTH(scan.htcap[1],
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang scan.htcap[0] == IEEE80211_ELEMID_VENDOR ?
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang 4 + sizeof (struct ieee80211_ie_htcap) - 2 :
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang sizeof (struct ieee80211_ie_htcap) - 2,
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang scan.htcap = NULL);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang }
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang if (scan.htinfo != NULL) {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang IEEE80211_VERIFY_LENGTH(scan.htinfo[1],
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang scan.htinfo[0] == IEEE80211_ELEMID_VENDOR ?
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang 4 + sizeof (struct ieee80211_ie_htinfo) - 2 :
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang sizeof (struct ieee80211_ie_htinfo) - 2,
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang scan.htinfo = NULL);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * When operating in station mode, check for state updates.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Be careful to ignore beacons received while doing a
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * background scan. We consider only 11g/WMM stuff right now.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ic->ic_opmode == IEEE80211_M_STA &&
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc in->in_associd != 0 &&
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc (!(ic->ic_flags & IEEE80211_F_SCAN) ||
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_ADDR_EQ(wh->i_addr2, in->in_bssid))) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /* record tsf of last beacon */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc bcopy(scan.tstamp, in->in_tstamp.data,
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc sizeof (in->in_tstamp));
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /* count beacon frame for s/w bmiss handling */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc im->im_swbmiss_count++;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc im->im_bmiss_count = 0;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if ((in->in_capinfo ^ scan.capinfo) &
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_CAPINFO_SHORT_SLOTTIME) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_dbg(IEEE80211_MSG_ASSOC,
ff3124eff995e6cd8ebd8c6543648e0670920034ff "ieee80211_recv_mgmt: "
ff3124eff995e6cd8ebd8c6543648e0670920034ff "[%s] cap change: before 0x%x, now 0x%x\n",
ff3124eff995e6cd8ebd8c6543648e0670920034ff ieee80211_macaddr_sprintf(wh->i_addr2),
ff3124eff995e6cd8ebd8c6543648e0670920034ff in->in_capinfo, scan.capinfo);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * NB: we assume short preamble doesn't
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * change dynamically
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_set_shortslottime(ic,
ff3124eff995e6cd8ebd8c6543648e0670920034ff ic->ic_curmode == IEEE80211_MODE_11A ||
ff3124eff995e6cd8ebd8c6543648e0670920034ff (scan.capinfo &
ff3124eff995e6cd8ebd8c6543648e0670920034ff IEEE80211_CAPINFO_SHORT_SLOTTIME));
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc in->in_capinfo = scan.capinfo;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang if (scan.wme != NULL &&
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang (in->in_flags & IEEE80211_NODE_QOS) &&
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang ieee80211_parse_wmeparams(ic, scan.wme, wh) > 0) {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang ieee80211_wme_updateparams(ic);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang }
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang if (scan.htcap != NULL)
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang ieee80211_parse_htcap(in, scan.htcap);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang if (scan.htinfo != NULL) {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang ieee80211_parse_htinfo(in, scan.htinfo);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang if (in->in_chan != ic->ic_curchan) {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang /*
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * Channel has been adjusted based on
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * negotiated HT parameters; force the
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * channel state to follow.
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang ieee80211_setcurchan(ic, in->in_chan);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang }
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (scan.tim != NULL) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc struct ieee80211_tim_ie *ie;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ie = (struct ieee80211_tim_ie *)scan.tim;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc in->in_dtim_count = ie->tim_count;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc in->in_dtim_period = ie->tim_period;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ic->ic_flags & IEEE80211_F_SCAN) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_add_scan(ic, &scan, wh, subtype, rssi,
ff3124eff995e6cd8ebd8c6543648e0670920034ff rstamp);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * If scanning, just pass information to the scan module.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ic->ic_flags & IEEE80211_F_SCAN) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_add_scan(ic, &scan, wh, subtype, rssi, rstamp);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
19d332fefbc61327bb6187d0eb818629f3b52c6ffei feng - Sun Microsystems - Beijing China if (ic->ic_opmode == IEEE80211_M_IBSS &&
19d332fefbc61327bb6187d0eb818629f3b52c6ffei feng - Sun Microsystems - Beijing China scan.capinfo & IEEE80211_CAPINFO_IBSS) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (!IEEE80211_ADDR_EQ(wh->i_addr2, in->in_macaddr)) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Create a new entry in the neighbor table.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc in = ieee80211_add_neighbor(ic, wh, &scan);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc } else {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
19d332fefbc61327bb6187d0eb818629f3b52c6ffei feng - Sun Microsystems - Beijing China * Copy data from beacon to neighbor table.
19d332fefbc61327bb6187d0eb818629f3b52c6ffei feng - Sun Microsystems - Beijing China * Some of this information might change after
19d332fefbc61327bb6187d0eb818629f3b52c6ffei feng - Sun Microsystems - Beijing China * ieee80211_add_neighbor(), so we just copy
19d332fefbc61327bb6187d0eb818629f3b52c6ffei feng - Sun Microsystems - Beijing China * everything over to be safe.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
19d332fefbc61327bb6187d0eb818629f3b52c6ffei feng - Sun Microsystems - Beijing China ieee80211_init_neighbor(in, wh, &scan);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (in != NULL) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc in->in_rssi = (uint8_t)rssi;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc in->in_rstamp = rstamp;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc}
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc/*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Perform input processing for 802.11 management frames.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * It's the default ic_recv_mgmt callback function for the interface
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * softc, ic. Tipically ic_recv_mgmt is called within ieee80211_input()
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcvoid
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcieee80211_recv_mgmt(ieee80211com_t *ic, mblk_t *mp, struct ieee80211_node *in,
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc int subtype, int rssi, uint32_t rstamp)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc struct ieee80211_frame *wh;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc uint8_t *frm; /* pointer to start of the frame */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc uint8_t *efrm; /* pointer to end of the frame */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc uint8_t *ssid;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc uint8_t *rates;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc uint8_t *xrates; /* extended rates */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang uint8_t *wme;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang uint8_t *htcap, *htinfo;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc boolean_t allocbs = B_FALSE;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc uint8_t rate;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc uint16_t algo; /* authentication algorithm */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc uint16_t seq; /* sequence no */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc uint16_t status;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc uint16_t capinfo;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc uint16_t associd; /* association ID */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang const struct ieee80211_action *ia;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_LOCK(ic);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc wh = (struct ieee80211_frame *)mp->b_rptr;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc frm = (uint8_t *)&wh[1];
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc efrm = (uint8_t *)mp->b_wptr;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc switch (subtype) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_FC0_SUBTYPE_BEACON:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_recv_beacon(ic, mp, in, subtype, rssi, rstamp);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ic->ic_opmode == IEEE80211_M_STA ||
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_state != IEEE80211_S_RUN ||
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_IS_MULTICAST(wh->i_addr2)) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * prreq frame format
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [tlv] ssid
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [tlv] supported rates
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [tlv] extended supported rates
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ssid = rates = xrates = NULL;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc while (frm < efrm) {
ff3124eff995e6cd8ebd8c6543648e0670920034ff IEEE80211_VERIFY_LENGTH(_PTRDIFF(efrm, frm),
ff3124eff995e6cd8ebd8c6543648e0670920034ff frm[1], goto out);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc switch (*frm) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_ELEMID_SSID:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ssid = frm;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_ELEMID_RATES:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc rates = frm;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_ELEMID_XRATES:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc xrates = frm;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc frm += frm[1] + 2;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE, break);
19d332fefbc61327bb6187d0eb818629f3b52c6ffei feng - Sun Microsystems - Beijing China if (xrates != NULL) {
19d332fefbc61327bb6187d0eb818629f3b52c6ffei feng - Sun Microsystems - Beijing China IEEE80211_VERIFY_ELEMENT(xrates,
19d332fefbc61327bb6187d0eb818629f3b52c6ffei feng - Sun Microsystems - Beijing China IEEE80211_RATE_MAXSIZE - rates[1], break);
19d332fefbc61327bb6187d0eb818629f3b52c6ffei feng - Sun Microsystems - Beijing China }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN, break);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_VERIFY_SSID(ic->ic_bss, ssid, break);
19d332fefbc61327bb6187d0eb818629f3b52c6ffei feng - Sun Microsystems - Beijing China if (ic->ic_flags & IEEE80211_F_HIDESSID) {
19d332fefbc61327bb6187d0eb818629f3b52c6ffei feng - Sun Microsystems - Beijing China if (ssid == NULL || ssid[1] == 0) {
19d332fefbc61327bb6187d0eb818629f3b52c6ffei feng - Sun Microsystems - Beijing China ieee80211_dbg(IEEE80211_MSG_INPUT,
19d332fefbc61327bb6187d0eb818629f3b52c6ffei feng - Sun Microsystems - Beijing China "ieee80211_recv_mgmt: ignore %s, "
19d332fefbc61327bb6187d0eb818629f3b52c6ffei feng - Sun Microsystems - Beijing China "no ssid with ssid suppression enabled",
19d332fefbc61327bb6187d0eb818629f3b52c6ffei feng - Sun Microsystems - Beijing China IEEE80211_SUBTYPE_NAME(subtype));
19d332fefbc61327bb6187d0eb818629f3b52c6ffei feng - Sun Microsystems - Beijing China break;
19d332fefbc61327bb6187d0eb818629f3b52c6ffei feng - Sun Microsystems - Beijing China }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (in == ic->ic_bss) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ic->ic_opmode != IEEE80211_M_IBSS) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc in = ieee80211_tmp_node(ic, wh->i_addr2);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc allocbs = B_TRUE;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc } else if (!IEEE80211_ADDR_EQ(wh->i_addr2,
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc in->in_macaddr)) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Cannot tell if the sender is operating
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * in ibss mode. But we need a new node to
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * send the response so blindly add them to the
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * neighbor table.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc in = ieee80211_fakeup_adhoc_node(&ic->ic_sta,
ff3124eff995e6cd8ebd8c6543648e0670920034ff wh->i_addr2);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (in == NULL)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_dbg(IEEE80211_MSG_ASSOC, "ieee80211_recv_mgmt: "
ff3124eff995e6cd8ebd8c6543648e0670920034ff "[%s] recv probe req\n",
ff3124eff995e6cd8ebd8c6543648e0670920034ff ieee80211_macaddr_sprintf(wh->i_addr2));
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc in->in_rssi = (uint8_t)rssi;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc in->in_rstamp = rstamp;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Adjust and check station's rate list with device's
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * supported rate. Send back response if there is at
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * least one rate or the fixed rate(if being set) is
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * supported by both station and the device
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc rate = ieee80211_setup_rates(in, rates, xrates,
ff3124eff995e6cd8ebd8c6543648e0670920034ff IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE |
ff3124eff995e6cd8ebd8c6543648e0670920034ff IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (rate & IEEE80211_RATE_BASIC) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_dbg(IEEE80211_MSG_XRATE, "ieee80211_recv_mgmt"
ff3124eff995e6cd8ebd8c6543648e0670920034ff "%s recv'd rate set invalid",
ff3124eff995e6cd8ebd8c6543648e0670920034ff IEEE80211_SUBTYPE_NAME(subtype));
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc } else {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_UNLOCK(ic);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_SEND_MGMT(ic, in,
ff3124eff995e6cd8ebd8c6543648e0670920034ff IEEE80211_FC0_SUBTYPE_PROBE_RESP, 0);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_LOCK(ic);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (allocbs) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Temporary node created just to send a
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * response, reclaim immediately.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_free_node(in);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_FC0_SUBTYPE_AUTH:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * auth frame format
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [2] algorithm
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [2] sequence
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [2] status
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [tlv*] challenge
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
ff3124eff995e6cd8ebd8c6543648e0670920034ff IEEE80211_VERIFY_LENGTH(_PTRDIFF(efrm, frm),
ff3124eff995e6cd8ebd8c6543648e0670920034ff IEEE80211_AUTH_ELEM_MIN, break);
b510adae7e8895b2bf58eda3537fd56df35302e4fei feng - Sun Microsystems - Beijing China algo = LE_16(*(uint16_t *)frm);
b510adae7e8895b2bf58eda3537fd56df35302e4fei feng - Sun Microsystems - Beijing China seq = LE_16(*(uint16_t *)(frm + 2));
b510adae7e8895b2bf58eda3537fd56df35302e4fei feng - Sun Microsystems - Beijing China status = LE_16(*(uint16_t *)(frm + 4));
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_dbg(IEEE80211_MSG_AUTH, "ieee80211_recv_mgmt: "
ff3124eff995e6cd8ebd8c6543648e0670920034ff "[%s] recv auth frame with algorithm %d seq %d\n",
ff3124eff995e6cd8ebd8c6543648e0670920034ff ieee80211_macaddr_sprintf(wh->i_addr2), algo, seq);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ic->ic_flags & IEEE80211_F_COUNTERM) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_dbg(IEEE80211_MSG_AUTH | IEEE80211_MSG_CRYPTO,
ff3124eff995e6cd8ebd8c6543648e0670920034ff "ieee80211_recv_mgmt: ignore auth, %s\n",
ff3124eff995e6cd8ebd8c6543648e0670920034ff "TKIP countermeasures enabled");
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc switch (algo) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_AUTH_ALG_SHARED:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_auth_shared(ic, wh, frm + 6, efrm, in,
ff3124eff995e6cd8ebd8c6543648e0670920034ff seq, status);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_AUTH_ALG_OPEN:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_auth_open(ic, wh, in, seq, status);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc default:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_dbg(IEEE80211_MSG_ANY, "ieee80211_recv_mgmt: "
ff3124eff995e6cd8ebd8c6543648e0670920034ff "ignore auth, unsupported alg %d", algo);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_FC0_SUBTYPE_REASSOC_RESP:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ic->ic_opmode != IEEE80211_M_STA ||
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_state != IEEE80211_S_ASSOC)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * asresp frame format
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [2] capability information
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [2] status
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [2] association ID
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [tlv] supported rates
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [tlv] extended supported rates
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [tlv] WME
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * [tlv] HT capabilities
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * [tlv] HT info
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
ff3124eff995e6cd8ebd8c6543648e0670920034ff IEEE80211_VERIFY_LENGTH(_PTRDIFF(efrm, frm),
ff3124eff995e6cd8ebd8c6543648e0670920034ff IEEE80211_ASSOC_RESP_ELEM_MIN, break);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc in = ic->ic_bss;
b510adae7e8895b2bf58eda3537fd56df35302e4fei feng - Sun Microsystems - Beijing China capinfo = LE_16(*(uint16_t *)frm);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc frm += 2;
b510adae7e8895b2bf58eda3537fd56df35302e4fei feng - Sun Microsystems - Beijing China status = LE_16(*(uint16_t *)frm);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc frm += 2;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (status != 0) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_dbg(IEEE80211_MSG_ASSOC,
ff3124eff995e6cd8ebd8c6543648e0670920034ff "assoc failed (reason %d)\n", status);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc in = ieee80211_find_node(&ic->ic_scan, wh->i_addr2);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (in != NULL) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc in->in_fails++;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_free_node(in);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
b510adae7e8895b2bf58eda3537fd56df35302e4fei feng - Sun Microsystems - Beijing China associd = LE_16(*(uint16_t *)frm);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc frm += 2;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang rates = xrates = wme = htcap = htinfo = NULL;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc while (frm < efrm) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Do not discard frames containing proprietary Agere
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * elements 128 and 129, as the reported element length
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * is often wrong. Skip rest of the frame, since we can
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * not rely on the given element length making it
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * impossible to know where the next element starts
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if ((*frm == IEEE80211_ELEMID_AGERE1) ||
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc (*frm == IEEE80211_ELEMID_AGERE2)) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc frm = efrm;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
ff3124eff995e6cd8ebd8c6543648e0670920034ff IEEE80211_VERIFY_LENGTH(_PTRDIFF(efrm, frm),
ff3124eff995e6cd8ebd8c6543648e0670920034ff frm[1], goto out);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc switch (*frm) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_ELEMID_RATES:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc rates = frm;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_ELEMID_XRATES:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc xrates = frm;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang case IEEE80211_ELEMID_HTCAP:
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang htcap = frm;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang break;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang case IEEE80211_ELEMID_HTINFO:
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang htinfo = frm;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang break;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang case IEEE80211_ELEMID_VENDOR:
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang if (iswmeoui(frm))
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang wme = frm;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang else if (ic->ic_flags_ext &
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang IEEE80211_FEXT_HTCOMPAT) {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang /*
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * Accept pre-draft HT ie's if the
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * standard ones have not been seen.
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang if (ishtcapoui(frm)) {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang if (htcap == NULL)
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang htcap = frm;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang } else if (ishtinfooui(frm)) {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang if (htinfo == NULL)
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang htinfo = frm;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang }
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang }
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc frm += frm[1] + 2;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE, break);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Adjust and check AP's rate list with device's
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * supported rate. Re-start scan if no rate is or the
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * fixed rate(if being set) cannot be supported by
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * either AP or the device.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc rate = ieee80211_setup_rates(in, rates, xrates,
ff3124eff995e6cd8ebd8c6543648e0670920034ff IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE |
ff3124eff995e6cd8ebd8c6543648e0670920034ff IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (rate & IEEE80211_RATE_BASIC) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_dbg(IEEE80211_MSG_ASSOC,
ff3124eff995e6cd8ebd8c6543648e0670920034ff "assoc failed (rate set mismatch)\n");
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (in != ic->ic_bss)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc in->in_fails++;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_UNLOCK(ic);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_new_state(ic, IEEE80211_S_SCAN, 0);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc in->in_capinfo = capinfo;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc in->in_associd = associd;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang if (wme != NULL &&
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang ieee80211_parse_wmeparams(ic, wme, wh) >= 0) {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang in->in_flags |= IEEE80211_NODE_QOS;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang ieee80211_wme_updateparams(ic);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang } else {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang in->in_flags &= ~IEEE80211_NODE_QOS;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang }
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang /*
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * Setup HT state according to the negotiation.
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang if ((ic->ic_htcaps & IEEE80211_HTC_HT) &&
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang htcap != NULL && htinfo != NULL) {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang ieee80211_ht_node_init(in, htcap);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang ieee80211_parse_htinfo(in, htinfo);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang (void) ieee80211_setup_htrates(in,
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang htcap, IEEE80211_F_JOIN | IEEE80211_F_DOBRS);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang ieee80211_setup_basic_htrates(in, htinfo);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang if (in->in_chan != ic->ic_curchan) {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang /*
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * Channel has been adjusted based on
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * negotiated HT parameters; force the
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * channel state to follow.
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang ieee80211_setcurchan(ic, in->in_chan);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang }
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Configure state now that we are associated.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ic->ic_curmode == IEEE80211_MODE_11A ||
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc (in->in_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE)) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_flags |= IEEE80211_F_SHPREAMBLE;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_flags &= ~IEEE80211_F_USEBARKER;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc } else {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_flags &= ~IEEE80211_F_SHPREAMBLE;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_flags |= IEEE80211_F_USEBARKER;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_set_shortslottime(ic,
ff3124eff995e6cd8ebd8c6543648e0670920034ff ic->ic_curmode == IEEE80211_MODE_11A ||
ff3124eff995e6cd8ebd8c6543648e0670920034ff (in->in_capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME));
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Honor ERP protection.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * NB: in_erp should zero for non-11g operation.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * check ic_curmode anyway
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ic->ic_curmode == IEEE80211_MODE_11G &&
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc (in->in_erp & IEEE80211_ERP_USE_PROTECTION))
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_flags |= IEEE80211_F_USEPROT;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc else
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_flags &= ~IEEE80211_F_USEPROT;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_dbg(IEEE80211_MSG_ASSOC,
ff3124eff995e6cd8ebd8c6543648e0670920034ff "assoc success: %s preamble, %s slot time%s%s\n",
ff3124eff995e6cd8ebd8c6543648e0670920034ff ic->ic_flags&IEEE80211_F_SHPREAMBLE ? "short" : "long",
ff3124eff995e6cd8ebd8c6543648e0670920034ff ic->ic_flags&IEEE80211_F_SHSLOT ? "short" : "long",
ff3124eff995e6cd8ebd8c6543648e0670920034ff ic->ic_flags&IEEE80211_F_USEPROT ? ", protection" : "",
ff3124eff995e6cd8ebd8c6543648e0670920034ff in->in_flags & IEEE80211_NODE_QOS ? ", QoS" : "");
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_UNLOCK(ic);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_new_state(ic, IEEE80211_S_RUN, subtype);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_FC0_SUBTYPE_DEAUTH:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ic->ic_state == IEEE80211_S_SCAN)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * deauth frame format
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [2] reason
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
ff3124eff995e6cd8ebd8c6543648e0670920034ff IEEE80211_VERIFY_LENGTH(_PTRDIFF(efrm, frm), 2, break);
b510adae7e8895b2bf58eda3537fd56df35302e4fei feng - Sun Microsystems - Beijing China status = LE_16(*(uint16_t *)frm);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_dbg(IEEE80211_MSG_AUTH,
ff3124eff995e6cd8ebd8c6543648e0670920034ff "recv deauthenticate (reason %d)\n", status);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc switch (ic->ic_opmode) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_M_STA:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_UNLOCK(ic);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_new_state(ic, IEEE80211_S_AUTH,
ff3124eff995e6cd8ebd8c6543648e0670920034ff wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc default:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_FC0_SUBTYPE_DISASSOC:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ic->ic_state != IEEE80211_S_RUN &&
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_state != IEEE80211_S_ASSOC &&
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_state != IEEE80211_S_AUTH)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * disassoc frame format
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [2] reason
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
ff3124eff995e6cd8ebd8c6543648e0670920034ff IEEE80211_VERIFY_LENGTH(_PTRDIFF(efrm, frm), 2, break);
b510adae7e8895b2bf58eda3537fd56df35302e4fei feng - Sun Microsystems - Beijing China status = LE_16(*(uint16_t *)frm);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_dbg(IEEE80211_MSG_ASSOC,
ff3124eff995e6cd8ebd8c6543648e0670920034ff "recv disassociate (reason %d)\n", status);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc switch (ic->ic_opmode) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_M_STA:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_UNLOCK(ic);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_new_state(ic, IEEE80211_S_ASSOC,
ff3124eff995e6cd8ebd8c6543648e0670920034ff wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc default:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang case IEEE80211_FC0_SUBTYPE_ACTION:
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang if (ic->ic_state != IEEE80211_S_RUN &&
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang ic->ic_state != IEEE80211_S_ASSOC &&
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang ic->ic_state != IEEE80211_S_AUTH)
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang break;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang /*
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * action frame format:
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * [1] category
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * [1] action
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * [tlv] parameters
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang IEEE80211_VERIFY_LENGTH(_PTRDIFF(efrm, frm),
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang sizeof (struct ieee80211_action), break);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang ia = (const struct ieee80211_action *) frm;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang /* verify frame payloads but defer processing */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang /* maybe push this to method */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang switch (ia->ia_category) {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang case IEEE80211_ACTION_CAT_BA:
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang switch (ia->ia_action) {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang case IEEE80211_ACTION_BA_ADDBA_REQUEST:
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang IEEE80211_VERIFY_LENGTH(_PTRDIFF(efrm, frm),
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang sizeof (struct ieee80211_action_ba_addbarequest),
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang break);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang break;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang case IEEE80211_ACTION_BA_ADDBA_RESPONSE:
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang IEEE80211_VERIFY_LENGTH(_PTRDIFF(efrm, frm),
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang sizeof (struct ieee80211_action_ba_addbaresponse),
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang break);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang break;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang case IEEE80211_ACTION_BA_DELBA:
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang IEEE80211_VERIFY_LENGTH(_PTRDIFF(efrm, frm),
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang sizeof (struct ieee80211_action_ba_delba),
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang break);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang break;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang }
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang break;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang case IEEE80211_ACTION_CAT_HT:
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang switch (ia->ia_action) {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang case IEEE80211_ACTION_HT_TXCHWIDTH:
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang IEEE80211_VERIFY_LENGTH(_PTRDIFF(efrm, frm),
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang sizeof (struct ieee80211_action_ht_txchwidth),
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang break);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang break;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang }
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang break;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang }
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang ic->ic_recv_action(in, frm, efrm);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang break;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc default:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_dbg(IEEE80211_MSG_ANY, "ieee80211_recv_mgmt: "
ff3124eff995e6cd8ebd8c6543648e0670920034ff "subtype 0x%x not handled\n", subtype);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc } /* switch subtype */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcout:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_UNLOCK(ic);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc}