diff options
author | Johannes Berg <johannes.berg@intel.com> | 2012-01-20 07:55:24 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-02-06 14:50:37 -0500 |
commit | 7852e36186d2a1983c215836d7e3d7b8927c930d (patch) | |
tree | 191ab7c06b1ab871b95c1d732e9ca67482dbce9d /net/mac80211/sta_info.c | |
parent | a4ec45a421b80bc36fd37578accf081f32527a7f (diff) |
mac80211: remove dummy STA support
The dummy STA support was added because I didn't
want to change the driver API at the time. Now
that we have state transitions triggering station
add/remove in the driver, we only call add once a
station reaches ASSOCIATED, so we can remove the
dummy station stuff again.
While at it, tighten the RX check and accept only
port control (EAP) frames from the AP station if
it's not associated yet -- in other cases there's
no race.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/sta_info.c')
-rw-r--r-- | net/mac80211/sta_info.c | 135 |
1 files changed, 25 insertions, 110 deletions
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 5e577bd0e6aa..31cd6d92531c 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -100,25 +100,6 @@ struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, | |||
100 | sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], | 100 | sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], |
101 | lockdep_is_held(&local->sta_mtx)); | 101 | lockdep_is_held(&local->sta_mtx)); |
102 | while (sta) { | 102 | while (sta) { |
103 | if (sta->sdata == sdata && !sta->dummy && | ||
104 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) | ||
105 | break; | ||
106 | sta = rcu_dereference_check(sta->hnext, | ||
107 | lockdep_is_held(&local->sta_mtx)); | ||
108 | } | ||
109 | return sta; | ||
110 | } | ||
111 | |||
112 | /* get a station info entry even if it is a dummy station*/ | ||
113 | struct sta_info *sta_info_get_rx(struct ieee80211_sub_if_data *sdata, | ||
114 | const u8 *addr) | ||
115 | { | ||
116 | struct ieee80211_local *local = sdata->local; | ||
117 | struct sta_info *sta; | ||
118 | |||
119 | sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], | ||
120 | lockdep_is_held(&local->sta_mtx)); | ||
121 | while (sta) { | ||
122 | if (sta->sdata == sdata && | 103 | if (sta->sdata == sdata && |
123 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) | 104 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) |
124 | break; | 105 | break; |
@@ -143,30 +124,6 @@ struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata, | |||
143 | while (sta) { | 124 | while (sta) { |
144 | if ((sta->sdata == sdata || | 125 | if ((sta->sdata == sdata || |
145 | (sta->sdata->bss && sta->sdata->bss == sdata->bss)) && | 126 | (sta->sdata->bss && sta->sdata->bss == sdata->bss)) && |
146 | !sta->dummy && | ||
147 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) | ||
148 | break; | ||
149 | sta = rcu_dereference_check(sta->hnext, | ||
150 | lockdep_is_held(&local->sta_mtx)); | ||
151 | } | ||
152 | return sta; | ||
153 | } | ||
154 | |||
155 | /* | ||
156 | * Get sta info either from the specified interface | ||
157 | * or from one of its vlans (including dummy stations) | ||
158 | */ | ||
159 | struct sta_info *sta_info_get_bss_rx(struct ieee80211_sub_if_data *sdata, | ||
160 | const u8 *addr) | ||
161 | { | ||
162 | struct ieee80211_local *local = sdata->local; | ||
163 | struct sta_info *sta; | ||
164 | |||
165 | sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], | ||
166 | lockdep_is_held(&local->sta_mtx)); | ||
167 | while (sta) { | ||
168 | if ((sta->sdata == sdata || | ||
169 | (sta->sdata->bss && sta->sdata->bss == sdata->bss)) && | ||
170 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) | 127 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) |
171 | break; | 128 | break; |
172 | sta = rcu_dereference_check(sta->hnext, | 129 | sta = rcu_dereference_check(sta->hnext, |
@@ -397,66 +354,43 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU) | |||
397 | { | 354 | { |
398 | struct ieee80211_local *local = sta->local; | 355 | struct ieee80211_local *local = sta->local; |
399 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 356 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
400 | struct sta_info *exist_sta; | 357 | struct station_info sinfo; |
401 | bool dummy_reinsert = false; | ||
402 | int err = 0; | 358 | int err = 0; |
403 | 359 | ||
404 | lockdep_assert_held(&local->sta_mtx); | 360 | lockdep_assert_held(&local->sta_mtx); |
405 | 361 | ||
406 | /* | 362 | /* check if STA exists already */ |
407 | * check if STA exists already. | 363 | if (sta_info_get_bss(sdata, sta->sta.addr)) { |
408 | * only accept a scenario of a second call to sta_info_insert_finish | 364 | err = -EEXIST; |
409 | * with a dummy station entry that was inserted earlier | 365 | goto out_err; |
410 | * in that case - assume that the dummy station flag should | ||
411 | * be removed. | ||
412 | */ | ||
413 | exist_sta = sta_info_get_bss_rx(sdata, sta->sta.addr); | ||
414 | if (exist_sta) { | ||
415 | if (exist_sta == sta && sta->dummy) { | ||
416 | dummy_reinsert = true; | ||
417 | } else { | ||
418 | err = -EEXIST; | ||
419 | goto out_err; | ||
420 | } | ||
421 | } | ||
422 | |||
423 | if (!sta->dummy || dummy_reinsert) { | ||
424 | /* notify driver */ | ||
425 | err = sta_info_insert_drv_state(local, sdata, sta); | ||
426 | if (err) | ||
427 | goto out_err; | ||
428 | } | 366 | } |
429 | 367 | ||
430 | if (!dummy_reinsert) { | 368 | /* notify driver */ |
431 | local->num_sta++; | 369 | err = sta_info_insert_drv_state(local, sdata, sta); |
432 | local->sta_generation++; | 370 | if (err) |
433 | smp_mb(); | 371 | goto out_err; |
434 | 372 | ||
435 | /* make the station visible */ | 373 | local->num_sta++; |
436 | sta_info_hash_add(local, sta); | 374 | local->sta_generation++; |
375 | smp_mb(); | ||
437 | 376 | ||
438 | list_add(&sta->list, &local->sta_list); | 377 | /* make the station visible */ |
378 | sta_info_hash_add(local, sta); | ||
439 | 379 | ||
440 | set_sta_flag(sta, WLAN_STA_INSERTED); | 380 | list_add(&sta->list, &local->sta_list); |
441 | } else { | ||
442 | sta->dummy = false; | ||
443 | } | ||
444 | 381 | ||
445 | if (!sta->dummy) { | 382 | set_sta_flag(sta, WLAN_STA_INSERTED); |
446 | struct station_info sinfo; | ||
447 | 383 | ||
448 | ieee80211_sta_debugfs_add(sta); | 384 | ieee80211_sta_debugfs_add(sta); |
449 | rate_control_add_sta_debugfs(sta); | 385 | rate_control_add_sta_debugfs(sta); |
450 | 386 | ||
451 | memset(&sinfo, 0, sizeof(sinfo)); | 387 | memset(&sinfo, 0, sizeof(sinfo)); |
452 | sinfo.filled = 0; | 388 | sinfo.filled = 0; |
453 | sinfo.generation = local->sta_generation; | 389 | sinfo.generation = local->sta_generation; |
454 | cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL); | 390 | cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL); |
455 | } | ||
456 | 391 | ||
457 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 392 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
458 | wiphy_debug(local->hw.wiphy, "Inserted %sSTA %pM\n", | 393 | wiphy_debug(local->hw.wiphy, "Inserted STA %pM\n", sta->sta.addr); |
459 | sta->dummy ? "dummy " : "", sta->sta.addr); | ||
460 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | 394 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ |
461 | 395 | ||
462 | /* move reference to rcu-protected */ | 396 | /* move reference to rcu-protected */ |
@@ -508,25 +442,6 @@ int sta_info_insert(struct sta_info *sta) | |||
508 | return err; | 442 | return err; |
509 | } | 443 | } |
510 | 444 | ||
511 | /* Caller must hold sta->local->sta_mtx */ | ||
512 | int sta_info_reinsert(struct sta_info *sta) | ||
513 | { | ||
514 | struct ieee80211_local *local = sta->local; | ||
515 | int err = 0; | ||
516 | |||
517 | err = sta_info_insert_check(sta); | ||
518 | if (err) { | ||
519 | mutex_unlock(&local->sta_mtx); | ||
520 | return err; | ||
521 | } | ||
522 | |||
523 | might_sleep(); | ||
524 | |||
525 | err = sta_info_insert_finish(sta); | ||
526 | rcu_read_unlock(); | ||
527 | return err; | ||
528 | } | ||
529 | |||
530 | static inline void __bss_tim_set(struct ieee80211_if_ap *bss, u16 aid) | 445 | static inline void __bss_tim_set(struct ieee80211_if_ap *bss, u16 aid) |
531 | { | 446 | { |
532 | /* | 447 | /* |
@@ -873,7 +788,7 @@ int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata, const u8 *addr) | |||
873 | int ret; | 788 | int ret; |
874 | 789 | ||
875 | mutex_lock(&sdata->local->sta_mtx); | 790 | mutex_lock(&sdata->local->sta_mtx); |
876 | sta = sta_info_get_rx(sdata, addr); | 791 | sta = sta_info_get(sdata, addr); |
877 | ret = __sta_info_destroy(sta); | 792 | ret = __sta_info_destroy(sta); |
878 | mutex_unlock(&sdata->local->sta_mtx); | 793 | mutex_unlock(&sdata->local->sta_mtx); |
879 | 794 | ||
@@ -887,7 +802,7 @@ int sta_info_destroy_addr_bss(struct ieee80211_sub_if_data *sdata, | |||
887 | int ret; | 802 | int ret; |
888 | 803 | ||
889 | mutex_lock(&sdata->local->sta_mtx); | 804 | mutex_lock(&sdata->local->sta_mtx); |
890 | sta = sta_info_get_bss_rx(sdata, addr); | 805 | sta = sta_info_get_bss(sdata, addr); |
891 | ret = __sta_info_destroy(sta); | 806 | ret = __sta_info_destroy(sta); |
892 | mutex_unlock(&sdata->local->sta_mtx); | 807 | mutex_unlock(&sdata->local->sta_mtx); |
893 | 808 | ||