Skip to content

Commit

Permalink
cfg80211: do not replace BSS structs
Browse files Browse the repository at this point in the history
Instead, allocate extra IE memory if necessary. Normally,
this isn't even necessary since there's enough space.

This is a better way of correcting the "held BSS can
disappear" issue, but also a lot more code. It is also
necessary for proper auth/assoc BSS handling in the
future.

Signed-off-by: Johannes Berg <[email protected]>
Signed-off-by: John W. Linville <[email protected]>
  • Loading branch information
jmberg authored and linvjw committed Apr 17, 2009
1 parent 160002f commit cd1658f
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 10 deletions.
2 changes: 1 addition & 1 deletion net/wireless/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ struct cfg80211_internal_bss {
struct rb_node rbn;
unsigned long ts;
struct kref ref;
bool hold;
bool hold, ies_allocated;

/* must be last because of priv member */
struct cfg80211_bss pub;
Expand Down
42 changes: 33 additions & 9 deletions net/wireless/scan.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ static void bss_release(struct kref *ref)
bss = container_of(ref, struct cfg80211_internal_bss, ref);
if (bss->pub.free_priv)
bss->pub.free_priv(&bss->pub);

if (bss->ies_allocated)
kfree(bss->pub.information_elements);

kfree(bss);
}

Expand Down Expand Up @@ -360,21 +364,41 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,

found = rb_find_bss(dev, res);

if (found && overwrite) {
list_replace(&found->list, &res->list);
rb_replace_node(&found->rbn, &res->rbn,
&dev->bss_tree);
/* XXX: workaround */
res->hold = found->hold;
kref_put(&found->ref, bss_release);
found = res;
} else if (found) {
if (found) {
kref_get(&found->ref);
found->pub.beacon_interval = res->pub.beacon_interval;
found->pub.tsf = res->pub.tsf;
found->pub.signal = res->pub.signal;
found->pub.capability = res->pub.capability;
found->ts = res->ts;

/* overwrite IEs */
if (overwrite) {
size_t used = dev->wiphy.bss_priv_size + sizeof(*res);
size_t ielen = res->pub.len_information_elements;

if (ksize(found) >= used + ielen) {
memcpy(found->pub.information_elements,
res->pub.information_elements, ielen);
found->pub.len_information_elements = ielen;
} else {
u8 *ies = found->pub.information_elements;

if (found->ies_allocated) {
if (ksize(ies) < ielen)
ies = krealloc(ies, ielen,
GFP_ATOMIC);
} else
ies = kmalloc(ielen, GFP_ATOMIC);

if (ies) {
memcpy(ies, res->pub.information_elements, ielen);
found->ies_allocated = true;
found->pub.information_elements = ies;
}
}
}

kref_put(&res->ref, bss_release);
} else {
/* this "consumes" the reference */
Expand Down

0 comments on commit cd1658f

Please sign in to comment.