diff options
| author | Eliad Peller <eliad@wizery.com> | 2011-05-29 08:53:20 -0400 |
|---|---|---|
| committer | John W. Linville <linville@tuxdriver.com> | 2011-06-01 14:34:01 -0400 |
| commit | 333ba7325213f0a09dfa5ceeddb056d6ad74b3b5 (patch) | |
| tree | 9dff6d71d30b863a30bc07c22326e32cd573eea5 | |
| parent | 1144181c1bc054dc5e001a6f10b4820167e6c883 (diff) | |
cfg80211: don't drop p2p probe responses
Commit 0a35d36 ("cfg80211: Use capability info to detect mesh beacons")
assumed that probe response with both ESS and IBSS bits cleared
means that the frame was sent by a mesh sta.
However, these capabilities are also being used in the p2p_find phase,
and the mesh-validation broke it.
Rename the WLAN_CAPABILITY_IS_MBSS macro, and verify that mesh ies
exist before assuming this frame was sent by a mesh sta.
Signed-off-by: Eliad Peller <eliad@wizery.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
| -rw-r--r-- | include/linux/ieee80211.h | 8 | ||||
| -rw-r--r-- | net/wireless/scan.c | 43 |
2 files changed, 30 insertions, 21 deletions
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index b2eee5879883..bf56b6f78270 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h | |||
| @@ -1003,8 +1003,12 @@ struct ieee80211_ht_info { | |||
| 1003 | #define WLAN_CAPABILITY_ESS (1<<0) | 1003 | #define WLAN_CAPABILITY_ESS (1<<0) |
| 1004 | #define WLAN_CAPABILITY_IBSS (1<<1) | 1004 | #define WLAN_CAPABILITY_IBSS (1<<1) |
| 1005 | 1005 | ||
| 1006 | /* A mesh STA sets the ESS and IBSS capability bits to zero */ | 1006 | /* |
| 1007 | #define WLAN_CAPABILITY_IS_MBSS(cap) \ | 1007 | * A mesh STA sets the ESS and IBSS capability bits to zero. |
| 1008 | * however, this holds true for p2p probe responses (in the p2p_find | ||
| 1009 | * phase) as well. | ||
| 1010 | */ | ||
| 1011 | #define WLAN_CAPABILITY_IS_STA_BSS(cap) \ | ||
| 1008 | (!((cap) & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS))) | 1012 | (!((cap) & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS))) |
| 1009 | 1013 | ||
| 1010 | #define WLAN_CAPABILITY_CF_POLLABLE (1<<2) | 1014 | #define WLAN_CAPABILITY_CF_POLLABLE (1<<2) |
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 73a441d237b5..7a6c67667d70 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c | |||
| @@ -267,13 +267,35 @@ static bool is_bss(struct cfg80211_bss *a, | |||
| 267 | return memcmp(ssidie + 2, ssid, ssid_len) == 0; | 267 | return memcmp(ssidie + 2, ssid, ssid_len) == 0; |
| 268 | } | 268 | } |
| 269 | 269 | ||
| 270 | static bool is_mesh_bss(struct cfg80211_bss *a) | ||
| 271 | { | ||
| 272 | const u8 *ie; | ||
| 273 | |||
| 274 | if (!WLAN_CAPABILITY_IS_STA_BSS(a->capability)) | ||
| 275 | return false; | ||
| 276 | |||
| 277 | ie = cfg80211_find_ie(WLAN_EID_MESH_ID, | ||
| 278 | a->information_elements, | ||
| 279 | a->len_information_elements); | ||
| 280 | if (!ie) | ||
| 281 | return false; | ||
| 282 | |||
| 283 | ie = cfg80211_find_ie(WLAN_EID_MESH_CONFIG, | ||
| 284 | a->information_elements, | ||
| 285 | a->len_information_elements); | ||
| 286 | if (!ie) | ||
| 287 | return false; | ||
| 288 | |||
| 289 | return true; | ||
| 290 | } | ||
| 291 | |||
| 270 | static bool is_mesh(struct cfg80211_bss *a, | 292 | static bool is_mesh(struct cfg80211_bss *a, |
| 271 | const u8 *meshid, size_t meshidlen, | 293 | const u8 *meshid, size_t meshidlen, |
| 272 | const u8 *meshcfg) | 294 | const u8 *meshcfg) |
| 273 | { | 295 | { |
| 274 | const u8 *ie; | 296 | const u8 *ie; |
| 275 | 297 | ||
| 276 | if (!WLAN_CAPABILITY_IS_MBSS(a->capability)) | 298 | if (!WLAN_CAPABILITY_IS_STA_BSS(a->capability)) |
| 277 | return false; | 299 | return false; |
| 278 | 300 | ||
| 279 | ie = cfg80211_find_ie(WLAN_EID_MESH_ID, | 301 | ie = cfg80211_find_ie(WLAN_EID_MESH_ID, |
| @@ -311,7 +333,7 @@ static int cmp_bss(struct cfg80211_bss *a, | |||
| 311 | if (a->channel != b->channel) | 333 | if (a->channel != b->channel) |
| 312 | return b->channel->center_freq - a->channel->center_freq; | 334 | return b->channel->center_freq - a->channel->center_freq; |
| 313 | 335 | ||
| 314 | if (WLAN_CAPABILITY_IS_MBSS(a->capability | b->capability)) { | 336 | if (is_mesh_bss(a) && is_mesh_bss(b)) { |
| 315 | r = cmp_ies(WLAN_EID_MESH_ID, | 337 | r = cmp_ies(WLAN_EID_MESH_ID, |
| 316 | a->information_elements, | 338 | a->information_elements, |
| 317 | a->len_information_elements, | 339 | a->len_information_elements, |
| @@ -457,7 +479,6 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, | |||
| 457 | struct cfg80211_internal_bss *res) | 479 | struct cfg80211_internal_bss *res) |
| 458 | { | 480 | { |
| 459 | struct cfg80211_internal_bss *found = NULL; | 481 | struct cfg80211_internal_bss *found = NULL; |
| 460 | const u8 *meshid, *meshcfg; | ||
| 461 | 482 | ||
| 462 | /* | 483 | /* |
| 463 | * The reference to "res" is donated to this function. | 484 | * The reference to "res" is donated to this function. |
| @@ -470,22 +491,6 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, | |||
| 470 | 491 | ||
| 471 | res->ts = jiffies; | 492 | res->ts = jiffies; |
| 472 | 493 | ||
| 473 | if (WLAN_CAPABILITY_IS_MBSS(res->pub.capability)) { | ||
| 474 | /* must be mesh, verify */ | ||
| 475 | meshid = cfg80211_find_ie(WLAN_EID_MESH_ID, | ||
| 476 | res->pub.information_elements, | ||
| 477 | res->pub.len_information_elements); | ||
| 478 | meshcfg = cfg80211_find_ie(WLAN_EID_MESH_CONFIG, | ||
| 479 | res->pub.information_elements, | ||
| 480 | res->pub.len_information_elements); | ||
| 481 | if (!meshid || !meshcfg || | ||
| 482 | meshcfg[1] != sizeof(struct ieee80211_meshconf_ie)) { | ||
| 483 | /* bogus mesh */ | ||
| 484 | kref_put(&res->ref, bss_release); | ||
| 485 | return NULL; | ||
| 486 | } | ||
| 487 | } | ||
| 488 | |||
| 489 | spin_lock_bh(&dev->bss_lock); | 494 | spin_lock_bh(&dev->bss_lock); |
| 490 | 495 | ||
| 491 | found = rb_find_bss(dev, res); | 496 | found = rb_find_bss(dev, res); |
