bss_t * wlan_node_remove(struct ieee80211_node_table *nt, A_UINT8 *bssid) { bss_t *bss, *nextBss; IEEE80211_NODE_LOCK(nt); bss = nt->nt_node_first; while (bss != NULL) { nextBss = bss->ni_list_next; if (A_MEMCMP(bssid, bss->ni_macaddr, 6) == 0) { wlan_node_remove_core (nt, bss); IEEE80211_NODE_UNLOCK(nt); return bss; } bss = nextBss; } IEEE80211_NODE_UNLOCK(nt); return NULL; }
/* Update the buffer alone, not the entire node. * This involves, * 1) Freeing the buffer alone. * 2) Allocating a new buffer * 3) Update the node timestamp with the current time. */ A_STATUS wlan_node_buf_update(struct ieee80211_node_table *nt, bss_t *ni, A_UINT32 len) { IEEE80211_NODE_LOCK(nt); /* Free the ni_buf alone. */ if (ni->ni_buf != NULL) { A_FREE(ni->ni_buf); ni->ni_buf = NULL; } /* Allocate ni_buf for the new length. */ if (len) { ni->ni_buf = A_MALLOC_NOWAIT(len); if (ni->ni_buf == NULL) { IEEE80211_NODE_UNLOCK(nt); return A_ERROR; } else { A_MEMZERO(ni->ni_buf, len); } } /* Update the Node's timestamp. */ wlan_node_update_timestamp(nt, ni); IEEE80211_NODE_UNLOCK(nt); return A_OK; }
/* * Timeout inactive nodes. Note that we cannot hold the node * lock while sending a frame as this would lead to a LOR. * Instead we use a generation number to mark nodes that we've * scanned and drop the lock and restart a scan if we have to * time out a node. Since we are single-threaded by virtue of * controlling the inactivity timer we can be sure this will * process each node only once. */ void ieee80211_clean_nodes(struct ieee80211com *ic) { struct ieee80211_node *ni, *next_ni; u_int gen = ic->ic_scangen++; /* NB: ok 'cuz single-threaded*/ IEEE80211_NODE_LOCK(ic); for (ni = RB_MIN(ieee80211_tree, &ic->ic_tree); ni != NULL; ni = next_ni) { next_ni = RB_NEXT(ieee80211_tree, &ic->ic_tree, ni); if (ic->ic_nnodes <= ic->ic_max_nnodes) break; if (ni->ni_scangen == gen) /* previously handled */ continue; ni->ni_scangen = gen; if (ni->ni_refcnt > 0) continue; IEEE80211_DPRINTF(("station %s purged from LRU cache\n", ether_sprintf(ni->ni_macaddr))); /* * Send a deauthenticate frame. */ if (ic->ic_opmode == IEEE80211_M_HOSTAP) { IEEE80211_NODE_UNLOCK(ic); IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DEAUTH, IEEE80211_REASON_AUTH_EXPIRE); IEEE80211_NODE_LOCK(ic); ieee80211_node_leave(ic, ni); } else ieee80211_free_node(ic, ni); ic->ic_stats.is_node_timeout++; } IEEE80211_NODE_UNLOCK(ic); }
void wlan_iterate_nodes(struct ieee80211_node_table *nt, wlan_node_iter_func *f, void *arg) { bss_t *ni; A_UINT32 gen; A_UINT32 numNodes = 0; gen = ++nt->nt_scangen; IEEE80211_NODE_LOCK (nt); for (ni = nt->nt_node_first; ni; ni = ni->ni_list_next) { /*if (ni->ni_scangen != gen) { */ { numNodes++; ni->ni_scangen = gen; (void) ieee80211_node_incref(ni); (*f)(arg, ni); wlan_node_dec_free(ni); } } IEEE80211_NODE_UNLOCK (nt); /*RETAILMSG (1, (L"numNodes available ==> %d\n", numNodes)); */ }
/* * Drivers call this, so increase the reference count before returning * the node. */ struct ieee80211_node * ieee80211_find_rxnode(struct ieee80211com *ic, struct ieee80211_frame *wh) { struct ieee80211_node *ni; const static u_int8_t zero[IEEE80211_ADDR_LEN]; u_int8_t *bssid; if (!ieee80211_needs_rxnode(ic, wh, &bssid)) return ieee80211_ref_node(ic->ic_bss); IEEE80211_NODE_LOCK(ic); ni = ieee80211_find_node(ic, wh->i_addr2); IEEE80211_NODE_UNLOCK(ic); if (ni != NULL) return ieee80211_ref_node(ni); if (ic->ic_opmode == IEEE80211_M_HOSTAP) return ieee80211_ref_node(ic->ic_bss); /* XXX see remarks in ieee80211_find_txnode */ /* XXX no rate negotiation; just dup */ if ((ni = ieee80211_dup_bss(ic, wh->i_addr2)) == NULL) return ieee80211_ref_node(ic->ic_bss); IEEE80211_ADDR_COPY(ni->ni_bssid, (bssid != NULL) ? bssid : zero); ni->ni_rates = ic->ic_bss->ni_rates; if (ic->ic_newassoc) (*ic->ic_newassoc)(ic, ni, 1); IEEE80211_DPRINTF(("%s: faked-up node %p for %s\n", __func__, ni, ether_sprintf(wh->i_addr2))); return ieee80211_ref_node(ni); }
void wlan_node_return (struct ieee80211_node_table *nt, bss_t *ni) { IEEE80211_NODE_LOCK (nt); wlan_node_dec_free (ni); IEEE80211_NODE_UNLOCK (nt); }
static void wlan_node_timeout(void *arg) { struct ieee80211_node_table *nt = (struct ieee80211_node_table *)arg; bss_t *bss, *nextBss; A_UINT8 myBssid[IEEE80211_ADDR_LEN]; wmi_get_current_bssid(nt->nt_wmip, myBssid); IEEE80211_NODE_LOCK(nt); bss = nt->nt_node_first; while (bss != NULL) { nextBss = bss->ni_list_next; if ((A_MEMCMP(myBssid, bss->ni_macaddr, sizeof(myBssid)) != 0) && (bss->ni_tstamp <= A_MS_TICKGET())) { /* * free up all but the current bss - if set */ wlan_node_reclaim(nt, bss); } bss = nextBss; } IEEE80211_NODE_UNLOCK(nt); A_TIMEOUT_MS(&nt->nt_inact_timer, WLAN_NODE_INACT_TIMEOUT_MSEC, 0); }
bss_t * wlan_find_Ssidnode (struct ieee80211_node_table *nt, A_UCHAR *pSsid, A_UINT32 ssidLength, A_BOOL bIsWPA2, A_BOOL bMatchSSID) { bss_t *ni = NULL; A_UCHAR *pIESsid = NULL; IEEE80211_NODE_LOCK (nt); for (ni = nt->nt_node_first; ni; ni = ni->ni_list_next) { pIESsid = ni->ni_cie.ie_ssid; if (pIESsid[1] <= 32) { // Step 1 : Check SSID if (0x00 == memcmp (pSsid, &pIESsid[2], ssidLength)) { // ni->ni_macaddr //builder: check BSSID match // // Step 2.1 : Check MatchSSID is TRUE, if so, return Matched SSID // Profile, otherwise check whether WPA2 or WPA // if (TRUE == bMatchSSID) { ieee80211_node_incref (ni); /* mark referenced */ IEEE80211_NODE_UNLOCK (nt); return ni; } // Step 2 : if SSID matches, check WPA or WPA2 if (TRUE == bIsWPA2 && NULL != ni->ni_cie.ie_rsn) { ieee80211_node_incref (ni); /* mark referenced */ IEEE80211_NODE_UNLOCK (nt); return ni; } if (FALSE == bIsWPA2 && NULL != ni->ni_cie.ie_wpa) { ieee80211_node_incref(ni); /* mark referenced */ IEEE80211_NODE_UNLOCK (nt); return ni; } } } } IEEE80211_NODE_UNLOCK (nt); return NULL; }
bss_t * wlan_find_node(struct ieee80211_node_table *nt, const A_UINT8 *macaddr) { bss_t *ni; IEEE80211_NODE_LOCK(nt); ni = _ieee80211_find_node(nt, macaddr); IEEE80211_NODE_UNLOCK(nt); return ni; }
void ieee80211_iterate_nodes(struct ieee80211com *ic, ieee80211_iter_func *f, void *arg) { struct ieee80211_node *ni; IEEE80211_NODE_LOCK(ic); RB_FOREACH(ni, ieee80211_tree, &ic->ic_tree) (*f)(arg, ni); IEEE80211_NODE_UNLOCK(ic); }
void wlan_free_allnodes(struct ieee80211_node_table *nt) { bss_t *ni; IEEE80211_NODE_LOCK(nt); while ((ni = nt->nt_node_first) != NULL) { wlan_node_reclaim(nt, ni); } IEEE80211_NODE_UNLOCK(nt); }
void wlan_node_ret_n_remove(struct ieee80211_node_table *nt, bss_t *ni) { IEEE80211_NODE_LOCK(nt); ieee80211_node_decref(ni); if (ieee80211_node_refcnt(ni) == 0) { wlan_node_free(ni); } else { wlan_node_reclaim(nt, ni); } IEEE80211_NODE_UNLOCK(nt); }
bss_t * wlan_find_node(struct ieee80211_node_table *nt, const A_UINT8 *macaddr) { bss_t *ni = NULL; if (NULL == nt || NULL == macaddr) { return ni; // NULL } IEEE80211_NODE_LOCK(nt); ni = _ieee80211_find_node(nt, macaddr); IEEE80211_NODE_UNLOCK(nt); return ni; }
/* * Reclaim a node. If this is the last reference count then * do the normal free work. Otherwise remove it from the node * table and mark it gone by clearing the back-reference. */ void wlan_node_reclaim(struct ieee80211_node_table *nt, bss_t *ni) { IEEE80211_NODE_LOCK(nt); if (ieee80211_node_dectestref(ni)) { if(ni->ni_list_prev == NULL) { /* First in list so fix the list head */ nt->nt_node_first = ni->ni_list_next; } else { ni->ni_list_prev->ni_list_next = ni->ni_list_next; } if(ni->ni_list_next == NULL) { /* Last in list so fix list tail */ nt->nt_node_last = ni->ni_list_prev; } else { ni->ni_list_next->ni_list_prev = ni->ni_list_prev; } if(ni->ni_hash_prev == NULL) { /* First in list so fix the list head */ int hash; hash = IEEE80211_NODE_HASH(ni->ni_macaddr); nt->nt_hash[hash] = ni->ni_hash_next; } else { ni->ni_hash_prev->ni_hash_next = ni->ni_hash_next; } if(ni->ni_hash_next != NULL) { ni->ni_hash_next->ni_hash_prev = ni->ni_hash_prev; } wlan_node_free(ni); } IEEE80211_NODE_UNLOCK(nt); }
void wlan_iterate_nodes(struct ieee80211_node_table *nt, wlan_node_iter_func *f, void *arg) { bss_t *ni; A_UINT32 gen; gen = nt->nt_scangen++; IEEE80211_NODE_LOCK(nt); for (ni = nt->nt_node_first; ni; ni = ni->ni_list_next) { if (ni->ni_scangen != gen) { ni->ni_scangen = gen; (*f)(arg, ni); } } IEEE80211_NODE_UNLOCK(nt); }
/* * Return a reference to the appropriate node for sending * a data frame. This handles node discovery in adhoc networks. * * Drivers will call this, so increase the reference count before * returning the node. */ struct ieee80211_node * ieee80211_find_txnode(struct ieee80211com *ic, u_int8_t *macaddr) { struct ieee80211_node *ni; /* * The destination address should be in the node table * unless we are operating in station mode or this is a * multicast/broadcast frame. */ if (ic->ic_opmode == IEEE80211_M_STA || IEEE80211_IS_MULTICAST(macaddr)) return ieee80211_ref_node(ic->ic_bss); /* XXX can't hold lock across dup_bss 'cuz of recursive locking */ IEEE80211_NODE_LOCK(ic); ni = ieee80211_find_node(ic, macaddr); IEEE80211_NODE_UNLOCK(ic); if (ni == NULL) { if (ic->ic_opmode != IEEE80211_M_IBSS && ic->ic_opmode != IEEE80211_M_AHDEMO) return NULL; /* * 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. * * XXX need better way to handle this; issue probe * request so we can deduce rate set, etc. */ if ((ni = ieee80211_dup_bss(ic, macaddr)) == NULL) return NULL; /* XXX no rate negotiation; just dup */ ni->ni_rates = ic->ic_bss->ni_rates; if (ic->ic_newassoc) (*ic->ic_newassoc)(ic, ni, 1); } return ieee80211_ref_node(ni); }
struct ieee80211_node * ieee80211_find_node_for_beacon(struct ieee80211com *ic, u_int8_t *macaddr, struct ieee80211_channel *chan, char *ssid, u_int8_t rssi) { struct ieee80211_node *ni, *keep = NULL; int score = 0; if ((ni = ieee80211_find_node(ic, macaddr)) != NULL) { IEEE80211_NODE_LOCK(ic); if (ni->ni_chan != chan && ni->ni_rssi >= rssi) score++; if (ssid[1] == 0 && ni->ni_esslen != 0) score++; if (score > 0) keep = ni; IEEE80211_NODE_UNLOCK(ic); } return (keep); }
void wlan_setup_node(struct ieee80211_node_table *nt, bss_t *ni, const A_UINT8 *macaddr) { A_INT32 hash; A_MEMCPY(ni->ni_macaddr, macaddr, IEEE80211_ADDR_LEN); hash = IEEE80211_NODE_HASH(macaddr); ieee80211_node_initref(ni); /* mark referenced */ ni->ni_tstamp = A_MS_TICKGET() + WLAN_NODE_INACT_TIMEOUT_MSEC; IEEE80211_NODE_LOCK(nt); /* Insert at the end of the node list */ ni->ni_list_next = NULL; ni->ni_list_prev = nt->nt_node_last; if(nt->nt_node_last != NULL) { nt->nt_node_last->ni_list_next = ni; } nt->nt_node_last = ni; if(nt->nt_node_first == NULL) { nt->nt_node_first = ni; } /* Insert into the hash list i.e. the bucket */ if((ni->ni_hash_next = nt->nt_hash[hash]) != NULL) { nt->nt_hash[hash]->ni_hash_prev = ni; } ni->ni_hash_prev = NULL; nt->nt_hash[hash] = ni; IEEE80211_NODE_UNLOCK(nt); }
bss_t * wlan_find_matching_Ssidnode (struct ieee80211_node_table *nt, A_UCHAR *pSsid, A_UINT32 ssidLength, A_UINT32 dot11AuthMode, A_UINT32 authMode, A_UINT32 pairwiseCryptoType, A_UINT32 grpwiseCryptoTyp) { bss_t *ni = NULL; bss_t *best_ni = NULL; A_UCHAR *pIESsid = NULL; IEEE80211_NODE_LOCK (nt); for (ni = nt->nt_node_first; ni; ni = ni->ni_list_next) { pIESsid = ni->ni_cie.ie_ssid; if (pIESsid[1] <= 32) { // Step 1 : Check SSID if (0x00 == memcmp (pSsid, &pIESsid[2], ssidLength)) { if (ni->ni_cie.ie_capInfo & 0x10) { if ((NULL != ni->ni_cie.ie_rsn) && (WPA2_PSK_AUTH == authMode)) { /* WPA2 */ if (NULL == best_ni) { best_ni = ni; } else if (ni->ni_rssi > best_ni->ni_rssi) { best_ni = ni; } } else if ((NULL != ni->ni_cie.ie_wpa) && (WPA_PSK_AUTH == authMode)) { /* WPA */ if (NULL == best_ni) { best_ni = ni; } else if (ni->ni_rssi > best_ni->ni_rssi) { best_ni = ni; } } else if (WEP_CRYPT == pairwiseCryptoType) { /* WEP */ if (NULL == best_ni) { best_ni = ni; } else if (ni->ni_rssi > best_ni->ni_rssi) { best_ni = ni; } } } else { /* open AP */ if ((OPEN_AUTH == authMode) && (NONE_CRYPT == pairwiseCryptoType)) { if (NULL == best_ni) { best_ni = ni; } else if (ni->ni_rssi > best_ni->ni_rssi) { best_ni = ni; } } } } } } IEEE80211_NODE_UNLOCK (nt); return best_ni; }