示例#1
0
void
ieee80211_create_ibss(struct ieee80211com* ic, struct ieee80211_channel *chan)
{
	struct ieee80211_node *ni;
	struct ifnet *ifp = &ic->ic_if;

	ni = ic->ic_bss;
	if (ifp->if_flags & IFF_DEBUG)
		printf("%s: creating ibss\n", ifp->if_xname);
	ic->ic_flags |= IEEE80211_F_SIBSS;
	ni->ni_chan = chan;
	ni->ni_rates = ic->ic_sup_rates[ieee80211_chan2mode(ic, ni->ni_chan)];
	IEEE80211_ADDR_COPY(ni->ni_macaddr, ic->ic_myaddr);
	IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_myaddr);
	if (ic->ic_opmode == IEEE80211_M_IBSS) {
		if ((ic->ic_flags & IEEE80211_F_DESBSSID) != 0)
			IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_des_bssid);
		else
			ni->ni_bssid[0] |= 0x02;	/* local bit for IBSS */
	}
	ni->ni_esslen = ic->ic_des_esslen;
	memcpy(ni->ni_essid, ic->ic_des_essid, ni->ni_esslen);
	ni->ni_rssi = 0;
	ni->ni_rstamp = 0;
	memset(ni->ni_tstamp, 0, sizeof(ni->ni_tstamp));
	ni->ni_intval = ic->ic_lintval;
	ni->ni_capinfo = IEEE80211_CAPINFO_IBSS;
	if (ic->ic_flags & IEEE80211_F_WEPON)
		ni->ni_capinfo |= IEEE80211_CAPINFO_PRIVACY;
	if (ic->ic_phytype == IEEE80211_T_FH) {
		ni->ni_fhdwell = 200;	/* XXX */
		ni->ni_fhindex = 1;
	}
	ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
}
示例#2
0
void
mlme_get_linkrate(struct ieee80211_node *ni, u_int32_t* rxlinkspeed, u_int32_t* txlinkspeed)
{
    struct ieee80211vap    *vap = ni->ni_vap;
    struct ieee80211com    *ic = ni->ni_ic;
    int                    ht_rates_allowed;
    u_int8_t               rate;

    /* Check if connected to BSS */
    if ((ni->ni_htrates.rs_nrates == 0) && (ni->ni_rates.rs_nrates == 0)) {

        /* Not connected */

        if (ic->ic_caps & IEEE80211_C_HT) {
            *txlinkspeed = get_max_phyrate(ic);
            *rxlinkspeed = *txlinkspeed;
        } else {
            struct ieee80211_rateset *rs;

            /* Legacy card, report highest rate */
            rs = &vap->iv_op_rates[ieee80211_chan2mode(ic->ic_curchan)];
            rate = rs->rs_rates[rs->rs_nrates - 1];
            *txlinkspeed = mlme_dot11rate_to_bps(rate & IEEE80211_RATE_VAL);
            *rxlinkspeed = *txlinkspeed;
        }
    } else {

        /* Connected */
        /*
         * With WEP and TKIP encryption algorithms:
         * Disable 11n if IEEE80211_FEXT_WEP_TKIP_HTRATE is not set.
         */
        ht_rates_allowed = (IEEE80211_IS_CHAN_11N(ic->ic_curchan) && 
                            ieee80211vap_htallowed(vap));

        if (ni->ni_htrates.rs_nrates &&
            ht_rates_allowed) {
            mlme_calculate_11n_connection_speed(ni, rxlinkspeed, txlinkspeed);
            if (ic->ic_reg_parm.indicateRxLinkSpeed)    *txlinkspeed = *rxlinkspeed;
        } else {
            /* get maximum rate from node rate set */
            rate = ni->ni_rates.rs_rates[ni->ni_rates.rs_nrates - 1] & IEEE80211_RATE_VAL;
            *txlinkspeed = mlme_dot11rate_to_bps(rate);
            *rxlinkspeed = *txlinkspeed;

        }
    }

    IEEE80211_DPRINTF(vap, IEEE80211_MSG_MLME, "%s: Rx Link speed Data rate: %d, Tx Link speed Data rate: %d\n", 
                      __func__, *rxlinkspeed, *txlinkspeed);
}
示例#3
0
void
ath_phyerr_reset(struct ath_softc *sc)
{
    struct ieee80211com *ic = &sc->sc_ic;
    u_int32_t mode;

    if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
        mode = ieee80211_chan2mode(ic, ic->ic_ibss_chan);
        if (mode == IEEE80211_MODE_TURBO_G)
            ath_reset_ar(sc);
        if ((mode == IEEE80211_MODE_11A) ||
                (mode == IEEE80211_MODE_TURBO_A))
            ath_reset_radar(sc);
    }

}
示例#4
0
void
ath_phyerr_diag(struct net_device *dev, u_int phyerr,
                struct ath_desc *ds, struct sk_buff *skb)
{
    struct ath_softc *sc = dev->priv;
    struct ieee80211com *ic = &sc->sc_ic;
    struct ieee80211_channel *chan;
    u_int32_t mode;

