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.c86
1 files changed, 83 insertions, 3 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index e83e7fee3bc0..2aa6a2189842 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -23,6 +23,12 @@
23#include "nl80211.h" 23#include "nl80211.h"
24#include "reg.h" 24#include "reg.h"
25 25
26static bool nl80211_valid_auth_type(enum nl80211_auth_type auth_type);
27static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev,
28 struct genl_info *info,
29 struct cfg80211_crypto_settings *settings,
30 int cipher_limit);
31
26static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb, 32static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
27 struct genl_info *info); 33 struct genl_info *info);
28static void nl80211_post_doit(struct genl_ops *ops, struct sk_buff *skb, 34static void nl80211_post_doit(struct genl_ops *ops, struct sk_buff *skb,
@@ -178,6 +184,11 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
178 [NL80211_ATTR_SCHED_SCAN_INTERVAL] = { .type = NLA_U32 }, 184 [NL80211_ATTR_SCHED_SCAN_INTERVAL] = { .type = NLA_U32 },
179 [NL80211_ATTR_REKEY_DATA] = { .type = NLA_NESTED }, 185 [NL80211_ATTR_REKEY_DATA] = { .type = NLA_NESTED },
180 [NL80211_ATTR_SCAN_SUPP_RATES] = { .type = NLA_NESTED }, 186 [NL80211_ATTR_SCAN_SUPP_RATES] = { .type = NLA_NESTED },
187 [NL80211_ATTR_HIDDEN_SSID] = { .type = NLA_U32 },
188 [NL80211_ATTR_IE_PROBE_RESP] = { .type = NLA_BINARY,
189 .len = IEEE80211_MAX_DATA_LEN },
190 [NL80211_ATTR_IE_ASSOC_RESP] = { .type = NLA_BINARY,
191 .len = IEEE80211_MAX_DATA_LEN },
181}; 192};
182 193
183/* policy for the key attributes */ 194/* policy for the key attributes */
@@ -871,8 +882,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
871 NLA_PUT_U32(msg, NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION, 882 NLA_PUT_U32(msg, NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION,
872 dev->wiphy.max_remain_on_channel_duration); 883 dev->wiphy.max_remain_on_channel_duration);
873 884
874 /* for now at least assume all drivers have it */ 885 if (dev->ops->mgmt_tx_cancel_wait)
875 if (dev->ops->mgmt_tx)
876 NLA_PUT_FLAG(msg, NL80211_ATTR_OFFCHANNEL_TX_OK); 886 NLA_PUT_FLAG(msg, NL80211_ATTR_OFFCHANNEL_TX_OK);
877 887
878 if (mgmt_stypes) { 888 if (mgmt_stypes) {
@@ -1985,7 +1995,10 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
1985 struct beacon_parameters params; 1995 struct beacon_parameters params;
1986 int haveinfo = 0, err; 1996 int haveinfo = 0, err;
1987 1997
1988 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_BEACON_TAIL])) 1998 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_BEACON_TAIL]) ||
1999 !is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]) ||
2000 !is_valid_ie_attr(info->attrs[NL80211_ATTR_IE_PROBE_RESP]) ||
2001 !is_valid_ie_attr(info->attrs[NL80211_ATTR_IE_ASSOC_RESP]))
1989 return -EINVAL; 2002 return -EINVAL;
1990 2003
1991 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && 2004 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
@@ -2011,6 +2024,49 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
2011 if (err) 2024 if (err)
2012 return err; 2025 return err;
2013 2026
2027 /*
2028 * In theory, some of these attributes could be required for
2029 * NEW_BEACON, but since they were not used when the command was
2030 * originally added, keep them optional for old user space
2031 * programs to work with drivers that do not need the additional
2032 * information.
2033 */
2034 if (info->attrs[NL80211_ATTR_SSID]) {
2035 params.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
2036 params.ssid_len =
2037 nla_len(info->attrs[NL80211_ATTR_SSID]);
2038 if (params.ssid_len == 0 ||
2039 params.ssid_len > IEEE80211_MAX_SSID_LEN)
2040 return -EINVAL;
2041 }
2042
2043 if (info->attrs[NL80211_ATTR_HIDDEN_SSID]) {
2044 params.hidden_ssid = nla_get_u32(
2045 info->attrs[NL80211_ATTR_HIDDEN_SSID]);
2046 if (params.hidden_ssid !=
2047 NL80211_HIDDEN_SSID_NOT_IN_USE &&
2048 params.hidden_ssid !=
2049 NL80211_HIDDEN_SSID_ZERO_LEN &&
2050 params.hidden_ssid !=
2051 NL80211_HIDDEN_SSID_ZERO_CONTENTS)
2052 return -EINVAL;
2053 }
2054
2055 params.privacy = !!info->attrs[NL80211_ATTR_PRIVACY];
2056
2057 if (info->attrs[NL80211_ATTR_AUTH_TYPE]) {
2058 params.auth_type = nla_get_u32(
2059 info->attrs[NL80211_ATTR_AUTH_TYPE]);
2060 if (!nl80211_valid_auth_type(params.auth_type))
2061 return -EINVAL;
2062 } else
2063 params.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
2064
2065 err = nl80211_crypto_settings(rdev, info, &params.crypto,
2066 NL80211_MAX_NR_CIPHER_SUITES);
2067 if (err)
2068 return err;
2069
2014 call = rdev->ops->add_beacon; 2070 call = rdev->ops->add_beacon;
2015 break; 2071 break;
2016 case NL80211_CMD_SET_BEACON: 2072 case NL80211_CMD_SET_BEACON:
@@ -2041,6 +2097,25 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
2041 if (!haveinfo) 2097 if (!haveinfo)
2042 return -EINVAL; 2098 return -EINVAL;
2043 2099
2100 if (info->attrs[NL80211_ATTR_IE]) {
2101 params.beacon_ies = nla_data(info->attrs[NL80211_ATTR_IE]);
2102 params.beacon_ies_len = nla_len(info->attrs[NL80211_ATTR_IE]);
2103 }
2104
2105 if (info->attrs[NL80211_ATTR_IE_PROBE_RESP]) {
2106 params.proberesp_ies =
2107 nla_data(info->attrs[NL80211_ATTR_IE_PROBE_RESP]);
2108 params.proberesp_ies_len =
2109 nla_len(info->attrs[NL80211_ATTR_IE_PROBE_RESP]);
2110 }
2111
2112 if (info->attrs[NL80211_ATTR_IE_ASSOC_RESP]) {
2113 params.assocresp_ies =
2114 nla_data(info->attrs[NL80211_ATTR_IE_ASSOC_RESP]);
2115 params.assocresp_ies_len =
2116 nla_len(info->attrs[NL80211_ATTR_IE_ASSOC_RESP]);
2117 }
2118
2044 err = call(&rdev->wiphy, dev, &params); 2119 err = call(&rdev->wiphy, dev, &params);
2045 if (!err && params.interval) 2120 if (!err && params.interval)
2046 wdev->beacon_interval = params.interval; 2121 wdev->beacon_interval = params.interval;
@@ -2237,6 +2312,10 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
2237 } 2312 }
2238 nla_nest_end(msg, sinfoattr); 2313 nla_nest_end(msg, sinfoattr);
2239 2314
2315 if (sinfo->filled & STATION_INFO_ASSOC_REQ_IES)
2316 NLA_PUT(msg, NL80211_ATTR_IE, sinfo->assoc_req_ies_len,
2317 sinfo->assoc_req_ies);
2318
2240 return genlmsg_end(msg, hdr); 2319 return genlmsg_end(msg, hdr);
2241 2320
2242 nla_put_failure: 2321 nla_put_failure:
@@ -2264,6 +2343,7 @@ static int nl80211_dump_station(struct sk_buff *skb,
2264 } 2343 }
2265 2344
2266 while (1) { 2345 while (1) {
2346 memset(&sinfo, 0, sizeof(sinfo));
2267 err = dev->ops->dump_station(&dev->wiphy, netdev, sta_idx, 2347 err = dev->ops->dump_station(&dev->wiphy, netdev, sta_idx,
2268 mac_addr, &sinfo); 2348 mac_addr, &sinfo);
2269 if (err == -ENOENT) 2349 if (err == -ENOENT)