2 * Copyright (c) 2001 Atsushi Onoe
3 * Copyright (c) 2002-2004 Sam Leffler, Errno Consulting
4 * Copyright (c) 2004-2005 Atheros Communications
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
18 * Alternatively, this software may be distributed under the terms of the
19 * GNU General Public License ("GPL") version 2 as published by the Free
20 * Software Foundation.
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 * $Id: //depot/sw/releases/olca2.0-GPL/host/wlan/src/wlan_node.c#1 $
36 * IEEE 802.11 node handling support.
43 #include <ieee80211.h>
45 #include <ieee80211_node.h>
50 static void wlan_node_timeout(A_ATH_TIMER arg
);
51 static bss_t
* _ieee80211_find_node(struct ieee80211_node_table
*nt
,
52 const A_UINT8
*macaddr
);
55 wlan_node_alloc(struct ieee80211_node_table
*nt
, int wh_size
)
59 ni
= A_MALLOC_NOWAIT(sizeof(bss_t
));
62 ni
->ni_buf
= A_MALLOC_NOWAIT(wh_size
);
63 if (ni
->ni_buf
== NULL
) {
72 /* Make sure our lists are clean */
73 ni
->ni_list_next
= NULL
;
74 ni
->ni_list_prev
= NULL
;
75 ni
->ni_hash_next
= NULL
;
76 ni
->ni_hash_prev
= NULL
;
79 // ni_scangen never initialized before and during suspend/resume of winmobile, customer (LG/SEMCO) identified
80 // that some junk has been stored in this, due to this scan list didn't properly updated
88 wlan_node_free(bss_t
*ni
)
90 if (ni
->ni_buf
!= NULL
) {
97 wlan_setup_node(struct ieee80211_node_table
*nt
, bss_t
*ni
,
98 const A_UINT8
*macaddr
)
102 A_MEMCPY(ni
->ni_macaddr
, macaddr
, IEEE80211_ADDR_LEN
);
103 hash
= IEEE80211_NODE_HASH(macaddr
);
104 ieee80211_node_initref(ni
); /* mark referenced */
106 ni
->ni_tstamp
= A_GET_MS(WLAN_NODE_INACT_TIMEOUT_MSEC
);
107 IEEE80211_NODE_LOCK_BH(nt
);
109 /* Insert at the end of the node list */
110 ni
->ni_list_next
= NULL
;
111 ni
->ni_list_prev
= nt
->nt_node_last
;
112 if(nt
->nt_node_last
!= NULL
)
114 nt
->nt_node_last
->ni_list_next
= ni
;
116 nt
->nt_node_last
= ni
;
117 if(nt
->nt_node_first
== NULL
)
119 nt
->nt_node_first
= ni
;
122 /* Insert into the hash list i.e. the bucket */
123 if((ni
->ni_hash_next
= nt
->nt_hash
[hash
]) != NULL
)
125 nt
->nt_hash
[hash
]->ni_hash_prev
= ni
;
127 ni
->ni_hash_prev
= NULL
;
128 nt
->nt_hash
[hash
] = ni
;
130 if (!nt
->isTimerArmed
) {
131 A_TIMEOUT_MS(&nt
->nt_inact_timer
, WLAN_NODE_INACT_TIMEOUT_MSEC
, 0);
132 nt
->isTimerArmed
= TRUE
;
135 IEEE80211_NODE_UNLOCK_BH(nt
);
139 _ieee80211_find_node(struct ieee80211_node_table
*nt
,
140 const A_UINT8
*macaddr
)
145 IEEE80211_NODE_LOCK_ASSERT(nt
);
147 hash
= IEEE80211_NODE_HASH(macaddr
);
148 for(ni
= nt
->nt_hash
[hash
]; ni
; ni
= ni
->ni_hash_next
) {
149 if (IEEE80211_ADDR_EQ(ni
->ni_macaddr
, macaddr
)) {
150 ieee80211_node_incref(ni
); /* mark referenced */
158 wlan_find_node(struct ieee80211_node_table
*nt
, const A_UINT8
*macaddr
)
162 IEEE80211_NODE_LOCK(nt
);
163 ni
= _ieee80211_find_node(nt
, macaddr
);
164 IEEE80211_NODE_UNLOCK(nt
);
169 * Reclaim a node. If this is the last reference count then
170 * do the normal free work. Otherwise remove it from the node
171 * table and mark it gone by clearing the back-reference.
174 wlan_node_reclaim(struct ieee80211_node_table
*nt
, bss_t
*ni
)
176 IEEE80211_NODE_LOCK(nt
);
178 if(ni
->ni_list_prev
== NULL
)
180 /* First in list so fix the list head */
181 nt
->nt_node_first
= ni
->ni_list_next
;
185 ni
->ni_list_prev
->ni_list_next
= ni
->ni_list_next
;
188 if(ni
->ni_list_next
== NULL
)
190 /* Last in list so fix list tail */
191 nt
->nt_node_last
= ni
->ni_list_prev
;
195 ni
->ni_list_next
->ni_list_prev
= ni
->ni_list_prev
;
198 if(ni
->ni_hash_prev
== NULL
)
200 /* First in list so fix the list head */
202 hash
= IEEE80211_NODE_HASH(ni
->ni_macaddr
);
203 nt
->nt_hash
[hash
] = ni
->ni_hash_next
;
207 ni
->ni_hash_prev
->ni_hash_next
= ni
->ni_hash_next
;
210 if(ni
->ni_hash_next
!= NULL
)
212 ni
->ni_hash_next
->ni_hash_prev
= ni
->ni_hash_prev
;
216 IEEE80211_NODE_UNLOCK(nt
);
220 wlan_node_dec_free(bss_t
*ni
)
222 if (ieee80211_node_dectestref(ni
)) {
228 wlan_free_allnodes(struct ieee80211_node_table
*nt
)
232 while ((ni
= nt
->nt_node_first
) != NULL
) {
233 wlan_node_reclaim(nt
, ni
);
238 wlan_iterate_nodes(struct ieee80211_node_table
*nt
, wlan_node_iter_func
*f
,
244 gen
= ++nt
->nt_scangen
;
246 IEEE80211_NODE_LOCK(nt
);
247 for (ni
= nt
->nt_node_first
; ni
; ni
= ni
->ni_list_next
) {
248 if (ni
->ni_scangen
!= gen
) {
249 ni
->ni_scangen
= gen
;
250 (void) ieee80211_node_incref(ni
);
252 wlan_node_dec_free(ni
);
255 IEEE80211_NODE_UNLOCK(nt
);
259 * Node table support.
262 wlan_node_table_init(void *wmip
, struct ieee80211_node_table
*nt
)
266 AR_DEBUG_PRINTF(ATH_DEBUG_WLAN
, ("node table = 0x%x\n", (A_UINT32
)nt
));
267 IEEE80211_NODE_LOCK_INIT(nt
);
269 nt
->nt_node_first
= nt
->nt_node_last
= NULL
;
270 for(i
= 0; i
< IEEE80211_NODE_HASHSIZE
; i
++)
272 nt
->nt_hash
[i
] = NULL
;
274 A_INIT_TIMER(&nt
->nt_inact_timer
, wlan_node_timeout
, nt
);
275 nt
->isTimerArmed
= FALSE
;
280 wlan_node_timeout(A_ATH_TIMER arg
)
282 struct ieee80211_node_table
*nt
= (struct ieee80211_node_table
*)arg
;
283 bss_t
*bss
, *nextBss
;
284 A_UINT8 myBssid
[IEEE80211_ADDR_LEN
], reArmTimer
= FALSE
;
286 wmi_get_current_bssid(nt
->nt_wmip
, myBssid
);
288 bss
= nt
->nt_node_first
;
291 nextBss
= bss
->ni_list_next
;
292 if (A_MEMCMP(myBssid
, bss
->ni_macaddr
, sizeof(myBssid
)) != 0)
295 if (bss
->ni_tstamp
<= A_GET_MS(0))
298 * free up all but the current bss - if set
300 wlan_node_reclaim(nt
, bss
);
305 * Re-arm timer, only when we have a bss other than
306 * current bss AND it is not aged-out.
315 A_TIMEOUT_MS(&nt
->nt_inact_timer
, WLAN_NODE_INACT_TIMEOUT_MSEC
, 0);
317 nt
->isTimerArmed
= reArmTimer
;
321 wlan_node_table_cleanup(struct ieee80211_node_table
*nt
)
323 A_UNTIMEOUT(&nt
->nt_inact_timer
);
324 A_DELETE_TIMER(&nt
->nt_inact_timer
);
325 wlan_free_allnodes(nt
);
326 IEEE80211_NODE_LOCK_DESTROY(nt
);
330 wlan_find_Ssidnode (struct ieee80211_node_table
*nt
, A_UCHAR
*pSsid
,
331 A_UINT32 ssidLength
, A_BOOL bIsWPA2
)
334 A_UCHAR
*pIESsid
= NULL
;
336 IEEE80211_NODE_LOCK (nt
);
338 for (ni
= nt
->nt_node_first
; ni
; ni
= ni
->ni_list_next
) {
339 pIESsid
= ni
->ni_cie
.ie_ssid
;
340 if (pIESsid
[1] <= 32) {
342 // Step 1 : Check SSID
343 if (0x00 == memcmp (pSsid
, &pIESsid
[2], ssidLength
)) {
345 // Step 2 : if SSID matches, check WPA or WPA2
346 if (TRUE
== bIsWPA2
&& NULL
!= ni
->ni_cie
.ie_rsn
) {
347 ieee80211_node_incref (ni
); /* mark referenced */
348 IEEE80211_NODE_UNLOCK (nt
);
351 if (FALSE
== bIsWPA2
&& NULL
!= ni
->ni_cie
.ie_wpa
) {
352 ieee80211_node_incref(ni
); /* mark referenced */
353 IEEE80211_NODE_UNLOCK (nt
);
360 IEEE80211_NODE_UNLOCK (nt
);
366 wlan_node_return (struct ieee80211_node_table
*nt
, bss_t
*ni
)
368 IEEE80211_NODE_LOCK (nt
);
369 wlan_node_dec_free (ni
);
370 IEEE80211_NODE_UNLOCK (nt
);