diff options
Diffstat (limited to 'net/wireless/nl80211.c')
-rw-r--r-- | net/wireless/nl80211.c | 86 |
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 | ||
26 | static bool nl80211_valid_auth_type(enum nl80211_auth_type auth_type); | ||
27 | static 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 | |||
26 | static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb, | 32 | static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb, |
27 | struct genl_info *info); | 33 | struct genl_info *info); |
28 | static void nl80211_post_doit(struct genl_ops *ops, struct sk_buff *skb, | 34 | static 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, ¶ms.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, ¶ms); | 2119 | err = call(&rdev->wiphy, dev, ¶ms); |
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) |