    chan = ic->ic_bss->ni_chan;
    if ((phyerr == HAL_PHYERR_RADAR) &&
            (ic->ic_opmode == IEEE80211_M_HOSTAP)) {
        mode = ieee80211_chan2mode(ic, chan);
        if (mode == IEEE80211_MODE_TURBO_G)
            ath_AR_event(dev, ds, skb);
        else
            ath_radar_event(dev, ds, skb);
    }
}
示例#5
0
static int ieee80211_mgmt_output(struct ieee80211_s *ic,
                                 struct ieee80211_node *ni, struct iob_s *iob,
                                 int type)
{
  struct ieee80211_frame *wh;
  int error;

  DEBUGASSERT(ni != NULL);
  ni->ni_inact = 0;

  /* We want to pass the node down to the driver's start routine.  We could
   * stick this in an m_tag and tack that on to the buffer.  However that's
   * rather expensive to do for every frame so instead we stuff it in a special 
   * pkthdr field.
   */

  error = iob_contig(iob, sizeof(struct ieee80211_frame));
  if (error < 0)
    {
      ndbg("ERROR: Failed to make contiguous: %d\n", error);
      return error;
    }

#warning REVISIT:  We do not want to burden everty IOB with this information
//iob->io_priv = ni;

  wh = (FAR struct ieee80211_frame *)IOB_DATA(iob);
  wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT | type;
  wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
  *(uint16_t *) & wh->i_dur[0] = 0;
  *(uint16_t *) & wh->i_seq[0] =
    htole16(ni->ni_txseq << IEEE80211_SEQ_SEQ_SHIFT);
  ni->ni_txseq++;
  IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_macaddr);
  IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_myaddr);
  IEEE80211_ADDR_COPY(wh->i_addr3, ni->ni_bssid);

  /* Check if protection is required for this mgmt frame */

  if ((ic->ic_caps & IEEE80211_C_MFP) &&
      (type == IEEE80211_FC0_SUBTYPE_DISASSOC ||
       type == IEEE80211_FC0_SUBTYPE_DEAUTH ||
       type == IEEE80211_FC0_SUBTYPE_ACTION))
    {
      /* Hack: we should not set the Protected bit in outgoing group management 
       * frames, however it is used as an indication to the drivers that they
       * must encrypt the frame.  Drivers should clear this bit from group
       * management frames (software crypto code will do it).
       */

      if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
          (ni->ni_flags & IEEE80211_NODE_TXMGMTPROT))
        {
          wh->i_fc[1] |= IEEE80211_FC1_PROTECTED;
        }
    }

#if defined(CONFIG_DEBUG_NET) && defined (CONFIG_DEBUG_VERBOSE)
  /* avoid to print too many frames */

  if ((type & IEEE80211_FC0_SUBTYPE_MASK) != IEEE80211_FC0_SUBTYPE_PROBE_RESP)
    {
      nvdbg("%s: sending %s to %s on channel %u mode %s\n",
            ic->ic_ifname,
            ieee80211_mgt_subtype_name[(type & IEEE80211_FC0_SUBTYPE_MASK) >>
                                       IEEE80211_FC0_SUBTYPE_SHIFT],
            ieee80211_addr2str(ni->ni_macaddr), ieee80211_chan2ieee(ic,
                                                                    ni->
                                                                    ni_chan),
            ieee80211_phymode_name[ieee80211_chan2mode(ic, ni->ni_chan)]);
    }
