Beispiel #1
0
/*
 * Handle bookkeeping for station deauthentication/disassociation
 * when operating as an ap.
 */
void
ieee80211_node_leave(struct ieee80211com *ic, struct ieee80211_node *ni)
{
	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
		panic("not in ap mode, mode %u", ic->ic_opmode);
	/*
	 * If node wasn't previously associated all
	 * we need to do is reclaim the reference.
	 */
	if (ni->ni_associd == 0)
		return;
	IEEE80211_AID_CLR(ni->ni_associd, ic->ic_aid_bitmap);
	ni->ni_associd = 0;

	if (ic->ic_curmode == IEEE80211_MODE_11G)
		ieee80211_node_leave_11g(ic, ni);

	ieee80211_node_newstate(ni, IEEE80211_STA_COLLECT);

#if NBRIDGE > 0
	/*
	 * If the parent interface belongs to a bridge, delete
	 * any dynamically learned address for this node.
	 */
	if (ic->ic_if.if_bridge != NULL)
		bridge_update(&ic->ic_if,
		    (struct ether_addr *)ni->ni_macaddr, 1);
#endif
}
Beispiel #2
0
/*
 * Handle bookkeeping for station deauthentication/disassociation
 * when operating as an ap.
 */
void
ieee80211_node_leave(struct ieee80211com *ic, struct ieee80211_node *ni)
{
	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
		panic("not in ap mode, mode %u", ic->ic_opmode);
	/*
	 * If node wasn't previously associated all we need to do is
	 * reclaim the reference.
	 */
	if (ni->ni_associd == 0) {
		ieee80211_node_newstate(ni, IEEE80211_STA_COLLECT);
		return;
	}

	if (ni->ni_pwrsave == IEEE80211_PS_DOZE) {
		ic->ic_pssta--;
		ni->ni_pwrsave = IEEE80211_PS_AWAKE;
	}

	if (!IF_IS_EMPTY(&ni->ni_savedq)) {
		IF_PURGE(&ni->ni_savedq);
		if (ic->ic_set_tim != NULL)
			(*ic->ic_set_tim)(ic, ni->ni_associd, 0);
	}

	if (ic->ic_flags & IEEE80211_F_RSNON)
		ieee80211_node_leave_rsn(ic, ni);

	if (ic->ic_curmode == IEEE80211_MODE_11G)
		ieee80211_node_leave_11g(ic, ni);

#ifndef IEEE80211_NO_HT
	if (ni->ni_flags & IEEE80211_NODE_HT)
		ieee80211_node_leave_ht(ic, ni);
#endif

	if (ic->ic_node_leave != NULL)
		(*ic->ic_node_leave)(ic, ni);

	IEEE80211_AID_CLR(ni->ni_associd, ic->ic_aid_bitmap);
	ni->ni_associd = 0;
	ieee80211_node_newstate(ni, IEEE80211_STA_COLLECT);

#if NBRIDGE > 0
	/*
	 * If the parent interface is a bridgeport, delete
	 * any dynamically learned address for this node.
	 */
	if (ic->ic_if.if_bridgeport != NULL)
		bridge_update(&ic->ic_if,
		    (struct ether_addr *)ni->ni_macaddr, 1);
#endif
}
Beispiel #3
0
bool _ieee80211_node_leave(struct ieee80211_node *ni)
#endif
{
    struct ieee80211com *ic = ni->ni_ic;
    struct ieee80211vap *vap = ni->ni_vap;
	bool   retval = false;
#ifdef IEEE80211_DEBUG_REFCNT
    TRACENODE(ni, func, line);
#endif
    IEEE80211_NOTE(vap, IEEE80211_MSG_ASSOC | IEEE80211_MSG_DEBUG, ni,
                   "station with aid %d leaves (refcnt %u) \n",
                   IEEE80211_NODE_AID(ni), ieee80211_node_refcnt(ni));
#ifdef ATH_SWRETRY
    (ni->ni_ic)->ic_reset_pause_tid(ni->ni_ic, ni);
#endif

    if (!IEEE80211_IS_TDLS_NODE(ni)) 
    KASSERT(vap->iv_opmode == IEEE80211_M_HOSTAP
            || vap->iv_opmode == IEEE80211_M_WDS || vap->iv_opmode == IEEE80211_M_BTAMP,
            ("unexpected operating mode %u", vap->iv_opmode));

    /* Multicast enhancement: If the entry with the node's address exists in 
     * the snoop table, it should be removed.
     */
    if (vap->iv_ique_ops.me_clean) {
        vap->iv_ique_ops.me_clean(ni);
    }
	/*    
     * HBR / headline block removal: delete the node entity from the table
     * for HBR purpose
     */
    if (vap->iv_ique_ops.hbr_nodeleave) {
        vap->iv_ique_ops.hbr_nodeleave(vap, ni);
    }
    /*
     * If node wasn't previously associated all
     * we need to do is reclaim the reference.
     */
    /* XXX ibss mode bypasses 11g and notification */

    IEEE80211_NODE_STATE_LOCK(ni);
    if (ni->ni_associd) {
        vap->iv_sta_assoc--;
        ic->ic_sta_assoc--;
        /* Update bss load element in beacon */
        ieee80211_vap_bssload_update_set(vap);

        if (IEEE80211_NODE_USEAMPDU(ni)) {
            ic->ic_ht_sta_assoc--;
            if (ni->ni_htcap & IEEE80211_HTCAP_C_GREENFIELD) {
                ASSERT(ic->ic_ht_gf_sta_assoc > 0);
                ic->ic_ht_gf_sta_assoc--;
            }
        }
        if (ni->ni_chwidth == IEEE80211_CWM_WIDTH40)
            ic->ic_ht40_sta_assoc--;

        if ((IEEE80211_IS_CHAN_ANYG(vap->iv_bsschan) ||
            IEEE80211_IS_CHAN_11NG(vap->iv_bsschan))  && !IEEE80211_IS_TDLS_NODE(ni))
            ieee80211_node_leave_11g(ni);

        IEEE80211_NODE_STATE_UNLOCK(ni);
        IEEE80211_DELETE_NODE_TARGET(ni, ic, vap, 0);
    } else {
        IEEE80211_NODE_STATE_UNLOCK(ni);
    }

    ieee80211_admctl_node_leave(vap, ni);

    /*
     * Cleanup station state.  In particular clear various state that 
     * might otherwise be reused if the node is reused before the
     * reference count goes to zero (and memory is reclaimed).
     *
     * If ni is not in node table, it has been reclaimed in another thread.
     */
    retval = ieee80211_sta_leave(ni);

    if ((ni->ni_flags & IEEE80211_NODE_HT) && 
        (ni->ni_flags & IEEE80211_NODE_40_INTOLERANT)) {
        ieee80211_change_cw(ic);
    }


	return retval;
}