📄 ieee80211_node.c.svn-base
字号:
if (show_counter) { snprintf(node_count, sizeof(node_count), "[#NODES=%05d] ", atomic_read(&ni->ni_ic->ic_node_counter)); } va_start(args, message); vsnprintf(expanded_message, sizeof(expanded_message), message, args); printk(KERN_DEBUG "%s/%s: %s %s [node %p<" MAC_FMT ">%s%s%s%s, refs=%02d]\n", ni->ni_ic->ic_dev->name, ni->ni_vap->iv_dev->name, node_count, expanded_message, ni, MAC_ADDR(ni->ni_macaddr), ni->ni_table != NULL ? " in " : "", ni->ni_table != NULL ? ni->ni_table->nt_name : "", ni->ni_table != NULL ? " table" : "", ni->ni_table != NULL ? "" : " (not in any tables)", adjusted_refcount); dump_stack(); va_end(args);}#else# define node_print_message(...)#endifstatic voidnode_free(struct ieee80211_node *ni){ KASSERT(atomic_read(&ni->ni_refcnt) == 0, ("node being free whilst still referenced")); if (ni->ni_challenge != NULL) FREE(ni->ni_challenge, M_DEVBUF); if (ni->ni_wpa_ie != NULL) FREE(ni->ni_wpa_ie, M_DEVBUF); if (ni->ni_rsn_ie != NULL) FREE(ni->ni_rsn_ie, M_DEVBUF); if (ni->ni_wme_ie != NULL) FREE(ni->ni_wme_ie, M_DEVBUF); if (ni->ni_ath_ie != NULL) FREE(ni->ni_ath_ie, M_DEVBUF); if (ni->ni_suppchans != NULL) FREE(ni->ni_suppchans, M_DEVBUF); if (ni->ni_suppchans_new != NULL) FREE(ni->ni_suppchans_new, M_DEVBUF); if (ni->ni_needed_chans != NULL) FREE(ni->ni_needed_chans, M_DEVBUF); IEEE80211_NODE_SAVEQ_DESTROY(ni); FREE(ni, M_80211_NODE);}static int32_tnode_count(struct ieee80211com *ic){ return atomic_read(&ic->ic_node_counter);}static u_int8_tnode_getrssi(const struct ieee80211_node *ni){ 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. * Dont assume a BSS? * Allocates a new struct ieee80211_node that has a reference * count of one, and adds it to the node table. */struct ieee80211_node *ieee80211_alloc_node_table(struct ieee80211vap *vap, const u_int8_t *macaddr){ struct ieee80211com *ic = vap->iv_ic; struct ieee80211_node_table *nt = &ic->ic_sta; struct ieee80211_node *ni; ni = ieee80211_alloc_node(vap, macaddr); if (ni != NULL) { ni->ni_inact = ni->ni_inact_reload = nt->nt_inact_init; WME_UAPSD_NODE_TRIGSEQINIT(ni); IEEE80211_NODE_SAVEQ_INIT(ni, "unknown"); IEEE80211_NODE_TABLE_LOCK_IRQ(nt); node_table_join_locked(nt, ni); IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt); } else { printk(KERN_ERR "Failed to allocate node for " MAC_FMT ".\n", MAC_ADDR(macaddr)); } return ni;}EXPORT_SYMBOL(ieee80211_alloc_node_table);/* Allocate a node structure and initialise specialised structures * This function does not add the node to the node table, thus this * node will not be found using ieee80211_find_*node. * This is useful when sending one off errors or request denials. */static struct ieee80211_node *ieee80211_alloc_node(struct ieee80211vap *vap, const u_int8_t *macaddr){ struct ieee80211com *ic = vap->iv_ic; struct ieee80211_node *ni; /* This always allocates zeroed memoery */ ni = ic->ic_node_alloc(vap); if (ni != NULL) { atomic_set(&ni->ni_refcnt, 1); IEEE80211_ADDR_COPY(ni->ni_macaddr, macaddr); ni->ni_chan = IEEE80211_CHAN_ANYC; ni->ni_authmode = IEEE80211_AUTH_OPEN; ni->ni_txpower = ic->ic_txpowlimit; ieee80211_crypto_resetkey(vap, &ni->ni_ucastkey, IEEE80211_KEYIX_NONE); ni->ni_ath_defkeyindex = IEEE80211_INVAL_DEFKEY; ni->ni_vap = vap; ni->ni_ic = ic; atomic_inc(&ni->ni_ic->ic_node_counter); node_print_message(IEEE80211_MSG_NODE | IEEE80211_MSG_NODE_REF, 1 /* show counter */, 0 /* adjust refcount */, ni, "alloc" /* message */); } else { /* XXX msg */ vap->iv_stats.is_rx_nodealloc++; } return ni;}/* 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_NODE_TABLE_LOCK_IRQ(nt); wds->wds_ni = ieee80211_ref_node(ni); LIST_INSERT_HEAD(&nt->nt_wds_hash[hash], wds, wds_hash); IEEE80211_NODE_TABLE_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, *twds; hash = IEEE80211_NODE_HASH(macaddr); IEEE80211_NODE_TABLE_LOCK_IRQ(nt); LIST_FOREACH_SAFE(wds, &nt->nt_wds_hash[hash], wds_hash, twds) { if (IEEE80211_ADDR_EQ(wds->wds_macaddr, macaddr)) { LIST_REMOVE(wds, wds_hash); ieee80211_unref_node(&wds->wds_ni); FREE(wds, M_80211_WDS); break; } } IEEE80211_NODE_TABLE_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, *twds; IEEE80211_NODE_TABLE_LOCK_IRQ(nt); for (hash = 0; hash < IEEE80211_NODE_HASHSIZE; hash++) { LIST_FOREACH_SAFE(wds, &nt->nt_wds_hash[hash], wds_hash, twds) { if (wds->wds_ni == ni) { LIST_REMOVE(wds, wds_hash); ieee80211_unref_node(&wds->wds_ni); FREE(wds, M_80211_WDS); } } } IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);}EXPORT_SYMBOL(ieee80211_del_wds_node);static voidieee80211_node_wds_ageout(unsigned long data){ struct ieee80211_node_table *nt = (struct ieee80211_node_table *)data; int hash; struct ieee80211_wds_addr *wds, *twds; IEEE80211_NODE_TABLE_LOCK_IRQ(nt); for (hash = 0; hash < IEEE80211_NODE_HASHSIZE; hash++) { LIST_FOREACH_SAFE(wds, &nt->nt_wds_hash[hash], wds_hash, twds) { if (wds->wds_agingcount != WDS_AGING_STATIC) { if (!wds->wds_agingcount) { LIST_REMOVE(wds, wds_hash); ieee80211_unref_node(&wds->wds_ni); FREE(wds, M_80211_WDS); } else wds->wds_agingcount--; } } } IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt); mod_timer(&nt->nt_wds_aging_timer, jiffies + HZ * WDS_AGING_TIMER_VAL);}/* Add the specified station to the station table. * Allocates a new struct ieee80211_node that has a reference count of one * If tmp is 0, it is added to the node table and the reference is used. * If tmp is 1, then the caller gets to use the reference. */struct ieee80211_node *ieee80211_dup_bss(struct ieee80211vap *vap, const u_int8_t *macaddr, unsigned char tmp){ struct ieee80211_node *ni; /* FIXME: Hack */ if (tmp) { ni = ieee80211_alloc_node(vap, macaddr); } else { ni = ieee80211_alloc_node_table(vap, macaddr); IEEE80211_DPRINTF(vap, IEEE80211_MSG_ASSOC, "%s: ni:%p allocated for " MAC_FMT "\n", __func__, ni, MAC_ADDR(macaddr)); } if (ni != NULL) { copy_bss_state(ni, vap->iv_bss); IEEE80211_ADDR_COPY(ni->ni_bssid, vap->iv_bssid); /* Do this only for nodes that already have a BSS. Otherwise * ic_bsschan is not set and we get a KASSERT failure. * Required by ieee80211_fix_rate */ ieee80211_node_set_chan(vap->iv_ic, ni); } return ni;}static struct ieee80211_node *ieee80211_find_wds_node_locked(struct ieee80211_node_table *nt, const u_int8_t *macaddr){ struct ieee80211_wds_addr *wds; int hash; IEEE80211_NODE_TABLE_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)) { /* Reset the aging count. */ if (wds->wds_agingcount != WDS_AGING_STATIC) wds->wds_agingcount = WDS_AGING_COUNT; return ieee80211_ref_node(wds->wds_ni); } } return NULL;}/* NB: A node reference is acquired here; the caller MUST release it. */static struct ieee80211_node *ieee80211_find_node_locked(struct ieee80211_node_table *nt, const u_int8_t *macaddr){ struct ieee80211_node *ni; int hash; struct ieee80211_wds_addr *wds; IEEE80211_NODE_TABLE_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); 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)) return ieee80211_ref_node(wds->wds_ni); } return NULL;}struct ieee80211_node *ieee80211_find_wds_node(struct ieee80211_node_table *nt, const u_int8_t *macaddr){ struct ieee80211_node *ni; IEEE80211_NODE_TABLE_LOCK_IRQ(nt); ni = ieee80211_find_wds_node_locked(nt, macaddr); IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt); return ni;}EXPORT_SYMBOL(ieee80211_find_wds_node);struct ieee80211_node *ieee80211_find_node(struct ieee80211_node_table *nt, const u_int8_t *macaddr){ struct ieee80211_node *ni; IEEE80211_NODE_TABLE_LOCK_IRQ(nt); ni = ieee80211_find_node_locked(nt, macaddr); IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt); return ni;}EXPORT_SYMBOL(ieee80211_find_node);/* * 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 * its 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, 0); 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); } 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 its 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, 0); 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 = IEEE80211_BINTVAL_SANITISE(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 * us to use QoS to disable ACKs and to use short * preamble on 2.4G channels. */ if (vap->iv_flags & IEEE80211_F_WME) ni->ni_flags |= IEEE80211_NODE_QOS; if (vap->iv_flags & IEEE80211_F_SHPREAMBLE) ni->ni_capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE; } } return ni;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -