/* * 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 }
/* * 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 }
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; }