示例#6
0
int
iwl_tx_data(struct iwl_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
{
	struct iwl_ops *ops = &sc->ops;
	const struct ieee80211_txparam *tp;
	struct ieee80211vap *vap = ni->ni_vap;
	struct ieee80211com *ic = ni->ni_ic;
	struct iwl_node *wn = (void *)ni;
	struct iwl_tx_ring *ring;
	struct iwl_tx_desc *desc;
	struct iwl_tx_data *data;
	struct iwl_tx_cmd *cmd;
	struct iwl_cmd_data *tx;
	struct ieee80211_frame *wh;
	struct ieee80211_key *k = NULL;
	struct mbuf *m1;
	uint32_t flags;
	uint16_t qos;
	u_int hdrlen;
	bus_dma_segment_t *seg, segs[IWL_MAX_SCATTER];
	uint8_t tid, ridx, txant, type;
	int ac, i, totlen, error, pad, nsegs = 0, rate;
	struct iwl_vap *ivp = IWL_VAP(vap);

	IWL_LOCK_ASSERT(sc);

	wh = mtod(m, struct ieee80211_frame *);
	hdrlen = ieee80211_anyhdrsize(wh);
	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;

	/* Select EDCA Access Category and TX ring for this frame. */
	if (IEEE80211_QOS_HAS_SEQ(wh)) {
		qos = ((const struct ieee80211_qosframe *)wh)->i_qos[0];
		tid = qos & IEEE80211_QOS_TID;
	} else {
		qos = 0;
		tid = 0;
	}

	if(ivp->ctx == IWL_RXON_PAN_CTX)
		ac = iwl_pan_ac_to_queue[M_WME_GETAC(m)];
	else
		ac = iwl_bss_ac_to_queue[M_WME_GETAC(m)];

	if (IEEE80211_QOS_HAS_SEQ(wh) &&
	    IEEE80211_AMPDU_RUNNING(&ni->ni_tx_ampdu[ac])) {
		struct ieee80211_tx_ampdu *tap = &ni->ni_tx_ampdu[ac];

		ring = &sc->txq[*(int *)tap->txa_private];
		*(uint16_t *)wh->i_seq =
		    htole16(ni->ni_txseqs[tid] << IEEE80211_SEQ_SEQ_SHIFT);
		ni->ni_txseqs[tid]++;
	} else 
		ring = &sc->txq[ac];

	desc = &ring->desc[ring->cur];
	data = &ring->data[ring->cur];

	/* Choose a TX rate index. */
	tp = &vap->iv_txparms[ieee80211_chan2mode(ni->ni_chan)];
	if (type == IEEE80211_FC0_TYPE_MGT)
		rate = tp->mgmtrate;
	else if (IEEE80211_IS_MULTICAST(wh->i_addr1))
		rate = tp->mcastrate;
	else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
		rate = tp->ucastrate;
	else
		rate = ni->ni_txrate;

	ridx = ic->ic_rt->rateCodeToIndex[rate];

	/* Encrypt the frame if need be. */
	if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
		/* Retrieve key for TX. */
		k = ieee80211_crypto_encap(ni, m);
		if (k == NULL) {
			m_freem(m);
			return ENOBUFS;
		}
		/* 802.11 header may have moved. */
		wh = mtod(m, struct ieee80211_frame *);
	}
示例#7
0
/*
 * Join an infrastructure network
 */
int
ieee80211_sta_join(struct ieee80211vap *vap, ieee80211_scan_entry_t scan_entry)
{
    struct ieee80211com *ic = vap->iv_ic;
    struct ieee80211_node_table *nt = &ic->ic_sta;
    struct ieee80211_node *ni = NULL;
    const u_int8_t *macaddr = ieee80211_scan_entry_macaddr(scan_entry);
    int error = 0;

    ASSERT(vap->iv_opmode == IEEE80211_M_STA);
    
    ni = ieee80211_find_node(nt, macaddr);
    if (ni) {
        /* 
         * reusing old node has a potential for several bugs . The old node may have some state info from previous association.
         * get rid of the old bss node and create a new bss node.
         */
        ieee80211_sta_leave(ni); 
        ieee80211_free_node(ni); 
    }
    /*
     * Create a BSS node.
     */
    ni = ieee80211_alloc_node(nt, vap, macaddr);
    if (ni == NULL)
        return -ENOMEM;
    /* set the maximum number frmaes to be queued when the vap is in fake sleep */        
    ieee80211_node_saveq_set_param(ni,IEEE80211_NODE_SAVEQ_DATA_Q_LEN,IEE80211_STA_MAX_NODE_SAVEQ_LEN);
    /* To become a bss node, a node need an extra reference count, which alloc node already gives */
#ifdef IEEE80211_DEBUG_REFCNT
    ieee80211_note(ni->ni_vap,"%s ,line %u: increase node %p <%s> refcnt to %d\n",
                   __func__, __LINE__, ni, ether_sprintf(ni->ni_macaddr),
                   ieee80211_node_refcnt(ni));
#endif

    /* setup the bss node for association */
    error = ieee80211_setup_node(ni, scan_entry);
    if (error != 0) {
        ieee80211_free_node(ni);
        return error;
    }

    /* copy the beacon timestamp */
    OS_MEMCPY(ni->ni_tstamp.data,
              ieee80211_scan_entry_tsf(scan_entry),
              sizeof(ni->ni_tstamp));

    /*
     * Join the BSS represented by this new node.
     * This function will free up the old BSS node
     * and use this one as the new BSS node.
     */
    ieee80211_sta_join_bss(ni);

    IEEE80211_ADD_NODE_TARGET(ni, ni->ni_vap, 0);

    /* Save our home channel */
    vap->iv_bsschan = ni->ni_chan;
    vap->iv_cur_mode = ieee80211_chan2mode(ni->ni_chan);

    /* Update the DotH falg */
    ieee80211_update_spectrumrequirement(vap);

    /*
     *  The OS will control our security keys.  
     *  If clear, keys will be cleared.
     *  If static WEP, keys will be plumbed before JoinInfra.
     *  If WPA/WPA2, ciphers will be setup, but no keys will be plumbed until 
     *    after they are negotiated.
     *  XXX We should ASSERT that all of the foregoing is true.
     */
    return 0;
}
示例#8
0
/*
 * Complete a scan of potential channels.
 */
void
ieee80211_end_scan(struct ifnet *ifp)
{
	struct ieee80211com *ic = (void *)ifp;
	struct ieee80211_node *ni, *nextbs, *selbs;

	if (ifp->if_flags & IFF_DEBUG)
		printf("%s: end %s scan\n", ifp->if_xname,
			(ic->ic_flags & IEEE80211_F_ASCAN) ?
				"active" : "passive");

	if (ic->ic_scan_count)
		ic->ic_flags &= ~IEEE80211_F_ASCAN;

	ni = RB_MIN(ieee80211_tree, &ic->ic_tree);

#ifndef IEEE80211_STA_ONLY
	if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
		/* XXX off stack? */
		u_char occupied[howmany(IEEE80211_CHAN_MAX, NBBY)];
		int i, fail;

		/*
		 * The passive scan to look for existing AP's completed,
		 * select a channel to camp on.  Identify the channels
		 * that already have one or more AP's and try to locate
		 * an unnoccupied one.  If that fails, pick a random
		 * channel from the active set.
		 */
		memset(occupied, 0, sizeof(occupied));
		RB_FOREACH(ni, ieee80211_tree, &ic->ic_tree)
			setbit(occupied, ieee80211_chan2ieee(ic, ni->ni_chan));
		for (i = 0; i < IEEE80211_CHAN_MAX; i++)
			if (isset(ic->ic_chan_active, i) && isclr(occupied, i))
				break;
		if (i == IEEE80211_CHAN_MAX) {
			fail = arc4random() & 3;	/* random 0-3 */
			for (i = 0; i < IEEE80211_CHAN_MAX; i++)
				if (isset(ic->ic_chan_active, i) && fail-- == 0)
					break;
		}
		ieee80211_create_ibss(ic, &ic->ic_channels[i]);
		goto wakeup;
	}
#endif
	if (ni == NULL) {
		DPRINTF(("no scan candidate\n"));
 notfound:

#ifndef IEEE80211_STA_ONLY
		if (ic->ic_opmode == IEEE80211_M_IBSS &&
		    (ic->ic_flags & IEEE80211_F_IBSSON) &&
		    ic->ic_des_esslen != 0) {
			ieee80211_create_ibss(ic, ic->ic_ibss_chan);
			goto wakeup;
		}
#endif
		/*
		 * Scan the next mode if nothing has been found. This
		 * is necessary if the device supports different
		 * incompatible modes in the same channel range, like
		 * like 11b and "pure" 11G mode. This will loop
		 * forever except for user-initiated scans.
		 */
		if (ieee80211_next_mode(ifp) == IEEE80211_MODE_AUTO) {
			if (ic->ic_scan_lock & IEEE80211_SCAN_REQUEST &&
			    ic->ic_scan_lock & IEEE80211_SCAN_RESUME) {
				ic->ic_scan_lock = IEEE80211_SCAN_LOCKED;
				/* Return from an user-initiated scan */
				wakeup(&ic->ic_scan_lock);
			} else if (ic->ic_scan_lock & IEEE80211_SCAN_REQUEST)
				goto wakeup;
			ic->ic_scan_count++;
		}

		/*
		 * Reset the list of channels to scan and start again.
		 */
		ieee80211_next_scan(ifp);
		return;
	}
	selbs = NULL;

	for (; ni != NULL; ni = nextbs) {
		nextbs = RB_NEXT(ieee80211_tree, &ic->ic_tree, ni);
		if (ni->ni_fails) {
			/*
			 * The configuration of the access points may change
			 * during my scan.  So delete the entry for the AP
			 * and retry to associate if there is another beacon.
			 */
			if (ni->ni_fails++ > 2)
				ieee80211_free_node(ic, ni);
			continue;
		}
		if (ieee80211_match_bss(ic, ni) == 0) {
			if (selbs == NULL)
				selbs = ni;
			else if (ni->ni_rssi > selbs->ni_rssi)
				selbs = ni;
		}
	}
	if (selbs == NULL)
		goto notfound;
	(*ic->ic_node_copy)(ic, ic->ic_bss, selbs);
	ni = ic->ic_bss;

	/*
	 * Set the erp state (mostly the slot time) to deal with
	 * the auto-select case; this should be redundant if the
	 * mode is locked.
	 */
	ic->ic_curmode = ieee80211_chan2mode(ic, ni->ni_chan);
	ieee80211_reset_erp(ic);

	if (ic->ic_flags & IEEE80211_F_RSNON)
		ieee80211_choose_rsnparams(ic);
	else if (ic->ic_flags & IEEE80211_F_WEPON)
		ni->ni_rsncipher = IEEE80211_CIPHER_USEGROUP;

	ieee80211_node_newstate(selbs, IEEE80211_STA_BSS);
#ifndef IEEE80211_STA_ONLY
	if (ic->ic_opmode == IEEE80211_M_IBSS) {
		ieee80211_fix_rate(ic, ni, IEEE80211_F_DOFRATE |
		    IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
		if (ni->ni_rates.rs_nrates == 0)
			goto notfound;
		ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
	} else
#endif
		ieee80211_new_state(ic, IEEE80211_S_AUTH, -1);

 wakeup:
	if (ic->ic_scan_lock & IEEE80211_SCAN_REQUEST) {
		/* Return from an user-initiated scan */
		wakeup(&ic->ic_scan_lock);
	}

	ic->ic_scan_lock = IEEE80211_SCAN_UNLOCKED;
}
示例#9
0
void
ieee80211_create_ibss(struct ieee80211com* ic, struct ieee80211_channel *chan)
{
	struct ieee80211_node *ni;
	struct ifnet *ifp = &ic->ic_if;

	ni = ic->ic_bss;
	if (ifp->if_flags & IFF_DEBUG)
		printf("%s: creating ibss\n", ifp->if_xname);
	ic->ic_flags |= IEEE80211_F_SIBSS;
	ni->ni_chan = chan;
	ni->ni_rates = ic->ic_sup_rates[ieee80211_chan2mode(ic, ni->ni_chan)];
	ni->ni_txrate = 0;
	IEEE80211_ADDR_COPY(ni->ni_macaddr, ic->ic_myaddr);
	IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_myaddr);
	if (ic->ic_opmode == IEEE80211_M_IBSS) {
		if ((ic->ic_flags & IEEE80211_F_DESBSSID) != 0)
			IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_des_bssid);
		else
			ni->ni_bssid[0] |= 0x02;	/* local bit for IBSS */
	}
	ni->ni_esslen = ic->ic_des_esslen;
	memcpy(ni->ni_essid, ic->ic_des_essid, ni->ni_esslen);
	ni->ni_rssi = 0;
	ni->ni_rstamp = 0;
	memset(ni->ni_tstamp, 0, sizeof(ni->ni_tstamp));
	ni->ni_intval = ic->ic_lintval;
	ni->ni_capinfo = IEEE80211_CAPINFO_IBSS;
	if (ic->ic_flags & IEEE80211_F_WEPON)
		ni->ni_capinfo |= IEEE80211_CAPINFO_PRIVACY;
	if (ic->ic_flags & IEEE80211_F_RSNON) {
		struct ieee80211_key *k;

		/* initialize 256-bit global key counter to a random value */
		arc4random_buf(ic->ic_globalcnt, EAPOL_KEY_NONCE_LEN);

		ni->ni_rsnprotos = ic->ic_rsnprotos;
		ni->ni_rsnakms = ic->ic_rsnakms;
		ni->ni_rsnciphers = ic->ic_rsnciphers;
		ni->ni_rsngroupcipher = ic->ic_rsngroupcipher;
		ni->ni_rsngroupmgmtcipher = ic->ic_rsngroupmgmtcipher;
		ni->ni_rsncaps = 0;
		if (ic->ic_caps & IEEE80211_C_MFP) {
			ni->ni_rsncaps |= IEEE80211_RSNCAP_MFPC;
			if (ic->ic_flags & IEEE80211_F_MFPR)
				ni->ni_rsncaps |= IEEE80211_RSNCAP_MFPR;
		}

		ic->ic_def_txkey = 1;
		k = &ic->ic_nw_keys[ic->ic_def_txkey];
		memset(k, 0, sizeof(*k));
		k->k_id = ic->ic_def_txkey;
		k->k_cipher = ni->ni_rsngroupcipher;
		k->k_flags = IEEE80211_KEY_GROUP | IEEE80211_KEY_TX;
		k->k_len = ieee80211_cipher_keylen(k->k_cipher);
		arc4random_buf(k->k_key, k->k_len);
		(*ic->ic_set_key)(ic, ni, k);	/* XXX */

		if (ic->ic_caps & IEEE80211_C_MFP) {
			ic->ic_igtk_kid = 4;
			k = &ic->ic_nw_keys[ic->ic_igtk_kid];
			memset(k, 0, sizeof(*k));
			k->k_id = ic->ic_igtk_kid;
			k->k_cipher = ni->ni_rsngroupmgmtcipher;
			k->k_flags = IEEE80211_KEY_IGTK | IEEE80211_KEY_TX;
			k->k_len = 16;
			arc4random_buf(k->k_key, k->k_len);
			(*ic->ic_set_key)(ic, ni, k);	/* XXX */
		}
		/*
		 * In HostAP mode, multicast traffic is sent using ic_bss
		 * as the Tx node, so mark our node as valid so we can send
		 * multicast frames using the group key we've just configured.
		 */
		ni->ni_port_valid = 1;
		ni->ni_flags |= IEEE80211_NODE_TXPROT;

		/* schedule a GTK/IGTK rekeying after 3600s */
		timeout_add_sec(&ic->ic_rsn_timeout, 3600);
	}
	timeout_add_sec(&ic->ic_inact_timeout, IEEE80211_INACT_WAIT);
	timeout_add_sec(&ic->ic_node_cache_timeout, IEEE80211_CACHE_WAIT);
	ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
}
示例#10
0
void
ath_phyerr_enable(struct ath_softc *sc, struct ieee80211_channel *chan)
{
    u_int32_t rfilt;
    struct ieee80211com *ic = &sc->sc_ic;
    u_int32_t index;
    struct ath_phyerr_state *pe;
    enum ieee80211_phymode mode;

    pe = (struct ath_phyerr_state *) sc->sc_phyerr_state;
    mode = ieee80211_chan2mode(ic, chan);
    if ((sc->sc_phyerr_cap & (ATH_RADAR_AR_EN | ATH_RADAR_EN)) &&
            (ic->ic_opmode == IEEE80211_M_HOSTAP) &&
            ((mode == IEEE80211_MODE_11A) ||
             (mode == IEEE80211_MODE_TURBO_A) ||
             (mode == IEEE80211_MODE_TURBO_G))) {
        if (mode == IEEE80211_MODE_TURBO_G) {
            /* We are in turbo G, so enable AR*/
            index = get_radar_chan_index(sc);
            pe->pe_curRadar = &pe->pe_radarState[index];
            ath_reset_ar(sc);
            pe->pe_curRadar->rad_radarRssi = ATH_AR_RADAR_RSSI_THR;
            ath_hal_setcapability(sc->sc_ah, HAL_CAP_PHYDIAG,
                                  HAL_CAP_RADAR_RRSSI,
                                  pe->pe_curRadar->rad_radarRssi, NULL);
        } else {
            ath_reset_radar(sc);
            index = get_radar_chan_index(sc);
            pe->pe_curRadar = &pe->pe_radarState[index];

            pe->pe_curRadar->rad_firpwr = ATH_RADAR_FIRPWR;
            ath_hal_setcapability(sc->sc_ah, HAL_CAP_PHYDIAG,
                                  HAL_CAP_RADAR_FIRPWR,
                                  (u_int32_t) pe->pe_curRadar->rad_firpwr, NULL);

            /* XXX - need to Set firpwr */
            pe->pe_curRadar->rad_radarRssi = ATH_RADAR_RRSSI;
            ath_hal_setcapability(sc->sc_ah, HAL_CAP_PHYDIAG,
                                  HAL_CAP_RADAR_RRSSI,
                                  pe->pe_curRadar->rad_radarRssi, NULL);
            pe->pe_curRadar->rad_height = ATH_RADAR_HEIGHT;
            ath_hal_setcapability(sc->sc_ah, HAL_CAP_PHYDIAG,
                                  HAL_CAP_RADAR_HEIGHT,
                                  pe->pe_curRadar->rad_height, NULL);
            pe->pe_curRadar->rad_pulseRssi = ATH_RADAR_PRSSI;
            ath_hal_setcapability(sc->sc_ah, HAL_CAP_PHYDIAG,
                                  HAL_CAP_RADAR_PRSSI,
                                  pe->pe_curRadar->rad_pulseRssi, NULL);
            pe->pe_curRadar->rad_inband = ATH_RADAR_INBAND;
            ath_hal_setcapability(sc->sc_ah, HAL_CAP_PHYDIAG,
                                  HAL_CAP_RADAR_INBAND,
                                  pe->pe_curRadar->rad_inband, NULL);
        }
        rfilt = ath_hal_getrxfilter(sc->sc_ah);
        rfilt |= HAL_RX_FILTER_PHYRADAR;
        ath_hal_setrxfilter(sc->sc_ah,rfilt);
        ath_hal_enablePhyDiag(sc->sc_ah);
    } else {
        rfilt = ath_hal_getrxfilter(sc->sc_ah);
        rfilt &= ~HAL_RX_FILTER_PHYRADAR;
        ath_hal_setrxfilter(sc->sc_ah,rfilt);
    }
}
示例#11
0
/*
 * Find the channel information according to the scan entry
 */
