diff options
Diffstat (limited to 'net/wireless')
-rw-r--r-- | net/wireless/mesh.c | 23 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 67 | ||||
-rw-r--r-- | net/wireless/nl80211.h | 4 |
3 files changed, 86 insertions, 8 deletions
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c index 73e39c171ffb..5c116083eeca 100644 --- a/net/wireless/mesh.c +++ b/net/wireless/mesh.c | |||
@@ -1,5 +1,6 @@ | |||
1 | #include <linux/ieee80211.h> | 1 | #include <linux/ieee80211.h> |
2 | #include <net/cfg80211.h> | 2 | #include <net/cfg80211.h> |
3 | #include "nl80211.h" | ||
3 | #include "core.h" | 4 | #include "core.h" |
4 | 5 | ||
5 | /* Default values, timeouts in ms */ | 6 | /* Default values, timeouts in ms */ |
@@ -53,8 +54,9 @@ const struct mesh_config default_mesh_config = { | |||
53 | const struct mesh_setup default_mesh_setup = { | 54 | const struct mesh_setup default_mesh_setup = { |
54 | .path_sel_proto = IEEE80211_PATH_PROTOCOL_HWMP, | 55 | .path_sel_proto = IEEE80211_PATH_PROTOCOL_HWMP, |
55 | .path_metric = IEEE80211_PATH_METRIC_AIRTIME, | 56 | .path_metric = IEEE80211_PATH_METRIC_AIRTIME, |
56 | .vendor_ie = NULL, | 57 | .ie = NULL, |
57 | .vendor_ie_len = 0, | 58 | .ie_len = 0, |
59 | .is_secure = false, | ||
58 | }; | 60 | }; |
59 | 61 | ||
60 | int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | 62 | int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, |
@@ -72,6 +74,10 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | |||
72 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) | 74 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) |
73 | return -EOPNOTSUPP; | 75 | return -EOPNOTSUPP; |
74 | 76 | ||
77 | if (!(rdev->wiphy.flags & WIPHY_FLAG_MESH_AUTH) && | ||
78 | setup->is_secure) | ||
79 | return -EOPNOTSUPP; | ||
80 | |||
75 | if (wdev->mesh_id_len) | 81 | if (wdev->mesh_id_len) |
76 | return -EALREADY; | 82 | return -EALREADY; |
77 | 83 | ||
@@ -105,6 +111,19 @@ int cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | |||
105 | return err; | 111 | return err; |
106 | } | 112 | } |
107 | 113 | ||
114 | void cfg80211_notify_new_peer_candidate(struct net_device *dev, | ||
115 | const u8 *macaddr, const u8* ie, u8 ie_len, gfp_t gfp) | ||
116 | { | ||
117 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
118 | |||
119 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_MESH_POINT)) | ||
120 | return; | ||
121 | |||
122 | nl80211_send_new_peer_candidate(wiphy_to_dev(wdev->wiphy), dev, | ||
123 | macaddr, ie, ie_len, gfp); | ||
124 | } | ||
125 | EXPORT_SYMBOL(cfg80211_notify_new_peer_candidate); | ||
126 | |||
108 | static int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, | 127 | static int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, |
109 | struct net_device *dev) | 128 | struct net_device *dev) |
110 | { | 129 | { |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 297d7ce4117b..0efa7fd01150 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -124,6 +124,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { | |||
124 | [NL80211_ATTR_BSS_HT_OPMODE] = { .type = NLA_U16 }, | 124 | [NL80211_ATTR_BSS_HT_OPMODE] = { .type = NLA_U16 }, |
125 | 125 | ||
126 | [NL80211_ATTR_MESH_CONFIG] = { .type = NLA_NESTED }, | 126 | [NL80211_ATTR_MESH_CONFIG] = { .type = NLA_NESTED }, |
127 | [NL80211_ATTR_SUPPORT_MESH_AUTH] = { .type = NLA_FLAG }, | ||
127 | 128 | ||
128 | [NL80211_ATTR_HT_CAPABILITY] = { .type = NLA_BINARY, | 129 | [NL80211_ATTR_HT_CAPABILITY] = { .type = NLA_BINARY, |
129 | .len = NL80211_HT_CAPABILITY_LEN }, | 130 | .len = NL80211_HT_CAPABILITY_LEN }, |
@@ -594,6 +595,8 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
594 | 595 | ||
595 | if (dev->wiphy.flags & WIPHY_FLAG_IBSS_RSN) | 596 | if (dev->wiphy.flags & WIPHY_FLAG_IBSS_RSN) |
596 | NLA_PUT_FLAG(msg, NL80211_ATTR_SUPPORT_IBSS_RSN); | 597 | NLA_PUT_FLAG(msg, NL80211_ATTR_SUPPORT_IBSS_RSN); |
598 | if (dev->wiphy.flags & WIPHY_FLAG_MESH_AUTH) | ||
599 | NLA_PUT_FLAG(msg, NL80211_ATTR_SUPPORT_MESH_AUTH); | ||
597 | 600 | ||
598 | NLA_PUT(msg, NL80211_ATTR_CIPHER_SUITES, | 601 | NLA_PUT(msg, NL80211_ATTR_CIPHER_SUITES, |
599 | sizeof(u32) * dev->wiphy.n_cipher_suites, | 602 | sizeof(u32) * dev->wiphy.n_cipher_suites, |
@@ -1922,6 +1925,7 @@ static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = { | |||
1922 | [NL80211_STA_FLAG_SHORT_PREAMBLE] = { .type = NLA_FLAG }, | 1925 | [NL80211_STA_FLAG_SHORT_PREAMBLE] = { .type = NLA_FLAG }, |
1923 | [NL80211_STA_FLAG_WME] = { .type = NLA_FLAG }, | 1926 | [NL80211_STA_FLAG_WME] = { .type = NLA_FLAG }, |
1924 | [NL80211_STA_FLAG_MFP] = { .type = NLA_FLAG }, | 1927 | [NL80211_STA_FLAG_MFP] = { .type = NLA_FLAG }, |
1928 | [NL80211_STA_FLAG_AUTHENTICATED] = { .type = NLA_FLAG }, | ||
1925 | }; | 1929 | }; |
1926 | 1930 | ||
1927 | static int parse_station_flags(struct genl_info *info, | 1931 | static int parse_station_flags(struct genl_info *info, |
@@ -2016,6 +2020,9 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq, | |||
2016 | sinfoattr = nla_nest_start(msg, NL80211_ATTR_STA_INFO); | 2020 | sinfoattr = nla_nest_start(msg, NL80211_ATTR_STA_INFO); |
2017 | if (!sinfoattr) | 2021 | if (!sinfoattr) |
2018 | goto nla_put_failure; | 2022 | goto nla_put_failure; |
2023 | if (sinfo->filled & STATION_INFO_CONNECTED_TIME) | ||
2024 | NLA_PUT_U32(msg, NL80211_STA_INFO_CONNECTED_TIME, | ||
2025 | sinfo->connected_time); | ||
2019 | if (sinfo->filled & STATION_INFO_INACTIVE_TIME) | 2026 | if (sinfo->filled & STATION_INFO_INACTIVE_TIME) |
2020 | NLA_PUT_U32(msg, NL80211_STA_INFO_INACTIVE_TIME, | 2027 | NLA_PUT_U32(msg, NL80211_STA_INFO_INACTIVE_TIME, |
2021 | sinfo->inactive_time); | 2028 | sinfo->inactive_time); |
@@ -2281,7 +2288,9 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) | |||
2281 | err = -EINVAL; | 2288 | err = -EINVAL; |
2282 | if (params.supported_rates) | 2289 | if (params.supported_rates) |
2283 | err = -EINVAL; | 2290 | err = -EINVAL; |
2284 | if (params.sta_flags_mask) | 2291 | if (params.sta_flags_mask & |
2292 | ~(BIT(NL80211_STA_FLAG_AUTHENTICATED) | | ||
2293 | BIT(NL80211_STA_FLAG_AUTHORIZED))) | ||
2285 | err = -EINVAL; | 2294 | err = -EINVAL; |
2286 | break; | 2295 | break; |
2287 | default: | 2296 | default: |
@@ -2343,11 +2352,16 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
2343 | params.ht_capa = | 2352 | params.ht_capa = |
2344 | nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); | 2353 | nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); |
2345 | 2354 | ||
2355 | if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) | ||
2356 | params.plink_action = | ||
2357 | nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]); | ||
2358 | |||
2346 | if (parse_station_flags(info, ¶ms)) | 2359 | if (parse_station_flags(info, ¶ms)) |
2347 | return -EINVAL; | 2360 | return -EINVAL; |
2348 | 2361 | ||
2349 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && | 2362 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && |
2350 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && | 2363 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && |
2364 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT && | ||
2351 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) | 2365 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) |
2352 | return -EINVAL; | 2366 | return -EINVAL; |
2353 | 2367 | ||
@@ -2823,7 +2837,8 @@ static const struct nla_policy | |||
2823 | nl80211_mesh_setup_params_policy[NL80211_MESH_SETUP_ATTR_MAX+1] = { | 2837 | nl80211_mesh_setup_params_policy[NL80211_MESH_SETUP_ATTR_MAX+1] = { |
2824 | [NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL] = { .type = NLA_U8 }, | 2838 | [NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL] = { .type = NLA_U8 }, |
2825 | [NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC] = { .type = NLA_U8 }, | 2839 | [NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC] = { .type = NLA_U8 }, |
2826 | [NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE] = { .type = NLA_BINARY, | 2840 | [NL80211_MESH_SETUP_USERSPACE_AUTH] = { .type = NLA_FLAG }, |
2841 | [NL80211_MESH_SETUP_IE] = { .type = NLA_BINARY, | ||
2827 | .len = IEEE80211_MAX_DATA_LEN }, | 2842 | .len = IEEE80211_MAX_DATA_LEN }, |
2828 | }; | 2843 | }; |
2829 | 2844 | ||
@@ -2925,14 +2940,16 @@ static int nl80211_parse_mesh_setup(struct genl_info *info, | |||
2925 | IEEE80211_PATH_METRIC_VENDOR : | 2940 | IEEE80211_PATH_METRIC_VENDOR : |
2926 | IEEE80211_PATH_METRIC_AIRTIME; | 2941 | IEEE80211_PATH_METRIC_AIRTIME; |
2927 | 2942 | ||
2928 | if (tb[NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE]) { | 2943 | |
2944 | if (tb[NL80211_MESH_SETUP_IE]) { | ||
2929 | struct nlattr *ieattr = | 2945 | struct nlattr *ieattr = |
2930 | tb[NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE]; | 2946 | tb[NL80211_MESH_SETUP_IE]; |
2931 | if (!is_valid_ie_attr(ieattr)) | 2947 | if (!is_valid_ie_attr(ieattr)) |
2932 | return -EINVAL; | 2948 | return -EINVAL; |
2933 | setup->vendor_ie = nla_data(ieattr); | 2949 | setup->ie = nla_data(ieattr); |
2934 | setup->vendor_ie_len = nla_len(ieattr); | 2950 | setup->ie_len = nla_len(ieattr); |
2935 | } | 2951 | } |
2952 | setup->is_secure = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AUTH]); | ||
2936 | 2953 | ||
2937 | return 0; | 2954 | return 0; |
2938 | } | 2955 | } |
@@ -5804,6 +5821,44 @@ void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev, | |||
5804 | nlmsg_free(msg); | 5821 | nlmsg_free(msg); |
5805 | } | 5822 | } |
5806 | 5823 | ||
5824 | void nl80211_send_new_peer_candidate(struct cfg80211_registered_device *rdev, | ||
5825 | struct net_device *netdev, | ||
5826 | const u8 *macaddr, const u8* ie, u8 ie_len, | ||
5827 | gfp_t gfp) | ||
5828 | { | ||
5829 | struct sk_buff *msg; | ||
5830 | void *hdr; | ||
5831 | |||
5832 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); | ||
5833 | if (!msg) | ||
5834 | return; | ||
5835 | |||
5836 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NEW_PEER_CANDIDATE); | ||
5837 | if (!hdr) { | ||
5838 | nlmsg_free(msg); | ||
5839 | return; | ||
5840 | } | ||
5841 | |||
5842 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); | ||
5843 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); | ||
5844 | NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, macaddr); | ||
5845 | if (ie_len && ie) | ||
5846 | NLA_PUT(msg, NL80211_ATTR_IE, ie_len , ie); | ||
5847 | |||
5848 | if (genlmsg_end(msg, hdr) < 0) { | ||
5849 | nlmsg_free(msg); | ||
5850 | return; | ||
5851 | } | ||
5852 | |||
5853 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, | ||
5854 | nl80211_mlme_mcgrp.id, gfp); | ||
5855 | return; | ||
5856 | |||
5857 | nla_put_failure: | ||
5858 | genlmsg_cancel(msg, hdr); | ||
5859 | nlmsg_free(msg); | ||
5860 | } | ||
5861 | |||
5807 | void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev, | 5862 | void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev, |
5808 | struct net_device *netdev, const u8 *addr, | 5863 | struct net_device *netdev, const u8 *addr, |
5809 | enum nl80211_key_type key_type, int key_id, | 5864 | enum nl80211_key_type key_type, int key_id, |
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index dcac5cd6f017..f2af6955a665 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h | |||
@@ -50,6 +50,10 @@ void nl80211_send_disconnected(struct cfg80211_registered_device *rdev, | |||
50 | struct net_device *netdev, u16 reason, | 50 | struct net_device *netdev, u16 reason, |
51 | const u8 *ie, size_t ie_len, bool from_ap); | 51 | const u8 *ie, size_t ie_len, bool from_ap); |
52 | 52 | ||
53 | void nl80211_send_new_peer_candidate(struct cfg80211_registered_device *rdev, | ||
54 | struct net_device *netdev, | ||
55 | const u8 *macaddr, const u8* ie, u8 ie_len, | ||
56 | gfp_t gfp); | ||
53 | void | 57 | void |
54 | nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev, | 58 | nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev, |
55 | struct net_device *netdev, const u8 *addr, | 59 | struct net_device *netdev, const u8 *addr, |