diff options
Diffstat (limited to 'net/wireless/scan.c')
| -rw-r--r-- | net/wireless/scan.c | 40 |
1 files changed, 33 insertions, 7 deletions
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 2a00e362f5fe..2ae65b39b529 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c | |||
| @@ -58,6 +58,10 @@ static void bss_release(struct kref *ref) | |||
| 58 | bss = container_of(ref, struct cfg80211_internal_bss, ref); | 58 | bss = container_of(ref, struct cfg80211_internal_bss, ref); |
| 59 | if (bss->pub.free_priv) | 59 | if (bss->pub.free_priv) |
| 60 | bss->pub.free_priv(&bss->pub); | 60 | bss->pub.free_priv(&bss->pub); |
| 61 | |||
| 62 | if (bss->ies_allocated) | ||
| 63 | kfree(bss->pub.information_elements); | ||
| 64 | |||
| 61 | kfree(bss); | 65 | kfree(bss); |
| 62 | } | 66 | } |
| 63 | 67 | ||
| @@ -360,19 +364,41 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, | |||
| 360 | 364 | ||
| 361 | found = rb_find_bss(dev, res); | 365 | found = rb_find_bss(dev, res); |
| 362 | 366 | ||
| 363 | if (found && overwrite) { | 367 | if (found) { |
| 364 | list_replace(&found->list, &res->list); | ||
| 365 | rb_replace_node(&found->rbn, &res->rbn, | ||
| 366 | &dev->bss_tree); | ||
| 367 | kref_put(&found->ref, bss_release); | ||
| 368 | found = res; | ||
| 369 | } else if (found) { | ||
| 370 | kref_get(&found->ref); | 368 | kref_get(&found->ref); |
| 371 | found->pub.beacon_interval = res->pub.beacon_interval; | 369 | found->pub.beacon_interval = res->pub.beacon_interval; |
| 372 | found->pub.tsf = res->pub.tsf; | 370 | found->pub.tsf = res->pub.tsf; |
| 373 | found->pub.signal = res->pub.signal; | 371 | found->pub.signal = res->pub.signal; |
| 374 | found->pub.capability = res->pub.capability; | 372 | found->pub.capability = res->pub.capability; |
| 375 | found->ts = res->ts; | 373 | found->ts = res->ts; |
| 374 | |||
| 375 | /* overwrite IEs */ | ||
| 376 | if (overwrite) { | ||
| 377 | size_t used = dev->wiphy.bss_priv_size + sizeof(*res); | ||
| 378 | size_t ielen = res->pub.len_information_elements; | ||
| 379 | |||
| 380 | if (ksize(found) >= used + ielen) { | ||
| 381 | memcpy(found->pub.information_elements, | ||
| 382 | res->pub.information_elements, ielen); | ||
| 383 | found->pub.len_information_elements = ielen; | ||
| 384 | } else { | ||
| 385 | u8 *ies = found->pub.information_elements; | ||
| 386 | |||
| 387 | if (found->ies_allocated) { | ||
| 388 | if (ksize(ies) < ielen) | ||
| 389 | ies = krealloc(ies, ielen, | ||
| 390 | GFP_ATOMIC); | ||
| 391 | } else | ||
| 392 | ies = kmalloc(ielen, GFP_ATOMIC); | ||
| 393 | |||
| 394 | if (ies) { | ||
| 395 | memcpy(ies, res->pub.information_elements, ielen); | ||
| 396 | found->ies_allocated = true; | ||
| 397 | found->pub.information_elements = ies; | ||
| 398 | } | ||
| 399 | } | ||
| 400 | } | ||
| 401 | |||
| 376 | kref_put(&res->ref, bss_release); | 402 | kref_put(&res->ref, bss_release); |
| 377 | } else { | 403 | } else { |
| 378 | /* this "consumes" the reference */ | 404 | /* this "consumes" the reference */ |
