0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc/*
19d332fefbc61327bb6187d0eb818629f3b52c6ffei feng - Sun Microsystems - Beijing China * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Use is subject to license terms.
034536e9c476303015b9836aca06e46531705f2aHans Rosenfeld *
034536e9c476303015b9836aca06e46531705f2aHans Rosenfeld * Copyright 2016 Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
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 * Send out 802.11 frames
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc#include <sys/byteorder.h>
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc#include <sys/strsun.h>
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc#include "net80211_impl.h"
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc/*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Set the direction field and address fields of an outgoing
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * non-QoS frame. Note this should be called early on in
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * constructing a frame as it sets i_fc[1]; other bits can
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * then be or'd in.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcstatic void
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcieee80211_send_setup(ieee80211com_t *ic, ieee80211_node_t *in,
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc struct ieee80211_frame *wh, int type, const uint8_t *sa, const uint8_t *da,
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc const uint8_t *bssid)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc wh->i_fc[0] = (uint8_t)(IEEE80211_FC0_VERSION_0 | type);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if ((type & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_DATA) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc switch (ic->ic_opmode) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_M_STA:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc wh->i_fc[1] = IEEE80211_FC1_DIR_TODS;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_ADDR_COPY(wh->i_addr1, bssid);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_ADDR_COPY(wh->i_addr2, sa);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_ADDR_COPY(wh->i_addr3, da);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_M_IBSS:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_M_AHDEMO:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_ADDR_COPY(wh->i_addr1, da);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_ADDR_COPY(wh->i_addr2, sa);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_ADDR_COPY(wh->i_addr3, bssid);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc default:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_err("ieee80211_send_setup: "
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx "Invalid mode %u\n", ic->ic_opmode);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc } else {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_ADDR_COPY(wh->i_addr1, da);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_ADDR_COPY(wh->i_addr2, sa);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_ADDR_COPY(wh->i_addr3, bssid);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *(uint16_t *)&wh->i_dur[0] = 0; /* set duration */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang /* NB: use non-QoS tid */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang *(uint16_t *)&wh->i_seq[0] =
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang LE_16(in->in_txseqs[IEEE80211_NONQOS_TID] <<
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang IEEE80211_SEQ_SEQ_SHIFT);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang in->in_txseqs[IEEE80211_NONQOS_TID]++;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc}
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc/*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Send a management frame to the specified node. The node pointer
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * must have a reference as the pointer will be passed to the driver
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * and potentially held for a long time. If the frame is successfully
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * dispatched to the driver, then it is responsible for freeing the
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * reference (and potentially free'ing up any associated storage).
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Return 0 on success
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fangint
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcieee80211_mgmt_output(ieee80211com_t *ic, ieee80211_node_t *in, mblk_t *mp,
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc int type, int timer)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_impl_t *im = ic->ic_private;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc struct ieee80211_frame *wh;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ASSERT(in != NULL);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc wh = (struct ieee80211_frame *)mp->b_rptr;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_send_setup(ic, in, wh, IEEE80211_FC0_TYPE_MGT | type,
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx ic->ic_macaddr, in->in_macaddr, in->in_bssid);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (in->in_challenge != NULL)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc wh->i_fc[1] |= IEEE80211_FC1_WEP;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (timer > 0) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Set the mgt frame timeout.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc im->im_mgt_timer = timer;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_start_watchdog(ic, 1);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return ((*ic->ic_xmit)(ic, mp, IEEE80211_FC0_TYPE_MGT));
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc}
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc/*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Send a null data frame to the specified node.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * NB: the caller is assumed to have setup a node reference
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * for use; this is necessary to deal with a race condition
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * when probing for inactive stations.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcint
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcieee80211_send_nulldata(ieee80211_node_t *in)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211com_t *ic = in->in_ic;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc mblk_t *m;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc struct ieee80211_frame *wh;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc uint8_t *frm;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc m = ieee80211_getmgtframe(&frm, 0);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (m == NULL) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_stats.is_tx_nobuf++;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (ENOMEM);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc wh = (struct ieee80211_frame *)m->b_rptr;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_send_setup(ic, in, wh,
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_NODATA,
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx ic->ic_macaddr, in->in_macaddr, in->in_bssid);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /* NB: power management bit is never sent by an AP */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if ((in->in_flags & IEEE80211_NODE_PWR_MGT) &&
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_opmode != IEEE80211_M_HOSTAP)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc wh->i_fc[1] |= IEEE80211_FC1_PWR_MGT;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc m->b_wptr = m->b_rptr + sizeof (struct ieee80211_frame);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_dbg(IEEE80211_MSG_DEBUG | IEEE80211_MSG_DUMPPKTS, "net80211: "
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx "send null data frame on channel %u, pwr mgt %s\n",
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx ieee80211_macaddr_sprintf(in->in_macaddr),
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx ieee80211_chan2ieee(ic, ic->ic_curchan),
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx wh->i_fc[1] & IEEE80211_FC1_PWR_MGT ? "ena" : "dis");
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc (void) (*ic->ic_xmit)(ic, m, IEEE80211_FC0_TYPE_MGT);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (0);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc}
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc/*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Encapsulate an outbound data frame for GLDv3 based driver.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Fill in the variable part of the 80211 frame
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc/* ARGSUSED */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcmblk_t *
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcieee80211_encap(ieee80211com_t *ic, mblk_t *mp, ieee80211_node_t *in)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc struct ieee80211_frame *wh;
a399b7655a1d835aa8606c2b29e4e777baac8635zf struct ieee80211_key *key;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang int addqos, ac, tid;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ASSERT(mp != NULL && MBLKL(mp) >= sizeof (struct ieee80211_frame));
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang /*
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * Some ap's don't handle QoS-encapsulated EAPOL
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * frames so suppress use. This may be an issue if other
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * ap's require all data frames to be QoS-encapsulated
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * once negotiated in which case we'll need to make this
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * configurable.
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang addqos = in->in_flags & (IEEE80211_NODE_QOS | IEEE80211_NODE_HT);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc wh = (struct ieee80211_frame *)mp->b_rptr;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *(uint16_t *)wh->i_dur = 0;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang if (addqos) {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang struct ieee80211_qosframe *qwh =
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang (struct ieee80211_qosframe *)wh;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang ac = ieee80211_classify(ic, mp, in);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang /* map from access class/queue to 11e header priorty value */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang tid = WME_AC_TO_TID(ac);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang qwh->i_qos[0] = tid & IEEE80211_QOS_TID;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang /*
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * Check if A-MPDU tx aggregation is setup or if we
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * should try to enable it. The sta must be associated
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * with HT and A-MPDU enabled for use. On the first
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * frame that goes out We issue an ADDBA request and
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * wait for a reply. The frame being encapsulated
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * will go out w/o using A-MPDU, or possibly it might
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * be collected by the driver and held/retransmit.
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * ieee80211_ampdu_request handles staggering requests
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * in case the receiver NAK's us or we are otherwise
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * unable to establish a BA stream.
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang if ((in->in_flags & IEEE80211_NODE_AMPDU_TX) &&
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang (ic->ic_flags_ext & IEEE80211_FEXT_AMPDU_TX)) {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang struct ieee80211_tx_ampdu *tap = &in->in_tx_ampdu[ac];
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang if (IEEE80211_AMPDU_RUNNING(tap)) {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang /*
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * Operational, mark frame for aggregation.
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang qwh->i_qos[0] |= IEEE80211_QOS_ACKPOLICY_BA;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang } else if (!IEEE80211_AMPDU_REQUESTED(tap)) {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang /*
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * Not negotiated yet, request service.
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang (void) ieee80211_ampdu_request(in, tap);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang }
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang }
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang /* works even when BA marked above */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang if (ic->ic_wme.wme_wmeChanParams.cap_wmeParams[ac].
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang wmep_noackPolicy) {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang qwh->i_qos[0] |= IEEE80211_QOS_ACKPOLICY_NOACK;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang }
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang *(uint16_t *)wh->i_seq =
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang LE_16(in->in_txseqs[tid] << IEEE80211_SEQ_SEQ_SHIFT);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang in->in_txseqs[tid]++;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang } else {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang *(uint16_t *)wh->i_seq =
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang LE_16(in->in_txseqs[IEEE80211_NONQOS_TID] <<
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang IEEE80211_SEQ_SEQ_SHIFT);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang in->in_txseqs[IEEE80211_NONQOS_TID]++;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
a399b7655a1d835aa8606c2b29e4e777baac8635zf if (ic->ic_flags & IEEE80211_F_PRIVACY)
a399b7655a1d835aa8606c2b29e4e777baac8635zf key = ieee80211_crypto_getkey(ic);
a399b7655a1d835aa8606c2b29e4e777baac8635zf else
a399b7655a1d835aa8606c2b29e4e777baac8635zf key = NULL;
a399b7655a1d835aa8606c2b29e4e777baac8635zf
a399b7655a1d835aa8606c2b29e4e777baac8635zf /*
a399b7655a1d835aa8606c2b29e4e777baac8635zf * IEEE 802.1X: send EAPOL frames always in the clear.
a399b7655a1d835aa8606c2b29e4e777baac8635zf * WPA/WPA2: encrypt EAPOL keys when pairwise keys are set.
a399b7655a1d835aa8606c2b29e4e777baac8635zf */
a399b7655a1d835aa8606c2b29e4e777baac8635zf if (key != NULL && (ic->ic_flags & IEEE80211_F_WPA)) {
a399b7655a1d835aa8606c2b29e4e777baac8635zf wh->i_fc[1] |= IEEE80211_FC1_WEP;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang if (!ieee80211_crypto_enmic(isc, key, mp, 0))
a399b7655a1d835aa8606c2b29e4e777baac8635zf ieee80211_err("ieee80211_crypto_enmic failed.\n");
a399b7655a1d835aa8606c2b29e4e777baac8635zf }
a399b7655a1d835aa8606c2b29e4e777baac8635zf
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (mp);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc}
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc/*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Add supported rates information element to a frame.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcstatic uint8_t *
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcieee80211_add_rates(uint8_t *frm, const struct ieee80211_rateset *rs)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc uint8_t nrates;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *frm++ = IEEE80211_ELEMID_RATES;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc nrates = rs->ir_nrates;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (nrates > IEEE80211_RATE_SIZE)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc nrates = IEEE80211_RATE_SIZE;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *frm++ = nrates;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc bcopy(rs->ir_rates, frm, nrates);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (frm + nrates);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc}
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc/*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Add extended supported rates element to a frame, usually for 11g mode
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcstatic uint8_t *
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcieee80211_add_xrates(uint8_t *frm, const struct ieee80211_rateset *rs)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (rs->ir_nrates > IEEE80211_RATE_SIZE) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc uint8_t nrates = rs->ir_nrates - IEEE80211_RATE_SIZE;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *frm++ = IEEE80211_ELEMID_XRATES;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *frm++ = nrates;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc bcopy(rs->ir_rates + IEEE80211_RATE_SIZE, frm, nrates);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc frm += nrates;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (frm);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc}
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang#define WME_OUI_BYTES 0x00, 0x50, 0xf2
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang/*
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * Add a WME information element to a frame.
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang/* ARGSUSED */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fangstatic uint8_t *
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fangieee80211_add_wme_info(uint8_t *frm, struct ieee80211_wme_state *wme)
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang{
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang static const struct ieee80211_wme_info info = {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang .wme_id = IEEE80211_ELEMID_VENDOR,
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang .wme_len = sizeof (struct ieee80211_wme_info) - 2,
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang .wme_oui = { WME_OUI_BYTES },
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang .wme_type = WME_OUI_TYPE,
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang .wme_subtype = WME_INFO_OUI_SUBTYPE,
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang .wme_version = WME_VERSION,
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang .wme_info = 0,
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang };
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang (void) memcpy(frm, &info, sizeof (info));
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang return (frm + sizeof (info));
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang}
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang/*
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * Add a WME parameters element to a frame.
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fangstatic uint8_t *
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fangieee80211_add_wme_param(uint8_t *frm, struct ieee80211_wme_state *wme)
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang{
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang#define SM(_v, _f) (((_v) << _f##_S) & _f)
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang#define ADDSHORT(frm, v) do { \
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang _NOTE(CONSTCOND) \
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang frm[0] = (v) & 0xff; \
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang frm[1] = (v) >> 8; \
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang frm += 2; \
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang _NOTE(CONSTCOND) \
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang} while (0)
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang /* NB: this works 'cuz a param has an info at the front */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang static const struct ieee80211_wme_info param = {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang .wme_id = IEEE80211_ELEMID_VENDOR,
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang .wme_len = sizeof (struct ieee80211_wme_param) - 2,
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang .wme_oui = { WME_OUI_BYTES },
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang .wme_type = WME_OUI_TYPE,
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang .wme_subtype = WME_PARAM_OUI_SUBTYPE,
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang .wme_version = WME_VERSION,
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang };
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang int i;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang (void) memcpy(frm, &param, sizeof (param));
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang frm += offsetof(struct ieee80211_wme_info, wme_info);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang *frm++ = wme->wme_bssChanParams.cap_info; /* AC info */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang *frm++ = 0; /* reserved field */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang for (i = 0; i < WME_NUM_AC; i++) {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang const struct wmeParams *ac =
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang &wme->wme_bssChanParams.cap_wmeParams[i];
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang *frm++ = SM(i, WME_PARAM_ACI)
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang | SM(ac->wmep_acm, WME_PARAM_ACM)
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang | SM(ac->wmep_aifsn, WME_PARAM_AIFSN);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang *frm++ = SM(ac->wmep_logcwmax, WME_PARAM_LOGCWMAX)
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang | SM(ac->wmep_logcwmin, WME_PARAM_LOGCWMIN);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang ADDSHORT(frm, ac->wmep_txopLimit);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang }
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang return (frm);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang#undef SM
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang#undef ADDSHORT
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang}
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang#undef WME_OUI_BYTES
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc/*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Add SSID element to a frame
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcstatic uint8_t *
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcieee80211_add_ssid(uint8_t *frm, const uint8_t *ssid, uint32_t len)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *frm++ = IEEE80211_ELEMID_SSID;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *frm++ = (uint8_t)len;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc bcopy(ssid, frm, len);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (frm + len);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc}
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc/*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Add an erp element to a frame.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcstatic uint8_t *
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcieee80211_add_erp(uint8_t *frm, ieee80211com_t *ic)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc uint8_t erp;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *frm++ = IEEE80211_ELEMID_ERP;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *frm++ = 1;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc erp = 0;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ic->ic_flags & IEEE80211_F_USEPROT)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc erp |= IEEE80211_ERP_USE_PROTECTION;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ic->ic_flags & IEEE80211_F_USEBARKER)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc erp |= IEEE80211_ERP_LONG_PREAMBLE;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *frm++ = erp;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (frm);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc}
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc/*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Get capability information from the interface softc, ic.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcstatic uint16_t
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcieee80211_get_capinfo(ieee80211com_t *ic)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc uint16_t capinfo;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ic->ic_opmode == IEEE80211_M_IBSS)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc capinfo = IEEE80211_CAPINFO_IBSS;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc else
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc capinfo = IEEE80211_CAPINFO_ESS;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ic->ic_flags & IEEE80211_F_PRIVACY)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc capinfo |= IEEE80211_CAPINFO_PRIVACY;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ic->ic_flags & IEEE80211_F_SHSLOT)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc capinfo |= IEEE80211_CAPINFO_SHORT_SLOTTIME;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (capinfo);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc}
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc/*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Send a probe request frame with the specified ssid
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * and any optional information element data.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcint
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcieee80211_send_probereq(ieee80211_node_t *in,
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc const uint8_t *sa, const uint8_t *da, const uint8_t *bssid,
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc const uint8_t *ssid, size_t ssidlen, const void *optie, size_t optielen)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc mblk_t *mp;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211com_t *ic = in->in_ic;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc enum ieee80211_phymode mode;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc struct ieee80211_frame *wh;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc uint8_t *frm;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * prreq frame format ([tlv] - 1 byte element ID + 1 byte length)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [tlv] ssid
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [tlv] supported rates
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [tlv] extended supported rates
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [tlv] user-specified ie's
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc mp = ieee80211_getmgtframe(&frm,
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx 2 + IEEE80211_NWID_LEN
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx + 2 + IEEE80211_RATE_SIZE +
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx + 2 + IEEE80211_XRATE_SIZE
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx + optielen);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (mp == NULL)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (ENOMEM);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc frm = ieee80211_add_ssid(frm, ssid, ssidlen);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc mode = ieee80211_chan2mode(ic, ic->ic_curchan);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc frm = ieee80211_add_rates(frm, &ic->ic_sup_rates[mode]);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc frm = ieee80211_add_xrates(frm, &ic->ic_sup_rates[mode]);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (optie != NULL) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc (void) memcpy(frm, optie, optielen);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc frm += optielen;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc mp->b_wptr = frm;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc wh = (struct ieee80211_frame *)mp->b_rptr;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_send_setup(ic, in, wh,
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_PROBE_REQ,
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx sa, da, bssid);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_dbg(IEEE80211_MSG_DEBUG | IEEE80211_MSG_DUMPPKTS,
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx "[%s] send probe req on channel %u\n",
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx ieee80211_macaddr_sprintf(wh->i_addr1),
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx ieee80211_chan2ieee(ic, ic->ic_curchan));
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc (void) (*ic->ic_xmit)(ic, mp, IEEE80211_FC0_TYPE_MGT);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (0);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc}
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc/*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Send a management frame. The node is for the destination (or ic_bss
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * when in station mode). Nodes other than ic_bss have their reference
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * count bumped to reflect our use for an indeterminant time.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcint
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcieee80211_send_mgmt(ieee80211com_t *ic, ieee80211_node_t *in, int type, int arg)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc mblk_t *mp;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc uint8_t *frm;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc uint16_t capinfo;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc struct ieee80211_key *key;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc boolean_t has_challenge;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc boolean_t is_shared_key;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc int ret;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc int timer;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc int status;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ASSERT(in != NULL);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc timer = 0;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc switch (type) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * 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] parameter set (FH/DS)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [tlv] parameter set (IBSS)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [tlv] extended rate phy (ERP)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [tlv] extended supported rates
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [tlv] WPA
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [tlv] WME (optional)
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * [tlv] HT capabilities
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * [tlv] HT information
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * [tlv] Vendor OUI HT capabilities (optional)
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * [tlv] Vendor OUI HT information (optional)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc mp = ieee80211_getmgtframe(&frm,
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx 8 /* time stamp */
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx + sizeof (uint16_t) /* beacon interval */
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx + sizeof (uint16_t) /* capability */
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx + 2 + IEEE80211_NWID_LEN
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx + 2 + IEEE80211_RATE_SIZE
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx + 2 + IEEE80211_FH_LEN
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx + 2 + IEEE80211_IBSS_LEN
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx + 2 + IEEE80211_ERP_LEN
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx + 2 + IEEE80211_XRATE_SIZE
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx + (ic->ic_flags & IEEE80211_F_WPA ?
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx 2 * sizeof (struct ieee80211_ie_wpa) : 0)
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx /* [tlv] WPA */
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx + (ic->ic_flags & IEEE80211_F_WME ?
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang sizeof (struct ieee80211_wme_param) : 0)
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx /* [tlv] WME */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang /* check for cluster requirement */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang + 2 * sizeof (struct ieee80211_ie_htcap) + 4
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang + 2 * sizeof (struct ieee80211_ie_htinfo) + 4);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (mp == NULL)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (ENOMEM);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
19d332fefbc61327bb6187d0eb818629f3b52c6ffei feng - Sun Microsystems - Beijing China bzero(frm, 8); /* timestamp should be filled later */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc frm += 8;
19d332fefbc61327bb6187d0eb818629f3b52c6ffei feng - Sun Microsystems - Beijing China *(uint16_t *)frm = LE_16(ic->ic_bss->in_intval);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc frm += 2;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc capinfo = ieee80211_get_capinfo(ic);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *(uint16_t *)frm = LE_16(capinfo);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc frm += 2;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
19d332fefbc61327bb6187d0eb818629f3b52c6ffei feng - Sun Microsystems - Beijing China /* ssid */
19d332fefbc61327bb6187d0eb818629f3b52c6ffei feng - Sun Microsystems - Beijing China frm = ieee80211_add_ssid(frm, ic->ic_bss->in_essid,
19d332fefbc61327bb6187d0eb818629f3b52c6ffei feng - Sun Microsystems - Beijing China ic->ic_bss->in_esslen);
19d332fefbc61327bb6187d0eb818629f3b52c6ffei feng - Sun Microsystems - Beijing China /* supported rates */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc frm = ieee80211_add_rates(frm, &in->in_rates);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
19d332fefbc61327bb6187d0eb818629f3b52c6ffei feng - Sun Microsystems - Beijing China if (IEEE80211_IS_CHAN_FHSS(ic->ic_curchan)) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *frm++ = IEEE80211_ELEMID_FHPARMS;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *frm++ = IEEE80211_FH_LEN;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *frm++ = in->in_fhdwell & 0x00ff;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *frm++ = (in->in_fhdwell >> 8) & 0x00ff;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *frm++ = IEEE80211_FH_CHANSET(
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx ieee80211_chan2ieee(ic, ic->ic_curchan));
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *frm++ = IEEE80211_FH_CHANPAT(
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx ieee80211_chan2ieee(ic, ic->ic_curchan));
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *frm++ = in->in_fhindex;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc } else {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *frm++ = IEEE80211_ELEMID_DSPARMS;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *frm++ = IEEE80211_DS_LEN;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *frm++ = ieee80211_chan2ieee(ic, ic->ic_curchan);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ic->ic_opmode == IEEE80211_M_IBSS) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *frm++ = IEEE80211_ELEMID_IBSSPARMS;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *frm++ = IEEE80211_IBSS_LEN;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *frm++ = 0; *frm++ = 0; /* ATIM window */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
19d332fefbc61327bb6187d0eb818629f3b52c6ffei feng - Sun Microsystems - Beijing China if (IEEE80211_IS_CHAN_ANYG(ic->ic_curchan))
19d332fefbc61327bb6187d0eb818629f3b52c6ffei feng - Sun Microsystems - Beijing China frm = ieee80211_add_erp(frm, ic);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc frm = ieee80211_add_xrates(frm, &in->in_rates);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang /*
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * NB: legacy 11b clients do not get certain ie's.
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * The caller identifies such clients by passing
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * a token in arg to us. Could expand this to be
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * any legacy client for stuff like HT ie's.
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang if (IEEE80211_IS_CHAN_HT(ic->ic_curchan) &&
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang arg != IEEE80211_SEND_LEGACY_11B) {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang frm = ieee80211_add_htcap(frm, in);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang frm = ieee80211_add_htinfo(frm, in);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang }
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang if (ic->ic_flags & IEEE80211_F_WME)
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang frm = ieee80211_add_wme_param(frm, &ic->ic_wme);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang if (IEEE80211_IS_CHAN_HT(ic->ic_curchan) &&
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang (ic->ic_flags_ext & IEEE80211_FEXT_HTCOMPAT) &&
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang arg != IEEE80211_SEND_LEGACY_11B) {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang frm = ieee80211_add_htcap_vendor(frm, in);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang frm = ieee80211_add_htinfo_vendor(frm, in);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang }
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang mp->b_wptr = frm; /* allocated is greater than used */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_FC0_SUBTYPE_AUTH:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc status = arg >> 16;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc arg &= 0xffff;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc has_challenge = ((arg == IEEE80211_AUTH_SHARED_CHALLENGE ||
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc arg == IEEE80211_AUTH_SHARED_RESPONSE) &&
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc in->in_challenge != NULL);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Deduce whether we're doing open authentication or
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * shared key authentication. We do the latter if
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * we're in the middle of a shared key authentication
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * handshake or if we're initiating an authentication
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * request and configured to use shared key.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc is_shared_key = has_challenge ||
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc arg >= IEEE80211_AUTH_SHARED_RESPONSE ||
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc (arg == IEEE80211_AUTH_SHARED_REQUEST &&
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_bss->in_authmode == IEEE80211_AUTH_SHARED);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (has_challenge && status == IEEE80211_STATUS_SUCCESS)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc key = ieee80211_crypto_getkey(ic);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc else
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc key = NULL;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc mp = ieee80211_getmgtframe(&frm,
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx 3 * sizeof (uint16_t)
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx + (has_challenge && status == IEEE80211_STATUS_SUCCESS ?
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx sizeof (uint16_t) + IEEE80211_CHALLENGE_LEN : 0)
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx + (key != NULL ? key->wk_cipher->ic_header : 0));
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (mp == NULL)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (ENOMEM);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (key != NULL)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc frm += key->wk_cipher->ic_header;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ((uint16_t *)frm)[0] =
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx (is_shared_key) ? LE_16(IEEE80211_AUTH_ALG_SHARED)
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx : LE_16(IEEE80211_AUTH_ALG_OPEN);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ((uint16_t *)frm)[1] = LE_16(arg); /* sequence number */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ((uint16_t *)frm)[2] = LE_16(status); /* status */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (has_challenge && status == IEEE80211_STATUS_SUCCESS) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc frm += IEEE80211_AUTH_ELEM_MIN;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *frm = IEEE80211_ELEMID_CHALLENGE;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc frm++;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *frm = IEEE80211_CHALLENGE_LEN;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc frm++;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc bcopy(in->in_challenge, frm, IEEE80211_CHALLENGE_LEN);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ic->ic_opmode == IEEE80211_M_STA)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc timer = IEEE80211_TRANS_WAIT;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_FC0_SUBTYPE_DEAUTH:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc mp = ieee80211_getmgtframe(&frm, sizeof (uint16_t));
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (mp == NULL)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (ENOMEM);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *(uint16_t *)frm = LE_16(arg); /* reason */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_node_unauthorize(in); /* port closed */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_FC0_SUBTYPE_REASSOC_REQ:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * asreq frame format
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [2] capability information
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [2] listen interval
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [6*] current AP address (reassoc only)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [tlv] ssid
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [tlv] supported rates
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [tlv] extended supported rates
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [tlv] WME
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * [tlv] HT capabilities
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * [tlv] Vendor OUI HT capabilities (optional)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [tlv] user-specified ie's
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc mp = ieee80211_getmgtframe(&frm,
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx sizeof (uint16_t)
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx + sizeof (uint16_t) + IEEE80211_ADDR_LEN
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx + 2 + IEEE80211_NWID_LEN
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx + 2 + IEEE80211_RATE_SIZE
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx + 2 + IEEE80211_XRATE_SIZE
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang + sizeof (struct ieee80211_wme_info)
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang + 2 * sizeof (struct ieee80211_ie_htcap) + 4
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx + ic->ic_opt_ie_len);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (mp == NULL)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (ENOMEM);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc capinfo = ieee80211_get_capinfo(ic);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (!(in->in_capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME) ||
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc !(ic->ic_caps & IEEE80211_C_SHSLOT)) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc capinfo &= ~IEEE80211_CAPINFO_SHORT_SLOTTIME;
c1500db945971ce16b2509a64fc04cd590779a2ezf } else {
c1500db945971ce16b2509a64fc04cd590779a2ezf capinfo |= IEEE80211_CAPINFO_SHORT_SLOTTIME;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx if (!(in->in_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE) ||
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx !(ic->ic_caps & IEEE80211_C_SHPREAMBLE)) {
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx capinfo &= ~IEEE80211_CAPINFO_SHORT_PREAMBLE;
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx } else {
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE;
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *(uint16_t *)frm = LE_16(capinfo);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc frm += 2;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *(uint16_t *)frm = LE_16(ic->ic_lintval);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc frm += 2;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (type == IEEE80211_FC0_SUBTYPE_REASSOC_REQ) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_ADDR_COPY(frm, ic->ic_bss->in_bssid);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc frm += IEEE80211_ADDR_LEN;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc frm = ieee80211_add_ssid(frm, in->in_essid, in->in_esslen);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc frm = ieee80211_add_rates(frm, &in->in_rates);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc frm = ieee80211_add_xrates(frm, &in->in_rates);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang if ((ic->ic_flags_ext & IEEE80211_FEXT_HT) &&
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang in->in_htcap_ie != NULL &&
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang in->in_htcap_ie[0] == IEEE80211_ELEMID_HTCAP)
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang frm = ieee80211_add_htcap(frm, in);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang if ((ic->ic_flags & IEEE80211_F_WME) && in->in_wme_ie != NULL)
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang frm = ieee80211_add_wme_info(frm, &ic->ic_wme);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang if ((ic->ic_flags_ext & IEEE80211_FEXT_HT) &&
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang in->in_htcap_ie != NULL &&
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang in->in_htcap_ie[0] == IEEE80211_ELEMID_VENDOR)
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang frm = ieee80211_add_htcap_vendor(frm, in);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ic->ic_opt_ie != NULL) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc bcopy(ic->ic_opt_ie, frm, ic->ic_opt_ie_len);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc frm += ic->ic_opt_ie_len;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc mp->b_wptr = frm; /* allocated is greater than used */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc timer = IEEE80211_TRANS_WAIT;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_FC0_SUBTYPE_REASSOC_RESP:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * asreq 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 (if enabled and STA enabled)
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * [tlv] HT capabilities (standard or vendor OUI)
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * [tlv] HT information (standard or vendor OUI)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc mp = ieee80211_getmgtframe(&frm,
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx 3 * sizeof (uint16_t)
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx + 2 + IEEE80211_RATE_SIZE
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx + 2 + IEEE80211_XRATE_SIZE);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (mp == NULL)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (ENOMEM);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc capinfo = ieee80211_get_capinfo(ic);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *(uint16_t *)frm = LE_16(capinfo);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc frm += 2;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *(uint16_t *)frm = LE_16(arg); /* status */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc frm += 2;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (arg == IEEE80211_STATUS_SUCCESS)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *(uint16_t *)frm = LE_16(in->in_associd);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc else
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *(uint16_t *)frm = LE_16(0);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc frm += 2;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc frm = ieee80211_add_rates(frm, &in->in_rates);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc frm = ieee80211_add_xrates(frm, &in->in_rates);
19d332fefbc61327bb6187d0eb818629f3b52c6ffei feng - Sun Microsystems - Beijing China mp->b_wptr = frm;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_FC0_SUBTYPE_DISASSOC:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc mp = ieee80211_getmgtframe(&frm, sizeof (uint16_t));
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (mp == NULL)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (ENOMEM);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *(uint16_t *)frm = LE_16(arg); /* reason */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc default:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_dbg(IEEE80211_MSG_ANY,
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx "[%s] invalid mgmt frame type %u\n",
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx ieee80211_macaddr_sprintf(in->in_macaddr), type);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (EINVAL);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc } /* type */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ret = ieee80211_mgmt_output(ic, in, mp, type, timer);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (ret);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc}
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc/*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Allocate a beacon frame and fillin the appropriate bits.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcmblk_t *
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcieee80211_beacon_alloc(ieee80211com_t *ic, ieee80211_node_t *in,
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc struct ieee80211_beacon_offsets *bo)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc struct ieee80211_frame *wh;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc struct ieee80211_rateset *rs;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc mblk_t *m;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc uint8_t *frm;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc int pktlen;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc uint16_t capinfo;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_LOCK(ic);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * beacon frame format
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [8] time stamp
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [2] beacon interval
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [2] cabability information
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [tlv] ssid
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [tlv] supported rates
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [3] parameter set (DS)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [tlv] parameter set (IBSS/TIM)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [tlv] extended rate phy (ERP)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [tlv] extended supported rates
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [tlv] WME parameters
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * [tlv] WPA/RSN parameters
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * [tlv] HT capabilities
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * [tlv] HT information
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * [tlv] Vendor OUI HT capabilities (optional)
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * [tlv] Vendor OUI HT information (optional)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Vendor-specific OIDs (e.g. Atheros)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * NB: we allocate the max space required for the TIM bitmap.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc rs = &in->in_rates;
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx pktlen = 8 /* time stamp */
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx + sizeof (uint16_t) /* beacon interval */
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx + sizeof (uint16_t) /* capabilities */
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx + 2 + in->in_esslen /* ssid */
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx + 2 + IEEE80211_RATE_SIZE /* supported rates */
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx + 2 + 1 /* DS parameters */
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx + 2 + 4 + ic->ic_tim_len /* DTIM/IBSSPARMS */
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx + 2 + 1 /* ERP */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang + 2 + IEEE80211_XRATE_SIZE
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang + (ic->ic_caps & IEEE80211_C_WME ? /* WME */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang sizeof (struct ieee80211_wme_param) : 0)
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang /* conditional? */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang + 4 + 2 * sizeof (struct ieee80211_ie_htcap) /* HT caps */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang + 4 + 2 * sizeof (struct ieee80211_ie_htinfo); /* HT info */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc m = ieee80211_getmgtframe(&frm, pktlen);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (m == NULL) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_dbg(IEEE80211_MSG_ANY, "ieee80211_beacon_alloc: "
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx "cannot get buf; size %u\n", pktlen);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_UNLOCK(ic);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (NULL);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /* timestamp is set by hardware/driver */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc (void) memset(frm, 0, 8);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc frm += 8;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *(uint16_t *)frm = LE_16(in->in_intval);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc frm += 2;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc capinfo = ieee80211_get_capinfo(ic);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc bo->bo_caps = (uint16_t *)frm;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *(uint16_t *)frm = LE_16(capinfo);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc frm += 2;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *frm++ = IEEE80211_ELEMID_SSID;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (!(ic->ic_flags & IEEE80211_F_HIDESSID)) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *frm++ = in->in_esslen;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc bcopy(in->in_essid, frm, in->in_esslen);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc frm += in->in_esslen;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc } else {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *frm++ = 0;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc frm = ieee80211_add_rates(frm, rs);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ic->ic_curmode != IEEE80211_MODE_FH) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *frm++ = IEEE80211_ELEMID_DSPARMS;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *frm++ = 1;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *frm++ = ieee80211_chan2ieee(ic, in->in_chan);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc bo->bo_tim = frm;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ic->ic_opmode == IEEE80211_M_IBSS) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *frm++ = IEEE80211_ELEMID_IBSSPARMS;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *frm++ = 2;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *frm++ = 0; *frm++ = 0; /* TODO: ATIM window */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc bo->bo_tim_len = 0;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc } else {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc struct ieee80211_tim_ie *tie =
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx (struct ieee80211_tim_ie *)frm;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc tie->tim_ie = IEEE80211_ELEMID_TIM;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc tie->tim_len = 4; /* length */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc tie->tim_count = 0; /* DTIM count */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc tie->tim_period = IEEE80211_DTIM_DEFAULT;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc tie->tim_bitctl = 0; /* bitmap control */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc tie->tim_bitmap[0] = 0; /* Partial Virtual Bitmap */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc frm += sizeof (struct ieee80211_tim_ie);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc bo->bo_tim_len = 1;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc bo->bo_trailer = frm;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ic->ic_curmode == IEEE80211_MODE_11G) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc bo->bo_erp = frm;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc frm = ieee80211_add_erp(frm, ic);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang frm = ieee80211_add_xrates(frm, rs);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang if (IEEE80211_IS_CHAN_HT(ic->ic_curchan)) {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang frm = ieee80211_add_htcap(frm, in);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang bo->bo_htinfo = frm;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang frm = ieee80211_add_htinfo(frm, in);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang }
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang if (ic->ic_flags & IEEE80211_F_WME) {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang bo->bo_wme = frm;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang frm = ieee80211_add_wme_param(frm, &ic->ic_wme);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang }
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang if (IEEE80211_IS_CHAN_HT(ic->ic_curchan) &&
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang (ic->ic_flags_ext & IEEE80211_FEXT_HTCOMPAT)) {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang frm = ieee80211_add_htcap_vendor(frm, in);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang frm = ieee80211_add_htinfo_vendor(frm, in);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang }
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang bo->bo_trailer_len = _PTRDIFF(frm, bo->bo_trailer);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang m->b_wptr = frm;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc wh = (struct ieee80211_frame *)m->b_rptr;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT |
239e91abc172c1397b1e94869c5d0e8ab67bfc22hx IEEE80211_FC0_SUBTYPE_BEACON;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *(uint16_t *)wh->i_dur = 0;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_ADDR_COPY(wh->i_addr1, wifi_bcastaddr);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_macaddr);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_ADDR_COPY(wh->i_addr3, in->in_bssid);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *(uint16_t *)wh->i_seq = 0;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_UNLOCK(ic);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (m);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc}
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc/*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Update the dynamic parts of a beacon frame based on the current state.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc/* ARGSUSED */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcint
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcieee80211_beacon_update(ieee80211com_t *ic, ieee80211_node_t *in,
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc struct ieee80211_beacon_offsets *bo, mblk_t *mp, int mcast)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc uint16_t capinfo;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_LOCK(ic);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc capinfo = ieee80211_get_capinfo(ic);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *bo->bo_caps = LE_16(capinfo);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_UNLOCK(ic);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (0);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc}
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang/*
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * Assign priority to a frame based on any vlan tag assigned
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * to the station and/or any Diffserv setting in an IP header.
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * Finally, if an ACM policy is setup (in station mode) it's
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * applied.
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang */
034536e9c476303015b9836aca06e46531705f2aHans Rosenfeld/* ARGSUSED */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fangint
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fangieee80211_classify(struct ieee80211com *ic, mblk_t *m,
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang struct ieee80211_node *ni)
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang{
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang int ac;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang if ((ni->in_flags & IEEE80211_NODE_QOS) == 0)
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang return (WME_AC_BE);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang /* Process VLan */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang /* Process IPQoS */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang ac = WME_AC_BE;
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang /*
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang * Apply ACM policy.
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang if (ic->ic_opmode == IEEE80211_M_STA) {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang static const int acmap[4] = {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang WME_AC_BK, /* WME_AC_BE */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang WME_AC_BK, /* WME_AC_BK */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang WME_AC_BE, /* WME_AC_VI */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang WME_AC_VI, /* WME_AC_VO */
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang };
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang while (ac != WME_AC_BK &&
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang ic->ic_wme.wme_wmeBssChanParams.cap_wmeParams[ac].
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang wmep_acm) {
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang ac = acmap[ac];
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang }
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang }
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang return (ac);
e2cf88ac9d753a00c17aa235f6afdc76574fe3a6Quaker Fang}