aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArik Nemtsov <arik@wizery.com>2011-09-28 07:12:53 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-09-30 15:57:08 -0400
commit07ba55d7f1d0da174c9bc545c713b44cee760197 (patch)
tree6ef39589ced179b1f76d7148652f10fc333f3349
parentdfe018bf99537e42c816d3f543620a7e09fcf3cd (diff)
nl80211/mac80211: allow adding TDLS peers as stations
When adding a TDLS peer STA, mark it with a new flag in both nl80211 and mac80211. Before adding a peer, make sure the wiphy supports TDLS and our operating mode is appropriate (managed). In addition, make sure all peers are removed on disassociation. A TDLS peer is first added just before link setup is initiated. In later setup stages we have more info about peer supported rates, capabilities, etc. This info is reported via nl80211_set_station(). Signed-off-by: Arik Nemtsov <arik@wizery.com> Cc: Kalyan C Gaddam <chakkal@iit.edu> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--include/linux/nl80211.h2
-rw-r--r--net/mac80211/cfg.c20
-rw-r--r--net/mac80211/mlme.c7
-rw-r--r--net/mac80211/sta_info.h2
-rw-r--r--net/wireless/nl80211.c26
5 files changed, 50 insertions, 7 deletions
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index a5ab23df5b17..9d797f253d8e 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -1434,6 +1434,7 @@ enum nl80211_iftype {
1434 * @NL80211_STA_FLAG_WME: station is WME/QoS capable 1434 * @NL80211_STA_FLAG_WME: station is WME/QoS capable
1435 * @NL80211_STA_FLAG_MFP: station uses management frame protection 1435 * @NL80211_STA_FLAG_MFP: station uses management frame protection
1436 * @NL80211_STA_FLAG_AUTHENTICATED: station is authenticated 1436 * @NL80211_STA_FLAG_AUTHENTICATED: station is authenticated
1437 * @NL80211_STA_FLAG_TDLS_PEER: station is a TDLS peer
1437 * @NL80211_STA_FLAG_MAX: highest station flag number currently defined 1438 * @NL80211_STA_FLAG_MAX: highest station flag number currently defined
1438 * @__NL80211_STA_FLAG_AFTER_LAST: internal use 1439 * @__NL80211_STA_FLAG_AFTER_LAST: internal use
1439 */ 1440 */
@@ -1444,6 +1445,7 @@ enum nl80211_sta_flags {
1444 NL80211_STA_FLAG_WME, 1445 NL80211_STA_FLAG_WME,
1445 NL80211_STA_FLAG_MFP, 1446 NL80211_STA_FLAG_MFP,
1446 NL80211_STA_FLAG_AUTHENTICATED, 1447 NL80211_STA_FLAG_AUTHENTICATED,
1448 NL80211_STA_FLAG_TDLS_PEER,
1447 1449
1448 /* keep last */ 1450 /* keep last */
1449 __NL80211_STA_FLAG_AFTER_LAST, 1451 __NL80211_STA_FLAG_AFTER_LAST,
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 1d17677a0ec1..119a573af14b 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -713,6 +713,12 @@ static void sta_apply_parameters(struct ieee80211_local *local,
713 if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED)) 713 if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED))
714 sta->flags |= WLAN_STA_AUTH; 714 sta->flags |= WLAN_STA_AUTH;
715 } 715 }
716
717 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
718 sta->flags &= ~WLAN_STA_TDLS_PEER;
719 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER))
720 sta->flags |= WLAN_STA_TDLS_PEER;
721 }
716 spin_unlock_irqrestore(&sta->flaglock, flags); 722 spin_unlock_irqrestore(&sta->flaglock, flags);
717 723
718 if (params->sta_modify_mask & STATION_PARAM_APPLY_UAPSD) { 724 if (params->sta_modify_mask & STATION_PARAM_APPLY_UAPSD) {
@@ -813,6 +819,12 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
813 819
814 sta_apply_parameters(local, sta, params); 820 sta_apply_parameters(local, sta, params);
815 821
822 /* Only TDLS-supporting stations can add TDLS peers */
823 if ((sta->flags & WLAN_STA_TDLS_PEER) &&
824 !((wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) &&
825 sdata->vif.type == NL80211_IFTYPE_STATION))
826 return -ENOTSUPP;
827
816 rate_control_rate_init(sta); 828 rate_control_rate_init(sta);
817 829
818 layer2_update = sdata->vif.type == NL80211_IFTYPE_AP_VLAN || 830 layer2_update = sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
@@ -865,6 +877,14 @@ static int ieee80211_change_station(struct wiphy *wiphy,
865 return -ENOENT; 877 return -ENOENT;
866 } 878 }
867 879
880 /* The TDLS bit cannot be toggled after the STA was added */
881 if ((params->sta_flags_mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) &&
882 !!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) !=
883 !!test_sta_flags(sta, WLAN_STA_TDLS_PEER)) {
884 rcu_read_unlock();
885 return -EINVAL;
886 }
887
868 if (params->vlan && params->vlan != sta->sdata->dev) { 888 if (params->vlan && params->vlan != sta->sdata->dev) {
869 vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); 889 vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
870 890
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index cd37a4e3c0d7..b98c43a7f191 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1137,8 +1137,9 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
1137 changed |= BSS_CHANGED_BSSID | BSS_CHANGED_HT; 1137 changed |= BSS_CHANGED_BSSID | BSS_CHANGED_HT;
1138 ieee80211_bss_info_change_notify(sdata, changed); 1138 ieee80211_bss_info_change_notify(sdata, changed);
1139 1139
1140 /* remove AP and TDLS peers */
1140 if (remove_sta) 1141 if (remove_sta)
1141 sta_info_destroy_addr(sdata, bssid); 1142 sta_info_flush(local, sdata);
1142 1143
1143 del_timer_sync(&sdata->u.mgd.conn_mon_timer); 1144 del_timer_sync(&sdata->u.mgd.conn_mon_timer);
1144 del_timer_sync(&sdata->u.mgd.bcn_mon_timer); 1145 del_timer_sync(&sdata->u.mgd.bcn_mon_timer);
@@ -2738,7 +2739,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
2738 req->reason_code, cookie, 2739 req->reason_code, cookie,
2739 !req->local_state_change); 2740 !req->local_state_change);
2740 if (assoc_bss) 2741 if (assoc_bss)
2741 sta_info_destroy_addr(sdata, bssid); 2742 sta_info_flush(sdata->local, sdata);
2742 2743
2743 mutex_lock(&sdata->local->mtx); 2744 mutex_lock(&sdata->local->mtx);
2744 ieee80211_recalc_idle(sdata->local); 2745 ieee80211_recalc_idle(sdata->local);
@@ -2778,7 +2779,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
2778 ieee80211_send_deauth_disassoc(sdata, req->bss->bssid, 2779 ieee80211_send_deauth_disassoc(sdata, req->bss->bssid,
2779 IEEE80211_STYPE_DISASSOC, req->reason_code, 2780 IEEE80211_STYPE_DISASSOC, req->reason_code,
2780 cookie, !req->local_state_change); 2781 cookie, !req->local_state_change);
2781 sta_info_destroy_addr(sdata, bssid); 2782 sta_info_flush(sdata->local, sdata);
2782 2783
2783 mutex_lock(&sdata->local->mtx); 2784 mutex_lock(&sdata->local->mtx);
2784 ieee80211_recalc_idle(sdata->local); 2785 ieee80211_recalc_idle(sdata->local);
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 56a3d38a2cd1..b6bd4e9d8722 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -45,6 +45,7 @@
45 * station in power-save mode, reply when the driver unblocks. 45 * station in power-save mode, reply when the driver unblocks.
46 * @WLAN_STA_PS_DRIVER_BUF: Station has frames pending in driver internal 46 * @WLAN_STA_PS_DRIVER_BUF: Station has frames pending in driver internal
47 * buffers. Automatically cleared on station wake-up. 47 * buffers. Automatically cleared on station wake-up.
48 * @WLAN_STA_TDLS_PEER: station is a TDLS peer.
48 */ 49 */
49enum ieee80211_sta_info_flags { 50enum ieee80211_sta_info_flags {
50 WLAN_STA_AUTH = 1<<0, 51 WLAN_STA_AUTH = 1<<0,
@@ -61,6 +62,7 @@ enum ieee80211_sta_info_flags {
61 WLAN_STA_PS_DRIVER = 1<<12, 62 WLAN_STA_PS_DRIVER = 1<<12,
62 WLAN_STA_PSPOLL = 1<<13, 63 WLAN_STA_PSPOLL = 1<<13,
63 WLAN_STA_PS_DRIVER_BUF = 1<<14, 64 WLAN_STA_PS_DRIVER_BUF = 1<<14,
65 WLAN_STA_TDLS_PEER = 1<<15,
64}; 66};
65 67
66#define STA_TID_NUM 16 68#define STA_TID_NUM 16
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 25a37fc951e3..edf655aeea00 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -2530,18 +2530,25 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
2530 break; 2530 break;
2531 case NL80211_IFTYPE_P2P_CLIENT: 2531 case NL80211_IFTYPE_P2P_CLIENT:
2532 case NL80211_IFTYPE_STATION: 2532 case NL80211_IFTYPE_STATION:
2533 /* disallow everything but AUTHORIZED flag */ 2533 /* disallow things sta doesn't support */
2534 if (params.plink_action) 2534 if (params.plink_action)
2535 err = -EINVAL; 2535 err = -EINVAL;
2536 if (params.vlan) 2536 if (params.vlan)
2537 err = -EINVAL; 2537 err = -EINVAL;
2538 if (params.supported_rates) 2538 if (params.supported_rates &&
2539 !(params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))
2539 err = -EINVAL; 2540 err = -EINVAL;
2540 if (params.ht_capa) 2541 if (params.ht_capa)
2541 err = -EINVAL; 2542 err = -EINVAL;
2542 if (params.listen_interval >= 0) 2543 if (params.listen_interval >= 0)
2543 err = -EINVAL; 2544 err = -EINVAL;
2544 if (params.sta_flags_mask & ~BIT(NL80211_STA_FLAG_AUTHORIZED)) 2545 if (params.sta_flags_mask &
2546 ~(BIT(NL80211_STA_FLAG_AUTHORIZED) |
2547 BIT(NL80211_STA_FLAG_TDLS_PEER)))
2548 err = -EINVAL;
2549 /* can't change the TDLS bit */
2550 if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) &&
2551 (params.sta_flags_mask & BIT(NL80211_STA_FLAG_TDLS_PEER)))
2545 err = -EINVAL; 2552 err = -EINVAL;
2546 break; 2553 break;
2547 case NL80211_IFTYPE_MESH_POINT: 2554 case NL80211_IFTYPE_MESH_POINT:
@@ -2662,7 +2669,18 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
2662 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && 2669 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
2663 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && 2670 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
2664 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT && 2671 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT &&
2665 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) 2672 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO &&
2673 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION)
2674 return -EINVAL;
2675
2676 /*
2677 * Only managed stations can add TDLS peers, and only when the
2678 * wiphy supports external TDLS setup.
2679 */
2680 if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_STATION &&
2681 !((params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) &&
2682 (rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) &&
2683 (rdev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP)))
2666 return -EINVAL; 2684 return -EINVAL;
2667 2685
2668 err = get_vlan(info, rdev, &params.vlan); 2686 err = get_vlan(info, rdev, &params.vlan);