int rtt_find_channel_info (void *arg, wlan_scan_entry_t scan_entry)
{
    wmi_channel *wmi_chan;
    u_int32_t chan_mode;
    struct ieee80211com *ic;
    struct ieee80211_channel *se_chan;
    static const u_int modeflags[] = {
        0,                            /* IEEE80211_MODE_AUTO           */
        MODE_11A,         /* IEEE80211_MODE_11A            */
        MODE_11B,         /* IEEE80211_MODE_11B            */
        MODE_11G,         /* IEEE80211_MODE_11G            */
        0,                            /* IEEE80211_MODE_FH             */
        0,                            /* IEEE80211_MODE_TURBO_A        */
        0,                            /* IEEE80211_MODE_TURBO_G        */
        MODE_11NA_HT20,   /* IEEE80211_MODE_11NA_HT20      */
        MODE_11NG_HT20,   /* IEEE80211_MODE_11NG_HT20      */
        MODE_11NA_HT40,   /* IEEE80211_MODE_11NA_HT40PLUS  */
        MODE_11NA_HT40,   /* IEEE80211_MODE_11NA_HT40MINUS */
        MODE_11NG_HT40,   /* IEEE80211_MODE_11NG_HT40PLUS  */
        MODE_11NG_HT40,   /* IEEE80211_MODE_11NG_HT40MINUS */
        MODE_11NG_HT40,   /* IEEE80211_MODE_11NG_HT40      */
        MODE_11NA_HT40,   /* IEEE80211_MODE_11NA_HT40      */
        MODE_11AC_VHT20,  /* IEEE80211_MODE_11AC_VHT20     */
        MODE_11AC_VHT40,  /* IEEE80211_MODE_11AC_VHT40PLUS */
        MODE_11AC_VHT40,  /* IEEE80211_MODE_11AC_VHT40MINUS*/
        MODE_11AC_VHT40,  /* IEEE80211_MODE_11AC_VHT40     */
        MODE_11AC_VHT80,  /* IEEE80211_MODE_11AC_VHT80     */
    };

    adf_os_print("%s:\n", __func__);

    if (!(arg && scan_entry)) {
        return -1; //critical error
    }

    wmi_chan = ((channel_search *)arg)->channel;
    ic = ((channel_search *)arg)->ic;

    if(!(wmi_chan && ic)) {
        return -1; //critical error
    }

    se_chan = wlan_scan_entry_channel(scan_entry);

    if(!se_chan) {
        return -1; //critical error
    }

    wmi_chan->mhz = ieee80211_chan2freq(ic,se_chan);
    chan_mode = ieee80211_chan2mode(se_chan);
    WMI_SET_CHANNEL_MODE(wmi_chan, modeflags[chan_mode]);

    if(chan_mode == IEEE80211_MODE_11AC_VHT80) {
        if (se_chan->ic_ieee < 20) {
            wmi_chan->band_center_freq1 = ieee80211_ieee2mhz(
                                             se_chan->ic_vhtop_ch_freq_seg1,
                                             IEEE80211_CHAN_2GHZ);
        } else {
            wmi_chan->band_center_freq1 = ieee80211_ieee2mhz(
                                            se_chan->ic_vhtop_ch_freq_seg1,
                                            IEEE80211_CHAN_5GHZ);
        }
    } else if((chan_mode == IEEE80211_MODE_11NA_HT40PLUS) ||
              (chan_mode == IEEE80211_MODE_11NG_HT40PLUS) ||
              (chan_mode == IEEE80211_MODE_11AC_VHT40PLUS)) {
        wmi_chan->band_center_freq1 = wmi_chan->mhz + 10;
    } else if((chan_mode == IEEE80211_MODE_11NA_HT40MINUS) ||
              (chan_mode == IEEE80211_MODE_11NG_HT40MINUS) ||
              (chan_mode == IEEE80211_MODE_11AC_VHT40MINUS)) {
        wmi_chan->band_center_freq1 = wmi_chan->mhz - 10;
    } else {
        wmi_chan->band_center_freq1 = wmi_chan->mhz;
    }

    /* we do not support HT80PLUS80 yet */
    wmi_chan->band_center_freq2=0;
    WMI_SET_CHANNEL_MIN_POWER(wmi_chan, se_chan->ic_minpower);
    WMI_SET_CHANNEL_MAX_POWER(wmi_chan, se_chan->ic_maxpower);
    WMI_SET_CHANNEL_REG_POWER(wmi_chan, se_chan->ic_maxregpower);
    WMI_SET_CHANNEL_ANTENNA_MAX(wmi_chan, se_chan->ic_antennamax);
    WMI_SET_CHANNEL_REG_CLASSID(wmi_chan, se_chan->ic_regClassId);

    if (IEEE80211_IS_CHAN_DFS(se_chan))
        WMI_SET_CHANNEL_FLAG(wmi_chan, WMI_CHAN_FLAG_DFS);

    adf_os_print("WMI channel freq=%d, mode=%x band_center_freq1=%d\n", wmi_chan->mhz, 
        WMI_GET_CHANNEL_MODE(wmi_chan), wmi_chan->band_center_freq1);

    return 1; //seccessful!    
}
示例#12
0
/*
 * Complete a scan of potential channels.
 */
