aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2013-01-29 18:26:45 -0500
committerJohannes Berg <johannes.berg@intel.com>2013-02-04 12:57:40 -0500
commit5622f5bb8dd3cafe0e56014ed03e31957d1b4a03 (patch)
tree43824a1d72ece689d2128077e139567499316f9d /net/wireless
parent42745e039312ab4672c60ec584651f0c74e8264f (diff)
cfg80211: refactor hidden SSID finding
Instead of duplicating the rbtree functions, pass an argument to the compare function. This removes the code duplication for the two searches. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/scan.c82
1 files changed, 20 insertions, 62 deletions
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index ca367c58a3e2..cfc4e1aa8dad 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -425,34 +425,13 @@ static int cmp_bss_core(struct cfg80211_bss *a, struct cfg80211_bss *b)
425} 425}
426 426
427static int cmp_bss(struct cfg80211_bss *a, 427static int cmp_bss(struct cfg80211_bss *a,
428 struct cfg80211_bss *b) 428 struct cfg80211_bss *b,
429{ 429 bool hide_ssid)
430 const struct cfg80211_bss_ies *a_ies, *b_ies;
431 int r;
432
433 r = cmp_bss_core(a, b);
434 if (r)
435 return r;
436
437 a_ies = rcu_access_pointer(a->ies);
438 if (!a_ies)
439 return -1;
440 b_ies = rcu_access_pointer(b->ies);
441 if (!b_ies)
442 return 1;
443
444 return cmp_ies(WLAN_EID_SSID,
445 a_ies->data, a_ies->len,
446 b_ies->data, b_ies->len);
447}
448
449static int cmp_hidden_bss(struct cfg80211_bss *a, struct cfg80211_bss *b)
450{ 430{
451 const struct cfg80211_bss_ies *a_ies, *b_ies; 431 const struct cfg80211_bss_ies *a_ies, *b_ies;
452 const u8 *ie1; 432 const u8 *ie1;
453 const u8 *ie2; 433 const u8 *ie2;
454 int i; 434 int i, r;
455 int r;
456 435
457 r = cmp_bss_core(a, b); 436 r = cmp_bss_core(a, b);
458 if (r) 437 if (r)
@@ -468,15 +447,13 @@ static int cmp_hidden_bss(struct cfg80211_bss *a, struct cfg80211_bss *b)
468 ie1 = cfg80211_find_ie(WLAN_EID_SSID, a_ies->data, a_ies->len); 447 ie1 = cfg80211_find_ie(WLAN_EID_SSID, a_ies->data, a_ies->len);
469 ie2 = cfg80211_find_ie(WLAN_EID_SSID, b_ies->data, b_ies->len); 448 ie2 = cfg80211_find_ie(WLAN_EID_SSID, b_ies->data, b_ies->len);
470 449
450 if (!ie1 && !ie2)
451 return 0;
452
471 /* 453 /*
472 * Key comparator must use same algorithm in any rb-tree 454 * Note that with "hide_ssid", the function returns a match if
473 * search function (order is important), otherwise ordering 455 * the already-present BSS ("b") is a hidden SSID beacon for
474 * of items in the tree is broken and search gives incorrect 456 * the new BSS ("a").
475 * results. This code uses same order as cmp_ies() does.
476 *
477 * Note that due to the differring behaviour with hidden SSIDs
478 * this function only works when "b" is the tree element and
479 * "a" is the key we're looking for.
480 */ 457 */
481 458
482 /* sort missing IE before (left of) present IE */ 459 /* sort missing IE before (left of) present IE */
@@ -485,14 +462,17 @@ static int cmp_hidden_bss(struct cfg80211_bss *a, struct cfg80211_bss *b)
485 if (!ie2) 462 if (!ie2)
486 return 1; 463 return 1;
487 464
488 /* zero-size SSID is used as an indication of the hidden bss */ 465 /* zero-length SSID is used as an indication of the hidden bss */
489 if (!ie2[1]) 466 if (hide_ssid && !ie2[1])
490 return 0; 467 return 0;
491 468
492 /* sort by length first, then by contents */ 469 /* sort by length first, then by contents */
493 if (ie1[1] != ie2[1]) 470 if (ie1[1] != ie2[1])
494 return ie2[1] - ie1[1]; 471 return ie2[1] - ie1[1];
495 472
473 if (!hide_ssid)
474 return memcmp(ie1 + 2, ie2 + 2, ie1[1]);
475
496 /* 476 /*
497 * zeroed SSID ie is another indication of a hidden bss; 477 * zeroed SSID ie is another indication of a hidden bss;
498 * if it isn't zeroed just return the regular sort value 478 * if it isn't zeroed just return the regular sort value
@@ -584,7 +564,7 @@ static void rb_insert_bss(struct cfg80211_registered_device *dev,
584 parent = *p; 564 parent = *p;
585 tbss = rb_entry(parent, struct cfg80211_internal_bss, rbn); 565 tbss = rb_entry(parent, struct cfg80211_internal_bss, rbn);
586 566
587 cmp = cmp_bss(&bss->pub, &tbss->pub); 567 cmp = cmp_bss(&bss->pub, &tbss->pub, false);
588 568
589 if (WARN_ON(!cmp)) { 569 if (WARN_ON(!cmp)) {
590 /* will sort of leak this BSS */ 570 /* will sort of leak this BSS */
@@ -603,30 +583,8 @@ static void rb_insert_bss(struct cfg80211_registered_device *dev,
603 583
604static struct cfg80211_internal_bss * 584static struct cfg80211_internal_bss *
605rb_find_bss(struct cfg80211_registered_device *dev, 585rb_find_bss(struct cfg80211_registered_device *dev,
606 struct cfg80211_internal_bss *res) 586 struct cfg80211_internal_bss *res,
607{ 587 bool hidden)
608 struct rb_node *n = dev->bss_tree.rb_node;
609 struct cfg80211_internal_bss *bss;
610 int r;
611
612 while (n) {
613 bss = rb_entry(n, struct cfg80211_internal_bss, rbn);
614 r = cmp_bss(&res->pub, &bss->pub);
615
616 if (r == 0)
617 return bss;
618 else if (r < 0)
619 n = n->rb_left;
620 else
621 n = n->rb_right;
622 }
623
624 return NULL;
625}
626
627static struct cfg80211_internal_bss *
628rb_find_hidden_bss(struct cfg80211_registered_device *dev,
629 struct cfg80211_internal_bss *res)
630{ 588{
631 struct rb_node *n = dev->bss_tree.rb_node; 589 struct rb_node *n = dev->bss_tree.rb_node;
632 struct cfg80211_internal_bss *bss; 590 struct cfg80211_internal_bss *bss;
@@ -634,7 +592,7 @@ rb_find_hidden_bss(struct cfg80211_registered_device *dev,
634 592
635 while (n) { 593 while (n) {
636 bss = rb_entry(n, struct cfg80211_internal_bss, rbn); 594 bss = rb_entry(n, struct cfg80211_internal_bss, rbn);
637 r = cmp_hidden_bss(&res->pub, &bss->pub); 595 r = cmp_bss(&res->pub, &bss->pub, hidden);
638 596
639 if (r == 0) 597 if (r == 0)
640 return bss; 598 return bss;
@@ -684,7 +642,7 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
684 return NULL; 642 return NULL;
685 } 643 }
686 644
687 found = rb_find_bss(dev, tmp); 645 found = rb_find_bss(dev, tmp, false);
688 646
689 if (found) { 647 if (found) {
690 found->pub.beacon_interval = tmp->pub.beacon_interval; 648 found->pub.beacon_interval = tmp->pub.beacon_interval;
@@ -739,7 +697,7 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
739 /* TODO: The code is not trying to update existing probe 697 /* TODO: The code is not trying to update existing probe
740 * response bss entries when beacon ies are 698 * response bss entries when beacon ies are
741 * getting changed. */ 699 * getting changed. */
742 hidden = rb_find_hidden_bss(dev, tmp); 700 hidden = rb_find_bss(dev, tmp, true);
743 if (hidden) 701 if (hidden)
744 copy_hidden_ies(tmp, hidden); 702 copy_hidden_ies(tmp, hidden);
745 703