aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/nl80211.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless/nl80211.c')
-rw-r--r--net/wireless/nl80211.c109
1 files changed, 104 insertions, 5 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index b85075761e24..edf655aeea00 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -192,6 +192,11 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
192 [NL80211_ATTR_ROAM_SUPPORT] = { .type = NLA_FLAG }, 192 [NL80211_ATTR_ROAM_SUPPORT] = { .type = NLA_FLAG },
193 [NL80211_ATTR_SCHED_SCAN_MATCH] = { .type = NLA_NESTED }, 193 [NL80211_ATTR_SCHED_SCAN_MATCH] = { .type = NLA_NESTED },
194 [NL80211_ATTR_TX_NO_CCK_RATE] = { .type = NLA_FLAG }, 194 [NL80211_ATTR_TX_NO_CCK_RATE] = { .type = NLA_FLAG },
195 [NL80211_ATTR_TDLS_ACTION] = { .type = NLA_U8 },
196 [NL80211_ATTR_TDLS_DIALOG_TOKEN] = { .type = NLA_U8 },
197 [NL80211_ATTR_TDLS_OPERATION] = { .type = NLA_U8 },
198 [NL80211_ATTR_TDLS_SUPPORT] = { .type = NLA_FLAG },
199 [NL80211_ATTR_TDLS_EXTERNAL_SETUP] = { .type = NLA_FLAG },
195}; 200};
196 201
197/* policy for the key attributes */ 202/* policy for the key attributes */
@@ -732,9 +737,12 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
732 NLA_PUT_FLAG(msg, NL80211_ATTR_SUPPORT_MESH_AUTH); 737 NLA_PUT_FLAG(msg, NL80211_ATTR_SUPPORT_MESH_AUTH);
733 if (dev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) 738 if (dev->wiphy.flags & WIPHY_FLAG_AP_UAPSD)
734 NLA_PUT_FLAG(msg, NL80211_ATTR_SUPPORT_AP_UAPSD); 739 NLA_PUT_FLAG(msg, NL80211_ATTR_SUPPORT_AP_UAPSD);
735
736 if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_FW_ROAM) 740 if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_FW_ROAM)
737 NLA_PUT_FLAG(msg, NL80211_ATTR_ROAM_SUPPORT); 741 NLA_PUT_FLAG(msg, NL80211_ATTR_ROAM_SUPPORT);
742 if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS)
743 NLA_PUT_FLAG(msg, NL80211_ATTR_TDLS_SUPPORT);
744 if (dev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP)
745 NLA_PUT_FLAG(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP);
738 746
739 NLA_PUT(msg, NL80211_ATTR_CIPHER_SUITES, 747 NLA_PUT(msg, NL80211_ATTR_CIPHER_SUITES,
740 sizeof(u32) * dev->wiphy.n_cipher_suites, 748 sizeof(u32) * dev->wiphy.n_cipher_suites,
@@ -877,6 +885,10 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
877 } 885 }
878 CMD(set_channel, SET_CHANNEL); 886 CMD(set_channel, SET_CHANNEL);
879 CMD(set_wds_peer, SET_WDS_PEER); 887 CMD(set_wds_peer, SET_WDS_PEER);
888 if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) {
889 CMD(tdls_mgmt, TDLS_MGMT);
890 CMD(tdls_oper, TDLS_OPER);
891 }
880 if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) 892 if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN)
881 CMD(sched_scan_start, START_SCHED_SCAN); 893 CMD(sched_scan_start, START_SCHED_SCAN);
882 894
@@ -2518,18 +2530,25 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
2518 break; 2530 break;
2519 case NL80211_IFTYPE_P2P_CLIENT: 2531 case NL80211_IFTYPE_P2P_CLIENT:
2520 case NL80211_IFTYPE_STATION: 2532 case NL80211_IFTYPE_STATION:
2521 /* disallow everything but AUTHORIZED flag */ 2533 /* disallow things sta doesn't support */
2522 if (params.plink_action) 2534 if (params.plink_action)
2523 err = -EINVAL; 2535 err = -EINVAL;
2524 if (params.vlan) 2536 if (params.vlan)
2525 err = -EINVAL; 2537 err = -EINVAL;
2526 if (params.supported_rates) 2538 if (params.supported_rates &&
2539 !(params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))
2527 err = -EINVAL; 2540 err = -EINVAL;
2528 if (params.ht_capa) 2541 if (params.ht_capa)
2529 err = -EINVAL; 2542 err = -EINVAL;
2530 if (params.listen_interval >= 0) 2543 if (params.listen_interval >= 0)
2531 err = -EINVAL; 2544 err = -EINVAL;
2532 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)))
2533 err = -EINVAL; 2552 err = -EINVAL;
2534 break; 2553 break;
2535 case NL80211_IFTYPE_MESH_POINT: 2554 case NL80211_IFTYPE_MESH_POINT:
@@ -2643,12 +2662,25 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
2643 2662
2644 if (params.max_sp & ~IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK) 2663 if (params.max_sp & ~IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK)
2645 return -EINVAL; 2664 return -EINVAL;
2665
2666 params.sta_modify_mask |= STATION_PARAM_APPLY_UAPSD;
2646 } 2667 }
2647 2668
2648 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && 2669 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
2649 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && 2670 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
2650 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT && 2671 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT &&
2651 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)))
2652 return -EINVAL; 2684 return -EINVAL;
2653 2685
2654 err = get_vlan(info, rdev, &params.vlan); 2686 err = get_vlan(info, rdev, &params.vlan);
@@ -4964,6 +4996,57 @@ static int nl80211_flush_pmksa(struct sk_buff *skb, struct genl_info *info)
4964 return rdev->ops->flush_pmksa(&rdev->wiphy, dev); 4996 return rdev->ops->flush_pmksa(&rdev->wiphy, dev);
4965} 4997}
4966 4998
4999static int nl80211_tdls_mgmt(struct sk_buff *skb, struct genl_info *info)
5000{
5001 struct cfg80211_registered_device *rdev = info->user_ptr[0];
5002 struct net_device *dev = info->user_ptr[1];
5003 u8 action_code, dialog_token;
5004 u16 status_code;
5005 u8 *peer;
5006
5007 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) ||
5008 !rdev->ops->tdls_mgmt)
5009 return -EOPNOTSUPP;
5010
5011 if (!info->attrs[NL80211_ATTR_TDLS_ACTION] ||
5012 !info->attrs[NL80211_ATTR_STATUS_CODE] ||
5013 !info->attrs[NL80211_ATTR_TDLS_DIALOG_TOKEN] ||
5014 !info->attrs[NL80211_ATTR_IE] ||
5015 !info->attrs[NL80211_ATTR_MAC])
5016 return -EINVAL;
5017
5018 peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
5019 action_code = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_ACTION]);
5020 status_code = nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]);
5021 dialog_token = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_DIALOG_TOKEN]);
5022
5023 return rdev->ops->tdls_mgmt(&rdev->wiphy, dev, peer, action_code,
5024 dialog_token, status_code,
5025 nla_data(info->attrs[NL80211_ATTR_IE]),
5026 nla_len(info->attrs[NL80211_ATTR_IE]));
5027}
5028
5029static int nl80211_tdls_oper(struct sk_buff *skb, struct genl_info *info)
5030{
5031 struct cfg80211_registered_device *rdev = info->user_ptr[0];
5032 struct net_device *dev = info->user_ptr[1];
5033 enum nl80211_tdls_operation operation;
5034 u8 *peer;
5035
5036 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) ||
5037 !rdev->ops->tdls_oper)
5038 return -EOPNOTSUPP;
5039
5040 if (!info->attrs[NL80211_ATTR_TDLS_OPERATION] ||
5041 !info->attrs[NL80211_ATTR_MAC])
5042 return -EINVAL;
5043
5044 operation = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_OPERATION]);
5045 peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
5046
5047 return rdev->ops->tdls_oper(&rdev->wiphy, dev, peer, operation);
5048}
5049
4967static int nl80211_remain_on_channel(struct sk_buff *skb, 5050static int nl80211_remain_on_channel(struct sk_buff *skb,
4968 struct genl_info *info) 5051 struct genl_info *info)
4969{ 5052{
@@ -6279,6 +6362,22 @@ static struct genl_ops nl80211_ops[] = {
6279 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 6362 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
6280 NL80211_FLAG_NEED_RTNL, 6363 NL80211_FLAG_NEED_RTNL,
6281 }, 6364 },
6365 {
6366 .cmd = NL80211_CMD_TDLS_MGMT,
6367 .doit = nl80211_tdls_mgmt,
6368 .policy = nl80211_policy,
6369 .flags = GENL_ADMIN_PERM,
6370 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
6371 NL80211_FLAG_NEED_RTNL,
6372 },
6373 {
6374 .cmd = NL80211_CMD_TDLS_OPER,
6375 .doit = nl80211_tdls_oper,
6376 .policy = nl80211_policy,
6377 .flags = GENL_ADMIN_PERM,
6378 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
6379 NL80211_FLAG_NEED_RTNL,
6380 },
6282}; 6381};
6283 6382
6284static struct genl_multicast_group nl80211_mlme_mcgrp = { 6383static struct genl_multicast_group nl80211_mlme_mcgrp = {