void Voodoo80211Device::
ieee80211_end_scan(struct ieee80211com *ic)
{
	struct ieee80211_node *ni, *nextbs, *selbs;
    
    /* TODO
	if (ifp->if_flags & IFF_DEBUG)
		printf("%s: end %s scan\n", ifp->if_xname,
               (ic->ic_flags & IEEE80211_F_ASCAN) ?
               "active" : "passive");
     */
    
	if (ic->ic_scan_count)
		ic->ic_flags &= ~IEEE80211_F_ASCAN;
    
	ni = RB_MIN(ieee80211_tree, &ic->ic_tree);
    
	if (ni == NULL) {
		DPRINTF(("no scan candidate\n"));
    notfound:
        
		/*
		 * Scan the next mode if nothing has been found. This
		 * is necessary if the device supports different
		 * incompatible modes in the same channel range, like
		 * like 11b and "pure" 11G mode. This will loop
		 * forever except for user-initiated scans.
		 */
		if (ieee80211_next_mode(ic) == IEEE80211_MODE_AUTO) {
			if (ic->ic_scan_lock & IEEE80211_SCAN_REQUEST &&
			    ic->ic_scan_lock & IEEE80211_SCAN_RESUME) {
				ic->ic_scan_lock = IEEE80211_SCAN_LOCKED;
				/* Return from an user-initiated scan */
				wakeupOn(&ic->ic_scan_lock);
				// XXX: pvaibhav: do this here?
				fInterface->postMessage(APPLE80211_M_SCAN_DONE);
			} else if (ic->ic_scan_lock & IEEE80211_SCAN_REQUEST)
				goto wakeup;
			ic->ic_scan_count++;
		}
        
		/*
		 * Reset the list of channels to scan and start again.
		 */
		ieee80211_next_scan(ic);
		return;
	}
	selbs = NULL;
    
	for (; ni != NULL; ni = nextbs) {
		nextbs = RB_NEXT(ieee80211_tree, &ic->ic_tree, ni);
		if (ni->ni_fails) {
			/*
			 * The configuration of the access points may change
			 * during my scan.  So delete the entry for the AP
			 * and retry to associate if there is another beacon.
			 */
			if (ni->ni_fails++ > 2)
				ieee80211_free_node(ic, ni);
			continue;
		}
		if (ieee80211_match_bss(ic, ni) == 0) {
			if (selbs == NULL)
				selbs = ni;
			else if (ni->ni_rssi > selbs->ni_rssi)
				selbs = ni;
		}
	}
	if (selbs == NULL)
		goto notfound;
	ieee80211_node_copy(ic, ic->ic_bss, selbs);
	ni = ic->ic_bss;
    
	/*
	 * Set the erp state (mostly the slot time) to deal with
	 * the auto-select case; this should be redundant if the
	 * mode is locked.
	 */
	ic->ic_curmode = ieee80211_chan2mode(ic, ni->ni_chan);
	ieee80211_reset_erp(ic);
    
	if (ic->ic_flags & IEEE80211_F_RSNON)
		ieee80211_choose_rsnparams(ic);
	else if (ic->ic_flags & IEEE80211_F_WEPON)
		ni->ni_rsncipher = IEEE80211_CIPHER_USEGROUP;
    
	ieee80211_node_newstate(selbs, IEEE80211_STA_BSS);
		ieee80211_newstate(ic, IEEE80211_S_AUTH, -1);
    
wakeup:
	if (ic->ic_scan_lock & IEEE80211_SCAN_REQUEST) {
		/* Return from an user-initiated scan */
		wakeupOn(&ic->ic_scan_lock);
		// XXX: pvaibhav: do this here?
		fInterface->postMessage(APPLE80211_M_SCAN_DONE);
	}
    
	ic->ic_scan_lock = IEEE80211_SCAN_UNLOCKED;
}
示例#13
0
static int
rtwn_tx_data(struct rtwn_softc *sc, struct ieee80211_node *ni,
    struct mbuf *m)
{
	const struct ieee80211_txparam *tp;
	struct ieee80211com *ic = &sc->sc_ic;
	struct ieee80211vap *vap = ni->ni_vap;
	struct ieee80211_key *k = NULL;
	struct ieee80211_channel *chan;
	struct ieee80211_frame *wh;
	struct rtwn_tx_desc_common *txd;
	struct rtwn_tx_buf buf;
	uint8_t rate, ridx, type;
	u_int cipher;
	int ismcast, maxretry;

