📄 ieee80211_node.c
字号:
return ni->ni_rssi;}/* * Create an entry in the specified node table. The node * is setup with the mac address, an initial reference count, * and some basic parameters obtained from global state. * This interface is not intended for general use, it is * used by the routines below to create entries with a * specific purpose. */struct ieee80211_node *ieee80211_alloc_node(struct ieee80211_node_table *nt, struct ieee80211vap *vap, const u_int8_t *macaddr){ struct ieee80211com *ic = nt->nt_ic; struct ieee80211_node *ni; int hash; int i; ni = ic->ic_node_alloc(nt, vap); if (ni == NULL) { /* XXX msg */ vap->iv_stats.is_rx_nodealloc++; return NULL; } IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE, "%s: %p<%s> in %s table, refcnt %d\n", __func__, ni, ether_sprintf(macaddr), nt->nt_name, ieee80211_node_refcnt(ni)+1); IEEE80211_ADDR_COPY(ni->ni_macaddr, macaddr); hash = IEEE80211_NODE_HASH(macaddr); ieee80211_node_initref(ni); /* mark referenced */ ni->ni_chan = IEEE80211_CHAN_ANYC; ni->ni_authmode = IEEE80211_AUTH_OPEN; ni->ni_txpower = ic->ic_txpowlimit; /* max power */ ieee80211_crypto_resetkey(vap, &ni->ni_ucastkey, IEEE80211_KEYIX_NONE); ni->ni_inact_reload = nt->nt_inact_init; ni->ni_inact = ni->ni_inact_reload; ni->ni_ath_defkeyindex = IEEE80211_INVAL_DEFKEY; ni->ni_rxkeyoff = 0; IEEE80211_NODE_SAVEQ_INIT(ni, "unknown"); IEEE80211_NODE_LOCK_IRQ(nt); ni->ni_vap = vap; ni->ni_ic = ic; ni->ni_table = nt; TAILQ_INSERT_TAIL(&nt->nt_node, ni, ni_list); LIST_INSERT_HEAD(&nt->nt_hash[hash], ni, ni_hash);#define N(a) (sizeof(a)/sizeof(a[0])) for (i = 0; i < N(ni->ni_rxfrag); i++) ni->ni_rxfrag[i] = NULL;#undef N ni->ni_challenge = NULL; IEEE80211_NODE_UNLOCK_IRQ(nt); WME_UAPSD_NODE_TRIGSEQINIT(ni); return ni;}EXPORT_SYMBOL(ieee80211_alloc_node);/* Add wds address to the node table */intieee80211_add_wds_addr(struct ieee80211_node_table *nt, struct ieee80211_node *ni, const u_int8_t *macaddr, u_int8_t wds_static){ int hash; struct ieee80211_wds_addr *wds; MALLOC(wds, struct ieee80211_wds_addr *, sizeof(struct ieee80211_wds_addr), M_80211_WDS, M_NOWAIT | M_ZERO); if (wds == NULL) { /* XXX msg */ return 1; } if (wds_static) wds->wds_agingcount = WDS_AGING_STATIC; else wds->wds_agingcount = WDS_AGING_COUNT; hash = IEEE80211_NODE_HASH(macaddr); IEEE80211_ADDR_COPY(wds->wds_macaddr, macaddr); ieee80211_ref_node(ni); /* Reference node */ wds->wds_ni = ni; IEEE80211_NODE_LOCK_IRQ(nt); LIST_INSERT_HEAD(&nt->nt_wds_hash[hash], wds, wds_hash); IEEE80211_NODE_UNLOCK_IRQ(nt); return 0;}EXPORT_SYMBOL(ieee80211_add_wds_addr);/* remove wds address from the wds hash table */voidieee80211_remove_wds_addr(struct ieee80211_node_table *nt, const u_int8_t *macaddr){ int hash; struct ieee80211_wds_addr *wds; hash = IEEE80211_NODE_HASH(macaddr); IEEE80211_NODE_LOCK_IRQ(nt); LIST_FOREACH(wds, &nt->nt_wds_hash[hash], wds_hash) { if (IEEE80211_ADDR_EQ(wds->wds_macaddr, macaddr)) { if (ieee80211_node_dectestref(wds->wds_ni)) { _ieee80211_free_node(wds->wds_ni); LIST_REMOVE(wds, wds_hash); FREE(wds, M_80211_WDS); break; } } } IEEE80211_NODE_UNLOCK_IRQ(nt);}EXPORT_SYMBOL(ieee80211_remove_wds_addr);/* Remove node references from wds table */voidieee80211_del_wds_node(struct ieee80211_node_table *nt, struct ieee80211_node *ni){ int hash; struct ieee80211_wds_addr *wds; IEEE80211_NODE_LOCK_IRQ(nt); for (hash = 0; hash < IEEE80211_NODE_HASHSIZE; hash++) { LIST_FOREACH(wds, &nt->nt_wds_hash[hash], wds_hash) { if (wds->wds_ni == ni) { if (ieee80211_node_dectestref(ni)) { _ieee80211_free_node(ni); LIST_REMOVE(wds, wds_hash); FREE(wds, M_80211_WDS); } } } } IEEE80211_NODE_UNLOCK_IRQ(nt);}EXPORT_SYMBOL(ieee80211_del_wds_node);static void ieee80211_node_wds_ageout(unsigned long data){ struct ieee80211_node_table *nt = (struct ieee80211_node_table *)data; int hash; struct ieee80211_wds_addr *wds; IEEE80211_NODE_LOCK_IRQ(nt); for (hash = 0; hash < IEEE80211_NODE_HASHSIZE; hash++) { LIST_FOREACH(wds, &nt->nt_wds_hash[hash], wds_hash) { if (wds->wds_agingcount != WDS_AGING_STATIC) { if (!wds->wds_agingcount) { if (ieee80211_node_dectestref(wds->wds_ni)) { _ieee80211_free_node(wds->wds_ni); LIST_REMOVE(wds, wds_hash); FREE(wds, M_80211_WDS); } } else wds->wds_agingcount--; } } } IEEE80211_NODE_UNLOCK_IRQ(nt); mod_timer(&nt->nt_wds_aging_timer, jiffies + HZ * WDS_AGING_TIMER_VAL);}/* * Craft a temporary node suitable for sending a management frame * to the specified station. We craft only as much state as we * need to do the work since the node will be immediately reclaimed * once the send completes. */struct ieee80211_node *ieee80211_tmp_node(struct ieee80211vap *vap, const u_int8_t *macaddr){ struct ieee80211com *ic = vap->iv_ic; struct ieee80211_node *ni; int i; ni = ic->ic_node_alloc(&ic->ic_sta,vap); if (ni != NULL) { IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE, "%s: %p<%s> refcnt %d\n", __func__, ni, ether_sprintf(macaddr), ieee80211_node_refcnt(ni)+1); IEEE80211_ADDR_COPY(ni->ni_macaddr, macaddr); IEEE80211_ADDR_COPY(ni->ni_bssid, vap->iv_bss->ni_bssid); ieee80211_node_initref(ni); /* mark referenced */ ni->ni_txpower = vap->iv_bss->ni_txpower; ni->ni_vap = vap; /* NB: required by ieee80211_fix_rate */ ieee80211_node_set_chan(ic, ni); ieee80211_crypto_resetkey(vap, &ni->ni_ucastkey, IEEE80211_KEYIX_NONE); /* XXX optimize away */ IEEE80211_NODE_SAVEQ_INIT(ni, "unknown"); ni->ni_table = NULL; /* NB: pedantic */ ni->ni_ic = ic;#define N(a) (sizeof(a)/sizeof(a[0])) for (i = 0; i < N(ni->ni_rxfrag); i++) ni->ni_rxfrag[i] = NULL;#undef N ni->ni_challenge = NULL; } else { /* XXX msg */ vap->iv_stats.is_rx_nodealloc++; } return ni;}/* * Add the specified station to the station table. */struct ieee80211_node *ieee80211_dup_bss(struct ieee80211vap *vap, const u_int8_t *macaddr){ struct ieee80211com *ic = vap->iv_ic; struct ieee80211_node *ni; int i; ni = ieee80211_alloc_node(&ic->ic_sta, vap, macaddr); if (ni != NULL) { /* * Inherit from iv_bss. */ ni->ni_authmode = vap->iv_bss->ni_authmode; ni->ni_txpower = vap->iv_bss->ni_txpower; ni->ni_vlan = vap->iv_bss->ni_vlan; /* XXX?? */ IEEE80211_ADDR_COPY(ni->ni_bssid, vap->iv_bss->ni_bssid); ieee80211_node_set_chan(ic, ni); ni->ni_rsn = vap->iv_bss->ni_rsn;#define N(a) (sizeof(a)/sizeof(a[0])) for (i = 0; i < N(ni->ni_rxfrag); i++) ni->ni_rxfrag[i] = NULL;#undef N } return ni;}static struct ieee80211_node *_ieee80211_find_wds_node(struct ieee80211_node_table *nt, const u_int8_t *macaddr){ struct ieee80211_node *ni; struct ieee80211_wds_addr *wds; int hash; IEEE80211_NODE_LOCK_ASSERT(nt); hash = IEEE80211_NODE_HASH(macaddr); LIST_FOREACH(wds, &nt->nt_wds_hash[hash], wds_hash) { if (IEEE80211_ADDR_EQ(wds->wds_macaddr, macaddr)) { ni = wds->wds_ni; if (wds->wds_agingcount != WDS_AGING_STATIC) wds->wds_agingcount = WDS_AGING_COUNT; /* reset the aging count */ ieee80211_ref_node(ni); return ni; } } return NULL;}static struct ieee80211_node *#ifdef IEEE80211_DEBUG_REFCNT_ieee80211_find_node_debug(struct ieee80211_node_table *nt, const u_int8_t *macaddr, const char *func, int line)#else_ieee80211_find_node(struct ieee80211_node_table *nt, const u_int8_t *macaddr)#endif{ struct ieee80211_node *ni; int hash; struct ieee80211_wds_addr *wds; IEEE80211_NODE_LOCK_ASSERT(nt); hash = IEEE80211_NODE_HASH(macaddr); LIST_FOREACH(ni, &nt->nt_hash[hash], ni_hash) { if (IEEE80211_ADDR_EQ(ni->ni_macaddr, macaddr)) { ieee80211_ref_node(ni); /* mark referenced */#ifdef IEEE80211_DEBUG_REFCNT IEEE80211_DPRINTF(ni->ni_vap, IEEE80211_MSG_NODE, "%s (%s:%u) %p<%s> refcnt %d\n", __func__, func, line, ni, ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni));#endif return ni; } } /* Now, we look for the desired mac address in the 4 address nodes. */ LIST_FOREACH(wds, &nt->nt_wds_hash[hash], wds_hash) { if (IEEE80211_ADDR_EQ(wds->wds_macaddr, macaddr)) { ni = wds->wds_ni; ieee80211_ref_node(ni); return ni; } } return NULL;}#ifdef IEEE80211_DEBUG_REFCNT#define _ieee80211_find_node(nt, mac) \ _ieee80211_find_node_debug(nt, mac, func, line)#endifstruct ieee80211_node *ieee80211_find_wds_node(struct ieee80211_node_table *nt, const u_int8_t *macaddr){ struct ieee80211_node *ni; IEEE80211_NODE_LOCK_IRQ(nt); ni = _ieee80211_find_wds_node(nt, macaddr); IEEE80211_NODE_UNLOCK_IRQ(nt); return ni;}EXPORT_SYMBOL(ieee80211_find_wds_node);struct ieee80211_node *#ifdef IEEE80211_DEBUG_REFCNTieee80211_find_node_debug(struct ieee80211_node_table *nt, const u_int8_t *macaddr, const char *func, int line)#elseieee80211_find_node(struct ieee80211_node_table *nt, const u_int8_t *macaddr)#endif{ struct ieee80211_node *ni; IEEE80211_NODE_LOCK_IRQ(nt); ni = _ieee80211_find_node(nt, macaddr); IEEE80211_NODE_UNLOCK_IRQ(nt); return ni;}#ifdef IEEE80211_DEBUG_REFCNTEXPORT_SYMBOL(ieee80211_find_node_debug);#elseEXPORT_SYMBOL(ieee80211_find_node);#endif/* * Fake up a node; this handles node discovery in adhoc mode. * Note that for the driver's benefit we we treat this like * an association so the driver has an opportunity to setup * it's private state. * * Caller must ieee80211_ref_node() */struct ieee80211_node *ieee80211_fakeup_adhoc_node(struct ieee80211vap *vap, const u_int8_t macaddr[IEEE80211_ADDR_LEN]){ struct ieee80211_node *ni; ni = ieee80211_dup_bss(vap, macaddr); if (ni != NULL) { /* XXX no rate negotiation; just dup */ ni->ni_rates = vap->iv_bss->ni_rates; if (vap->iv_ic->ic_newassoc != NULL) vap->iv_ic->ic_newassoc(ni, 1); /* XXX not right for 802.1x/WPA */ ieee80211_node_authorize(ni); IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE, "%s: %p<%s> refcnt %d\n", __func__, ni, ether_sprintf(macaddr), ieee80211_node_refcnt(ni)); } return ni;}/* * Do node discovery in adhoc mode on receipt of a beacon * or probe response frame. Note that for the driver's * benefit we treat this like an association so the * driver has an opportunity to setup it's private state. */struct ieee80211_node *ieee80211_add_neighbor(struct ieee80211vap *vap, const struct ieee80211_frame *wh, const struct ieee80211_scanparams *sp){ struct ieee80211com *ic = vap->iv_ic; struct ieee80211_node *ni; ni = ieee80211_dup_bss(vap, wh->i_addr2); /* XXX alloc_node? */ /* TODO: not really putting itself in a table */ if (ni != NULL) { ni->ni_esslen = sp->ssid[1]; memcpy(ni->ni_essid, sp->ssid + 2, sp->ssid[1]); IEEE80211_ADDR_COPY(ni->ni_bssid, wh->i_addr3); memcpy(ni->ni_tstamp.data, sp->tstamp, sizeof(ni->ni_tstamp)); ni->ni_intval = sp->bintval; ni->ni_capinfo = sp->capinfo; ni->ni_chan = ic->ic_curchan; ni->ni_fhdwell = sp->fhdwell; ni->ni_fhindex = sp->fhindex; ni->ni_erp = sp->erp; ni->ni_timoff = sp->timoff; if (sp->wme != NULL) ieee80211_saveie(&ni->ni_wme_ie, sp->wme); if (sp->wpa != NULL) ieee80211_saveie(&ni->ni_wpa_ie, sp->wpa); if (sp->rsn != NULL) ieee80211_saveie(&ni->ni_rsn_ie, sp->rsn); if (sp->ath != NULL) ieee80211_saveath(ni, sp->ath); /* NB: must be after ni_chan is setup */ ieee80211_setup_rates(ni, sp->rates, sp->xrates, IEEE80211_F_DOSORT); if (ic->ic_newassoc != NULL) ic->ic_newassoc(ni, 1); /* XXX not right for 802.1x/WPA */ ieee80211_node_authorize(ni); if (vap->iv_opmode == IEEE80211_M_AHDEMO) { /* * Blindly propagate capabilities based on the * local configuration. In particular this permits
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -