1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25#include <a_config.h>
26#include <athdefs.h>
27#include <a_types.h>
28#include <a_osapi.h>
29#define ATH_MODULE_NAME wlan
30#include <a_debug.h>
31#include "htc.h"
32#include "htc_api.h"
33#include <wmi.h>
34#include <ieee80211.h>
35#include <wlan_api.h>
36#include <wmi_api.h>
37#include <ieee80211_node.h>
38
39#define ATH_DEBUG_WLAN ATH_DEBUG_MAKE_MODULE_MASK(0)
40
41#ifdef ATH_DEBUG_MODULE
42
43static ATH_DEBUG_MASK_DESCRIPTION wlan_debug_desc[] = {
44 { ATH_DEBUG_WLAN , "General WLAN Node Tracing"},
45};
46
47ATH_DEBUG_INSTANTIATE_MODULE_VAR(wlan,
48 "wlan",
49 "WLAN Node Management",
50 ATH_DEBUG_MASK_DEFAULTS,
51 ATH_DEBUG_DESCRIPTION_COUNT(wlan_debug_desc),
52 wlan_debug_desc);
53
54#endif
55
56#ifdef THREAD_X
57static void wlan_node_timeout(A_ATH_TIMER arg);
58#endif
59
60static bss_t * _ieee80211_find_node (struct ieee80211_node_table *nt,
61 const A_UINT8 *macaddr);
62
63bss_t *
64wlan_node_alloc(struct ieee80211_node_table *nt, int wh_size)
65{
66 bss_t *ni;
67
68 ni = A_MALLOC_NOWAIT(sizeof(bss_t));
69
70 if (ni != NULL) {
71 if (wh_size)
72 {
73 ni->ni_buf = A_MALLOC_NOWAIT(wh_size);
74 if (ni->ni_buf == NULL) {
75 A_FREE(ni);
76 ni = NULL;
77 return ni;
78 }
79 }
80 } else {
81 return ni;
82 }
83
84
85 ni->ni_list_next = NULL;
86 ni->ni_list_prev = NULL;
87 ni->ni_hash_next = NULL;
88 ni->ni_hash_prev = NULL;
89
90
91
92
93
94 ni->ni_scangen = 0;
95
96#ifdef OS_ROAM_MANAGEMENT
97 ni->ni_si_gen = 0;
98#endif
99
100 return ni;
101}
102
103void
104wlan_node_free(bss_t *ni)
105{
106 if (ni->ni_buf != NULL) {
107 A_FREE(ni->ni_buf);
108 }
109 A_FREE(ni);
110}
111
112void
113wlan_setup_node(struct ieee80211_node_table *nt, bss_t *ni,
114 const A_UINT8 *macaddr)
115{
116 int hash;
117 A_UINT32 timeoutValue = 0;
118
119 A_MEMCPY(ni->ni_macaddr, macaddr, IEEE80211_ADDR_LEN);
120 hash = IEEE80211_NODE_HASH (macaddr);
121 ieee80211_node_initref (ni);
122
123 timeoutValue = nt->nt_nodeAge;
124
125 ni->ni_tstamp = A_GET_MS (timeoutValue);
126 ni->ni_actcnt = WLAN_NODE_INACT_CNT;
127
128 IEEE80211_NODE_LOCK_BH(nt);
129
130
131 ni->ni_list_next = NULL;
132 ni->ni_list_prev = nt->nt_node_last;
133 if(nt->nt_node_last != NULL)
134 {
135 nt->nt_node_last->ni_list_next = ni;
136 }
137 nt->nt_node_last = ni;
138 if(nt->nt_node_first == NULL)
139 {
140 nt->nt_node_first = ni;
141 }
142
143
144 if((ni->ni_hash_next = nt->nt_hash[hash]) != NULL)
145 {
146 nt->nt_hash[hash]->ni_hash_prev = ni;
147 }
148 ni->ni_hash_prev = NULL;
149 nt->nt_hash[hash] = ni;
150
151#ifdef THREAD_X
152 if (!nt->isTimerArmed) {
153 A_TIMEOUT_MS(&nt->nt_inact_timer, timeoutValue, 0);
154 nt->isTimerArmed = TRUE;
155 }
156#endif
157
158 IEEE80211_NODE_UNLOCK_BH(nt);
159}
160
161static bss_t *
162_ieee80211_find_node(struct ieee80211_node_table *nt,
163 const A_UINT8 *macaddr)
164{
165 bss_t *ni;
166 int hash;
167
168 IEEE80211_NODE_LOCK_ASSERT(nt);
169
170 hash = IEEE80211_NODE_HASH(macaddr);
171 for(ni = nt->nt_hash[hash]; ni; ni = ni->ni_hash_next) {
172 if (IEEE80211_ADDR_EQ(ni->ni_macaddr, macaddr)) {
173 ieee80211_node_incref(ni);
174 return ni;
175 }
176 }
177 return NULL;
178}
179
180bss_t *
181wlan_find_node(struct ieee80211_node_table *nt, const A_UINT8 *macaddr)
182{
183 bss_t *ni;
184
185 IEEE80211_NODE_LOCK(nt);
186 ni = _ieee80211_find_node(nt, macaddr);
187 IEEE80211_NODE_UNLOCK(nt);
188 return ni;
189}
190
191
192
193
194
195
196void
197wlan_node_reclaim(struct ieee80211_node_table *nt, bss_t *ni)
198{
199 IEEE80211_NODE_LOCK(nt);
200
201 if(ni->ni_list_prev == NULL)
202 {
203
204 nt->nt_node_first = ni->ni_list_next;
205 }
206 else
207 {
208 ni->ni_list_prev->ni_list_next = ni->ni_list_next;
209 }
210
211 if(ni->ni_list_next == NULL)
212 {
213
214 nt->nt_node_last = ni->ni_list_prev;
215 }
216 else
217 {
218 ni->ni_list_next->ni_list_prev = ni->ni_list_prev;
219 }
220
221 if(ni->ni_hash_prev == NULL)
222 {
223
224 int hash;
225 hash = IEEE80211_NODE_HASH(ni->ni_macaddr);
226 nt->nt_hash[hash] = ni->ni_hash_next;
227 }
228 else
229 {
230 ni->ni_hash_prev->ni_hash_next = ni->ni_hash_next;
231 }
232
233 if(ni->ni_hash_next != NULL)
234 {
235 ni->ni_hash_next->ni_hash_prev = ni->ni_hash_prev;
236 }
237 wlan_node_free(ni);
238
239 IEEE80211_NODE_UNLOCK(nt);
240}
241
242static void
243wlan_node_dec_free(bss_t *ni)
244{
245 if (ieee80211_node_dectestref(ni)) {
246 wlan_node_free(ni);
247 }
248}
249
250void
251wlan_free_allnodes(struct ieee80211_node_table *nt)
252{
253 bss_t *ni;
254
255 while ((ni = nt->nt_node_first) != NULL) {
256 wlan_node_reclaim(nt, ni);
257 }
258}
259
260void
261wlan_iterate_nodes(struct ieee80211_node_table *nt, wlan_node_iter_func *f,
262 void *arg)
263{
264 bss_t *ni;
265 A_UINT32 gen;
266
267 gen = ++nt->nt_scangen;
268
269 IEEE80211_NODE_LOCK(nt);
270 for (ni = nt->nt_node_first; ni; ni = ni->ni_list_next) {
271 if (ni->ni_scangen != gen) {
272 ni->ni_scangen = gen;
273 (void) ieee80211_node_incref(ni);
274 (*f)(arg, ni);
275 wlan_node_dec_free(ni);
276 }
277 }
278 IEEE80211_NODE_UNLOCK(nt);
279}
280
281
282
283
284void
285wlan_node_table_init(void *wmip, struct ieee80211_node_table *nt)
286{
287 int i;
288
289 AR_DEBUG_PRINTF(ATH_DEBUG_WLAN, ("node table = 0x%lx\n", (unsigned long)nt));
290 IEEE80211_NODE_LOCK_INIT(nt);
291
292 A_REGISTER_MODULE_DEBUG_INFO(wlan);
293
294 nt->nt_node_first = nt->nt_node_last = NULL;
295 for(i = 0; i < IEEE80211_NODE_HASHSIZE; i++)
296 {
297 nt->nt_hash[i] = NULL;
298 }
299
300#ifdef THREAD_X
301 A_INIT_TIMER(&nt->nt_inact_timer, wlan_node_timeout, nt);
302 nt->isTimerArmed = FALSE;
303#endif
304 nt->nt_wmip = wmip;
305 nt->nt_nodeAge = WLAN_NODE_INACT_TIMEOUT_MSEC;
306
307
308
309
310
311 nt->nt_scangen = 0;
312
313#ifdef OS_ROAM_MANAGEMENT
314 nt->nt_si_gen = 0;
315#endif
316}
317
318void
319wlan_set_nodeage(struct ieee80211_node_table *nt, A_UINT32 nodeAge)
320{
321 nt->nt_nodeAge = nodeAge;
322 return;
323}
324void
325wlan_refresh_inactive_nodes (struct ieee80211_node_table *nt)
326{
327#ifdef THREAD_X
328 bss_t *bss, *nextBss;
329 A_UINT8 myBssid[IEEE80211_ADDR_LEN], reArmTimer = FALSE;
330
331 wmi_get_current_bssid(nt->nt_wmip, myBssid);
332
333 bss = nt->nt_node_first;
334 while (bss != NULL)
335 {
336 nextBss = bss->ni_list_next;
337 if (A_MEMCMP(myBssid, bss->ni_macaddr, sizeof(myBssid)) != 0)
338 {
339
340
341
342 wlan_node_reclaim(nt, bss);
343
344 }
345 bss = nextBss;
346 }
347#else
348 bss_t *bss, *nextBss;
349 A_UINT8 myBssid[IEEE80211_ADDR_LEN];
350 A_UINT32 timeoutValue = 0;
351 A_UINT32 now = A_GET_MS(0);
352 timeoutValue = nt->nt_nodeAge;
353
354 wmi_get_current_bssid(nt->nt_wmip, myBssid);
355
356 bss = nt->nt_node_first;
357 while (bss != NULL)
358 {
359 nextBss = bss->ni_list_next;
360 if (A_MEMCMP(myBssid, bss->ni_macaddr, sizeof(myBssid)) != 0)
361 {
362
363 if (bss->ni_tstamp <= now || --bss->ni_actcnt == 0)
364 {
365
366
367
368 wlan_node_reclaim(nt, bss);
369 }
370 }
371 bss = nextBss;
372 }
373#endif
374}
375
376#ifdef THREAD_X
377static void
378wlan_node_timeout (A_ATH_TIMER arg)
379{
380 struct ieee80211_node_table *nt = (struct ieee80211_node_table *)arg;
381 bss_t *bss, *nextBss;
382 A_UINT8 myBssid[IEEE80211_ADDR_LEN], reArmTimer = FALSE;
383 A_UINT32 timeoutValue = 0;
384
385 timeoutValue = nt->nt_nodeAge;
386
387 wmi_get_current_bssid(nt->nt_wmip, myBssid);
388
389 bss = nt->nt_node_first;
390 while (bss != NULL)
391 {
392 nextBss = bss->ni_list_next;
393 if (A_MEMCMP(myBssid, bss->ni_macaddr, sizeof(myBssid)) != 0)
394 {
395
396 if (bss->ni_tstamp <= A_GET_MS(0))
397 {
398
399
400
401 wlan_node_reclaim(nt, bss);
402 }
403 else
404 {
405
406
407
408
409 reArmTimer = TRUE;
410 }
411 }
412 bss = nextBss;
413 }
414
415 if (reArmTimer)
416 A_TIMEOUT_MS (&nt->nt_inact_timer, timeoutValue, 0);
417
418 nt->isTimerArmed = reArmTimer;
419}
420#endif
421
422void
423wlan_node_table_cleanup(struct ieee80211_node_table *nt)
424{
425#ifdef THREAD_X
426 A_UNTIMEOUT(&nt->nt_inact_timer);
427 A_DELETE_TIMER(&nt->nt_inact_timer);
428#endif
429 wlan_free_allnodes(nt);
430 IEEE80211_NODE_LOCK_DESTROY(nt);
431}
432
433bss_t *
434wlan_find_Ssidnode (struct ieee80211_node_table *nt, A_UCHAR *pSsid,
435 A_UINT32 ssidLength, A_BOOL bIsWPA2, A_BOOL bMatchSSID)
436{
437 bss_t *ni = NULL;
438 A_UCHAR *pIESsid = NULL;
439
440 IEEE80211_NODE_LOCK (nt);
441
442 for (ni = nt->nt_node_first; ni; ni = ni->ni_list_next) {
443 pIESsid = ni->ni_cie.ie_ssid;
444 if (pIESsid[1] <= 32) {
445
446
447 if (0x00 == memcmp (pSsid, &pIESsid[2], ssidLength)) {
448
449
450
451
452
453 if (TRUE == bMatchSSID) {
454 ieee80211_node_incref (ni);
455 IEEE80211_NODE_UNLOCK (nt);
456 return ni;
457 }
458
459
460 if (TRUE == bIsWPA2 && NULL != ni->ni_cie.ie_rsn) {
461 ieee80211_node_incref (ni);
462 IEEE80211_NODE_UNLOCK (nt);
463 return ni;
464 }
465 if (FALSE == bIsWPA2 && NULL != ni->ni_cie.ie_wpa) {
466 ieee80211_node_incref(ni);
467 IEEE80211_NODE_UNLOCK (nt);
468 return ni;
469 }
470 }
471 }
472 }
473
474 IEEE80211_NODE_UNLOCK (nt);
475
476 return NULL;
477}
478
479void
480wlan_node_return (struct ieee80211_node_table *nt, bss_t *ni)
481{
482 IEEE80211_NODE_LOCK (nt);
483 wlan_node_dec_free (ni);
484 IEEE80211_NODE_UNLOCK (nt);
485}
486
487void
488wlan_node_remove_core (struct ieee80211_node_table *nt, bss_t *ni)
489{
490 if(ni->ni_list_prev == NULL)
491 {
492
493 nt->nt_node_first = ni->ni_list_next;
494 }
495 else
496 {
497 ni->ni_list_prev->ni_list_next = ni->ni_list_next;
498 }
499
500 if(ni->ni_list_next == NULL)
501 {
502
503 nt->nt_node_last = ni->ni_list_prev;
504 }
505 else
506 {
507 ni->ni_list_next->ni_list_prev = ni->ni_list_prev;
508 }
509
510 if(ni->ni_hash_prev == NULL)
511 {
512
513 int hash;
514 hash = IEEE80211_NODE_HASH(ni->ni_macaddr);
515 nt->nt_hash[hash] = ni->ni_hash_next;
516 }
517 else
518 {
519 ni->ni_hash_prev->ni_hash_next = ni->ni_hash_next;
520 }
521
522 if(ni->ni_hash_next != NULL)
523 {
524 ni->ni_hash_next->ni_hash_prev = ni->ni_hash_prev;
525 }
526}
527
528bss_t *
529wlan_node_remove(struct ieee80211_node_table *nt, A_UINT8 *bssid)
530{
531 bss_t *bss, *nextBss;
532
533 IEEE80211_NODE_LOCK(nt);
534
535 bss = nt->nt_node_first;
536
537 while (bss != NULL)
538 {
539 nextBss = bss->ni_list_next;
540
541 if (A_MEMCMP(bssid, bss->ni_macaddr, 6) == 0)
542 {
543 wlan_node_remove_core (nt, bss);
544 IEEE80211_NODE_UNLOCK(nt);
545 return bss;
546 }
547
548 bss = nextBss;
549 }
550
551 IEEE80211_NODE_UNLOCK(nt);
552 return NULL;
553}
554
555bss_t *
556wlan_find_matching_Ssidnode (struct ieee80211_node_table *nt, A_UCHAR *pSsid,
557 A_UINT32 ssidLength, A_UINT32 dot11AuthMode, A_UINT32 authMode,
558 A_UINT32 pairwiseCryptoType, A_UINT32 grpwiseCryptoTyp)
559{
560 bss_t *ni = NULL;
561 bss_t *best_ni = NULL;
562 A_UCHAR *pIESsid = NULL;
563
564 IEEE80211_NODE_LOCK (nt);
565
566 for (ni = nt->nt_node_first; ni; ni = ni->ni_list_next) {
567 pIESsid = ni->ni_cie.ie_ssid;
568 if (pIESsid[1] <= 32) {
569
570
571 if (0x00 == memcmp (pSsid, &pIESsid[2], ssidLength)) {
572
573 if (ni->ni_cie.ie_capInfo & 0x10)
574 {
575
576 if ((NULL != ni->ni_cie.ie_rsn) && (WPA2_PSK_AUTH == authMode))
577 {
578
579 if (NULL == best_ni)
580 {
581 best_ni = ni;
582 }
583 else if (ni->ni_rssi > best_ni->ni_rssi)
584 {
585 best_ni = ni;
586 }
587 }
588 else if ((NULL != ni->ni_cie.ie_wpa) && (WPA_PSK_AUTH == authMode))
589 {
590
591 if (NULL == best_ni)
592 {
593 best_ni = ni;
594 }
595 else if (ni->ni_rssi > best_ni->ni_rssi)
596 {
597 best_ni = ni;
598 }
599 }
600 else if (WEP_CRYPT == pairwiseCryptoType)
601 {
602
603 if (NULL == best_ni)
604 {
605 best_ni = ni;
606 }
607 else if (ni->ni_rssi > best_ni->ni_rssi)
608 {
609 best_ni = ni;
610 }
611 }
612 }
613 else
614 {
615
616 if ((OPEN_AUTH == authMode) && (NONE_CRYPT == pairwiseCryptoType))
617 {
618 if (NULL == best_ni)
619 {
620 best_ni = ni;
621 }
622 else if (ni->ni_rssi > best_ni->ni_rssi)
623 {
624 best_ni = ni;
625 }
626 }
627 }
628 }
629 }
630 }
631
632 IEEE80211_NODE_UNLOCK (nt);
633
634 return best_ni;
635}
636
637