	RTWN_ASSERT_LOCKED(sc);

	wh = mtod(m, struct ieee80211_frame *);
	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
	ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);

	chan = (ni->ni_chan != IEEE80211_CHAN_ANYC) ?
		ni->ni_chan : ic->ic_curchan;
	tp = &vap->iv_txparms[ieee80211_chan2mode(chan)];
	maxretry = tp->maxretry;

	/* Choose a TX rate index. */
	if (type == IEEE80211_FC0_TYPE_MGT)
		rate = tp->mgmtrate;
	else if (ismcast)
		rate = tp->mcastrate;
	else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
		rate = tp->ucastrate;
	else if (m->m_flags & M_EAPOL)
		rate = tp->mgmtrate;
	else {
		if (sc->sc_ratectl == RTWN_RATECTL_NET80211) {
			/* XXX pass pktlen */
			(void) ieee80211_ratectl_rate(ni, NULL, 0);
			rate = ni->ni_txrate;
		} else {
			if (ni->ni_flags & IEEE80211_NODE_HT)
				rate = IEEE80211_RATE_MCS | 0x4; /* MCS4 */
			else if (ic->ic_curmode != IEEE80211_MODE_11B)
				rate = ridx2rate[RTWN_RIDX_OFDM36];
			else
				rate = ridx2rate[RTWN_RIDX_CCK55];
		}
	}

	ridx = rate2ridx(rate);

	cipher = IEEE80211_CIPHER_NONE;
	if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
		k = ieee80211_crypto_encap(ni, m);
		if (k == NULL) {
			device_printf(sc->sc_dev,
			    "ieee80211_crypto_encap returns NULL.\n");
			return (ENOBUFS);
		}
		if (!(k->wk_flags & IEEE80211_KEY_SWCRYPT))
			cipher = k->wk_cipher->ic_cipher;

		/* in case packet header moved, reset pointer */
		wh = mtod(m, struct ieee80211_frame *);
	}
