diff options
author | Johannes Berg <johannes.berg@intel.com> | 2013-01-29 18:26:45 -0500 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2013-02-04 12:57:40 -0500 |
commit | 5622f5bb8dd3cafe0e56014ed03e31957d1b4a03 (patch) | |
tree | 43824a1d72ece689d2128077e139567499316f9d /net/wireless | |
parent | 42745e039312ab4672c60ec584651f0c74e8264f (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.c | 82 |
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 | ||
427 | static int cmp_bss(struct cfg80211_bss *a, | 427 | static 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 | |||
449 | static 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 | ||
604 | static struct cfg80211_internal_bss * | 584 | static struct cfg80211_internal_bss * |
605 | rb_find_bss(struct cfg80211_registered_device *dev, | 585 | rb_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 | |||
627 | static struct cfg80211_internal_bss * | ||
628 | rb_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 | ||