diff options
Diffstat (limited to 'net/mac80211/cfg.c')
-rw-r--r-- | net/mac80211/cfg.c | 110 |
1 files changed, 56 insertions, 54 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 6ac49231efa9..e9ba6fcc0e45 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -136,7 +136,6 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
136 | struct ieee80211_sub_if_data *sdata; | 136 | struct ieee80211_sub_if_data *sdata; |
137 | struct sta_info *sta = NULL; | 137 | struct sta_info *sta = NULL; |
138 | enum ieee80211_key_alg alg; | 138 | enum ieee80211_key_alg alg; |
139 | int ret; | ||
140 | struct ieee80211_key *key; | 139 | struct ieee80211_key *key; |
141 | 140 | ||
142 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 141 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
@@ -170,12 +169,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
170 | 169 | ||
171 | ieee80211_key_link(key, sdata, sta); | 170 | ieee80211_key_link(key, sdata, sta); |
172 | 171 | ||
173 | ret = 0; | 172 | return 0; |
174 | |||
175 | if (sta) | ||
176 | sta_info_put(sta); | ||
177 | |||
178 | return ret; | ||
179 | } | 173 | } |
180 | 174 | ||
181 | static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, | 175 | static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, |
@@ -184,7 +178,6 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, | |||
184 | struct ieee80211_sub_if_data *sdata; | 178 | struct ieee80211_sub_if_data *sdata; |
185 | struct sta_info *sta; | 179 | struct sta_info *sta; |
186 | int ret; | 180 | int ret; |
187 | struct ieee80211_key *key; | ||
188 | 181 | ||
189 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 182 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
190 | 183 | ||
@@ -195,21 +188,18 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, | |||
195 | 188 | ||
196 | ret = 0; | 189 | ret = 0; |
197 | if (sta->key) { | 190 | if (sta->key) { |
198 | key = sta->key; | 191 | ieee80211_key_free(sta->key); |
199 | ieee80211_key_free(key); | ||
200 | WARN_ON(sta->key); | 192 | WARN_ON(sta->key); |
201 | } else | 193 | } else |
202 | ret = -ENOENT; | 194 | ret = -ENOENT; |
203 | 195 | ||
204 | sta_info_put(sta); | ||
205 | return ret; | 196 | return ret; |
206 | } | 197 | } |
207 | 198 | ||
208 | if (!sdata->keys[key_idx]) | 199 | if (!sdata->keys[key_idx]) |
209 | return -ENOENT; | 200 | return -ENOENT; |
210 | 201 | ||
211 | key = sdata->keys[key_idx]; | 202 | ieee80211_key_free(sdata->keys[key_idx]); |
212 | ieee80211_key_free(key); | ||
213 | WARN_ON(sdata->keys[key_idx]); | 203 | WARN_ON(sdata->keys[key_idx]); |
214 | 204 | ||
215 | return 0; | 205 | return 0; |
@@ -292,8 +282,6 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
292 | err = 0; | 282 | err = 0; |
293 | 283 | ||
294 | out: | 284 | out: |
295 | if (sta) | ||
296 | sta_info_put(sta); | ||
297 | return err; | 285 | return err; |
298 | } | 286 | } |
299 | 287 | ||
@@ -311,7 +299,7 @@ static int ieee80211_config_default_key(struct wiphy *wiphy, | |||
311 | 299 | ||
312 | static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | 300 | static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) |
313 | { | 301 | { |
314 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev); | 302 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
315 | 303 | ||
316 | sinfo->filled = STATION_INFO_INACTIVE_TIME | | 304 | sinfo->filled = STATION_INFO_INACTIVE_TIME | |
317 | STATION_INFO_RX_BYTES | | 305 | STATION_INFO_RX_BYTES | |
@@ -340,16 +328,20 @@ static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev, | |||
340 | { | 328 | { |
341 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 329 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
342 | struct sta_info *sta; | 330 | struct sta_info *sta; |
331 | int ret = -ENOENT; | ||
332 | |||
333 | rcu_read_lock(); | ||
343 | 334 | ||
344 | sta = sta_info_get_by_idx(local, idx, dev); | 335 | sta = sta_info_get_by_idx(local, idx, dev); |
345 | if (!sta) | 336 | if (sta) { |
346 | return -ENOENT; | 337 | ret = 0; |
338 | memcpy(mac, sta->addr, ETH_ALEN); | ||
339 | sta_set_sinfo(sta, sinfo); | ||
340 | } | ||
347 | 341 | ||
348 | memcpy(mac, sta->addr, ETH_ALEN); | 342 | rcu_read_unlock(); |
349 | sta_set_sinfo(sta, sinfo); | ||
350 | sta_info_put(sta); | ||
351 | 343 | ||
352 | return 0; | 344 | return ret; |
353 | } | 345 | } |
354 | 346 | ||
355 | static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev, | 347 | static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev, |
@@ -357,16 +349,21 @@ static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev, | |||
357 | { | 349 | { |
358 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 350 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
359 | struct sta_info *sta; | 351 | struct sta_info *sta; |
352 | int ret = -ENOENT; | ||
360 | 353 | ||
361 | sta = sta_info_get(local, mac); | 354 | rcu_read_lock(); |
362 | if (!sta) | ||
363 | return -ENOENT; | ||
364 | 355 | ||
365 | /* XXX: verify sta->dev == dev */ | 356 | /* XXX: verify sta->dev == dev */ |
366 | sta_set_sinfo(sta, sinfo); | ||
367 | sta_info_put(sta); | ||
368 | 357 | ||
369 | return 0; | 358 | sta = sta_info_get(local, mac); |
359 | if (sta) { | ||
360 | ret = 0; | ||
361 | sta_set_sinfo(sta, sinfo); | ||
362 | } | ||
363 | |||
364 | rcu_read_unlock(); | ||
365 | |||
366 | return ret; | ||
370 | } | 367 | } |
371 | 368 | ||
372 | /* | 369 | /* |
@@ -559,8 +556,8 @@ static void ieee80211_send_layer2_update(struct sta_info *sta) | |||
559 | msg->xid_info[1] = 1; /* LLC types/classes: Type 1 LLC */ | 556 | msg->xid_info[1] = 1; /* LLC types/classes: Type 1 LLC */ |
560 | msg->xid_info[2] = 0; /* XID sender's receive window size (RW) */ | 557 | msg->xid_info[2] = 0; /* XID sender's receive window size (RW) */ |
561 | 558 | ||
562 | skb->dev = sta->dev; | 559 | skb->dev = sta->sdata->dev; |
563 | skb->protocol = eth_type_trans(skb, sta->dev); | 560 | skb->protocol = eth_type_trans(skb, sta->sdata->dev); |
564 | memset(skb->cb, 0, sizeof(skb->cb)); | 561 | memset(skb->cb, 0, sizeof(skb->cb)); |
565 | netif_rx(skb); | 562 | netif_rx(skb); |
566 | } | 563 | } |
@@ -572,7 +569,7 @@ static void sta_apply_parameters(struct ieee80211_local *local, | |||
572 | u32 rates; | 569 | u32 rates; |
573 | int i, j; | 570 | int i, j; |
574 | struct ieee80211_supported_band *sband; | 571 | struct ieee80211_supported_band *sband; |
575 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev); | 572 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
576 | 573 | ||
577 | if (params->station_flags & STATION_FLAG_CHANGED) { | 574 | if (params->station_flags & STATION_FLAG_CHANGED) { |
578 | sta->flags &= ~WLAN_STA_AUTHORIZED; | 575 | sta->flags &= ~WLAN_STA_AUTHORIZED; |
@@ -644,14 +641,13 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
644 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 641 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
645 | 642 | ||
646 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 643 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
647 | sta = mesh_plink_add(mac, DEFAULT_RATES, dev); | 644 | sta = mesh_plink_add(mac, DEFAULT_RATES, sdata); |
648 | else | 645 | else |
649 | sta = sta_info_add(local, dev, mac, GFP_KERNEL); | 646 | sta = sta_info_add(sdata, mac); |
650 | 647 | ||
651 | if (IS_ERR(sta)) | 648 | if (IS_ERR(sta)) |
652 | return PTR_ERR(sta); | 649 | return PTR_ERR(sta); |
653 | 650 | ||
654 | sta->dev = sdata->dev; | ||
655 | if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN || | 651 | if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN || |
656 | sdata->vif.type == IEEE80211_IF_TYPE_AP) | 652 | sdata->vif.type == IEEE80211_IF_TYPE_AP) |
657 | ieee80211_send_layer2_update(sta); | 653 | ieee80211_send_layer2_update(sta); |
@@ -662,15 +658,14 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
662 | 658 | ||
663 | rate_control_rate_init(sta, local); | 659 | rate_control_rate_init(sta, local); |
664 | 660 | ||
665 | sta_info_put(sta); | ||
666 | |||
667 | return 0; | 661 | return 0; |
668 | } | 662 | } |
669 | 663 | ||
670 | static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev, | 664 | static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev, |
671 | u8 *mac) | 665 | u8 *mac) |
672 | { | 666 | { |
673 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 667 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
668 | struct ieee80211_local *local = sdata->local; | ||
674 | struct sta_info *sta; | 669 | struct sta_info *sta; |
675 | 670 | ||
676 | if (mac) { | 671 | if (mac) { |
@@ -679,10 +674,14 @@ static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev, | |||
679 | if (!sta) | 674 | if (!sta) |
680 | return -ENOENT; | 675 | return -ENOENT; |
681 | 676 | ||
682 | sta_info_free(sta); | 677 | sta_info_unlink(&sta); |
683 | sta_info_put(sta); | 678 | |
679 | if (sta) { | ||
680 | synchronize_rcu(); | ||
681 | sta_info_destroy(sta); | ||
682 | } | ||
684 | } else | 683 | } else |
685 | sta_info_flush(local, dev); | 684 | sta_info_flush(local, sdata); |
686 | 685 | ||
687 | return 0; | 686 | return 0; |
688 | } | 687 | } |
@@ -701,21 +700,19 @@ static int ieee80211_change_station(struct wiphy *wiphy, | |||
701 | if (!sta) | 700 | if (!sta) |
702 | return -ENOENT; | 701 | return -ENOENT; |
703 | 702 | ||
704 | if (params->vlan && params->vlan != sta->dev) { | 703 | if (params->vlan && params->vlan != sta->sdata->dev) { |
705 | vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); | 704 | vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); |
706 | 705 | ||
707 | if (vlansdata->vif.type != IEEE80211_IF_TYPE_VLAN || | 706 | if (vlansdata->vif.type != IEEE80211_IF_TYPE_VLAN || |
708 | vlansdata->vif.type != IEEE80211_IF_TYPE_AP) | 707 | vlansdata->vif.type != IEEE80211_IF_TYPE_AP) |
709 | return -EINVAL; | 708 | return -EINVAL; |
710 | 709 | ||
711 | sta->dev = params->vlan; | 710 | sta->sdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); |
712 | ieee80211_send_layer2_update(sta); | 711 | ieee80211_send_layer2_update(sta); |
713 | } | 712 | } |
714 | 713 | ||
715 | sta_apply_parameters(local, sta, params); | 714 | sta_apply_parameters(local, sta, params); |
716 | 715 | ||
717 | sta_info_put(sta); | ||
718 | |||
719 | return 0; | 716 | return 0; |
720 | } | 717 | } |
721 | 718 | ||
@@ -735,23 +732,26 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
735 | if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT) | 732 | if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT) |
736 | return -ENOTSUPP; | 733 | return -ENOTSUPP; |
737 | 734 | ||
735 | rcu_read_lock(); | ||
738 | sta = sta_info_get(local, next_hop); | 736 | sta = sta_info_get(local, next_hop); |
739 | if (!sta) | 737 | if (!sta) { |
738 | rcu_read_unlock(); | ||
740 | return -ENOENT; | 739 | return -ENOENT; |
740 | } | ||
741 | 741 | ||
742 | err = mesh_path_add(dst, dev); | 742 | err = mesh_path_add(dst, dev); |
743 | if (err) | 743 | if (err) { |
744 | rcu_read_unlock(); | ||
744 | return err; | 745 | return err; |
746 | } | ||
745 | 747 | ||
746 | rcu_read_lock(); | ||
747 | mpath = mesh_path_lookup(dst, dev); | 748 | mpath = mesh_path_lookup(dst, dev); |
748 | if (!mpath) { | 749 | if (!mpath) { |
749 | rcu_read_unlock(); | 750 | rcu_read_unlock(); |
750 | sta_info_put(sta); | ||
751 | return -ENXIO; | 751 | return -ENXIO; |
752 | } | 752 | } |
753 | mesh_path_fix_nexthop(mpath, sta); | 753 | mesh_path_fix_nexthop(mpath, sta); |
754 | sta_info_put(sta); | 754 | |
755 | rcu_read_unlock(); | 755 | rcu_read_unlock(); |
756 | return 0; | 756 | return 0; |
757 | } | 757 | } |
@@ -760,7 +760,7 @@ static int ieee80211_del_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
760 | u8 *dst) | 760 | u8 *dst) |
761 | { | 761 | { |
762 | if (dst) | 762 | if (dst) |
763 | return mesh_path_del(dst, dev); | 763 | return mesh_path_del(dst, dev, false); |
764 | 764 | ||
765 | mesh_path_flush(dev); | 765 | mesh_path_flush(dev); |
766 | return 0; | 766 | return 0; |
@@ -781,20 +781,22 @@ static int ieee80211_change_mpath(struct wiphy *wiphy, | |||
781 | if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT) | 781 | if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT) |
782 | return -ENOTSUPP; | 782 | return -ENOTSUPP; |
783 | 783 | ||
784 | rcu_read_lock(); | ||
785 | |||
784 | sta = sta_info_get(local, next_hop); | 786 | sta = sta_info_get(local, next_hop); |
785 | if (!sta) | 787 | if (!sta) { |
788 | rcu_read_unlock(); | ||
786 | return -ENOENT; | 789 | return -ENOENT; |
790 | } | ||
787 | 791 | ||
788 | rcu_read_lock(); | ||
789 | mpath = mesh_path_lookup(dst, dev); | 792 | mpath = mesh_path_lookup(dst, dev); |
790 | if (!mpath) { | 793 | if (!mpath) { |
791 | rcu_read_unlock(); | 794 | rcu_read_unlock(); |
792 | sta_info_put(sta); | ||
793 | return -ENOENT; | 795 | return -ENOENT; |
794 | } | 796 | } |
795 | 797 | ||
796 | mesh_path_fix_nexthop(mpath, sta); | 798 | mesh_path_fix_nexthop(mpath, sta); |
797 | sta_info_put(sta); | 799 | |
798 | rcu_read_unlock(); | 800 | rcu_read_unlock(); |
799 | return 0; | 801 | return 0; |
800 | } | 802 | } |