示例#14
0
static void
r12a_tx_raid(struct rtwn_softc *sc, struct r12a_tx_desc *txd,
    struct ieee80211_node *ni, int ismcast)
{
	struct ieee80211com *ic = &sc->sc_ic;
	struct ieee80211vap *vap = ni->ni_vap;
	struct ieee80211_channel *chan;
	enum ieee80211_phymode mode;
	uint8_t raid;

	chan = (ni->ni_chan != IEEE80211_CHAN_ANYC) ?
		ni->ni_chan : ic->ic_curchan;
	mode = ieee80211_chan2mode(chan);

	/* NB: group addressed frames are done at 11bg rates for now */
	if (ismcast || !(ni->ni_flags & IEEE80211_NODE_HT)) {
		switch (mode) {
		case IEEE80211_MODE_11A:
		case IEEE80211_MODE_11B:
		case IEEE80211_MODE_11G:
			break;
		case IEEE80211_MODE_11NA:
			mode = IEEE80211_MODE_11A;
			break;
		case IEEE80211_MODE_11NG:
			mode = IEEE80211_MODE_11G;
			break;
		default:
			device_printf(sc->sc_dev, "unknown mode(1) %d!\n",
			    ic->ic_curmode);
			return;
		}
	}

	switch (mode) {
	case IEEE80211_MODE_11A:
		raid = R12A_RAID_11G;
		break;
	case IEEE80211_MODE_11B:
		raid = R12A_RAID_11B;
		break;
	case IEEE80211_MODE_11G:
		if (vap->iv_flags & IEEE80211_F_PUREG)
			raid = R12A_RAID_11G;
		else
			raid = R12A_RAID_11BG;
		break;
	case IEEE80211_MODE_11NA:
		if (sc->ntxchains == 1)
			raid = R12A_RAID_11GN_1;
		else
			raid = R12A_RAID_11GN_2;
		break;
	case IEEE80211_MODE_11NG:
		if (sc->ntxchains == 1) {
			if (IEEE80211_IS_CHAN_HT40(chan))
				raid = R12A_RAID_11BGN_1_40;
			else
				raid = R12A_RAID_11BGN_1;
		} else {
			if (IEEE80211_IS_CHAN_HT40(chan))
				raid = R12A_RAID_11BGN_2_40;
			else
				raid = R12A_RAID_11BGN_2;
		}
		break;
	default:
		/* TODO: 80 MHz / 11ac */
		device_printf(sc->sc_dev, "unknown mode(2) %d!\n", mode);
		return;
	}

	txd->txdw1 |= htole32(SM(R12A_TXDW1_RAID, raid));
}