mac80211: support S1G association
[linux-block.git] / net / wireless / nl80211.c
CommitLineData
457c8996 1// SPDX-License-Identifier: GPL-2.0-only
55682965
JB
2/*
3 * This is the new netlink-based wireless configuration interface.
4 *
026331c4 5 * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
2740f0cf 6 * Copyright 2013-2014 Intel Mobile Communications GmbH
66cd794e 7 * Copyright 2015-2017 Intel Deutschland GmbH
7e8d6f12 8 * Copyright (C) 2018-2020 Intel Corporation
55682965
JB
9 */
10
11#include <linux/if.h>
12#include <linux/module.h>
13#include <linux/err.h>
5a0e3ad6 14#include <linux/slab.h>
55682965
JB
15#include <linux/list.h>
16#include <linux/if_ether.h>
17#include <linux/ieee80211.h>
18#include <linux/nl80211.h>
19#include <linux/rtnetlink.h>
20#include <linux/netlink.h>
259d8c1e 21#include <linux/nospec.h>
2a519311 22#include <linux/etherdevice.h>
e3ae39ed 23#include <linux/if_vlan.h>
463d0183 24#include <net/net_namespace.h>
55682965
JB
25#include <net/genetlink.h>
26#include <net/cfg80211.h>
463d0183 27#include <net/sock.h>
2a0e047e 28#include <net/inet_connection_sock.h>
55682965
JB
29#include "core.h"
30#include "nl80211.h"
b2e1b302 31#include "reg.h"
e35e4d28 32#include "rdev-ops.h"
55682965 33
5fb628e9
JM
34static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev,
35 struct genl_info *info,
36 struct cfg80211_crypto_settings *settings,
37 int cipher_limit);
38
55682965 39/* the netlink family */
489111e5 40static struct genl_family nl80211_fam;
55682965 41
2a94fe48
JB
42/* multicast groups */
43enum nl80211_multicast_groups {
44 NL80211_MCGRP_CONFIG,
45 NL80211_MCGRP_SCAN,
46 NL80211_MCGRP_REGULATORY,
47 NL80211_MCGRP_MLME,
567ffc35 48 NL80211_MCGRP_VENDOR,
50bcd31d 49 NL80211_MCGRP_NAN,
2a94fe48
JB
50 NL80211_MCGRP_TESTMODE /* keep last - ifdef! */
51};
52
53static const struct genl_multicast_group nl80211_mcgrps[] = {
71b836ec
JB
54 [NL80211_MCGRP_CONFIG] = { .name = NL80211_MULTICAST_GROUP_CONFIG },
55 [NL80211_MCGRP_SCAN] = { .name = NL80211_MULTICAST_GROUP_SCAN },
56 [NL80211_MCGRP_REGULATORY] = { .name = NL80211_MULTICAST_GROUP_REG },
57 [NL80211_MCGRP_MLME] = { .name = NL80211_MULTICAST_GROUP_MLME },
58 [NL80211_MCGRP_VENDOR] = { .name = NL80211_MULTICAST_GROUP_VENDOR },
50bcd31d 59 [NL80211_MCGRP_NAN] = { .name = NL80211_MULTICAST_GROUP_NAN },
2a94fe48 60#ifdef CONFIG_NL80211_TESTMODE
71b836ec 61 [NL80211_MCGRP_TESTMODE] = { .name = NL80211_MULTICAST_GROUP_TESTMODE }
2a94fe48
JB
62#endif
63};
64
89a54e48
JB
65/* returns ERR_PTR values */
66static struct wireless_dev *
67__cfg80211_wdev_from_attrs(struct net *netns, struct nlattr **attrs)
55682965 68{
89a54e48
JB
69 struct cfg80211_registered_device *rdev;
70 struct wireless_dev *result = NULL;
71 bool have_ifidx = attrs[NL80211_ATTR_IFINDEX];
72 bool have_wdev_id = attrs[NL80211_ATTR_WDEV];
73 u64 wdev_id;
74 int wiphy_idx = -1;
75 int ifidx = -1;
55682965 76
5fe231e8 77 ASSERT_RTNL();
55682965 78
89a54e48
JB
79 if (!have_ifidx && !have_wdev_id)
80 return ERR_PTR(-EINVAL);
55682965 81
89a54e48
JB
82 if (have_ifidx)
83 ifidx = nla_get_u32(attrs[NL80211_ATTR_IFINDEX]);
84 if (have_wdev_id) {
85 wdev_id = nla_get_u64(attrs[NL80211_ATTR_WDEV]);
86 wiphy_idx = wdev_id >> 32;
55682965
JB
87 }
88
89a54e48
JB
89 list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
90 struct wireless_dev *wdev;
91
92 if (wiphy_net(&rdev->wiphy) != netns)
93 continue;
94
95 if (have_wdev_id && rdev->wiphy_idx != wiphy_idx)
96 continue;
97
53873f13 98 list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
89a54e48
JB
99 if (have_ifidx && wdev->netdev &&
100 wdev->netdev->ifindex == ifidx) {
101 result = wdev;
102 break;
103 }
104 if (have_wdev_id && wdev->identifier == (u32)wdev_id) {
105 result = wdev;
106 break;
107 }
108 }
89a54e48
JB
109
110 if (result)
111 break;
112 }
113
114 if (result)
115 return result;
116 return ERR_PTR(-ENODEV);
55682965
JB
117}
118
a9455408 119static struct cfg80211_registered_device *
878d9ec7 120__cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
a9455408 121{
7fee4778
JB
122 struct cfg80211_registered_device *rdev = NULL, *tmp;
123 struct net_device *netdev;
a9455408 124
5fe231e8 125 ASSERT_RTNL();
a9455408 126
878d9ec7 127 if (!attrs[NL80211_ATTR_WIPHY] &&
89a54e48
JB
128 !attrs[NL80211_ATTR_IFINDEX] &&
129 !attrs[NL80211_ATTR_WDEV])
7fee4778
JB
130 return ERR_PTR(-EINVAL);
131
878d9ec7 132 if (attrs[NL80211_ATTR_WIPHY])
7fee4778 133 rdev = cfg80211_rdev_by_wiphy_idx(
878d9ec7 134 nla_get_u32(attrs[NL80211_ATTR_WIPHY]));
a9455408 135
89a54e48
JB
136 if (attrs[NL80211_ATTR_WDEV]) {
137 u64 wdev_id = nla_get_u64(attrs[NL80211_ATTR_WDEV]);
138 struct wireless_dev *wdev;
139 bool found = false;
140
141 tmp = cfg80211_rdev_by_wiphy_idx(wdev_id >> 32);
142 if (tmp) {
143 /* make sure wdev exists */
53873f13 144 list_for_each_entry(wdev, &tmp->wiphy.wdev_list, list) {
89a54e48
JB
145 if (wdev->identifier != (u32)wdev_id)
146 continue;
147 found = true;
148 break;
149 }
89a54e48
JB
150
151 if (!found)
152 tmp = NULL;
153
154 if (rdev && tmp != rdev)
155 return ERR_PTR(-EINVAL);
156 rdev = tmp;
157 }
158 }
159
878d9ec7
JB
160 if (attrs[NL80211_ATTR_IFINDEX]) {
161 int ifindex = nla_get_u32(attrs[NL80211_ATTR_IFINDEX]);
7a087e74 162
7f2b8562 163 netdev = __dev_get_by_index(netns, ifindex);
7fee4778
JB
164 if (netdev) {
165 if (netdev->ieee80211_ptr)
f26cbf40
ZG
166 tmp = wiphy_to_rdev(
167 netdev->ieee80211_ptr->wiphy);
7fee4778
JB
168 else
169 tmp = NULL;
170
7fee4778
JB
171 /* not wireless device -- return error */
172 if (!tmp)
173 return ERR_PTR(-EINVAL);
174
175 /* mismatch -- return error */
176 if (rdev && tmp != rdev)
177 return ERR_PTR(-EINVAL);
178
179 rdev = tmp;
a9455408 180 }
a9455408 181 }
a9455408 182
4f7eff10
JB
183 if (!rdev)
184 return ERR_PTR(-ENODEV);
a9455408 185
4f7eff10
JB
186 if (netns != wiphy_net(&rdev->wiphy))
187 return ERR_PTR(-ENODEV);
188
189 return rdev;
a9455408
JB
190}
191
192/*
193 * This function returns a pointer to the driver
194 * that the genl_info item that is passed refers to.
a9455408
JB
195 *
196 * The result of this can be a PTR_ERR and hence must
197 * be checked with IS_ERR() for errors.
198 */
199static struct cfg80211_registered_device *
4f7eff10 200cfg80211_get_dev_from_info(struct net *netns, struct genl_info *info)
a9455408 201{
5fe231e8 202 return __cfg80211_rdev_from_attrs(netns, info->attrs);
a9455408
JB
203}
204
f88eb7c0
JB
205static int validate_beacon_head(const struct nlattr *attr,
206 struct netlink_ext_ack *extack)
207{
208 const u8 *data = nla_data(attr);
209 unsigned int len = nla_len(attr);
210 const struct element *elem;
211 const struct ieee80211_mgmt *mgmt = (void *)data;
1d47f119
TP
212 bool s1g_bcn = ieee80211_is_s1g_beacon(mgmt->frame_control);
213 unsigned int fixedlen, hdrlen;
214
215 if (s1g_bcn) {
216 fixedlen = offsetof(struct ieee80211_ext,
217 u.s1g_beacon.variable);
218 hdrlen = offsetof(struct ieee80211_ext, u.s1g_beacon);
219 } else {
220 fixedlen = offsetof(struct ieee80211_mgmt,
221 u.beacon.variable);
222 hdrlen = offsetof(struct ieee80211_mgmt, u.beacon);
223 }
f88eb7c0
JB
224
225 if (len < fixedlen)
226 goto err;
227
1d47f119 228 if (ieee80211_hdrlen(mgmt->frame_control) != hdrlen)
f88eb7c0
JB
229 goto err;
230
231 data += fixedlen;
232 len -= fixedlen;
233
234 for_each_element(elem, data, len) {
235 /* nothing */
236 }
237
238 if (for_each_element_completed(elem, data, len))
239 return 0;
240
241err:
242 NL_SET_ERR_MSG_ATTR(extack, attr, "malformed beacon head");
243 return -EINVAL;
244}
245
3d7af878
JB
246static int validate_ie_attr(const struct nlattr *attr,
247 struct netlink_ext_ack *extack)
248{
9f308616
JB
249 const u8 *data = nla_data(attr);
250 unsigned int len = nla_len(attr);
7388afe0 251 const struct element *elem;
3d7af878 252
9f308616
JB
253 for_each_element(elem, data, len) {
254 /* nothing */
3d7af878
JB
255 }
256
9f308616
JB
257 if (for_each_element_completed(elem, data, len))
258 return 0;
259
3d7af878
JB
260 NL_SET_ERR_MSG_ATTR(extack, attr, "malformed information elements");
261 return -EINVAL;
262}
263
55682965 264/* policy for the attributes */
d15da2a2
JB
265static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR];
266
81e54d08
PKC
267static const struct nla_policy
268nl80211_ftm_responder_policy[NL80211_FTM_RESP_ATTR_MAX + 1] = {
269 [NL80211_FTM_RESP_ATTR_ENABLED] = { .type = NLA_FLAG, },
270 [NL80211_FTM_RESP_ATTR_LCI] = { .type = NLA_BINARY,
271 .len = U8_MAX },
272 [NL80211_FTM_RESP_ATTR_CIVICLOC] = { .type = NLA_BINARY,
273 .len = U8_MAX },
274};
275
9bb7e0f2
JB
276static const struct nla_policy
277nl80211_pmsr_ftm_req_attr_policy[NL80211_PMSR_FTM_REQ_ATTR_MAX + 1] = {
278 [NL80211_PMSR_FTM_REQ_ATTR_ASAP] = { .type = NLA_FLAG },
279 [NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE] = { .type = NLA_U32 },
280 [NL80211_PMSR_FTM_REQ_ATTR_NUM_BURSTS_EXP] =
281 NLA_POLICY_MAX(NLA_U8, 15),
282 [NL80211_PMSR_FTM_REQ_ATTR_BURST_PERIOD] = { .type = NLA_U16 },
283 [NL80211_PMSR_FTM_REQ_ATTR_BURST_DURATION] =
284 NLA_POLICY_MAX(NLA_U8, 15),
285 [NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST] =
ea18709a 286 NLA_POLICY_MAX(NLA_U8, 31),
9bb7e0f2
JB
287 [NL80211_PMSR_FTM_REQ_ATTR_NUM_FTMR_RETRIES] = { .type = NLA_U8 },
288 [NL80211_PMSR_FTM_REQ_ATTR_REQUEST_LCI] = { .type = NLA_FLAG },
289 [NL80211_PMSR_FTM_REQ_ATTR_REQUEST_CIVICLOC] = { .type = NLA_FLAG },
efb5520d
AS
290 [NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED] = { .type = NLA_FLAG },
291 [NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED] = { .type = NLA_FLAG },
9bb7e0f2
JB
292};
293
294static const struct nla_policy
295nl80211_pmsr_req_data_policy[NL80211_PMSR_TYPE_MAX + 1] = {
296 [NL80211_PMSR_TYPE_FTM] =
23323289 297 NLA_POLICY_NESTED(nl80211_pmsr_ftm_req_attr_policy),
9bb7e0f2
JB
298};
299
300static const struct nla_policy
301nl80211_pmsr_req_attr_policy[NL80211_PMSR_REQ_ATTR_MAX + 1] = {
302 [NL80211_PMSR_REQ_ATTR_DATA] =
23323289 303 NLA_POLICY_NESTED(nl80211_pmsr_req_data_policy),
9bb7e0f2
JB
304 [NL80211_PMSR_REQ_ATTR_GET_AP_TSF] = { .type = NLA_FLAG },
305};
306
307static const struct nla_policy
308nl80211_psmr_peer_attr_policy[NL80211_PMSR_PEER_ATTR_MAX + 1] = {
309 [NL80211_PMSR_PEER_ATTR_ADDR] = NLA_POLICY_ETH_ADDR,
d15da2a2 310 [NL80211_PMSR_PEER_ATTR_CHAN] = NLA_POLICY_NESTED(nl80211_policy),
9bb7e0f2 311 [NL80211_PMSR_PEER_ATTR_REQ] =
23323289 312 NLA_POLICY_NESTED(nl80211_pmsr_req_attr_policy),
9bb7e0f2
JB
313 [NL80211_PMSR_PEER_ATTR_RESP] = { .type = NLA_REJECT },
314};
315
316static const struct nla_policy
317nl80211_pmsr_attr_policy[NL80211_PMSR_ATTR_MAX + 1] = {
318 [NL80211_PMSR_ATTR_MAX_PEERS] = { .type = NLA_REJECT },
319 [NL80211_PMSR_ATTR_REPORT_AP_TSF] = { .type = NLA_REJECT },
320 [NL80211_PMSR_ATTR_RANDOMIZE_MAC_ADDR] = { .type = NLA_REJECT },
321 [NL80211_PMSR_ATTR_TYPE_CAPA] = { .type = NLA_REJECT },
322 [NL80211_PMSR_ATTR_PEERS] =
23323289 323 NLA_POLICY_NESTED_ARRAY(nl80211_psmr_peer_attr_policy),
9bb7e0f2
JB
324};
325
796e90f4
JC
326static const struct nla_policy
327he_obss_pd_policy[NL80211_HE_OBSS_PD_ATTR_MAX + 1] = {
328 [NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET] =
329 NLA_POLICY_RANGE(NLA_U8, 1, 20),
330 [NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET] =
331 NLA_POLICY_RANGE(NLA_U8, 1, 20),
332};
333
5c5e52d1
JC
334static const struct nla_policy
335he_bss_color_policy[NL80211_HE_BSS_COLOR_ATTR_MAX + 1] = {
336 [NL80211_HE_BSS_COLOR_ATTR_COLOR] = NLA_POLICY_RANGE(NLA_U8, 1, 63),
337 [NL80211_HE_BSS_COLOR_ATTR_DISABLED] = { .type = NLA_FLAG },
338 [NL80211_HE_BSS_COLOR_ATTR_PARTIAL] = { .type = NLA_FLAG },
339};
340
9a5f6488
TC
341static const struct nla_policy nl80211_txattr_policy[NL80211_TXRATE_MAX + 1] = {
342 [NL80211_TXRATE_LEGACY] = { .type = NLA_BINARY,
343 .len = NL80211_MAX_SUPP_RATES },
344 [NL80211_TXRATE_HT] = { .type = NLA_BINARY,
345 .len = NL80211_MAX_SUPP_HT_RATES },
346 [NL80211_TXRATE_VHT] = NLA_POLICY_EXACT_LEN_WARN(sizeof(struct nl80211_txrate_vht)),
347 [NL80211_TXRATE_GI] = { .type = NLA_U8 },
eb89a6a6
MH
348 [NL80211_TXRATE_HE] = NLA_POLICY_EXACT_LEN(sizeof(struct nl80211_txrate_he)),
349 [NL80211_TXRATE_HE_GI] = NLA_POLICY_RANGE(NLA_U8,
350 NL80211_RATE_INFO_HE_GI_0_8,
351 NL80211_RATE_INFO_HE_GI_3_2),
352 [NL80211_TXRATE_HE_LTF] = NLA_POLICY_RANGE(NLA_U8,
353 NL80211_RATE_INFO_HE_1XLTF,
354 NL80211_RATE_INFO_HE_4XLTF),
9a5f6488
TC
355};
356
77f576de
T
357static const struct nla_policy
358nl80211_tid_config_attr_policy[NL80211_TID_CONFIG_ATTR_MAX + 1] = {
3710a8a6
JB
359 [NL80211_TID_CONFIG_ATTR_VIF_SUPP] = { .type = NLA_U64 },
360 [NL80211_TID_CONFIG_ATTR_PEER_SUPP] = { .type = NLA_U64 },
77f576de 361 [NL80211_TID_CONFIG_ATTR_OVERRIDE] = { .type = NLA_FLAG },
3710a8a6 362 [NL80211_TID_CONFIG_ATTR_TIDS] = NLA_POLICY_RANGE(NLA_U16, 1, 0xff),
77f576de
T
363 [NL80211_TID_CONFIG_ATTR_NOACK] =
364 NLA_POLICY_MAX(NLA_U8, NL80211_TID_CONFIG_DISABLE),
6a21d16c
T
365 [NL80211_TID_CONFIG_ATTR_RETRY_SHORT] = NLA_POLICY_MIN(NLA_U8, 1),
366 [NL80211_TID_CONFIG_ATTR_RETRY_LONG] = NLA_POLICY_MIN(NLA_U8, 1),
ade274b2
T
367 [NL80211_TID_CONFIG_ATTR_AMPDU_CTRL] =
368 NLA_POLICY_MAX(NLA_U8, NL80211_TID_CONFIG_DISABLE),
04f7d142
T
369 [NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL] =
370 NLA_POLICY_MAX(NLA_U8, NL80211_TID_CONFIG_DISABLE),
33462e68
SM
371 [NL80211_TID_CONFIG_ATTR_AMSDU_CTRL] =
372 NLA_POLICY_MAX(NLA_U8, NL80211_TID_CONFIG_DISABLE),
9a5f6488
TC
373 [NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE] =
374 NLA_POLICY_MAX(NLA_U8, NL80211_TX_RATE_FIXED),
375 [NL80211_TID_CONFIG_ATTR_TX_RATE] =
376 NLA_POLICY_NESTED(nl80211_txattr_policy),
77f576de
T
377};
378
291c49de
AD
379static const struct nla_policy
380nl80211_fils_discovery_policy[NL80211_FILS_DISCOVERY_ATTR_MAX + 1] = {
381 [NL80211_FILS_DISCOVERY_ATTR_INT_MIN] = NLA_POLICY_MAX(NLA_U32, 10000),
382 [NL80211_FILS_DISCOVERY_ATTR_INT_MAX] = NLA_POLICY_MAX(NLA_U32, 10000),
383 NLA_POLICY_RANGE(NLA_BINARY,
384 NL80211_FILS_DISCOVERY_TMPL_MIN_LEN,
385 IEEE80211_MAX_DATA_LEN),
386};
387
7443dcd1
AD
388static const struct nla_policy
389nl80211_unsol_bcast_probe_resp_policy[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_MAX + 1] = {
390 [NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INT] = NLA_POLICY_MAX(NLA_U32, 20),
391 [NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL] = { .type = NLA_BINARY,
392 .len = IEEE80211_MAX_DATA_LEN }
393};
394
d15da2a2 395static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
6d4dd4ef 396 [0] = { .strict_start_type = NL80211_ATTR_HE_OBSS_PD },
55682965
JB
397 [NL80211_ATTR_WIPHY] = { .type = NLA_U32 },
398 [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING,
079e24ed 399 .len = 20-1 },
31888487 400 [NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED },
3d9d1d66 401
72bdcf34 402 [NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 },
094d05dc 403 [NL80211_ATTR_WIPHY_CHANNEL_TYPE] = { .type = NLA_U32 },
2a38075c
AAL
404 [NL80211_ATTR_WIPHY_EDMG_CHANNELS] = NLA_POLICY_RANGE(NLA_U8,
405 NL80211_EDMG_CHANNELS_MIN,
406 NL80211_EDMG_CHANNELS_MAX),
407 [NL80211_ATTR_WIPHY_EDMG_BW_CONFIG] = NLA_POLICY_RANGE(NLA_U8,
408 NL80211_EDMG_BW_CONFIG_MIN,
409 NL80211_EDMG_BW_CONFIG_MAX),
410
3d9d1d66
JB
411 [NL80211_ATTR_CHANNEL_WIDTH] = { .type = NLA_U32 },
412 [NL80211_ATTR_CENTER_FREQ1] = { .type = NLA_U32 },
942ba88b 413 [NL80211_ATTR_CENTER_FREQ1_OFFSET] = NLA_POLICY_RANGE(NLA_U32, 0, 999),
3d9d1d66
JB
414 [NL80211_ATTR_CENTER_FREQ2] = { .type = NLA_U32 },
415
ab0d76f6
JB
416 [NL80211_ATTR_WIPHY_RETRY_SHORT] = NLA_POLICY_MIN(NLA_U8, 1),
417 [NL80211_ATTR_WIPHY_RETRY_LONG] = NLA_POLICY_MIN(NLA_U8, 1),
b9a5f8ca
JM
418 [NL80211_ATTR_WIPHY_FRAG_THRESHOLD] = { .type = NLA_U32 },
419 [NL80211_ATTR_WIPHY_RTS_THRESHOLD] = { .type = NLA_U32 },
81077e82 420 [NL80211_ATTR_WIPHY_COVERAGE_CLASS] = { .type = NLA_U8 },
3057dbfd 421 [NL80211_ATTR_WIPHY_DYN_ACK] = { .type = NLA_FLAG },
55682965 422
ab0d76f6 423 [NL80211_ATTR_IFTYPE] = NLA_POLICY_MAX(NLA_U32, NL80211_IFTYPE_MAX),
55682965
JB
424 [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 },
425 [NL80211_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 },
41ade00f 426
c7721c05
JB
427 [NL80211_ATTR_MAC] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
428 [NL80211_ATTR_PREV_BSSID] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
41ade00f 429
b9454e83 430 [NL80211_ATTR_KEY] = { .type = NLA_NESTED, },
41ade00f
JB
431 [NL80211_ATTR_KEY_DATA] = { .type = NLA_BINARY,
432 .len = WLAN_MAX_KEY_LEN },
56be393f 433 [NL80211_ATTR_KEY_IDX] = NLA_POLICY_MAX(NLA_U8, 7),
41ade00f
JB
434 [NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 },
435 [NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG },
81962267 436 [NL80211_ATTR_KEY_SEQ] = { .type = NLA_BINARY, .len = 16 },
ab0d76f6
JB
437 [NL80211_ATTR_KEY_TYPE] =
438 NLA_POLICY_MAX(NLA_U32, NUM_NL80211_KEYTYPES),
ed1b6cc7
JB
439
440 [NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 },
441 [NL80211_ATTR_DTIM_PERIOD] = { .type = NLA_U32 },
f88eb7c0
JB
442 [NL80211_ATTR_BEACON_HEAD] =
443 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_beacon_head,
444 IEEE80211_MAX_DATA_LEN),
3d7af878
JB
445 [NL80211_ATTR_BEACON_TAIL] =
446 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr,
447 IEEE80211_MAX_DATA_LEN),
ab0d76f6
JB
448 [NL80211_ATTR_STA_AID] =
449 NLA_POLICY_RANGE(NLA_U16, 1, IEEE80211_MAX_AID),
5727ef1b
JB
450 [NL80211_ATTR_STA_FLAGS] = { .type = NLA_NESTED },
451 [NL80211_ATTR_STA_LISTEN_INTERVAL] = { .type = NLA_U16 },
452 [NL80211_ATTR_STA_SUPPORTED_RATES] = { .type = NLA_BINARY,
453 .len = NL80211_MAX_SUPP_RATES },
ab0d76f6
JB
454 [NL80211_ATTR_STA_PLINK_ACTION] =
455 NLA_POLICY_MAX(NLA_U8, NUM_NL80211_PLINK_ACTIONS - 1),
e96d1cd2
ARN
456 [NL80211_ATTR_STA_TX_POWER_SETTING] =
457 NLA_POLICY_RANGE(NLA_U8,
458 NL80211_TX_POWER_AUTOMATIC,
459 NL80211_TX_POWER_FIXED),
460 [NL80211_ATTR_STA_TX_POWER] = { .type = NLA_S16 },
5727ef1b 461 [NL80211_ATTR_STA_VLAN] = { .type = NLA_U32 },
0a9542ee 462 [NL80211_ATTR_MNTR_FLAGS] = { /* NLA_NESTED can't be empty */ },
2ec600d6 463 [NL80211_ATTR_MESH_ID] = { .type = NLA_BINARY,
a4f606ea 464 .len = IEEE80211_MAX_MESH_ID_LEN },
1fab1b89 465 [NL80211_ATTR_MPATH_NEXT_HOP] = NLA_POLICY_ETH_ADDR_COMPAT,
9f1ba906 466
b2e1b302
LR
467 [NL80211_ATTR_REG_ALPHA2] = { .type = NLA_STRING, .len = 2 },
468 [NL80211_ATTR_REG_RULES] = { .type = NLA_NESTED },
469
9f1ba906
JM
470 [NL80211_ATTR_BSS_CTS_PROT] = { .type = NLA_U8 },
471 [NL80211_ATTR_BSS_SHORT_PREAMBLE] = { .type = NLA_U8 },
472 [NL80211_ATTR_BSS_SHORT_SLOT_TIME] = { .type = NLA_U8 },
90c97a04
JM
473 [NL80211_ATTR_BSS_BASIC_RATES] = { .type = NLA_BINARY,
474 .len = NL80211_MAX_SUPP_RATES },
50b12f59 475 [NL80211_ATTR_BSS_HT_OPMODE] = { .type = NLA_U16 },
36aedc90 476
24bdd9f4 477 [NL80211_ATTR_MESH_CONFIG] = { .type = NLA_NESTED },
15d5dda6 478 [NL80211_ATTR_SUPPORT_MESH_AUTH] = { .type = NLA_FLAG },
93da9cc1 479
c7721c05 480 [NL80211_ATTR_HT_CAPABILITY] = NLA_POLICY_EXACT_LEN_WARN(NL80211_HT_CAPABILITY_LEN),
9aed3cc1
JM
481
482 [NL80211_ATTR_MGMT_SUBTYPE] = { .type = NLA_U8 },
3d7af878
JB
483 [NL80211_ATTR_IE] = NLA_POLICY_VALIDATE_FN(NLA_BINARY,
484 validate_ie_attr,
485 IEEE80211_MAX_DATA_LEN),
2a519311
JB
486 [NL80211_ATTR_SCAN_FREQUENCIES] = { .type = NLA_NESTED },
487 [NL80211_ATTR_SCAN_SSIDS] = { .type = NLA_NESTED },
636a5d36
JM
488
489 [NL80211_ATTR_SSID] = { .type = NLA_BINARY,
490 .len = IEEE80211_MAX_SSID_LEN },
491 [NL80211_ATTR_AUTH_TYPE] = { .type = NLA_U32 },
492 [NL80211_ATTR_REASON_CODE] = { .type = NLA_U16 },
04a773ad 493 [NL80211_ATTR_FREQ_FIXED] = { .type = NLA_FLAG },
1965c853 494 [NL80211_ATTR_TIMED_OUT] = { .type = NLA_FLAG },
ab0d76f6
JB
495 [NL80211_ATTR_USE_MFP] = NLA_POLICY_RANGE(NLA_U32,
496 NL80211_MFP_NO,
497 NL80211_MFP_OPTIONAL),
eccb8e8f
JB
498 [NL80211_ATTR_STA_FLAGS2] = {
499 .len = sizeof(struct nl80211_sta_flag_update),
500 },
3f77316c 501 [NL80211_ATTR_CONTROL_PORT] = { .type = NLA_FLAG },
c0692b8f
JB
502 [NL80211_ATTR_CONTROL_PORT_ETHERTYPE] = { .type = NLA_U16 },
503 [NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT] = { .type = NLA_FLAG },
64bf3d4b 504 [NL80211_ATTR_CONTROL_PORT_OVER_NL80211] = { .type = NLA_FLAG },
b23aa676 505 [NL80211_ATTR_PRIVACY] = { .type = NLA_FLAG },
ea750801 506 [NL80211_ATTR_STATUS_CODE] = { .type = NLA_U16 },
b23aa676
SO
507 [NL80211_ATTR_CIPHER_SUITE_GROUP] = { .type = NLA_U32 },
508 [NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 },
463d0183 509 [NL80211_ATTR_PID] = { .type = NLA_U32 },
8b787643 510 [NL80211_ATTR_4ADDR] = { .type = NLA_U8 },
c7721c05 511 [NL80211_ATTR_PMKID] = NLA_POLICY_EXACT_LEN_WARN(WLAN_PMKID_LEN),
9588bbd5
JM
512 [NL80211_ATTR_DURATION] = { .type = NLA_U32 },
513 [NL80211_ATTR_COOKIE] = { .type = NLA_U64 },
13ae75b1 514 [NL80211_ATTR_TX_RATES] = { .type = NLA_NESTED },
026331c4
JM
515 [NL80211_ATTR_FRAME] = { .type = NLA_BINARY,
516 .len = IEEE80211_MAX_DATA_LEN },
517 [NL80211_ATTR_FRAME_MATCH] = { .type = NLA_BINARY, },
ab0d76f6
JB
518 [NL80211_ATTR_PS_STATE] = NLA_POLICY_RANGE(NLA_U32,
519 NL80211_PS_DISABLED,
520 NL80211_PS_ENABLED),
d6dc1a38 521 [NL80211_ATTR_CQM] = { .type = NLA_NESTED, },
d5cdfacb 522 [NL80211_ATTR_LOCAL_STATE_CHANGE] = { .type = NLA_FLAG },
fd8aaaf3 523 [NL80211_ATTR_AP_ISOLATE] = { .type = NLA_U8 },
98d2ff8b
JO
524 [NL80211_ATTR_WIPHY_TX_POWER_SETTING] = { .type = NLA_U32 },
525 [NL80211_ATTR_WIPHY_TX_POWER_LEVEL] = { .type = NLA_U32 },
2e161f78 526 [NL80211_ATTR_FRAME_TYPE] = { .type = NLA_U16 },
afe0cbf8
BR
527 [NL80211_ATTR_WIPHY_ANTENNA_TX] = { .type = NLA_U32 },
528 [NL80211_ATTR_WIPHY_ANTENNA_RX] = { .type = NLA_U32 },
885a46d0 529 [NL80211_ATTR_MCAST_RATE] = { .type = NLA_U32 },
f7ca38df 530 [NL80211_ATTR_OFFCHANNEL_TX_OK] = { .type = NLA_FLAG },
dbd2fd65 531 [NL80211_ATTR_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED },
ff1b6e69 532 [NL80211_ATTR_WOWLAN_TRIGGERS] = { .type = NLA_NESTED },
ab0d76f6
JB
533 [NL80211_ATTR_STA_PLINK_STATE] =
534 NLA_POLICY_MAX(NLA_U8, NUM_NL80211_PLINK_STATES - 1),
056e9375
JK
535 [NL80211_ATTR_MEASUREMENT_DURATION] = { .type = NLA_U16 },
536 [NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY] = { .type = NLA_FLAG },
ab0d76f6
JB
537 [NL80211_ATTR_MESH_PEER_AID] =
538 NLA_POLICY_RANGE(NLA_U16, 1, IEEE80211_MAX_AID),
bbe6ad6d 539 [NL80211_ATTR_SCHED_SCAN_INTERVAL] = { .type = NLA_U32 },
e5497d76 540 [NL80211_ATTR_REKEY_DATA] = { .type = NLA_NESTED },
34850ab2 541 [NL80211_ATTR_SCAN_SUPP_RATES] = { .type = NLA_NESTED },
ab0d76f6
JB
542 [NL80211_ATTR_HIDDEN_SSID] =
543 NLA_POLICY_RANGE(NLA_U32,
544 NL80211_HIDDEN_SSID_NOT_IN_USE,
545 NL80211_HIDDEN_SSID_ZERO_CONTENTS),
3d7af878
JB
546 [NL80211_ATTR_IE_PROBE_RESP] =
547 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr,
548 IEEE80211_MAX_DATA_LEN),
549 [NL80211_ATTR_IE_ASSOC_RESP] =
550 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr,
551 IEEE80211_MAX_DATA_LEN),
f4b34b55 552 [NL80211_ATTR_ROAM_SUPPORT] = { .type = NLA_FLAG },
a1f1c21c 553 [NL80211_ATTR_SCHED_SCAN_MATCH] = { .type = NLA_NESTED },
e9f935e3 554 [NL80211_ATTR_TX_NO_CCK_RATE] = { .type = NLA_FLAG },
109086ce
AN
555 [NL80211_ATTR_TDLS_ACTION] = { .type = NLA_U8 },
556 [NL80211_ATTR_TDLS_DIALOG_TOKEN] = { .type = NLA_U8 },
557 [NL80211_ATTR_TDLS_OPERATION] = { .type = NLA_U8 },
558 [NL80211_ATTR_TDLS_SUPPORT] = { .type = NLA_FLAG },
559 [NL80211_ATTR_TDLS_EXTERNAL_SETUP] = { .type = NLA_FLAG },
31fa97c5 560 [NL80211_ATTR_TDLS_INITIATOR] = { .type = NLA_FLAG },
e247bd90 561 [NL80211_ATTR_DONT_WAIT_FOR_ACK] = { .type = NLA_FLAG },
00f740e1
AN
562 [NL80211_ATTR_PROBE_RESP] = { .type = NLA_BINARY,
563 .len = IEEE80211_MAX_DATA_LEN },
8b60b078 564 [NL80211_ATTR_DFS_REGION] = { .type = NLA_U8 },
7e7c8926
BG
565 [NL80211_ATTR_DISABLE_HT] = { .type = NLA_FLAG },
566 [NL80211_ATTR_HT_CAPABILITY_MASK] = {
567 .len = NL80211_HT_CAPABILITY_LEN
568 },
1d9d9213 569 [NL80211_ATTR_NOACK_MAP] = { .type = NLA_U16 },
1b658f11 570 [NL80211_ATTR_INACTIVITY_TIMEOUT] = { .type = NLA_U16 },
4486ea98 571 [NL80211_ATTR_BG_SCAN_PERIOD] = { .type = NLA_U16 },
89a54e48 572 [NL80211_ATTR_WDEV] = { .type = NLA_U64 },
57b5ce07 573 [NL80211_ATTR_USER_REG_HINT_TYPE] = { .type = NLA_U32 },
cb9abd48
JB
574
575 /* need to include at least Auth Transaction and Status Code */
576 [NL80211_ATTR_AUTH_DATA] = NLA_POLICY_MIN_LEN(4),
577
c7721c05 578 [NL80211_ATTR_VHT_CAPABILITY] = NLA_POLICY_EXACT_LEN_WARN(NL80211_VHT_CAPABILITY_LEN),
ed473771 579 [NL80211_ATTR_SCAN_FLAGS] = { .type = NLA_U32 },
ab0d76f6
JB
580 [NL80211_ATTR_P2P_CTWINDOW] = NLA_POLICY_MAX(NLA_U8, 127),
581 [NL80211_ATTR_P2P_OPPPS] = NLA_POLICY_MAX(NLA_U8, 1),
582 [NL80211_ATTR_LOCAL_MESH_POWER_MODE] =
583 NLA_POLICY_RANGE(NLA_U32,
584 NL80211_MESH_POWER_UNKNOWN + 1,
585 NL80211_MESH_POWER_MAX),
77765eaf
VT
586 [NL80211_ATTR_ACL_POLICY] = {. type = NLA_U32 },
587 [NL80211_ATTR_MAC_ADDRS] = { .type = NLA_NESTED },
9d62a986
JM
588 [NL80211_ATTR_STA_CAPABILITY] = { .type = NLA_U16 },
589 [NL80211_ATTR_STA_EXT_CAPABILITY] = { .type = NLA_BINARY, },
3713b4e3 590 [NL80211_ATTR_SPLIT_WIPHY_DUMP] = { .type = NLA_FLAG, },
ee2aca34
JB
591 [NL80211_ATTR_DISABLE_VHT] = { .type = NLA_FLAG },
592 [NL80211_ATTR_VHT_CAPABILITY_MASK] = {
593 .len = NL80211_VHT_CAPABILITY_LEN,
594 },
355199e0
JM
595 [NL80211_ATTR_MDID] = { .type = NLA_U16 },
596 [NL80211_ATTR_IE_RIC] = { .type = NLA_BINARY,
597 .len = IEEE80211_MAX_DATA_LEN },
0e1a1d85 598 [NL80211_ATTR_CRIT_PROT_ID] = { .type = NLA_U16 },
cb9abd48
JB
599 [NL80211_ATTR_MAX_CRIT_PROT_DURATION] =
600 NLA_POLICY_MAX(NLA_U16, NL80211_CRIT_PROTO_MAX_DURATION),
ab0d76f6
JB
601 [NL80211_ATTR_PEER_AID] =
602 NLA_POLICY_RANGE(NLA_U16, 1, IEEE80211_MAX_AID),
16ef1fe2
SW
603 [NL80211_ATTR_CH_SWITCH_COUNT] = { .type = NLA_U32 },
604 [NL80211_ATTR_CH_SWITCH_BLOCK_TX] = { .type = NLA_FLAG },
605 [NL80211_ATTR_CSA_IES] = { .type = NLA_NESTED },
00c207ed
JC
606 [NL80211_ATTR_CNTDWN_OFFS_BEACON] = { .type = NLA_BINARY },
607 [NL80211_ATTR_CNTDWN_OFFS_PRESP] = { .type = NLA_BINARY },
cb9abd48 608 [NL80211_ATTR_STA_SUPPORTED_CHANNELS] = NLA_POLICY_MIN_LEN(2),
c8b82802
JB
609 /*
610 * The value of the Length field of the Supported Operating
611 * Classes element is between 2 and 253.
612 */
613 [NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES] =
614 NLA_POLICY_RANGE(NLA_BINARY, 2, 253),
5336fa88 615 [NL80211_ATTR_HANDLE_DFS] = { .type = NLA_FLAG },
60f4a7b1 616 [NL80211_ATTR_OPMODE_NOTIF] = { .type = NLA_U8 },
ad7e718c
JB
617 [NL80211_ATTR_VENDOR_ID] = { .type = NLA_U32 },
618 [NL80211_ATTR_VENDOR_SUBCMD] = { .type = NLA_U32 },
619 [NL80211_ATTR_VENDOR_DATA] = { .type = NLA_BINARY },
c8b82802
JB
620 [NL80211_ATTR_QOS_MAP] = NLA_POLICY_RANGE(NLA_BINARY,
621 IEEE80211_QOS_MAP_LEN_MIN,
622 IEEE80211_QOS_MAP_LEN_MAX),
c7721c05 623 [NL80211_ATTR_MAC_HINT] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
1df4a510 624 [NL80211_ATTR_WIPHY_FREQ_HINT] = { .type = NLA_U32 },
df942e7b 625 [NL80211_ATTR_TDLS_PEER_CAPABILITY] = { .type = NLA_U32 },
18e5ca65 626 [NL80211_ATTR_SOCKET_OWNER] = { .type = NLA_FLAG },
34d22ce2 627 [NL80211_ATTR_CSA_C_OFFSETS_TX] = { .type = NLA_BINARY },
bab5ab7d 628 [NL80211_ATTR_USE_RRM] = { .type = NLA_FLAG },
ab0d76f6
JB
629 [NL80211_ATTR_TSID] = NLA_POLICY_MAX(NLA_U8, IEEE80211_NUM_TIDS - 1),
630 [NL80211_ATTR_USER_PRIO] =
631 NLA_POLICY_MAX(NLA_U8, IEEE80211_NUM_UPS - 1),
960d01ac 632 [NL80211_ATTR_ADMITTED_TIME] = { .type = NLA_U16 },
18998c38 633 [NL80211_ATTR_SMPS_MODE] = { .type = NLA_U8 },
5cde05c6 634 [NL80211_ATTR_OPER_CLASS] = { .type = NLA_U8 },
c7721c05 635 [NL80211_ATTR_MAC_MASK] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
1bdd716c 636 [NL80211_ATTR_WIPHY_SELF_MANAGED_REG] = { .type = NLA_FLAG },
4b681c82 637 [NL80211_ATTR_NETNS_FD] = { .type = NLA_U32 },
9c748934 638 [NL80211_ATTR_SCHED_SCAN_DELAY] = { .type = NLA_U32 },
05050753 639 [NL80211_ATTR_REG_INDOOR] = { .type = NLA_FLAG },
34d50519 640 [NL80211_ATTR_PBSS] = { .type = NLA_FLAG },
38de03d2 641 [NL80211_ATTR_BSS_SELECT] = { .type = NLA_NESTED },
ab0d76f6
JB
642 [NL80211_ATTR_STA_SUPPORT_P2P_PS] =
643 NLA_POLICY_MAX(NLA_U8, NUM_NL80211_P2P_PS_STATUS - 1),
c6e6a0c8
AE
644 [NL80211_ATTR_MU_MIMO_GROUP_DATA] = {
645 .len = VHT_MUMIMO_GROUPS_DATA_LEN
646 },
c7721c05 647 [NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
ab0d76f6 648 [NL80211_ATTR_NAN_MASTER_PREF] = NLA_POLICY_MIN(NLA_U8, 1),
8585989d 649 [NL80211_ATTR_BANDS] = { .type = NLA_U32 },
a442b761 650 [NL80211_ATTR_NAN_FUNC] = { .type = NLA_NESTED },
348bd456
JM
651 [NL80211_ATTR_FILS_KEK] = { .type = NLA_BINARY,
652 .len = FILS_MAX_KEK_LEN },
c7721c05 653 [NL80211_ATTR_FILS_NONCES] = NLA_POLICY_EXACT_LEN_WARN(2 * FILS_NONCE_LEN),
ce0ce13a 654 [NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED] = { .type = NLA_FLAG, },
c7721c05 655 [NL80211_ATTR_BSSID] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
bf95ecdb 656 [NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI] = { .type = NLA_S8 },
657 [NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST] = {
658 .len = sizeof(struct nl80211_bss_select_rssi_adjust)
659 },
3093ebbe 660 [NL80211_ATTR_TIMEOUT_REASON] = { .type = NLA_U32 },
a3caf744
VK
661 [NL80211_ATTR_FILS_ERP_USERNAME] = { .type = NLA_BINARY,
662 .len = FILS_ERP_MAX_USERNAME_LEN },
663 [NL80211_ATTR_FILS_ERP_REALM] = { .type = NLA_BINARY,
664 .len = FILS_ERP_MAX_REALM_LEN },
665 [NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] = { .type = NLA_U16 },
666 [NL80211_ATTR_FILS_ERP_RRK] = { .type = NLA_BINARY,
667 .len = FILS_ERP_MAX_RRK_LEN },
c7721c05 668 [NL80211_ATTR_FILS_CACHE_ID] = NLA_POLICY_EXACT_LEN_WARN(2),
a3caf744 669 [NL80211_ATTR_PMK] = { .type = NLA_BINARY, .len = PMK_MAX_LEN },
cb9abd48 670 [NL80211_ATTR_PMKR0_NAME] = NLA_POLICY_EXACT_LEN(WLAN_PMK_NAME_LEN),
ca986ad9 671 [NL80211_ATTR_SCHED_SCAN_MULTI] = { .type = NLA_FLAG },
40cbfa90 672 [NL80211_ATTR_EXTERNAL_AUTH_SUPPORT] = { .type = NLA_FLAG },
52539ca8
THJ
673
674 [NL80211_ATTR_TXQ_LIMIT] = { .type = NLA_U32 },
675 [NL80211_ATTR_TXQ_MEMORY_LIMIT] = { .type = NLA_U32 },
676 [NL80211_ATTR_TXQ_QUANTUM] = { .type = NLA_U32 },
c8b82802
JB
677 [NL80211_ATTR_HE_CAPABILITY] =
678 NLA_POLICY_RANGE(NLA_BINARY,
679 NL80211_HE_MIN_CAPABILITY_LEN,
680 NL80211_HE_MAX_CAPABILITY_LEN),
0e012b4e
JB
681 [NL80211_ATTR_FTM_RESPONDER] =
682 NLA_POLICY_NESTED(nl80211_ftm_responder_policy),
9bb7e0f2
JB
683 [NL80211_ATTR_TIMEOUT] = NLA_POLICY_MIN(NLA_U32, 1),
684 [NL80211_ATTR_PEER_MEASUREMENTS] =
23323289 685 NLA_POLICY_NESTED(nl80211_pmsr_attr_policy),
36647055 686 [NL80211_ATTR_AIRTIME_WEIGHT] = NLA_POLICY_MIN(NLA_U16, 1),
26f7044e
CHH
687 [NL80211_ATTR_SAE_PASSWORD] = { .type = NLA_BINARY,
688 .len = SAE_PASSWORD_MAX_LEN },
a0de1ca3 689 [NL80211_ATTR_TWT_RESPONDER] = { .type = NLA_FLAG },
796e90f4 690 [NL80211_ATTR_HE_OBSS_PD] = NLA_POLICY_NESTED(he_obss_pd_policy),
14f34e36 691 [NL80211_ATTR_VLAN_ID] = NLA_POLICY_RANGE(NLA_U16, 1, VLAN_N_VID - 2),
5c5e52d1 692 [NL80211_ATTR_HE_BSS_COLOR] = NLA_POLICY_NESTED(he_bss_color_policy),
77f576de
T
693 [NL80211_ATTR_TID_CONFIG] =
694 NLA_POLICY_NESTED_ARRAY(nl80211_tid_config_attr_policy),
5631d96a 695 [NL80211_ATTR_CONTROL_PORT_NO_PREAUTH] = { .type = NLA_FLAG },
7fc82af8
VJ
696 [NL80211_ATTR_PMK_LIFETIME] = NLA_POLICY_MIN(NLA_U32, 1),
697 [NL80211_ATTR_PMK_REAUTH_THRESHOLD] = NLA_POLICY_RANGE(NLA_U8, 1, 100),
9dba48a6 698 [NL80211_ATTR_RECEIVE_MULTICAST] = { .type = NLA_FLAG },
942ba88b 699 [NL80211_ATTR_WIPHY_FREQ_OFFSET] = NLA_POLICY_RANGE(NLA_U32, 0, 999),
2032f3b2 700 [NL80211_ATTR_SCAN_FREQ_KHZ] = { .type = NLA_NESTED },
8140860c
JB
701 [NL80211_ATTR_HE_6GHZ_CAPABILITY] =
702 NLA_POLICY_EXACT_LEN(sizeof(struct ieee80211_he_6ghz_capa)),
291c49de
AD
703 [NL80211_ATTR_FILS_DISCOVERY] =
704 NLA_POLICY_NESTED(nl80211_fils_discovery_policy),
7443dcd1
AD
705 [NL80211_ATTR_UNSOL_BCAST_PROBE_RESP] =
706 NLA_POLICY_NESTED(nl80211_unsol_bcast_probe_resp_policy),
d2b7588a
TP
707 [NL80211_ATTR_S1G_CAPABILITY] =
708 NLA_POLICY_EXACT_LEN(IEEE80211_S1G_CAPABILITY_LEN),
709 [NL80211_ATTR_S1G_CAPABILITY_MASK] =
710 NLA_POLICY_EXACT_LEN(IEEE80211_S1G_CAPABILITY_LEN),
55682965
JB
711};
712
e31b8213 713/* policy for the key attributes */
b54452b0 714static const struct nla_policy nl80211_key_policy[NL80211_KEY_MAX + 1] = {
fffd0934 715 [NL80211_KEY_DATA] = { .type = NLA_BINARY, .len = WLAN_MAX_KEY_LEN },
b9454e83
JB
716 [NL80211_KEY_IDX] = { .type = NLA_U8 },
717 [NL80211_KEY_CIPHER] = { .type = NLA_U32 },
81962267 718 [NL80211_KEY_SEQ] = { .type = NLA_BINARY, .len = 16 },
b9454e83
JB
719 [NL80211_KEY_DEFAULT] = { .type = NLA_FLAG },
720 [NL80211_KEY_DEFAULT_MGMT] = { .type = NLA_FLAG },
ab0d76f6 721 [NL80211_KEY_TYPE] = NLA_POLICY_MAX(NLA_U32, NUM_NL80211_KEYTYPES - 1),
dbd2fd65 722 [NL80211_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED },
6cdd3979 723 [NL80211_KEY_MODE] = NLA_POLICY_RANGE(NLA_U8, 0, NL80211_KEY_SET_TX),
dbd2fd65
JB
724};
725
726/* policy for the key default flags */
727static const struct nla_policy
728nl80211_key_default_policy[NUM_NL80211_KEY_DEFAULT_TYPES] = {
729 [NL80211_KEY_DEFAULT_TYPE_UNICAST] = { .type = NLA_FLAG },
730 [NL80211_KEY_DEFAULT_TYPE_MULTICAST] = { .type = NLA_FLAG },
b9454e83
JB
731};
732
f83ace3b 733#ifdef CONFIG_PM
ff1b6e69
JB
734/* policy for WoWLAN attributes */
735static const struct nla_policy
736nl80211_wowlan_policy[NUM_NL80211_WOWLAN_TRIG] = {
737 [NL80211_WOWLAN_TRIG_ANY] = { .type = NLA_FLAG },
738 [NL80211_WOWLAN_TRIG_DISCONNECT] = { .type = NLA_FLAG },
739 [NL80211_WOWLAN_TRIG_MAGIC_PKT] = { .type = NLA_FLAG },
740 [NL80211_WOWLAN_TRIG_PKT_PATTERN] = { .type = NLA_NESTED },
77dbbb13
JB
741 [NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE] = { .type = NLA_FLAG },
742 [NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST] = { .type = NLA_FLAG },
743 [NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE] = { .type = NLA_FLAG },
744 [NL80211_WOWLAN_TRIG_RFKILL_RELEASE] = { .type = NLA_FLAG },
2a0e047e 745 [NL80211_WOWLAN_TRIG_TCP_CONNECTION] = { .type = NLA_NESTED },
8cd4d456 746 [NL80211_WOWLAN_TRIG_NET_DETECT] = { .type = NLA_NESTED },
2a0e047e
JB
747};
748
749static const struct nla_policy
750nl80211_wowlan_tcp_policy[NUM_NL80211_WOWLAN_TCP] = {
751 [NL80211_WOWLAN_TCP_SRC_IPV4] = { .type = NLA_U32 },
752 [NL80211_WOWLAN_TCP_DST_IPV4] = { .type = NLA_U32 },
c7721c05 753 [NL80211_WOWLAN_TCP_DST_MAC] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
2a0e047e
JB
754 [NL80211_WOWLAN_TCP_SRC_PORT] = { .type = NLA_U16 },
755 [NL80211_WOWLAN_TCP_DST_PORT] = { .type = NLA_U16 },
bc043585 756 [NL80211_WOWLAN_TCP_DATA_PAYLOAD] = NLA_POLICY_MIN_LEN(1),
2a0e047e
JB
757 [NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ] = {
758 .len = sizeof(struct nl80211_wowlan_tcp_data_seq)
759 },
760 [NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN] = {
761 .len = sizeof(struct nl80211_wowlan_tcp_data_token)
762 },
763 [NL80211_WOWLAN_TCP_DATA_INTERVAL] = { .type = NLA_U32 },
bc043585
JB
764 [NL80211_WOWLAN_TCP_WAKE_PAYLOAD] = NLA_POLICY_MIN_LEN(1),
765 [NL80211_WOWLAN_TCP_WAKE_MASK] = NLA_POLICY_MIN_LEN(1),
ff1b6e69 766};
f83ace3b 767#endif /* CONFIG_PM */
ff1b6e69 768
be29b99a
AK
769/* policy for coalesce rule attributes */
770static const struct nla_policy
771nl80211_coalesce_policy[NUM_NL80211_ATTR_COALESCE_RULE] = {
772 [NL80211_ATTR_COALESCE_RULE_DELAY] = { .type = NLA_U32 },
ab0d76f6
JB
773 [NL80211_ATTR_COALESCE_RULE_CONDITION] =
774 NLA_POLICY_RANGE(NLA_U32,
775 NL80211_COALESCE_CONDITION_MATCH,
776 NL80211_COALESCE_CONDITION_NO_MATCH),
be29b99a
AK
777 [NL80211_ATTR_COALESCE_RULE_PKT_PATTERN] = { .type = NLA_NESTED },
778};
779
e5497d76
JB
780/* policy for GTK rekey offload attributes */
781static const struct nla_policy
782nl80211_rekey_policy[NUM_NL80211_REKEY_DATA] = {
093a48d2
NE
783 [NL80211_REKEY_DATA_KEK] = {
784 .type = NLA_BINARY,
785 .len = NL80211_KEK_EXT_LEN
786 },
787 [NL80211_REKEY_DATA_KCK] = {
788 .type = NLA_BINARY,
789 .len = NL80211_KCK_EXT_LEN
790 },
cb9abd48 791 [NL80211_REKEY_DATA_REPLAY_CTR] = NLA_POLICY_EXACT_LEN(NL80211_REPLAY_CTR_LEN),
093a48d2 792 [NL80211_REKEY_DATA_AKM] = { .type = NLA_U32 },
e5497d76
JB
793};
794
1e1b11b6 795static const struct nla_policy
796nl80211_match_band_rssi_policy[NUM_NL80211_BANDS] = {
797 [NL80211_BAND_2GHZ] = { .type = NLA_S32 },
798 [NL80211_BAND_5GHZ] = { .type = NLA_S32 },
e548a1c3 799 [NL80211_BAND_6GHZ] = { .type = NLA_S32 },
1e1b11b6 800 [NL80211_BAND_60GHZ] = { .type = NLA_S32 },
801};
802
a1f1c21c
LC
803static const struct nla_policy
804nl80211_match_policy[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1] = {
4a4ab0d7 805 [NL80211_SCHED_SCAN_MATCH_ATTR_SSID] = { .type = NLA_BINARY,
a1f1c21c 806 .len = IEEE80211_MAX_SSID_LEN },
c7721c05 807 [NL80211_SCHED_SCAN_MATCH_ATTR_BSSID] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
88e920b4 808 [NL80211_SCHED_SCAN_MATCH_ATTR_RSSI] = { .type = NLA_U32 },
1e1b11b6 809 [NL80211_SCHED_SCAN_MATCH_PER_BAND_RSSI] =
810 NLA_POLICY_NESTED(nl80211_match_band_rssi_policy),
a1f1c21c
LC
811};
812
3b06d277
AS
813static const struct nla_policy
814nl80211_plan_policy[NL80211_SCHED_SCAN_PLAN_MAX + 1] = {
815 [NL80211_SCHED_SCAN_PLAN_INTERVAL] = { .type = NLA_U32 },
816 [NL80211_SCHED_SCAN_PLAN_ITERATIONS] = { .type = NLA_U32 },
817};
818
38de03d2
AS
819static const struct nla_policy
820nl80211_bss_select_policy[NL80211_BSS_SELECT_ATTR_MAX + 1] = {
821 [NL80211_BSS_SELECT_ATTR_RSSI] = { .type = NLA_FLAG },
822 [NL80211_BSS_SELECT_ATTR_BAND_PREF] = { .type = NLA_U32 },
823 [NL80211_BSS_SELECT_ATTR_RSSI_ADJUST] = {
824 .len = sizeof(struct nl80211_bss_select_rssi_adjust)
825 },
826};
827
a442b761
AB
828/* policy for NAN function attributes */
829static const struct nla_policy
830nl80211_nan_func_policy[NL80211_NAN_FUNC_ATTR_MAX + 1] = {
cb9abd48
JB
831 [NL80211_NAN_FUNC_TYPE] =
832 NLA_POLICY_MAX(NLA_U8, NL80211_NAN_FUNC_MAX_TYPE),
0a27844c 833 [NL80211_NAN_FUNC_SERVICE_ID] = {
a442b761
AB
834 .len = NL80211_NAN_FUNC_SERVICE_ID_LEN },
835 [NL80211_NAN_FUNC_PUBLISH_TYPE] = { .type = NLA_U8 },
836 [NL80211_NAN_FUNC_PUBLISH_BCAST] = { .type = NLA_FLAG },
837 [NL80211_NAN_FUNC_SUBSCRIBE_ACTIVE] = { .type = NLA_FLAG },
838 [NL80211_NAN_FUNC_FOLLOW_UP_ID] = { .type = NLA_U8 },
839 [NL80211_NAN_FUNC_FOLLOW_UP_REQ_ID] = { .type = NLA_U8 },
c7721c05 840 [NL80211_NAN_FUNC_FOLLOW_UP_DEST] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
a442b761
AB
841 [NL80211_NAN_FUNC_CLOSE_RANGE] = { .type = NLA_FLAG },
842 [NL80211_NAN_FUNC_TTL] = { .type = NLA_U32 },
843 [NL80211_NAN_FUNC_SERVICE_INFO] = { .type = NLA_BINARY,
844 .len = NL80211_NAN_FUNC_SERVICE_SPEC_INFO_MAX_LEN },
845 [NL80211_NAN_FUNC_SRF] = { .type = NLA_NESTED },
846 [NL80211_NAN_FUNC_RX_MATCH_FILTER] = { .type = NLA_NESTED },
847 [NL80211_NAN_FUNC_TX_MATCH_FILTER] = { .type = NLA_NESTED },
848 [NL80211_NAN_FUNC_INSTANCE_ID] = { .type = NLA_U8 },
849 [NL80211_NAN_FUNC_TERM_REASON] = { .type = NLA_U8 },
850};
851
852/* policy for Service Response Filter attributes */
853static const struct nla_policy
854nl80211_nan_srf_policy[NL80211_NAN_SRF_ATTR_MAX + 1] = {
855 [NL80211_NAN_SRF_INCLUDE] = { .type = NLA_FLAG },
856 [NL80211_NAN_SRF_BF] = { .type = NLA_BINARY,
857 .len = NL80211_NAN_FUNC_SRF_MAX_LEN },
858 [NL80211_NAN_SRF_BF_IDX] = { .type = NLA_U8 },
859 [NL80211_NAN_SRF_MAC_ADDRS] = { .type = NLA_NESTED },
860};
861
ad670233
PX
862/* policy for packet pattern attributes */
863static const struct nla_policy
864nl80211_packet_pattern_policy[MAX_NL80211_PKTPAT + 1] = {
865 [NL80211_PKTPAT_MASK] = { .type = NLA_BINARY, },
866 [NL80211_PKTPAT_PATTERN] = { .type = NLA_BINARY, },
867 [NL80211_PKTPAT_OFFSET] = { .type = NLA_U32 },
868};
869
9bb7e0f2
JB
870int nl80211_prepare_wdev_dump(struct netlink_callback *cb,
871 struct cfg80211_registered_device **rdev,
872 struct wireless_dev **wdev)
a043897a 873{
97990a06 874 int err;
a043897a 875
97990a06 876 if (!cb->args[0]) {
50508d94
JB
877 struct nlattr **attrbuf;
878
879 attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf),
880 GFP_KERNEL);
881 if (!attrbuf)
882 return -ENOMEM;
883
8cb08174
JB
884 err = nlmsg_parse_deprecated(cb->nlh,
885 GENL_HDRLEN + nl80211_fam.hdrsize,
50508d94 886 attrbuf, nl80211_fam.maxattr,
8cb08174 887 nl80211_policy, NULL);
50508d94
JB
888 if (err) {
889 kfree(attrbuf);
ea90e0dc 890 return err;
50508d94 891 }
67748893 892
50508d94
JB
893 *wdev = __cfg80211_wdev_from_attrs(sock_net(cb->skb->sk),
894 attrbuf);
895 kfree(attrbuf);
ea90e0dc
JB
896 if (IS_ERR(*wdev))
897 return PTR_ERR(*wdev);
f26cbf40 898 *rdev = wiphy_to_rdev((*wdev)->wiphy);
c319d50b
JB
899 /* 0 is the first index - add 1 to parse only once */
900 cb->args[0] = (*rdev)->wiphy_idx + 1;
97990a06
JB
901 cb->args[1] = (*wdev)->identifier;
902 } else {
c319d50b
JB
903 /* subtract the 1 again here */
904 struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0] - 1);
97990a06 905 struct wireless_dev *tmp;
67748893 906
ea90e0dc
JB
907 if (!wiphy)
908 return -ENODEV;
f26cbf40 909 *rdev = wiphy_to_rdev(wiphy);
97990a06 910 *wdev = NULL;
67748893 911
53873f13 912 list_for_each_entry(tmp, &(*rdev)->wiphy.wdev_list, list) {
97990a06
JB
913 if (tmp->identifier == cb->args[1]) {
914 *wdev = tmp;
915 break;
916 }
917 }
67748893 918
ea90e0dc
JB
919 if (!*wdev)
920 return -ENODEV;
67748893
JB
921 }
922
67748893 923 return 0;
67748893
JB
924}
925
55682965 926/* message building helper */
9bb7e0f2
JB
927void *nl80211hdr_put(struct sk_buff *skb, u32 portid, u32 seq,
928 int flags, u8 cmd)
55682965
JB
929{
930 /* since there is no private header just add the generic one */
15e47304 931 return genlmsg_put(skb, portid, seq, &nl80211_fam, flags, cmd);
55682965
JB
932}
933
50f32718
HD
934static int nl80211_msg_put_wmm_rules(struct sk_buff *msg,
935 const struct ieee80211_reg_rule *rule)
936{
937 int j;
938 struct nlattr *nl_wmm_rules =
ae0be8de 939 nla_nest_start_noflag(msg, NL80211_FREQUENCY_ATTR_WMM);
50f32718
HD
940
941 if (!nl_wmm_rules)
942 goto nla_put_failure;
943
944 for (j = 0; j < IEEE80211_NUM_ACS; j++) {
ae0be8de 945 struct nlattr *nl_wmm_rule = nla_nest_start_noflag(msg, j);
50f32718
HD
946
947 if (!nl_wmm_rule)
948 goto nla_put_failure;
949
950 if (nla_put_u16(msg, NL80211_WMMR_CW_MIN,
38cb87ee 951 rule->wmm_rule.client[j].cw_min) ||
50f32718 952 nla_put_u16(msg, NL80211_WMMR_CW_MAX,
38cb87ee 953 rule->wmm_rule.client[j].cw_max) ||
50f32718 954 nla_put_u8(msg, NL80211_WMMR_AIFSN,
38cb87ee 955 rule->wmm_rule.client[j].aifsn) ||
d3c89bbc
HD
956 nla_put_u16(msg, NL80211_WMMR_TXOP,
957 rule->wmm_rule.client[j].cot))
50f32718
HD
958 goto nla_put_failure;
959
960 nla_nest_end(msg, nl_wmm_rule);
961 }
962 nla_nest_end(msg, nl_wmm_rules);
963
964 return 0;
965
966nla_put_failure:
967 return -ENOBUFS;
968}
969
970static int nl80211_msg_put_channel(struct sk_buff *msg, struct wiphy *wiphy,
cdc89b97
JB
971 struct ieee80211_channel *chan,
972 bool large)
5dab3b8a 973{
ea077c1c
RL
974 /* Some channels must be completely excluded from the
975 * list to protect old user-space tools from breaking
976 */
977 if (!large && chan->flags &
978 (IEEE80211_CHAN_NO_10MHZ | IEEE80211_CHAN_NO_20MHZ))
979 return 0;
980
9360ffd1
DM
981 if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_FREQ,
982 chan->center_freq))
983 goto nla_put_failure;
5dab3b8a 984
942ba88b
TP
985 if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_OFFSET, chan->freq_offset))
986 goto nla_put_failure;
987
9360ffd1
DM
988 if ((chan->flags & IEEE80211_CHAN_DISABLED) &&
989 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_DISABLED))
990 goto nla_put_failure;
8fe02e16
LR
991 if (chan->flags & IEEE80211_CHAN_NO_IR) {
992 if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_IR))
993 goto nla_put_failure;
994 if (nla_put_flag(msg, __NL80211_FREQUENCY_ATTR_NO_IBSS))
995 goto nla_put_failure;
996 }
cdc89b97
JB
997 if (chan->flags & IEEE80211_CHAN_RADAR) {
998 if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR))
999 goto nla_put_failure;
1000 if (large) {
1001 u32 time;
1002
1003 time = elapsed_jiffies_msecs(chan->dfs_state_entered);
1004
1005 if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_STATE,
1006 chan->dfs_state))
1007 goto nla_put_failure;
1008 if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_TIME,
1009 time))
1010 goto nla_put_failure;
089027e5
JD
1011 if (nla_put_u32(msg,
1012 NL80211_FREQUENCY_ATTR_DFS_CAC_TIME,
1013 chan->dfs_cac_ms))
1014 goto nla_put_failure;
cdc89b97
JB
1015 }
1016 }
5dab3b8a 1017
fe1abafd
JB
1018 if (large) {
1019 if ((chan->flags & IEEE80211_CHAN_NO_HT40MINUS) &&
1020 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HT40_MINUS))
1021 goto nla_put_failure;
1022 if ((chan->flags & IEEE80211_CHAN_NO_HT40PLUS) &&
1023 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HT40_PLUS))
1024 goto nla_put_failure;
1025 if ((chan->flags & IEEE80211_CHAN_NO_80MHZ) &&
1026 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_80MHZ))
1027 goto nla_put_failure;
1028 if ((chan->flags & IEEE80211_CHAN_NO_160MHZ) &&
1029 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_160MHZ))
1030 goto nla_put_failure;
570dbde1
DS
1031 if ((chan->flags & IEEE80211_CHAN_INDOOR_ONLY) &&
1032 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_INDOOR_ONLY))
1033 goto nla_put_failure;
06f207fc
AN
1034 if ((chan->flags & IEEE80211_CHAN_IR_CONCURRENT) &&
1035 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_IR_CONCURRENT))
570dbde1 1036 goto nla_put_failure;
ea077c1c
RL
1037 if ((chan->flags & IEEE80211_CHAN_NO_20MHZ) &&
1038 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_20MHZ))
1039 goto nla_put_failure;
1040 if ((chan->flags & IEEE80211_CHAN_NO_10MHZ) &&
1041 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_10MHZ))
1042 goto nla_put_failure;
1e61d82c
HD
1043 if ((chan->flags & IEEE80211_CHAN_NO_HE) &&
1044 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HE))
1045 goto nla_put_failure;
d65a9770
TP
1046 if ((chan->flags & IEEE80211_CHAN_1MHZ) &&
1047 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_1MHZ))
1048 goto nla_put_failure;
1049 if ((chan->flags & IEEE80211_CHAN_2MHZ) &&
1050 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_2MHZ))
1051 goto nla_put_failure;
1052 if ((chan->flags & IEEE80211_CHAN_4MHZ) &&
1053 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_4MHZ))
1054 goto nla_put_failure;
1055 if ((chan->flags & IEEE80211_CHAN_8MHZ) &&
1056 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_8MHZ))
1057 goto nla_put_failure;
1058 if ((chan->flags & IEEE80211_CHAN_16MHZ) &&
1059 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_16MHZ))
1060 goto nla_put_failure;
fe1abafd
JB
1061 }
1062
9360ffd1
DM
1063 if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER,
1064 DBM_TO_MBM(chan->max_power)))
1065 goto nla_put_failure;
5dab3b8a 1066
50f32718
HD
1067 if (large) {
1068 const struct ieee80211_reg_rule *rule =
b88d26d9 1069 freq_reg_info(wiphy, MHZ_TO_KHZ(chan->center_freq));
50f32718 1070
38cb87ee 1071 if (!IS_ERR_OR_NULL(rule) && rule->has_wmm) {
50f32718
HD
1072 if (nl80211_msg_put_wmm_rules(msg, rule))
1073 goto nla_put_failure;
1074 }
1075 }
1076
5dab3b8a
LR
1077 return 0;
1078
1079 nla_put_failure:
1080 return -ENOBUFS;
1081}
1082
52539ca8
THJ
1083static bool nl80211_put_txq_stats(struct sk_buff *msg,
1084 struct cfg80211_txq_stats *txqstats,
1085 int attrtype)
1086{
1087 struct nlattr *txqattr;
1088
1089#define PUT_TXQVAL_U32(attr, memb) do { \
1090 if (txqstats->filled & BIT(NL80211_TXQ_STATS_ ## attr) && \
1091 nla_put_u32(msg, NL80211_TXQ_STATS_ ## attr, txqstats->memb)) \
1092 return false; \
1093 } while (0)
1094
ae0be8de 1095 txqattr = nla_nest_start_noflag(msg, attrtype);
52539ca8
THJ
1096 if (!txqattr)
1097 return false;
1098
1099 PUT_TXQVAL_U32(BACKLOG_BYTES, backlog_bytes);
1100 PUT_TXQVAL_U32(BACKLOG_PACKETS, backlog_packets);
1101 PUT_TXQVAL_U32(FLOWS, flows);
1102 PUT_TXQVAL_U32(DROPS, drops);
1103 PUT_TXQVAL_U32(ECN_MARKS, ecn_marks);
1104 PUT_TXQVAL_U32(OVERLIMIT, overlimit);
1105 PUT_TXQVAL_U32(OVERMEMORY, overmemory);
1106 PUT_TXQVAL_U32(COLLISIONS, collisions);
1107 PUT_TXQVAL_U32(TX_BYTES, tx_bytes);
1108 PUT_TXQVAL_U32(TX_PACKETS, tx_packets);
1109 PUT_TXQVAL_U32(MAX_FLOWS, max_flows);
1110 nla_nest_end(msg, txqattr);
1111
1112#undef PUT_TXQVAL_U32
1113 return true;
1114}
1115
55682965
JB
1116/* netlink command implementations */
1117
b9454e83
JB
1118struct key_parse {
1119 struct key_params p;
1120 int idx;
e31b8213 1121 int type;
56be393f 1122 bool def, defmgmt, defbeacon;
dbd2fd65 1123 bool def_uni, def_multi;
b9454e83
JB
1124};
1125
768075eb
JB
1126static int nl80211_parse_key_new(struct genl_info *info, struct nlattr *key,
1127 struct key_parse *k)
b9454e83
JB
1128{
1129 struct nlattr *tb[NL80211_KEY_MAX + 1];
8cb08174
JB
1130 int err = nla_parse_nested_deprecated(tb, NL80211_KEY_MAX, key,
1131 nl80211_key_policy,
1132 info->extack);
b9454e83
JB
1133 if (err)
1134 return err;
1135
1136 k->def = !!tb[NL80211_KEY_DEFAULT];
1137 k->defmgmt = !!tb[NL80211_KEY_DEFAULT_MGMT];
56be393f 1138 k->defbeacon = !!tb[NL80211_KEY_DEFAULT_BEACON];
b9454e83 1139
dbd2fd65
JB
1140 if (k->def) {
1141 k->def_uni = true;
1142 k->def_multi = true;
1143 }
56be393f 1144 if (k->defmgmt || k->defbeacon)
dbd2fd65
JB
1145 k->def_multi = true;
1146
b9454e83
JB
1147 if (tb[NL80211_KEY_IDX])
1148 k->idx = nla_get_u8(tb[NL80211_KEY_IDX]);
1149
1150 if (tb[NL80211_KEY_DATA]) {
1151 k->p.key = nla_data(tb[NL80211_KEY_DATA]);
1152 k->p.key_len = nla_len(tb[NL80211_KEY_DATA]);
1153 }
1154
1155 if (tb[NL80211_KEY_SEQ]) {
1156 k->p.seq = nla_data(tb[NL80211_KEY_SEQ]);
1157 k->p.seq_len = nla_len(tb[NL80211_KEY_SEQ]);
1158 }
1159
1160 if (tb[NL80211_KEY_CIPHER])
1161 k->p.cipher = nla_get_u32(tb[NL80211_KEY_CIPHER]);
1162
ab0d76f6 1163 if (tb[NL80211_KEY_TYPE])
e31b8213 1164 k->type = nla_get_u32(tb[NL80211_KEY_TYPE]);
e31b8213 1165
dbd2fd65
JB
1166 if (tb[NL80211_KEY_DEFAULT_TYPES]) {
1167 struct nlattr *kdt[NUM_NL80211_KEY_DEFAULT_TYPES];
7a087e74 1168
8cb08174
JB
1169 err = nla_parse_nested_deprecated(kdt,
1170 NUM_NL80211_KEY_DEFAULT_TYPES - 1,
1171 tb[NL80211_KEY_DEFAULT_TYPES],
1172 nl80211_key_default_policy,
1173 info->extack);
dbd2fd65
JB
1174 if (err)
1175 return err;
1176
1177 k->def_uni = kdt[NL80211_KEY_DEFAULT_TYPE_UNICAST];
1178 k->def_multi = kdt[NL80211_KEY_DEFAULT_TYPE_MULTICAST];
1179 }
1180
6cdd3979
AW
1181 if (tb[NL80211_KEY_MODE])
1182 k->p.mode = nla_get_u8(tb[NL80211_KEY_MODE]);
1183
b9454e83
JB
1184 return 0;
1185}
1186
1187static int nl80211_parse_key_old(struct genl_info *info, struct key_parse *k)
1188{
1189 if (info->attrs[NL80211_ATTR_KEY_DATA]) {
1190 k->p.key = nla_data(info->attrs[NL80211_ATTR_KEY_DATA]);
1191 k->p.key_len = nla_len(info->attrs[NL80211_ATTR_KEY_DATA]);
1192 }
1193
1194 if (info->attrs[NL80211_ATTR_KEY_SEQ]) {
1195 k->p.seq = nla_data(info->attrs[NL80211_ATTR_KEY_SEQ]);
1196 k->p.seq_len = nla_len(info->attrs[NL80211_ATTR_KEY_SEQ]);
1197 }
1198
1199 if (info->attrs[NL80211_ATTR_KEY_IDX])
1200 k->idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
1201
1202 if (info->attrs[NL80211_ATTR_KEY_CIPHER])
1203 k->p.cipher = nla_get_u32(info->attrs[NL80211_ATTR_KEY_CIPHER]);
1204
1205 k->def = !!info->attrs[NL80211_ATTR_KEY_DEFAULT];
1206 k->defmgmt = !!info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT];
1207
dbd2fd65
JB
1208 if (k->def) {
1209 k->def_uni = true;
1210 k->def_multi = true;
1211 }
1212 if (k->defmgmt)
1213 k->def_multi = true;
1214
ab0d76f6 1215 if (info->attrs[NL80211_ATTR_KEY_TYPE])
e31b8213 1216 k->type = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]);
e31b8213 1217
dbd2fd65
JB
1218 if (info->attrs[NL80211_ATTR_KEY_DEFAULT_TYPES]) {
1219 struct nlattr *kdt[NUM_NL80211_KEY_DEFAULT_TYPES];
8cb08174
JB
1220 int err = nla_parse_nested_deprecated(kdt,
1221 NUM_NL80211_KEY_DEFAULT_TYPES - 1,
1222 info->attrs[NL80211_ATTR_KEY_DEFAULT_TYPES],
1223 nl80211_key_default_policy,
1224 info->extack);
dbd2fd65
JB
1225 if (err)
1226 return err;
1227
1228 k->def_uni = kdt[NL80211_KEY_DEFAULT_TYPE_UNICAST];
1229 k->def_multi = kdt[NL80211_KEY_DEFAULT_TYPE_MULTICAST];
1230 }
1231
b9454e83
JB
1232 return 0;
1233}
1234
1235static int nl80211_parse_key(struct genl_info *info, struct key_parse *k)
1236{
1237 int err;
1238
1239 memset(k, 0, sizeof(*k));
1240 k->idx = -1;
e31b8213 1241 k->type = -1;
b9454e83
JB
1242
1243 if (info->attrs[NL80211_ATTR_KEY])
768075eb 1244 err = nl80211_parse_key_new(info, info->attrs[NL80211_ATTR_KEY], k);
b9454e83
JB
1245 else
1246 err = nl80211_parse_key_old(info, k);
1247
1248 if (err)
1249 return err;
1250
56be393f
JM
1251 if ((k->def ? 1 : 0) + (k->defmgmt ? 1 : 0) +
1252 (k->defbeacon ? 1 : 0) > 1) {
1253 GENL_SET_ERR_MSG(info,
1254 "key with multiple default flags is invalid");
b9454e83 1255 return -EINVAL;
768075eb 1256 }
b9454e83 1257
56be393f 1258 if (k->defmgmt || k->defbeacon) {
768075eb 1259 if (k->def_uni || !k->def_multi) {
56be393f
JM
1260 GENL_SET_ERR_MSG(info,
1261 "defmgmt/defbeacon key must be mcast");
dbd2fd65 1262 return -EINVAL;
768075eb 1263 }
dbd2fd65
JB
1264 }
1265
b9454e83
JB
1266 if (k->idx != -1) {
1267 if (k->defmgmt) {
768075eb
JB
1268 if (k->idx < 4 || k->idx > 5) {
1269 GENL_SET_ERR_MSG(info,
1270 "defmgmt key idx not 4 or 5");
b9454e83 1271 return -EINVAL;
768075eb 1272 }
56be393f
JM
1273 } else if (k->defbeacon) {
1274 if (k->idx < 6 || k->idx > 7) {
1275 GENL_SET_ERR_MSG(info,
1276 "defbeacon key idx not 6 or 7");
1277 return -EINVAL;
1278 }
b9454e83 1279 } else if (k->def) {
768075eb
JB
1280 if (k->idx < 0 || k->idx > 3) {
1281 GENL_SET_ERR_MSG(info, "def key idx not 0-3");
b9454e83 1282 return -EINVAL;
768075eb 1283 }
b9454e83 1284 } else {
56be393f
JM
1285 if (k->idx < 0 || k->idx > 7) {
1286 GENL_SET_ERR_MSG(info, "key idx not 0-7");
b9454e83 1287 return -EINVAL;
768075eb 1288 }
b9454e83
JB
1289 }
1290 }
1291
1292 return 0;
1293}
1294
fffd0934
JB
1295static struct cfg80211_cached_keys *
1296nl80211_parse_connkeys(struct cfg80211_registered_device *rdev,
768075eb 1297 struct genl_info *info, bool *no_ht)
fffd0934 1298{
768075eb 1299 struct nlattr *keys = info->attrs[NL80211_ATTR_KEYS];
fffd0934
JB
1300 struct key_parse parse;
1301 struct nlattr *key;
1302 struct cfg80211_cached_keys *result;
1303 int rem, err, def = 0;
f1c1f17a
JB
1304 bool have_key = false;
1305
1306 nla_for_each_nested(key, keys, rem) {
1307 have_key = true;
1308 break;
1309 }
1310
1311 if (!have_key)
1312 return NULL;
fffd0934
JB
1313
1314 result = kzalloc(sizeof(*result), GFP_KERNEL);
1315 if (!result)
1316 return ERR_PTR(-ENOMEM);
1317
1318 result->def = -1;
fffd0934
JB
1319
1320 nla_for_each_nested(key, keys, rem) {
1321 memset(&parse, 0, sizeof(parse));
1322 parse.idx = -1;
1323
768075eb 1324 err = nl80211_parse_key_new(info, key, &parse);
fffd0934
JB
1325 if (err)
1326 goto error;
1327 err = -EINVAL;
1328 if (!parse.p.key)
1329 goto error;
768075eb
JB
1330 if (parse.idx < 0 || parse.idx > 3) {
1331 GENL_SET_ERR_MSG(info, "key index out of range [0-3]");
fffd0934 1332 goto error;
768075eb 1333 }
fffd0934 1334 if (parse.def) {
768075eb
JB
1335 if (def) {
1336 GENL_SET_ERR_MSG(info,
1337 "only one key can be default");
fffd0934 1338 goto error;
768075eb 1339 }
fffd0934
JB
1340 def = 1;
1341 result->def = parse.idx;
dbd2fd65
JB
1342 if (!parse.def_uni || !parse.def_multi)
1343 goto error;
fffd0934
JB
1344 } else if (parse.defmgmt)
1345 goto error;
1346 err = cfg80211_validate_key_settings(rdev, &parse.p,
e31b8213 1347 parse.idx, false, NULL);
fffd0934
JB
1348 if (err)
1349 goto error;
386b1f27
JB
1350 if (parse.p.cipher != WLAN_CIPHER_SUITE_WEP40 &&
1351 parse.p.cipher != WLAN_CIPHER_SUITE_WEP104) {
768075eb 1352 GENL_SET_ERR_MSG(info, "connect key must be WEP");
386b1f27
JB
1353 err = -EINVAL;
1354 goto error;
1355 }
fffd0934
JB
1356 result->params[parse.idx].cipher = parse.p.cipher;
1357 result->params[parse.idx].key_len = parse.p.key_len;
1358 result->params[parse.idx].key = result->data[parse.idx];
1359 memcpy(result->data[parse.idx], parse.p.key, parse.p.key_len);
de7044ee 1360
386b1f27
JB
1361 /* must be WEP key if we got here */
1362 if (no_ht)
1363 *no_ht = true;
fffd0934
JB
1364 }
1365
f1c1f17a
JB
1366 if (result->def < 0) {
1367 err = -EINVAL;
768075eb 1368 GENL_SET_ERR_MSG(info, "need a default/TX key");
f1c1f17a
JB
1369 goto error;
1370 }
1371
fffd0934
JB
1372 return result;
1373 error:
1374 kfree(result);
1375 return ERR_PTR(err);
1376}
1377
1378static int nl80211_key_allowed(struct wireless_dev *wdev)
1379{
1380 ASSERT_WDEV_LOCK(wdev);
1381
fffd0934
JB
1382 switch (wdev->iftype) {
1383 case NL80211_IFTYPE_AP:
1384 case NL80211_IFTYPE_AP_VLAN:
074ac8df 1385 case NL80211_IFTYPE_P2P_GO:
ff973af7 1386 case NL80211_IFTYPE_MESH_POINT:
fffd0934
JB
1387 break;
1388 case NL80211_IFTYPE_ADHOC:
fffd0934 1389 case NL80211_IFTYPE_STATION:
074ac8df 1390 case NL80211_IFTYPE_P2P_CLIENT:
ceca7b71 1391 if (!wdev->current_bss)
fffd0934
JB
1392 return -ENOLINK;
1393 break;
de4fcbad 1394 case NL80211_IFTYPE_UNSPECIFIED:
6e0bd6c3 1395 case NL80211_IFTYPE_OCB:
de4fcbad 1396 case NL80211_IFTYPE_MONITOR:
cb3b7d87 1397 case NL80211_IFTYPE_NAN:
de4fcbad
JB
1398 case NL80211_IFTYPE_P2P_DEVICE:
1399 case NL80211_IFTYPE_WDS:
1400 case NUM_NL80211_IFTYPES:
fffd0934
JB
1401 return -EINVAL;
1402 }
1403
1404 return 0;
1405}
1406
664834de 1407static struct ieee80211_channel *nl80211_get_valid_chan(struct wiphy *wiphy,
942ba88b 1408 u32 freq)
664834de
JM
1409{
1410 struct ieee80211_channel *chan;
1411
942ba88b 1412 chan = ieee80211_get_channel_khz(wiphy, freq);
664834de
JM
1413 if (!chan || chan->flags & IEEE80211_CHAN_DISABLED)
1414 return NULL;
1415 return chan;
1416}
1417
7527a782
JB
1418static int nl80211_put_iftypes(struct sk_buff *msg, u32 attr, u16 ifmodes)
1419{
ae0be8de 1420 struct nlattr *nl_modes = nla_nest_start_noflag(msg, attr);
7527a782
JB
1421 int i;
1422
1423 if (!nl_modes)
1424 goto nla_put_failure;
1425
1426 i = 0;
1427 while (ifmodes) {
9360ffd1
DM
1428 if ((ifmodes & 1) && nla_put_flag(msg, i))
1429 goto nla_put_failure;
7527a782
JB
1430 ifmodes >>= 1;
1431 i++;
1432 }
1433
1434 nla_nest_end(msg, nl_modes);
1435 return 0;
1436
1437nla_put_failure:
1438 return -ENOBUFS;
1439}
1440
1441static int nl80211_put_iface_combinations(struct wiphy *wiphy,
cdc89b97
JB
1442 struct sk_buff *msg,
1443 bool large)
7527a782
JB
1444{
1445 struct nlattr *nl_combis;
1446 int i, j;
1447
ae0be8de
MK
1448 nl_combis = nla_nest_start_noflag(msg,
1449 NL80211_ATTR_INTERFACE_COMBINATIONS);
7527a782
JB
1450 if (!nl_combis)
1451 goto nla_put_failure;
1452
1453 for (i = 0; i < wiphy->n_iface_combinations; i++) {
1454 const struct ieee80211_iface_combination *c;
1455 struct nlattr *nl_combi, *nl_limits;
1456
1457 c = &wiphy->iface_combinations[i];
1458
ae0be8de 1459 nl_combi = nla_nest_start_noflag(msg, i + 1);
7527a782
JB
1460 if (!nl_combi)
1461 goto nla_put_failure;
1462
ae0be8de
MK
1463 nl_limits = nla_nest_start_noflag(msg,
1464 NL80211_IFACE_COMB_LIMITS);
7527a782
JB
1465 if (!nl_limits)
1466 goto nla_put_failure;
1467
1468 for (j = 0; j < c->n_limits; j++) {
1469 struct nlattr *nl_limit;
1470
ae0be8de 1471 nl_limit = nla_nest_start_noflag(msg, j + 1);
7527a782
JB
1472 if (!nl_limit)
1473 goto nla_put_failure;
9360ffd1
DM
1474 if (nla_put_u32(msg, NL80211_IFACE_LIMIT_MAX,
1475 c->limits[j].max))
1476 goto nla_put_failure;
7527a782
JB
1477 if (nl80211_put_iftypes(msg, NL80211_IFACE_LIMIT_TYPES,
1478 c->limits[j].types))
1479 goto nla_put_failure;
1480 nla_nest_end(msg, nl_limit);
1481 }
1482
1483 nla_nest_end(msg, nl_limits);
1484
9360ffd1
DM
1485 if (c->beacon_int_infra_match &&
1486 nla_put_flag(msg, NL80211_IFACE_COMB_STA_AP_BI_MATCH))
1487 goto nla_put_failure;
1488 if (nla_put_u32(msg, NL80211_IFACE_COMB_NUM_CHANNELS,
1489 c->num_different_channels) ||
1490 nla_put_u32(msg, NL80211_IFACE_COMB_MAXNUM,
1491 c->max_interfaces))
1492 goto nla_put_failure;
cdc89b97 1493 if (large &&
8c48b50a
FF
1494 (nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS,
1495 c->radar_detect_widths) ||
1496 nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_REGIONS,
1497 c->radar_detect_regions)))
cdc89b97 1498 goto nla_put_failure;
0c317a02
PK
1499 if (c->beacon_int_min_gcd &&
1500 nla_put_u32(msg, NL80211_IFACE_COMB_BI_MIN_GCD,
1501 c->beacon_int_min_gcd))
1502 goto nla_put_failure;
7527a782
JB
1503
1504 nla_nest_end(msg, nl_combi);
1505 }
1506
1507 nla_nest_end(msg, nl_combis);
1508
1509 return 0;
1510nla_put_failure:
1511 return -ENOBUFS;
1512}
1513
3713b4e3 1514#ifdef CONFIG_PM
b56cf720
JB
1515static int nl80211_send_wowlan_tcp_caps(struct cfg80211_registered_device *rdev,
1516 struct sk_buff *msg)
1517{
964dc9e2 1518 const struct wiphy_wowlan_tcp_support *tcp = rdev->wiphy.wowlan->tcp;
b56cf720
JB
1519 struct nlattr *nl_tcp;
1520
1521 if (!tcp)
1522 return 0;
1523
ae0be8de
MK
1524 nl_tcp = nla_nest_start_noflag(msg,
1525 NL80211_WOWLAN_TRIG_TCP_CONNECTION);
b56cf720
JB
1526 if (!nl_tcp)
1527 return -ENOBUFS;
1528
1529 if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD,
1530 tcp->data_payload_max))
1531 return -ENOBUFS;
1532
1533 if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD,
1534 tcp->data_payload_max))
1535 return -ENOBUFS;
1536
1537 if (tcp->seq && nla_put_flag(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ))
1538 return -ENOBUFS;
1539
1540 if (tcp->tok && nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN,
1541 sizeof(*tcp->tok), tcp->tok))
1542 return -ENOBUFS;
1543
1544 if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_INTERVAL,
1545 tcp->data_interval_max))
1546 return -ENOBUFS;
1547
1548 if (nla_put_u32(msg, NL80211_WOWLAN_TCP_WAKE_PAYLOAD,
1549 tcp->wake_payload_max))
1550 return -ENOBUFS;
1551
1552 nla_nest_end(msg, nl_tcp);
1553 return 0;
1554}
1555
3713b4e3 1556static int nl80211_send_wowlan(struct sk_buff *msg,
1b8ec87a 1557 struct cfg80211_registered_device *rdev,
b56cf720 1558 bool large)
55682965 1559{
3713b4e3 1560 struct nlattr *nl_wowlan;
55682965 1561
1b8ec87a 1562 if (!rdev->wiphy.wowlan)
3713b4e3 1563 return 0;
55682965 1564
ae0be8de
MK
1565 nl_wowlan = nla_nest_start_noflag(msg,
1566 NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED);
3713b4e3
JB
1567 if (!nl_wowlan)
1568 return -ENOBUFS;
9360ffd1 1569
1b8ec87a 1570 if (((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_ANY) &&
3713b4e3 1571 nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) ||
1b8ec87a 1572 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_DISCONNECT) &&
3713b4e3 1573 nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) ||
1b8ec87a 1574 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_MAGIC_PKT) &&
3713b4e3 1575 nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) ||
1b8ec87a 1576 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_SUPPORTS_GTK_REKEY) &&
3713b4e3 1577 nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED)) ||
1b8ec87a 1578 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE) &&
3713b4e3 1579 nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) ||
1b8ec87a 1580 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ) &&
3713b4e3 1581 nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) ||
1b8ec87a 1582 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_4WAY_HANDSHAKE) &&
3713b4e3 1583 nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) ||
1b8ec87a 1584 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_RFKILL_RELEASE) &&
3713b4e3
JB
1585 nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE)))
1586 return -ENOBUFS;
9360ffd1 1587
1b8ec87a 1588 if (rdev->wiphy.wowlan->n_patterns) {
50ac6607 1589 struct nl80211_pattern_support pat = {
1b8ec87a
ZG
1590 .max_patterns = rdev->wiphy.wowlan->n_patterns,
1591 .min_pattern_len = rdev->wiphy.wowlan->pattern_min_len,
1592 .max_pattern_len = rdev->wiphy.wowlan->pattern_max_len,
1593 .max_pkt_offset = rdev->wiphy.wowlan->max_pkt_offset,
3713b4e3 1594 };
9360ffd1 1595
3713b4e3
JB
1596 if (nla_put(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN,
1597 sizeof(pat), &pat))
1598 return -ENOBUFS;
1599 }
9360ffd1 1600
75453ccb
LC
1601 if ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_NET_DETECT) &&
1602 nla_put_u32(msg, NL80211_WOWLAN_TRIG_NET_DETECT,
1603 rdev->wiphy.wowlan->max_nd_match_sets))
1604 return -ENOBUFS;
1605
1b8ec87a 1606 if (large && nl80211_send_wowlan_tcp_caps(rdev, msg))
b56cf720
JB
1607 return -ENOBUFS;
1608
3713b4e3 1609 nla_nest_end(msg, nl_wowlan);
9360ffd1 1610
3713b4e3
JB
1611 return 0;
1612}
1613#endif
9360ffd1 1614
be29b99a 1615static int nl80211_send_coalesce(struct sk_buff *msg,
1b8ec87a 1616 struct cfg80211_registered_device *rdev)
be29b99a
AK
1617{
1618 struct nl80211_coalesce_rule_support rule;
1619
1b8ec87a 1620 if (!rdev->wiphy.coalesce)
be29b99a
AK
1621 return 0;
1622
1b8ec87a
ZG
1623 rule.max_rules = rdev->wiphy.coalesce->n_rules;
1624 rule.max_delay = rdev->wiphy.coalesce->max_delay;
1625 rule.pat.max_patterns = rdev->wiphy.coalesce->n_patterns;
1626 rule.pat.min_pattern_len = rdev->wiphy.coalesce->pattern_min_len;
1627 rule.pat.max_pattern_len = rdev->wiphy.coalesce->pattern_max_len;
1628 rule.pat.max_pkt_offset = rdev->wiphy.coalesce->max_pkt_offset;
be29b99a
AK
1629
1630 if (nla_put(msg, NL80211_ATTR_COALESCE_RULE, sizeof(rule), &rule))
1631 return -ENOBUFS;
1632
1633 return 0;
1634}
1635
c4cbaf79
LC
1636static int
1637nl80211_send_iftype_data(struct sk_buff *msg,
22395217 1638 const struct ieee80211_supported_band *sband,
c4cbaf79
LC
1639 const struct ieee80211_sband_iftype_data *iftdata)
1640{
1641 const struct ieee80211_sta_he_cap *he_cap = &iftdata->he_cap;
1642
1643 if (nl80211_put_iftypes(msg, NL80211_BAND_IFTYPE_ATTR_IFTYPES,
1644 iftdata->types_mask))
1645 return -ENOBUFS;
1646
1647 if (he_cap->has_he) {
1648 if (nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_CAP_MAC,
1649 sizeof(he_cap->he_cap_elem.mac_cap_info),
1650 he_cap->he_cap_elem.mac_cap_info) ||
1651 nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY,
1652 sizeof(he_cap->he_cap_elem.phy_cap_info),
1653 he_cap->he_cap_elem.phy_cap_info) ||
1654 nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET,
1655 sizeof(he_cap->he_mcs_nss_supp),
1656 &he_cap->he_mcs_nss_supp) ||
1657 nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE,
1658 sizeof(he_cap->ppe_thres), he_cap->ppe_thres))
1659 return -ENOBUFS;
1660 }
1661
22395217
JB
1662 if (sband->band == NL80211_BAND_6GHZ &&
1663 nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA,
1664 sizeof(iftdata->he_6ghz_capa),
1665 &iftdata->he_6ghz_capa))
1666 return -ENOBUFS;
1667
c4cbaf79
LC
1668 return 0;
1669}
1670
3713b4e3
JB
1671static int nl80211_send_band_rateinfo(struct sk_buff *msg,
1672 struct ieee80211_supported_band *sband)
1673{
1674 struct nlattr *nl_rates, *nl_rate;
1675 struct ieee80211_rate *rate;
1676 int i;
87bbbe22 1677
3713b4e3
JB
1678 /* add HT info */
1679 if (sband->ht_cap.ht_supported &&
1680 (nla_put(msg, NL80211_BAND_ATTR_HT_MCS_SET,
1681 sizeof(sband->ht_cap.mcs),
1682 &sband->ht_cap.mcs) ||
1683 nla_put_u16(msg, NL80211_BAND_ATTR_HT_CAPA,
1684 sband->ht_cap.cap) ||
1685 nla_put_u8(msg, NL80211_BAND_ATTR_HT_AMPDU_FACTOR,
1686 sband->ht_cap.ampdu_factor) ||
1687 nla_put_u8(msg, NL80211_BAND_ATTR_HT_AMPDU_DENSITY,
1688 sband->ht_cap.ampdu_density)))
1689 return -ENOBUFS;
afe0cbf8 1690
3713b4e3
JB
1691 /* add VHT info */
1692 if (sband->vht_cap.vht_supported &&
1693 (nla_put(msg, NL80211_BAND_ATTR_VHT_MCS_SET,
1694 sizeof(sband->vht_cap.vht_mcs),
1695 &sband->vht_cap.vht_mcs) ||
1696 nla_put_u32(msg, NL80211_BAND_ATTR_VHT_CAPA,
1697 sband->vht_cap.cap)))
1698 return -ENOBUFS;
f59ac048 1699
c4cbaf79
LC
1700 if (sband->n_iftype_data) {
1701 struct nlattr *nl_iftype_data =
ae0be8de
MK
1702 nla_nest_start_noflag(msg,
1703 NL80211_BAND_ATTR_IFTYPE_DATA);
c4cbaf79
LC
1704 int err;
1705
1706 if (!nl_iftype_data)
1707 return -ENOBUFS;
1708
1709 for (i = 0; i < sband->n_iftype_data; i++) {
1710 struct nlattr *iftdata;
1711
ae0be8de 1712 iftdata = nla_nest_start_noflag(msg, i + 1);
c4cbaf79
LC
1713 if (!iftdata)
1714 return -ENOBUFS;
1715
22395217 1716 err = nl80211_send_iftype_data(msg, sband,
c4cbaf79
LC
1717 &sband->iftype_data[i]);
1718 if (err)
1719 return err;
1720
1721 nla_nest_end(msg, iftdata);
1722 }
1723
1724 nla_nest_end(msg, nl_iftype_data);
1725 }
1726
2a38075c
AAL
1727 /* add EDMG info */
1728 if (sband->edmg_cap.channels &&
1729 (nla_put_u8(msg, NL80211_BAND_ATTR_EDMG_CHANNELS,
1730 sband->edmg_cap.channels) ||
1731 nla_put_u8(msg, NL80211_BAND_ATTR_EDMG_BW_CONFIG,
1732 sband->edmg_cap.bw_config)))
1733
1734 return -ENOBUFS;
1735
3713b4e3 1736 /* add bitrates */
ae0be8de 1737 nl_rates = nla_nest_start_noflag(msg, NL80211_BAND_ATTR_RATES);
3713b4e3
JB
1738 if (!nl_rates)
1739 return -ENOBUFS;
ee688b00 1740
3713b4e3 1741 for (i = 0; i < sband->n_bitrates; i++) {
ae0be8de 1742 nl_rate = nla_nest_start_noflag(msg, i);
3713b4e3
JB
1743 if (!nl_rate)
1744 return -ENOBUFS;
ee688b00 1745
3713b4e3
JB
1746 rate = &sband->bitrates[i];
1747 if (nla_put_u32(msg, NL80211_BITRATE_ATTR_RATE,
1748 rate->bitrate))
1749 return -ENOBUFS;
1750 if ((rate->flags & IEEE80211_RATE_SHORT_PREAMBLE) &&
1751 nla_put_flag(msg,
1752 NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE))
1753 return -ENOBUFS;
ee688b00 1754
3713b4e3
JB
1755 nla_nest_end(msg, nl_rate);
1756 }
d51626df 1757
3713b4e3 1758 nla_nest_end(msg, nl_rates);
bf0c111e 1759
3713b4e3
JB
1760 return 0;
1761}
ee688b00 1762
3713b4e3
JB
1763static int
1764nl80211_send_mgmt_stypes(struct sk_buff *msg,
1765 const struct ieee80211_txrx_stypes *mgmt_stypes)
1766{
1767 u16 stypes;
1768 struct nlattr *nl_ftypes, *nl_ifs;
1769 enum nl80211_iftype ift;
1770 int i;
ee688b00 1771
3713b4e3
JB
1772 if (!mgmt_stypes)
1773 return 0;
5dab3b8a 1774
ae0be8de 1775 nl_ifs = nla_nest_start_noflag(msg, NL80211_ATTR_TX_FRAME_TYPES);
3713b4e3
JB
1776 if (!nl_ifs)
1777 return -ENOBUFS;
e2f367f2 1778
3713b4e3 1779 for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) {
ae0be8de 1780 nl_ftypes = nla_nest_start_noflag(msg, ift);
3713b4e3
JB
1781 if (!nl_ftypes)
1782 return -ENOBUFS;
1783 i = 0;
1784 stypes = mgmt_stypes[ift].tx;
1785 while (stypes) {
1786 if ((stypes & 1) &&
1787 nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE,
1788 (i << 4) | IEEE80211_FTYPE_MGMT))
1789 return -ENOBUFS;
1790 stypes >>= 1;
1791 i++;
ee688b00 1792 }
3713b4e3
JB
1793 nla_nest_end(msg, nl_ftypes);
1794 }
ee688b00 1795
3713b4e3 1796 nla_nest_end(msg, nl_ifs);
ee688b00 1797
ae0be8de 1798 nl_ifs = nla_nest_start_noflag(msg, NL80211_ATTR_RX_FRAME_TYPES);
3713b4e3
JB
1799 if (!nl_ifs)
1800 return -ENOBUFS;
ee688b00 1801
3713b4e3 1802 for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) {
ae0be8de 1803 nl_ftypes = nla_nest_start_noflag(msg, ift);
3713b4e3
JB
1804 if (!nl_ftypes)
1805 return -ENOBUFS;
1806 i = 0;
1807 stypes = mgmt_stypes[ift].rx;
1808 while (stypes) {
1809 if ((stypes & 1) &&
1810 nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE,
1811 (i << 4) | IEEE80211_FTYPE_MGMT))
1812 return -ENOBUFS;
1813 stypes >>= 1;
1814 i++;
1815 }
1816 nla_nest_end(msg, nl_ftypes);
1817 }
1818 nla_nest_end(msg, nl_ifs);
ee688b00 1819
3713b4e3
JB
1820 return 0;
1821}
ee688b00 1822
1794899e
JB
1823#define CMD(op, n) \
1824 do { \
1825 if (rdev->ops->op) { \
1826 i++; \
1827 if (nla_put_u32(msg, i, NL80211_CMD_ ## n)) \
1828 goto nla_put_failure; \
1829 } \
1830 } while (0)
1831
1832static int nl80211_add_commands_unsplit(struct cfg80211_registered_device *rdev,
1833 struct sk_buff *msg)
1834{
1835 int i = 0;
1836
1837 /*
1838 * do *NOT* add anything into this function, new things need to be
1839 * advertised only to new versions of userspace that can deal with
1840 * the split (and they can't possibly care about new features...
1841 */
1842 CMD(add_virtual_intf, NEW_INTERFACE);
1843 CMD(change_virtual_intf, SET_INTERFACE);
1844 CMD(add_key, NEW_KEY);
1845 CMD(start_ap, START_AP);
1846 CMD(add_station, NEW_STATION);
1847 CMD(add_mpath, NEW_MPATH);
1848 CMD(update_mesh_config, SET_MESH_CONFIG);
1849 CMD(change_bss, SET_BSS);
1850 CMD(auth, AUTHENTICATE);
1851 CMD(assoc, ASSOCIATE);
1852 CMD(deauth, DEAUTHENTICATE);
1853 CMD(disassoc, DISASSOCIATE);
1854 CMD(join_ibss, JOIN_IBSS);
1855 CMD(join_mesh, JOIN_MESH);
1856 CMD(set_pmksa, SET_PMKSA);
1857 CMD(del_pmksa, DEL_PMKSA);
1858 CMD(flush_pmksa, FLUSH_PMKSA);
1859 if (rdev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL)
1860 CMD(remain_on_channel, REMAIN_ON_CHANNEL);
1861 CMD(set_bitrate_mask, SET_TX_BITRATE_MASK);
1862 CMD(mgmt_tx, FRAME);
1863 CMD(mgmt_tx_cancel_wait, FRAME_WAIT_CANCEL);
1864 if (rdev->wiphy.flags & WIPHY_FLAG_NETNS_OK) {
1865 i++;
1866 if (nla_put_u32(msg, i, NL80211_CMD_SET_WIPHY_NETNS))
1867 goto nla_put_failure;
1868 }
1869 if (rdev->ops->set_monitor_channel || rdev->ops->start_ap ||
1870 rdev->ops->join_mesh) {
1871 i++;
1872 if (nla_put_u32(msg, i, NL80211_CMD_SET_CHANNEL))
1873 goto nla_put_failure;
1874 }
1875 CMD(set_wds_peer, SET_WDS_PEER);
1876 if (rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) {
1877 CMD(tdls_mgmt, TDLS_MGMT);
1878 CMD(tdls_oper, TDLS_OPER);
1879 }
ca986ad9 1880 if (rdev->wiphy.max_sched_scan_reqs)
1794899e
JB
1881 CMD(sched_scan_start, START_SCHED_SCAN);
1882 CMD(probe_client, PROBE_CLIENT);
1883 CMD(set_noack_map, SET_NOACK_MAP);
1884 if (rdev->wiphy.flags & WIPHY_FLAG_REPORTS_OBSS) {
1885 i++;
1886 if (nla_put_u32(msg, i, NL80211_CMD_REGISTER_BEACONS))
1887 goto nla_put_failure;
1888 }
1889 CMD(start_p2p_device, START_P2P_DEVICE);
1890 CMD(set_mcast_rate, SET_MCAST_RATE);
1891#ifdef CONFIG_NL80211_TESTMODE
1892 CMD(testmode_cmd, TESTMODE);
1893#endif
1894
1895 if (rdev->ops->connect || rdev->ops->auth) {
1896 i++;
1897 if (nla_put_u32(msg, i, NL80211_CMD_CONNECT))
1898 goto nla_put_failure;
1899 }
1900
1901 if (rdev->ops->disconnect || rdev->ops->deauth) {
1902 i++;
1903 if (nla_put_u32(msg, i, NL80211_CMD_DISCONNECT))
1904 goto nla_put_failure;
1905 }
1906
1907 return i;
1908 nla_put_failure:
1909 return -ENOBUFS;
1910}
1911
9bb7e0f2
JB
1912static int
1913nl80211_send_pmsr_ftm_capa(const struct cfg80211_pmsr_capabilities *cap,
1914 struct sk_buff *msg)
1915{
1916 struct nlattr *ftm;
1917
1918 if (!cap->ftm.supported)
1919 return 0;
1920
ae0be8de 1921 ftm = nla_nest_start_noflag(msg, NL80211_PMSR_TYPE_FTM);
9bb7e0f2
JB
1922 if (!ftm)
1923 return -ENOBUFS;
1924
1925 if (cap->ftm.asap && nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_ASAP))
1926 return -ENOBUFS;
1927 if (cap->ftm.non_asap &&
1928 nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_NON_ASAP))
1929 return -ENOBUFS;
1930 if (cap->ftm.request_lci &&
1931 nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_REQ_LCI))
1932 return -ENOBUFS;
1933 if (cap->ftm.request_civicloc &&
1934 nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_REQ_CIVICLOC))
1935 return -ENOBUFS;
1936 if (nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_PREAMBLES,
1937 cap->ftm.preambles))
1938 return -ENOBUFS;
1939 if (nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_BANDWIDTHS,
1940 cap->ftm.bandwidths))
1941 return -ENOBUFS;
1942 if (cap->ftm.max_bursts_exponent >= 0 &&
1943 nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_MAX_BURSTS_EXPONENT,
1944 cap->ftm.max_bursts_exponent))
1945 return -ENOBUFS;
1946 if (cap->ftm.max_ftms_per_burst &&
1947 nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_MAX_FTMS_PER_BURST,
1948 cap->ftm.max_ftms_per_burst))
1949 return -ENOBUFS;
efb5520d
AS
1950 if (cap->ftm.trigger_based &&
1951 nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_TRIGGER_BASED))
1952 return -ENOBUFS;
1953 if (cap->ftm.non_trigger_based &&
1954 nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_NON_TRIGGER_BASED))
1955 return -ENOBUFS;
9bb7e0f2
JB
1956
1957 nla_nest_end(msg, ftm);
1958 return 0;
1959}
1960
1961static int nl80211_send_pmsr_capa(struct cfg80211_registered_device *rdev,
1962 struct sk_buff *msg)
1963{
1964 const struct cfg80211_pmsr_capabilities *cap = rdev->wiphy.pmsr_capa;
1965 struct nlattr *pmsr, *caps;
1966
1967 if (!cap)
1968 return 0;
1969
1970 /*
1971 * we don't need to clean up anything here since the caller
1972 * will genlmsg_cancel() if we fail
1973 */
1974
ae0be8de 1975 pmsr = nla_nest_start_noflag(msg, NL80211_ATTR_PEER_MEASUREMENTS);
9bb7e0f2
JB
1976 if (!pmsr)
1977 return -ENOBUFS;
1978
1979 if (nla_put_u32(msg, NL80211_PMSR_ATTR_MAX_PEERS, cap->max_peers))
1980 return -ENOBUFS;
1981
1982 if (cap->report_ap_tsf &&
1983 nla_put_flag(msg, NL80211_PMSR_ATTR_REPORT_AP_TSF))
1984 return -ENOBUFS;
1985
1986 if (cap->randomize_mac_addr &&
1987 nla_put_flag(msg, NL80211_PMSR_ATTR_RANDOMIZE_MAC_ADDR))
1988 return -ENOBUFS;
1989
ae0be8de 1990 caps = nla_nest_start_noflag(msg, NL80211_PMSR_ATTR_TYPE_CAPA);
9bb7e0f2
JB
1991 if (!caps)
1992 return -ENOBUFS;
1993
1994 if (nl80211_send_pmsr_ftm_capa(cap, msg))
1995 return -ENOBUFS;
1996
1997 nla_nest_end(msg, caps);
1998 nla_nest_end(msg, pmsr);
1999
2000 return 0;
2001}
2002
d6039a34
VJ
2003static int
2004nl80211_put_iftype_akm_suites(struct cfg80211_registered_device *rdev,
2005 struct sk_buff *msg)
2006{
2007 int i;
2008 struct nlattr *nested, *nested_akms;
2009 const struct wiphy_iftype_akm_suites *iftype_akms;
2010
2011 if (!rdev->wiphy.num_iftype_akm_suites ||
2012 !rdev->wiphy.iftype_akm_suites)
2013 return 0;
2014
2015 nested = nla_nest_start(msg, NL80211_ATTR_IFTYPE_AKM_SUITES);
2016 if (!nested)
2017 return -ENOBUFS;
2018
2019 for (i = 0; i < rdev->wiphy.num_iftype_akm_suites; i++) {
2020 nested_akms = nla_nest_start(msg, i + 1);
2021 if (!nested_akms)
2022 return -ENOBUFS;
2023
2024 iftype_akms = &rdev->wiphy.iftype_akm_suites[i];
2025
2026 if (nl80211_put_iftypes(msg, NL80211_IFTYPE_AKM_ATTR_IFTYPES,
2027 iftype_akms->iftypes_mask))
2028 return -ENOBUFS;
2029
2030 if (nla_put(msg, NL80211_IFTYPE_AKM_ATTR_SUITES,
2031 sizeof(u32) * iftype_akms->n_akm_suites,
2032 iftype_akms->akm_suites)) {
2033 return -ENOBUFS;
2034 }
2035 nla_nest_end(msg, nested_akms);
2036 }
2037
2038 nla_nest_end(msg, nested);
2039
2040 return 0;
2041}
2042
3710a8a6
JB
2043static int
2044nl80211_put_tid_config_support(struct cfg80211_registered_device *rdev,
2045 struct sk_buff *msg)
2046{
2047 struct nlattr *supp;
2048
2049 if (!rdev->wiphy.tid_config_support.vif &&
2050 !rdev->wiphy.tid_config_support.peer)
2051 return 0;
2052
2053 supp = nla_nest_start(msg, NL80211_ATTR_TID_CONFIG);
2054 if (!supp)
2055 return -ENOSPC;
2056
2057 if (rdev->wiphy.tid_config_support.vif &&
2058 nla_put_u64_64bit(msg, NL80211_TID_CONFIG_ATTR_VIF_SUPP,
2059 rdev->wiphy.tid_config_support.vif,
2060 NL80211_TID_CONFIG_ATTR_PAD))
2061 goto fail;
2062
2063 if (rdev->wiphy.tid_config_support.peer &&
2064 nla_put_u64_64bit(msg, NL80211_TID_CONFIG_ATTR_PEER_SUPP,
2065 rdev->wiphy.tid_config_support.peer,
2066 NL80211_TID_CONFIG_ATTR_PAD))
2067 goto fail;
2068
6a21d16c
T
2069 /* for now we just use the same value ... makes more sense */
2070 if (nla_put_u8(msg, NL80211_TID_CONFIG_ATTR_RETRY_SHORT,
2071 rdev->wiphy.tid_config_support.max_retry))
2072 goto fail;
2073 if (nla_put_u8(msg, NL80211_TID_CONFIG_ATTR_RETRY_LONG,
2074 rdev->wiphy.tid_config_support.max_retry))
2075 goto fail;
2076
3710a8a6
JB
2077 nla_nest_end(msg, supp);
2078
2079 return 0;
2080fail:
2081 nla_nest_cancel(msg, supp);
2082 return -ENOBUFS;
2083}
2084
86e8cf98
JB
2085struct nl80211_dump_wiphy_state {
2086 s64 filter_wiphy;
2087 long start;
019ae3a9 2088 long split_start, band_start, chan_start, capa_start;
86e8cf98
JB
2089 bool split;
2090};
2091
1b8ec87a 2092static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
3bb20556 2093 enum nl80211_commands cmd,
3713b4e3 2094 struct sk_buff *msg, u32 portid, u32 seq,
86e8cf98 2095 int flags, struct nl80211_dump_wiphy_state *state)
3713b4e3
JB
2096{
2097 void *hdr;
2098 struct nlattr *nl_bands, *nl_band;
2099 struct nlattr *nl_freqs, *nl_freq;
2100 struct nlattr *nl_cmds;
57fbcce3 2101 enum nl80211_band band;
3713b4e3
JB
2102 struct ieee80211_channel *chan;
2103 int i;
2104 const struct ieee80211_txrx_stypes *mgmt_stypes =
1b8ec87a 2105 rdev->wiphy.mgmt_stypes;
fe1abafd 2106 u32 features;
ee688b00 2107
3bb20556 2108 hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
3713b4e3
JB
2109 if (!hdr)
2110 return -ENOBUFS;
ee688b00 2111
86e8cf98
JB
2112 if (WARN_ON(!state))
2113 return -EINVAL;
ee688b00 2114
1b8ec87a 2115 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
3713b4e3 2116 nla_put_string(msg, NL80211_ATTR_WIPHY_NAME,
1b8ec87a 2117 wiphy_name(&rdev->wiphy)) ||
3713b4e3
JB
2118 nla_put_u32(msg, NL80211_ATTR_GENERATION,
2119 cfg80211_rdev_list_generation))
8fdc621d
JB
2120 goto nla_put_failure;
2121
3bb20556
JB
2122 if (cmd != NL80211_CMD_NEW_WIPHY)
2123 goto finish;
2124
86e8cf98 2125 switch (state->split_start) {
3713b4e3
JB
2126 case 0:
2127 if (nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_SHORT,
1b8ec87a 2128 rdev->wiphy.retry_short) ||
3713b4e3 2129 nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_LONG,
1b8ec87a 2130 rdev->wiphy.retry_long) ||
3713b4e3 2131 nla_put_u32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD,
1b8ec87a 2132 rdev->wiphy.frag_threshold) ||
3713b4e3 2133 nla_put_u32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD,
1b8ec87a 2134 rdev->wiphy.rts_threshold) ||
3713b4e3 2135 nla_put_u8(msg, NL80211_ATTR_WIPHY_COVERAGE_CLASS,
1b8ec87a 2136 rdev->wiphy.coverage_class) ||
3713b4e3 2137 nla_put_u8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS,
1b8ec87a 2138 rdev->wiphy.max_scan_ssids) ||
3713b4e3 2139 nla_put_u8(msg, NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS,
1b8ec87a 2140 rdev->wiphy.max_sched_scan_ssids) ||
3713b4e3 2141 nla_put_u16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN,
1b8ec87a 2142 rdev->wiphy.max_scan_ie_len) ||
3713b4e3 2143 nla_put_u16(msg, NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN,
1b8ec87a 2144 rdev->wiphy.max_sched_scan_ie_len) ||
3713b4e3 2145 nla_put_u8(msg, NL80211_ATTR_MAX_MATCH_SETS,
3b06d277
AS
2146 rdev->wiphy.max_match_sets) ||
2147 nla_put_u32(msg, NL80211_ATTR_MAX_NUM_SCHED_SCAN_PLANS,
2148 rdev->wiphy.max_sched_scan_plans) ||
2149 nla_put_u32(msg, NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL,
2150 rdev->wiphy.max_sched_scan_plan_interval) ||
2151 nla_put_u32(msg, NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS,
2152 rdev->wiphy.max_sched_scan_plan_iterations))
9360ffd1 2153 goto nla_put_failure;
3713b4e3 2154
1b8ec87a 2155 if ((rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN) &&
3713b4e3 2156 nla_put_flag(msg, NL80211_ATTR_SUPPORT_IBSS_RSN))
aa430da4 2157 goto nla_put_failure;
1b8ec87a 2158 if ((rdev->wiphy.flags & WIPHY_FLAG_MESH_AUTH) &&
3713b4e3
JB
2159 nla_put_flag(msg, NL80211_ATTR_SUPPORT_MESH_AUTH))
2160 goto nla_put_failure;
1b8ec87a 2161 if ((rdev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) &&
3713b4e3
JB
2162 nla_put_flag(msg, NL80211_ATTR_SUPPORT_AP_UAPSD))
2163 goto nla_put_failure;
1b8ec87a 2164 if ((rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_FW_ROAM) &&
3713b4e3
JB
2165 nla_put_flag(msg, NL80211_ATTR_ROAM_SUPPORT))
2166 goto nla_put_failure;
1b8ec87a 2167 if ((rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) &&
3713b4e3
JB
2168 nla_put_flag(msg, NL80211_ATTR_TDLS_SUPPORT))
2169 goto nla_put_failure;
1b8ec87a 2170 if ((rdev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP) &&
3713b4e3 2171 nla_put_flag(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP))
9360ffd1 2172 goto nla_put_failure;
86e8cf98
JB
2173 state->split_start++;
2174 if (state->split)
3713b4e3 2175 break;
7b506ff6 2176 fallthrough;
3713b4e3
JB
2177 case 1:
2178 if (nla_put(msg, NL80211_ATTR_CIPHER_SUITES,
1b8ec87a
ZG
2179 sizeof(u32) * rdev->wiphy.n_cipher_suites,
2180 rdev->wiphy.cipher_suites))
3713b4e3 2181 goto nla_put_failure;
4745fc09 2182
3713b4e3 2183 if (nla_put_u8(msg, NL80211_ATTR_MAX_NUM_PMKIDS,
1b8ec87a 2184 rdev->wiphy.max_num_pmkids))
3713b4e3 2185 goto nla_put_failure;
b23aa676 2186
1b8ec87a 2187 if ((rdev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) &&
3713b4e3 2188 nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE))
9360ffd1 2189 goto nla_put_failure;
b23aa676 2190
3713b4e3 2191 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX,
1b8ec87a 2192 rdev->wiphy.available_antennas_tx) ||
3713b4e3 2193 nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX,
1b8ec87a 2194 rdev->wiphy.available_antennas_rx))
9360ffd1 2195 goto nla_put_failure;
b23aa676 2196
1b8ec87a 2197 if ((rdev->wiphy.flags & WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD) &&
3713b4e3 2198 nla_put_u32(msg, NL80211_ATTR_PROBE_RESP_OFFLOAD,
1b8ec87a 2199 rdev->wiphy.probe_resp_offload))
3713b4e3 2200 goto nla_put_failure;
8fdc621d 2201
1b8ec87a
ZG
2202 if ((rdev->wiphy.available_antennas_tx ||
2203 rdev->wiphy.available_antennas_rx) &&
2204 rdev->ops->get_antenna) {
3713b4e3
JB
2205 u32 tx_ant = 0, rx_ant = 0;
2206 int res;
7a087e74 2207
1b8ec87a 2208 res = rdev_get_antenna(rdev, &tx_ant, &rx_ant);
3713b4e3
JB
2209 if (!res) {
2210 if (nla_put_u32(msg,
2211 NL80211_ATTR_WIPHY_ANTENNA_TX,
2212 tx_ant) ||
2213 nla_put_u32(msg,
2214 NL80211_ATTR_WIPHY_ANTENNA_RX,
2215 rx_ant))
2216 goto nla_put_failure;
2217 }
2218 }
a293911d 2219
86e8cf98
JB
2220 state->split_start++;
2221 if (state->split)
3713b4e3 2222 break;
7b506ff6 2223 fallthrough;
3713b4e3
JB
2224 case 2:
2225 if (nl80211_put_iftypes(msg, NL80211_ATTR_SUPPORTED_IFTYPES,
1b8ec87a 2226 rdev->wiphy.interface_modes))
3713b4e3 2227 goto nla_put_failure;
86e8cf98
JB
2228 state->split_start++;
2229 if (state->split)
3713b4e3 2230 break;
7b506ff6 2231 fallthrough;
3713b4e3 2232 case 3:
ae0be8de
MK
2233 nl_bands = nla_nest_start_noflag(msg,
2234 NL80211_ATTR_WIPHY_BANDS);
3713b4e3
JB
2235 if (!nl_bands)
2236 goto nla_put_failure;
f7ca38df 2237
86e8cf98 2238 for (band = state->band_start;
57fbcce3 2239 band < NUM_NL80211_BANDS; band++) {
3713b4e3 2240 struct ieee80211_supported_band *sband;
2e161f78 2241
1b8ec87a 2242 sband = rdev->wiphy.bands[band];
2e161f78 2243
3713b4e3
JB
2244 if (!sband)
2245 continue;
2246
ae0be8de 2247 nl_band = nla_nest_start_noflag(msg, band);
3713b4e3 2248 if (!nl_band)
2e161f78 2249 goto nla_put_failure;
3713b4e3 2250
86e8cf98 2251 switch (state->chan_start) {
3713b4e3
JB
2252 case 0:
2253 if (nl80211_send_band_rateinfo(msg, sband))
9360ffd1 2254 goto nla_put_failure;
86e8cf98
JB
2255 state->chan_start++;
2256 if (state->split)
3713b4e3 2257 break;
7b506ff6 2258 fallthrough;
3713b4e3
JB
2259 default:
2260 /* add frequencies */
ae0be8de
MK
2261 nl_freqs = nla_nest_start_noflag(msg,
2262 NL80211_BAND_ATTR_FREQS);
3713b4e3
JB
2263 if (!nl_freqs)
2264 goto nla_put_failure;
2265
86e8cf98 2266 for (i = state->chan_start - 1;
3713b4e3
JB
2267 i < sband->n_channels;
2268 i++) {
ae0be8de
MK
2269 nl_freq = nla_nest_start_noflag(msg,
2270 i);
3713b4e3
JB
2271 if (!nl_freq)
2272 goto nla_put_failure;
2273
2274 chan = &sband->channels[i];
2275
86e8cf98 2276 if (nl80211_msg_put_channel(
50f32718 2277 msg, &rdev->wiphy, chan,
86e8cf98 2278 state->split))
3713b4e3
JB
2279 goto nla_put_failure;
2280
2281 nla_nest_end(msg, nl_freq);
86e8cf98 2282 if (state->split)
3713b4e3
JB
2283 break;
2284 }
2285 if (i < sband->n_channels)
86e8cf98 2286 state->chan_start = i + 2;
3713b4e3 2287 else
86e8cf98 2288 state->chan_start = 0;
3713b4e3
JB
2289 nla_nest_end(msg, nl_freqs);
2290 }
2291
2292 nla_nest_end(msg, nl_band);
2293
86e8cf98 2294 if (state->split) {
3713b4e3 2295 /* start again here */
86e8cf98 2296 if (state->chan_start)
3713b4e3
JB
2297 band--;
2298 break;
2e161f78 2299 }
2e161f78 2300 }
3713b4e3 2301 nla_nest_end(msg, nl_bands);
2e161f78 2302
57fbcce3 2303 if (band < NUM_NL80211_BANDS)
86e8cf98 2304 state->band_start = band + 1;
3713b4e3 2305 else
86e8cf98 2306 state->band_start = 0;
74b70a4e 2307
3713b4e3 2308 /* if bands & channels are done, continue outside */
86e8cf98
JB
2309 if (state->band_start == 0 && state->chan_start == 0)
2310 state->split_start++;
2311 if (state->split)
3713b4e3 2312 break;
7b506ff6 2313 fallthrough;
3713b4e3 2314 case 4:
ae0be8de
MK
2315 nl_cmds = nla_nest_start_noflag(msg,
2316 NL80211_ATTR_SUPPORTED_COMMANDS);
3713b4e3 2317 if (!nl_cmds)
2e161f78
JB
2318 goto nla_put_failure;
2319
1794899e
JB
2320 i = nl80211_add_commands_unsplit(rdev, msg);
2321 if (i < 0)
2322 goto nla_put_failure;
86e8cf98 2323 if (state->split) {
5de17984
AS
2324 CMD(crit_proto_start, CRIT_PROTOCOL_START);
2325 CMD(crit_proto_stop, CRIT_PROTOCOL_STOP);
1b8ec87a 2326 if (rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH)
16ef1fe2 2327 CMD(channel_switch, CHANNEL_SWITCH);
02df00eb 2328 CMD(set_qos_map, SET_QOS_MAP);
723e73ac
JB
2329 if (rdev->wiphy.features &
2330 NL80211_FEATURE_SUPPORTS_WMM_ADMISSION)
960d01ac 2331 CMD(add_tx_ts, ADD_TX_TS);
ce0ce13a 2332 CMD(set_multicast_to_unicast, SET_MULTICAST_TO_UNICAST);
088e8df8 2333 CMD(update_connect_params, UPDATE_CONNECT_PARAMS);
7010998c 2334 CMD(update_ft_ies, UPDATE_FT_IES);
5de17984 2335 }
3713b4e3 2336#undef CMD
ff1b6e69 2337
3713b4e3 2338 nla_nest_end(msg, nl_cmds);
86e8cf98
JB
2339 state->split_start++;
2340 if (state->split)
3713b4e3 2341 break;
7b506ff6 2342 fallthrough;
3713b4e3 2343 case 5:
1b8ec87a
ZG
2344 if (rdev->ops->remain_on_channel &&
2345 (rdev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL) &&
3713b4e3
JB
2346 nla_put_u32(msg,
2347 NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION,
1b8ec87a 2348 rdev->wiphy.max_remain_on_channel_duration))
3713b4e3
JB
2349 goto nla_put_failure;
2350
1b8ec87a 2351 if ((rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX) &&
3713b4e3
JB
2352 nla_put_flag(msg, NL80211_ATTR_OFFCHANNEL_TX_OK))
2353 goto nla_put_failure;
2354
2355 if (nl80211_send_mgmt_stypes(msg, mgmt_stypes))
2356 goto nla_put_failure;
86e8cf98
JB
2357 state->split_start++;
2358 if (state->split)
3713b4e3 2359 break;
7b506ff6 2360 fallthrough;
3713b4e3
JB
2361 case 6:
2362#ifdef CONFIG_PM
1b8ec87a 2363 if (nl80211_send_wowlan(msg, rdev, state->split))
3713b4e3 2364 goto nla_put_failure;
86e8cf98
JB
2365 state->split_start++;
2366 if (state->split)
3713b4e3
JB
2367 break;
2368#else
86e8cf98 2369 state->split_start++;
dfb89c56 2370#endif
7b506ff6 2371 fallthrough;
3713b4e3
JB
2372 case 7:
2373 if (nl80211_put_iftypes(msg, NL80211_ATTR_SOFTWARE_IFTYPES,
1b8ec87a 2374 rdev->wiphy.software_iftypes))
3713b4e3 2375 goto nla_put_failure;
ff1b6e69 2376
1b8ec87a 2377 if (nl80211_put_iface_combinations(&rdev->wiphy, msg,
86e8cf98 2378 state->split))
3713b4e3 2379 goto nla_put_failure;
7527a782 2380
86e8cf98
JB
2381 state->split_start++;
2382 if (state->split)
3713b4e3 2383 break;
7b506ff6 2384 fallthrough;
3713b4e3 2385 case 8:
1b8ec87a 2386 if ((rdev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME) &&
3713b4e3 2387 nla_put_u32(msg, NL80211_ATTR_DEVICE_AP_SME,
1b8ec87a 2388 rdev->wiphy.ap_sme_capa))
3713b4e3 2389 goto nla_put_failure;
7527a782 2390
1b8ec87a 2391 features = rdev->wiphy.features;
fe1abafd
JB
2392 /*
2393 * We can only add the per-channel limit information if the
2394 * dump is split, otherwise it makes it too big. Therefore
2395 * only advertise it in that case.
2396 */
86e8cf98 2397 if (state->split)
fe1abafd
JB
2398 features |= NL80211_FEATURE_ADVERTISE_CHAN_LIMITS;
2399 if (nla_put_u32(msg, NL80211_ATTR_FEATURE_FLAGS, features))
3713b4e3 2400 goto nla_put_failure;
562a7480 2401
1b8ec87a 2402 if (rdev->wiphy.ht_capa_mod_mask &&
3713b4e3 2403 nla_put(msg, NL80211_ATTR_HT_CAPABILITY_MASK,
1b8ec87a
ZG
2404 sizeof(*rdev->wiphy.ht_capa_mod_mask),
2405 rdev->wiphy.ht_capa_mod_mask))
3713b4e3 2406 goto nla_put_failure;
1f074bd8 2407
1b8ec87a
ZG
2408 if (rdev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME &&
2409 rdev->wiphy.max_acl_mac_addrs &&
3713b4e3 2410 nla_put_u32(msg, NL80211_ATTR_MAC_ACL_MAX,
1b8ec87a 2411 rdev->wiphy.max_acl_mac_addrs))
3713b4e3 2412 goto nla_put_failure;
7e7c8926 2413
3713b4e3
JB
2414 /*
2415 * Any information below this point is only available to
2416 * applications that can deal with it being split. This
2417 * helps ensure that newly added capabilities don't break
2418 * older tools by overrunning their buffers.
2419 *
2420 * We still increment split_start so that in the split
2421 * case we'll continue with more data in the next round,
2422 * but break unconditionally so unsplit data stops here.
2423 */
86e8cf98 2424 state->split_start++;
3713b4e3
JB
2425 break;
2426 case 9:
1b8ec87a 2427 if (rdev->wiphy.extended_capabilities &&
fe1abafd 2428 (nla_put(msg, NL80211_ATTR_EXT_CAPA,
1b8ec87a
ZG
2429 rdev->wiphy.extended_capabilities_len,
2430 rdev->wiphy.extended_capabilities) ||
fe1abafd 2431 nla_put(msg, NL80211_ATTR_EXT_CAPA_MASK,
1b8ec87a
ZG
2432 rdev->wiphy.extended_capabilities_len,
2433 rdev->wiphy.extended_capabilities_mask)))
fe1abafd 2434 goto nla_put_failure;
a50df0c4 2435
1b8ec87a 2436 if (rdev->wiphy.vht_capa_mod_mask &&
ee2aca34 2437 nla_put(msg, NL80211_ATTR_VHT_CAPABILITY_MASK,
1b8ec87a
ZG
2438 sizeof(*rdev->wiphy.vht_capa_mod_mask),
2439 rdev->wiphy.vht_capa_mod_mask))
ee2aca34
JB
2440 goto nla_put_failure;
2441
ae6fa4d5
DK
2442 if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN,
2443 rdev->wiphy.perm_addr))
2444 goto nla_put_failure;
2445
2446 if (!is_zero_ether_addr(rdev->wiphy.addr_mask) &&
2447 nla_put(msg, NL80211_ATTR_MAC_MASK, ETH_ALEN,
2448 rdev->wiphy.addr_mask))
2449 goto nla_put_failure;
2450
2451 if (rdev->wiphy.n_addresses > 1) {
2452 void *attr;
2453
2454 attr = nla_nest_start(msg, NL80211_ATTR_MAC_ADDRS);
2455 if (!attr)
2456 goto nla_put_failure;
2457
2458 for (i = 0; i < rdev->wiphy.n_addresses; i++)
2459 if (nla_put(msg, i + 1, ETH_ALEN,
2460 rdev->wiphy.addresses[i].addr))
2461 goto nla_put_failure;
2462
2463 nla_nest_end(msg, attr);
2464 }
2465
be29b99a
AK
2466 state->split_start++;
2467 break;
2468 case 10:
1b8ec87a 2469 if (nl80211_send_coalesce(msg, rdev))
be29b99a
AK
2470 goto nla_put_failure;
2471
1b8ec87a 2472 if ((rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_5_10_MHZ) &&
01e0daa4
FF
2473 (nla_put_flag(msg, NL80211_ATTR_SUPPORT_5_MHZ) ||
2474 nla_put_flag(msg, NL80211_ATTR_SUPPORT_10_MHZ)))
2475 goto nla_put_failure;
b43504cf 2476
1b8ec87a 2477 if (rdev->wiphy.max_ap_assoc_sta &&
b43504cf 2478 nla_put_u32(msg, NL80211_ATTR_MAX_AP_ASSOC_STA,
1b8ec87a 2479 rdev->wiphy.max_ap_assoc_sta))
b43504cf
JM
2480 goto nla_put_failure;
2481
ad7e718c
JB
2482 state->split_start++;
2483 break;
2484 case 11:
1b8ec87a 2485 if (rdev->wiphy.n_vendor_commands) {
567ffc35
JB
2486 const struct nl80211_vendor_cmd_info *info;
2487 struct nlattr *nested;
2488
ae0be8de
MK
2489 nested = nla_nest_start_noflag(msg,
2490 NL80211_ATTR_VENDOR_DATA);
567ffc35
JB
2491 if (!nested)
2492 goto nla_put_failure;
2493
1b8ec87a
ZG
2494 for (i = 0; i < rdev->wiphy.n_vendor_commands; i++) {
2495 info = &rdev->wiphy.vendor_commands[i].info;
567ffc35
JB
2496 if (nla_put(msg, i + 1, sizeof(*info), info))
2497 goto nla_put_failure;
2498 }
2499 nla_nest_end(msg, nested);
2500 }
2501
1b8ec87a 2502 if (rdev->wiphy.n_vendor_events) {
567ffc35
JB
2503 const struct nl80211_vendor_cmd_info *info;
2504 struct nlattr *nested;
ad7e718c 2505
ae0be8de
MK
2506 nested = nla_nest_start_noflag(msg,
2507 NL80211_ATTR_VENDOR_EVENTS);
567ffc35 2508 if (!nested)
ad7e718c 2509 goto nla_put_failure;
567ffc35 2510
1b8ec87a
ZG
2511 for (i = 0; i < rdev->wiphy.n_vendor_events; i++) {
2512 info = &rdev->wiphy.vendor_events[i];
567ffc35
JB
2513 if (nla_put(msg, i + 1, sizeof(*info), info))
2514 goto nla_put_failure;
2515 }
2516 nla_nest_end(msg, nested);
2517 }
9a774c78
AO
2518 state->split_start++;
2519 break;
2520 case 12:
2521 if (rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH &&
2522 nla_put_u8(msg, NL80211_ATTR_MAX_CSA_COUNTERS,
2523 rdev->wiphy.max_num_csa_counters))
2524 goto nla_put_failure;
01e0daa4 2525
1bdd716c
AN
2526 if (rdev->wiphy.regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED &&
2527 nla_put_flag(msg, NL80211_ATTR_WIPHY_SELF_MANAGED_REG))
2528 goto nla_put_failure;
2529
ca986ad9
AVS
2530 if (rdev->wiphy.max_sched_scan_reqs &&
2531 nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_MAX_REQS,
2532 rdev->wiphy.max_sched_scan_reqs))
2533 goto nla_put_failure;
2534
d75bb06b
GKS
2535 if (nla_put(msg, NL80211_ATTR_EXT_FEATURES,
2536 sizeof(rdev->wiphy.ext_features),
2537 rdev->wiphy.ext_features))
2538 goto nla_put_failure;
2539
38de03d2
AS
2540 if (rdev->wiphy.bss_select_support) {
2541 struct nlattr *nested;
2542 u32 bss_select_support = rdev->wiphy.bss_select_support;
2543
ae0be8de
MK
2544 nested = nla_nest_start_noflag(msg,
2545 NL80211_ATTR_BSS_SELECT);
38de03d2
AS
2546 if (!nested)
2547 goto nla_put_failure;
2548
2549 i = 0;
2550 while (bss_select_support) {
2551 if ((bss_select_support & 1) &&
2552 nla_put_flag(msg, i))
2553 goto nla_put_failure;
2554 i++;
2555 bss_select_support >>= 1;
2556 }
2557 nla_nest_end(msg, nested);
2558 }
2559
019ae3a9
KV
2560 state->split_start++;
2561 break;
2562 case 13:
2563 if (rdev->wiphy.num_iftype_ext_capab &&
2564 rdev->wiphy.iftype_ext_capab) {
2565 struct nlattr *nested_ext_capab, *nested;
2566
ae0be8de
MK
2567 nested = nla_nest_start_noflag(msg,
2568 NL80211_ATTR_IFTYPE_EXT_CAPA);
019ae3a9
KV
2569 if (!nested)
2570 goto nla_put_failure;
2571
2572 for (i = state->capa_start;
2573 i < rdev->wiphy.num_iftype_ext_capab; i++) {
2574 const struct wiphy_iftype_ext_capab *capab;
2575
2576 capab = &rdev->wiphy.iftype_ext_capab[i];
2577
ae0be8de
MK
2578 nested_ext_capab = nla_nest_start_noflag(msg,
2579 i);
019ae3a9
KV
2580 if (!nested_ext_capab ||
2581 nla_put_u32(msg, NL80211_ATTR_IFTYPE,
2582 capab->iftype) ||
2583 nla_put(msg, NL80211_ATTR_EXT_CAPA,
2584 capab->extended_capabilities_len,
2585 capab->extended_capabilities) ||
2586 nla_put(msg, NL80211_ATTR_EXT_CAPA_MASK,
2587 capab->extended_capabilities_len,
2588 capab->extended_capabilities_mask))
2589 goto nla_put_failure;
2590
2591 nla_nest_end(msg, nested_ext_capab);
2592 if (state->split)
2593 break;
2594 }
2595 nla_nest_end(msg, nested);
2596 if (i < rdev->wiphy.num_iftype_ext_capab) {
2597 state->capa_start = i + 1;
2598 break;
2599 }
2600 }
2601
8585989d
LC
2602 if (nla_put_u32(msg, NL80211_ATTR_BANDS,
2603 rdev->wiphy.nan_supported_bands))
2604 goto nla_put_failure;
2605
52539ca8
THJ
2606 if (wiphy_ext_feature_isset(&rdev->wiphy,
2607 NL80211_EXT_FEATURE_TXQS)) {
2608 struct cfg80211_txq_stats txqstats = {};
2609 int res;
2610
2611 res = rdev_get_txq_stats(rdev, NULL, &txqstats);
2612 if (!res &&
2613 !nl80211_put_txq_stats(msg, &txqstats,
2614 NL80211_ATTR_TXQ_STATS))
2615 goto nla_put_failure;
2616
2617 if (nla_put_u32(msg, NL80211_ATTR_TXQ_LIMIT,
2618 rdev->wiphy.txq_limit))
2619 goto nla_put_failure;
2620 if (nla_put_u32(msg, NL80211_ATTR_TXQ_MEMORY_LIMIT,
2621 rdev->wiphy.txq_memory_limit))
2622 goto nla_put_failure;
2623 if (nla_put_u32(msg, NL80211_ATTR_TXQ_QUANTUM,
2624 rdev->wiphy.txq_quantum))
2625 goto nla_put_failure;
2626 }
2627
9bb7e0f2
JB
2628 state->split_start++;
2629 break;
2630 case 14:
2631 if (nl80211_send_pmsr_capa(rdev, msg))
2632 goto nla_put_failure;
2633
ab4dfa20
VJ
2634 state->split_start++;
2635 break;
2636 case 15:
2637 if (rdev->wiphy.akm_suites &&
2638 nla_put(msg, NL80211_ATTR_AKM_SUITES,
2639 sizeof(u32) * rdev->wiphy.n_akm_suites,
2640 rdev->wiphy.akm_suites))
2641 goto nla_put_failure;
2642
d6039a34
VJ
2643 if (nl80211_put_iftype_akm_suites(rdev, msg))
2644 goto nla_put_failure;
2645
3710a8a6
JB
2646 if (nl80211_put_tid_config_support(rdev, msg))
2647 goto nla_put_failure;
2648
3713b4e3 2649 /* done */
86e8cf98 2650 state->split_start = 0;
3713b4e3
JB
2651 break;
2652 }
3bb20556 2653 finish:
053c095a
JB
2654 genlmsg_end(msg, hdr);
2655 return 0;
55682965
JB
2656
2657 nla_put_failure:
bc3ed28c
TG
2658 genlmsg_cancel(msg, hdr);
2659 return -EMSGSIZE;
55682965
JB
2660}
2661
86e8cf98
JB
2662static int nl80211_dump_wiphy_parse(struct sk_buff *skb,
2663 struct netlink_callback *cb,
2664 struct nl80211_dump_wiphy_state *state)
2665{
50508d94
JB
2666 struct nlattr **tb = kcalloc(NUM_NL80211_ATTR, sizeof(*tb), GFP_KERNEL);
2667 int ret;
2668
2669 if (!tb)
2670 return -ENOMEM;
2671
2672 ret = nlmsg_parse_deprecated(cb->nlh,
2673 GENL_HDRLEN + nl80211_fam.hdrsize,
2674 tb, nl80211_fam.maxattr,
2675 nl80211_policy, NULL);
86e8cf98 2676 /* ignore parse errors for backward compatibility */
50508d94
JB
2677 if (ret) {
2678 ret = 0;
2679 goto out;
2680 }
86e8cf98
JB
2681
2682 state->split = tb[NL80211_ATTR_SPLIT_WIPHY_DUMP];
2683 if (tb[NL80211_ATTR_WIPHY])
2684 state->filter_wiphy = nla_get_u32(tb[NL80211_ATTR_WIPHY]);
2685 if (tb[NL80211_ATTR_WDEV])
2686 state->filter_wiphy = nla_get_u64(tb[NL80211_ATTR_WDEV]) >> 32;
2687 if (tb[NL80211_ATTR_IFINDEX]) {
2688 struct net_device *netdev;
2689 struct cfg80211_registered_device *rdev;
2690 int ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
2691
7f2b8562 2692 netdev = __dev_get_by_index(sock_net(skb->sk), ifidx);
50508d94
JB
2693 if (!netdev) {
2694 ret = -ENODEV;
2695 goto out;
2696 }
86e8cf98 2697 if (netdev->ieee80211_ptr) {
f26cbf40 2698 rdev = wiphy_to_rdev(
86e8cf98
JB
2699 netdev->ieee80211_ptr->wiphy);
2700 state->filter_wiphy = rdev->wiphy_idx;
2701 }
86e8cf98
JB
2702 }
2703
50508d94
JB
2704 ret = 0;
2705out:
2706 kfree(tb);
2707 return ret;
86e8cf98
JB
2708}
2709
55682965
JB
2710static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
2711{
645e77de 2712 int idx = 0, ret;
86e8cf98 2713 struct nl80211_dump_wiphy_state *state = (void *)cb->args[0];
1b8ec87a 2714 struct cfg80211_registered_device *rdev;
3a5a423b 2715
5fe231e8 2716 rtnl_lock();
86e8cf98
JB
2717 if (!state) {
2718 state = kzalloc(sizeof(*state), GFP_KERNEL);
57ed5cd6
JL
2719 if (!state) {
2720 rtnl_unlock();
86e8cf98 2721 return -ENOMEM;
3713b4e3 2722 }
86e8cf98
JB
2723 state->filter_wiphy = -1;
2724 ret = nl80211_dump_wiphy_parse(skb, cb, state);
2725 if (ret) {
2726 kfree(state);
2727 rtnl_unlock();
2728 return ret;
3713b4e3 2729 }
86e8cf98 2730 cb->args[0] = (long)state;
3713b4e3
JB
2731 }
2732
1b8ec87a
ZG
2733 list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
2734 if (!net_eq(wiphy_net(&rdev->wiphy), sock_net(skb->sk)))
463d0183 2735 continue;
86e8cf98 2736 if (++idx <= state->start)
55682965 2737 continue;
86e8cf98 2738 if (state->filter_wiphy != -1 &&
1b8ec87a 2739 state->filter_wiphy != rdev->wiphy_idx)
3713b4e3
JB
2740 continue;
2741 /* attempt to fit multiple wiphy data chunks into the skb */
2742 do {
3bb20556
JB
2743 ret = nl80211_send_wiphy(rdev, NL80211_CMD_NEW_WIPHY,
2744 skb,
3713b4e3
JB
2745 NETLINK_CB(cb->skb).portid,
2746 cb->nlh->nlmsg_seq,
86e8cf98 2747 NLM_F_MULTI, state);
3713b4e3
JB
2748 if (ret < 0) {
2749 /*
2750 * If sending the wiphy data didn't fit (ENOBUFS
2751 * or EMSGSIZE returned), this SKB is still
2752 * empty (so it's not too big because another
2753 * wiphy dataset is already in the skb) and
2754 * we've not tried to adjust the dump allocation
2755 * yet ... then adjust the alloc size to be
2756 * bigger, and return 1 but with the empty skb.
2757 * This results in an empty message being RX'ed
2758 * in userspace, but that is ignored.
2759 *
2760 * We can then retry with the larger buffer.
2761 */
2762 if ((ret == -ENOBUFS || ret == -EMSGSIZE) &&
f12cb289 2763 !skb->len && !state->split &&
3713b4e3
JB
2764 cb->min_dump_alloc < 4096) {
2765 cb->min_dump_alloc = 4096;
f12cb289 2766 state->split_start = 0;
d98cae64 2767 rtnl_unlock();
3713b4e3
JB
2768 return 1;
2769 }
2770 idx--;
2771 break;
645e77de 2772 }
86e8cf98 2773 } while (state->split_start > 0);
3713b4e3 2774 break;
55682965 2775 }
5fe231e8 2776 rtnl_unlock();
55682965 2777
86e8cf98 2778 state->start = idx;
55682965
JB
2779
2780 return skb->len;
2781}
2782
86e8cf98
JB
2783static int nl80211_dump_wiphy_done(struct netlink_callback *cb)
2784{
2785 kfree((void *)cb->args[0]);
2786 return 0;
2787}
2788
55682965
JB
2789static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info)
2790{
2791 struct sk_buff *msg;
1b8ec87a 2792 struct cfg80211_registered_device *rdev = info->user_ptr[0];
86e8cf98 2793 struct nl80211_dump_wiphy_state state = {};
55682965 2794
645e77de 2795 msg = nlmsg_new(4096, GFP_KERNEL);
55682965 2796 if (!msg)
4c476991 2797 return -ENOMEM;
55682965 2798
3bb20556
JB
2799 if (nl80211_send_wiphy(rdev, NL80211_CMD_NEW_WIPHY, msg,
2800 info->snd_portid, info->snd_seq, 0,
86e8cf98 2801 &state) < 0) {
4c476991
JB
2802 nlmsg_free(msg);
2803 return -ENOBUFS;
2804 }
55682965 2805
134e6375 2806 return genlmsg_reply(msg, info);
55682965
JB
2807}
2808
31888487
JM
2809static const struct nla_policy txq_params_policy[NL80211_TXQ_ATTR_MAX + 1] = {
2810 [NL80211_TXQ_ATTR_QUEUE] = { .type = NLA_U8 },
2811 [NL80211_TXQ_ATTR_TXOP] = { .type = NLA_U16 },
2812 [NL80211_TXQ_ATTR_CWMIN] = { .type = NLA_U16 },
2813 [NL80211_TXQ_ATTR_CWMAX] = { .type = NLA_U16 },
2814 [NL80211_TXQ_ATTR_AIFS] = { .type = NLA_U8 },
2815};
2816
2817static int parse_txq_params(struct nlattr *tb[],
2818 struct ieee80211_txq_params *txq_params)
2819{
259d8c1e
DW
2820 u8 ac;
2821
a3304b0a 2822 if (!tb[NL80211_TXQ_ATTR_AC] || !tb[NL80211_TXQ_ATTR_TXOP] ||
31888487
JM
2823 !tb[NL80211_TXQ_ATTR_CWMIN] || !tb[NL80211_TXQ_ATTR_CWMAX] ||
2824 !tb[NL80211_TXQ_ATTR_AIFS])
2825 return -EINVAL;
2826
259d8c1e 2827 ac = nla_get_u8(tb[NL80211_TXQ_ATTR_AC]);
31888487
JM
2828 txq_params->txop = nla_get_u16(tb[NL80211_TXQ_ATTR_TXOP]);
2829 txq_params->cwmin = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMIN]);
2830 txq_params->cwmax = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMAX]);
2831 txq_params->aifs = nla_get_u8(tb[NL80211_TXQ_ATTR_AIFS]);
2832
259d8c1e 2833 if (ac >= NL80211_NUM_ACS)
a3304b0a 2834 return -EINVAL;
259d8c1e 2835 txq_params->ac = array_index_nospec(ac, NL80211_NUM_ACS);
31888487
JM
2836 return 0;
2837}
2838
f444de05
JB
2839static bool nl80211_can_set_dev_channel(struct wireless_dev *wdev)
2840{
2841 /*
cc1d2806
JB
2842 * You can only set the channel explicitly for WDS interfaces,
2843 * all others have their channel managed via their respective
2844 * "establish a connection" command (connect, join, ...)
2845 *
2846 * For AP/GO and mesh mode, the channel can be set with the
2847 * channel userspace API, but is only stored and passed to the
2848 * low-level driver when the AP starts or the mesh is joined.
2849 * This is for backward compatibility, userspace can also give
2850 * the channel in the start-ap or join-mesh commands instead.
f444de05
JB
2851 *
2852 * Monitors are special as they are normally slaved to
e8c9bd5b
JB
2853 * whatever else is going on, so they have their own special
2854 * operation to set the monitor channel if possible.
f444de05
JB
2855 */
2856 return !wdev ||
2857 wdev->iftype == NL80211_IFTYPE_AP ||
f444de05 2858 wdev->iftype == NL80211_IFTYPE_MESH_POINT ||
074ac8df
JB
2859 wdev->iftype == NL80211_IFTYPE_MONITOR ||
2860 wdev->iftype == NL80211_IFTYPE_P2P_GO;
f444de05
JB
2861}
2862
9bb7e0f2
JB
2863int nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
2864 struct genl_info *info,
2865 struct cfg80211_chan_def *chandef)
683b6d3b 2866{
49f9cf0e
JB
2867 struct netlink_ext_ack *extack = info->extack;
2868 struct nlattr **attrs = info->attrs;
dbeca2ea 2869 u32 control_freq;
683b6d3b 2870
49f9cf0e 2871 if (!attrs[NL80211_ATTR_WIPHY_FREQ])
683b6d3b
JB
2872 return -EINVAL;
2873
942ba88b
TP
2874 control_freq = MHZ_TO_KHZ(
2875 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
2876 if (info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET])
2877 control_freq +=
2878 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET]);
683b6d3b 2879
f43e5210 2880 memset(chandef, 0, sizeof(*chandef));
942ba88b 2881 chandef->chan = ieee80211_get_channel_khz(&rdev->wiphy, control_freq);
3d9d1d66 2882 chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
942ba88b
TP
2883 chandef->center_freq1 = KHZ_TO_MHZ(control_freq);
2884 chandef->freq1_offset = control_freq % 1000;
3d9d1d66 2885 chandef->center_freq2 = 0;
683b6d3b
JB
2886
2887 /* Primary channel not allowed */
49f9cf0e
JB
2888 if (!chandef->chan || chandef->chan->flags & IEEE80211_CHAN_DISABLED) {
2889 NL_SET_ERR_MSG_ATTR(extack, attrs[NL80211_ATTR_WIPHY_FREQ],
2890 "Channel is disabled");
683b6d3b 2891 return -EINVAL;
49f9cf0e 2892 }
683b6d3b 2893
49f9cf0e 2894 if (attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
3d9d1d66
JB
2895 enum nl80211_channel_type chantype;
2896
49f9cf0e 2897 chantype = nla_get_u32(attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
3d9d1d66
JB
2898
2899 switch (chantype) {
2900 case NL80211_CHAN_NO_HT:
2901 case NL80211_CHAN_HT20:
2902 case NL80211_CHAN_HT40PLUS:
2903 case NL80211_CHAN_HT40MINUS:
2904 cfg80211_chandef_create(chandef, chandef->chan,
2905 chantype);
ffa4629e 2906 /* user input for center_freq is incorrect */
49f9cf0e
JB
2907 if (attrs[NL80211_ATTR_CENTER_FREQ1] &&
2908 chandef->center_freq1 != nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ1])) {
2909 NL_SET_ERR_MSG_ATTR(extack,
2910 attrs[NL80211_ATTR_CENTER_FREQ1],
2911 "bad center frequency 1");
ffa4629e 2912 return -EINVAL;
49f9cf0e 2913 }
ffa4629e 2914 /* center_freq2 must be zero */
49f9cf0e
JB
2915 if (attrs[NL80211_ATTR_CENTER_FREQ2] &&
2916 nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ2])) {
2917 NL_SET_ERR_MSG_ATTR(extack,
2918 attrs[NL80211_ATTR_CENTER_FREQ2],
2919 "center frequency 2 can't be used");
ffa4629e 2920 return -EINVAL;
49f9cf0e 2921 }
3d9d1d66
JB
2922 break;
2923 default:
49f9cf0e
JB
2924 NL_SET_ERR_MSG_ATTR(extack,
2925 attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE],
2926 "invalid channel type");
3d9d1d66
JB
2927 return -EINVAL;
2928 }
49f9cf0e 2929 } else if (attrs[NL80211_ATTR_CHANNEL_WIDTH]) {
3d9d1d66 2930 chandef->width =
49f9cf0e 2931 nla_get_u32(attrs[NL80211_ATTR_CHANNEL_WIDTH]);
942ba88b 2932 if (attrs[NL80211_ATTR_CENTER_FREQ1]) {
3d9d1d66 2933 chandef->center_freq1 =
49f9cf0e 2934 nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ1]);
942ba88b
TP
2935 if (attrs[NL80211_ATTR_CENTER_FREQ1_OFFSET])
2936 chandef->freq1_offset = nla_get_u32(
2937 attrs[NL80211_ATTR_CENTER_FREQ1_OFFSET]);
2938 else
2939 chandef->freq1_offset = 0;
2940 }
49f9cf0e 2941 if (attrs[NL80211_ATTR_CENTER_FREQ2])
3d9d1d66 2942 chandef->center_freq2 =
49f9cf0e 2943 nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ2]);
3d9d1d66
JB
2944 }
2945
2a38075c
AAL
2946 if (info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]) {
2947 chandef->edmg.channels =
2948 nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]);
2949
2950 if (info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG])
2951 chandef->edmg.bw_config =
2952 nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG]);
2953 } else {
2954 chandef->edmg.bw_config = 0;
2955 chandef->edmg.channels = 0;
2956 }
2957
49f9cf0e
JB
2958 if (!cfg80211_chandef_valid(chandef)) {
2959 NL_SET_ERR_MSG(extack, "invalid channel definition");
3d9d1d66 2960 return -EINVAL;
49f9cf0e 2961 }
3d9d1d66 2962
9f5e8f6e 2963 if (!cfg80211_chandef_usable(&rdev->wiphy, chandef,
49f9cf0e
JB
2964 IEEE80211_CHAN_DISABLED)) {
2965 NL_SET_ERR_MSG(extack, "(extension) channel is disabled");
3d9d1d66 2966 return -EINVAL;
49f9cf0e 2967 }
3d9d1d66 2968
2f301ab2
SW
2969 if ((chandef->width == NL80211_CHAN_WIDTH_5 ||
2970 chandef->width == NL80211_CHAN_WIDTH_10) &&
49f9cf0e
JB
2971 !(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_5_10_MHZ)) {
2972 NL_SET_ERR_MSG(extack, "5/10 MHz not supported");
2f301ab2 2973 return -EINVAL;
49f9cf0e 2974 }
2f301ab2 2975
683b6d3b
JB
2976 return 0;
2977}
2978
f444de05 2979static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
e16821bc 2980 struct net_device *dev,
f444de05
JB
2981 struct genl_info *info)
2982{
683b6d3b 2983 struct cfg80211_chan_def chandef;
f444de05 2984 int result;
e8c9bd5b 2985 enum nl80211_iftype iftype = NL80211_IFTYPE_MONITOR;
e16821bc 2986 struct wireless_dev *wdev = NULL;
e8c9bd5b 2987
e16821bc
JM
2988 if (dev)
2989 wdev = dev->ieee80211_ptr;
f444de05
JB
2990 if (!nl80211_can_set_dev_channel(wdev))
2991 return -EOPNOTSUPP;
e16821bc
JM
2992 if (wdev)
2993 iftype = wdev->iftype;
f444de05 2994
683b6d3b
JB
2995 result = nl80211_parse_chandef(rdev, info, &chandef);
2996 if (result)
2997 return result;
f444de05 2998
e8c9bd5b 2999 switch (iftype) {
aa430da4
JB
3000 case NL80211_IFTYPE_AP:
3001 case NL80211_IFTYPE_P2P_GO:
923b352f
AN
3002 if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &chandef,
3003 iftype)) {
aa430da4
JB
3004 result = -EINVAL;
3005 break;
3006 }
e16821bc
JM
3007 if (wdev->beacon_interval) {
3008 if (!dev || !rdev->ops->set_ap_chanwidth ||
3009 !(rdev->wiphy.features &
3010 NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE)) {
3011 result = -EBUSY;
3012 break;
3013 }
3014
3015 /* Only allow dynamic channel width changes */
3016 if (chandef.chan != wdev->preset_chandef.chan) {
3017 result = -EBUSY;
3018 break;
3019 }
3020 result = rdev_set_ap_chanwidth(rdev, dev, &chandef);
3021 if (result)
3022 break;
3023 }
683b6d3b 3024 wdev->preset_chandef = chandef;
aa430da4
JB
3025 result = 0;
3026 break;
cc1d2806 3027 case NL80211_IFTYPE_MESH_POINT:
683b6d3b 3028 result = cfg80211_set_mesh_channel(rdev, wdev, &chandef);
cc1d2806 3029 break;
e8c9bd5b 3030 case NL80211_IFTYPE_MONITOR:
683b6d3b 3031 result = cfg80211_set_monitor_channel(rdev, &chandef);
e8c9bd5b 3032 break;
aa430da4 3033 default:
e8c9bd5b 3034 result = -EINVAL;
f444de05 3035 }
f444de05
JB
3036
3037 return result;
3038}
3039
3040static int nl80211_set_channel(struct sk_buff *skb, struct genl_info *info)
3041{
4c476991
JB
3042 struct cfg80211_registered_device *rdev = info->user_ptr[0];
3043 struct net_device *netdev = info->user_ptr[1];
f444de05 3044
e16821bc 3045 return __nl80211_set_channel(rdev, netdev, info);
f444de05
JB
3046}
3047
e8347eba
BJ
3048static int nl80211_set_wds_peer(struct sk_buff *skb, struct genl_info *info)
3049{
43b19952
JB
3050 struct cfg80211_registered_device *rdev = info->user_ptr[0];
3051 struct net_device *dev = info->user_ptr[1];
3052 struct wireless_dev *wdev = dev->ieee80211_ptr;
388ac775 3053 const u8 *bssid;
e8347eba
BJ
3054
3055 if (!info->attrs[NL80211_ATTR_MAC])
3056 return -EINVAL;
3057
43b19952
JB
3058 if (netif_running(dev))
3059 return -EBUSY;
e8347eba 3060
43b19952
JB
3061 if (!rdev->ops->set_wds_peer)
3062 return -EOPNOTSUPP;
e8347eba 3063
43b19952
JB
3064 if (wdev->iftype != NL80211_IFTYPE_WDS)
3065 return -EOPNOTSUPP;
e8347eba
BJ
3066
3067 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
e35e4d28 3068 return rdev_set_wds_peer(rdev, dev, bssid);
e8347eba
BJ
3069}
3070
55682965
JB
3071static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
3072{
3073 struct cfg80211_registered_device *rdev;
f444de05
JB
3074 struct net_device *netdev = NULL;
3075 struct wireless_dev *wdev;
a1e567c8 3076 int result = 0, rem_txq_params = 0;
31888487 3077 struct nlattr *nl_txq_params;
b9a5f8ca
JM
3078 u32 changed;
3079 u8 retry_short = 0, retry_long = 0;
3080 u32 frag_threshold = 0, rts_threshold = 0;
81077e82 3081 u8 coverage_class = 0;
52539ca8 3082 u32 txq_limit = 0, txq_memory_limit = 0, txq_quantum = 0;
55682965 3083
5fe231e8
JB
3084 ASSERT_RTNL();
3085
f444de05
JB
3086 /*
3087 * Try to find the wiphy and netdev. Normally this
3088 * function shouldn't need the netdev, but this is
3089 * done for backward compatibility -- previously
3090 * setting the channel was done per wiphy, but now
3091 * it is per netdev. Previous userland like hostapd
3092 * also passed a netdev to set_wiphy, so that it is
3093 * possible to let that go to the right netdev!
3094 */
4bbf4d56 3095
f444de05
JB
3096 if (info->attrs[NL80211_ATTR_IFINDEX]) {
3097 int ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]);
3098
7f2b8562 3099 netdev = __dev_get_by_index(genl_info_net(info), ifindex);
5fe231e8 3100 if (netdev && netdev->ieee80211_ptr)
f26cbf40 3101 rdev = wiphy_to_rdev(netdev->ieee80211_ptr->wiphy);
5fe231e8 3102 else
f444de05 3103 netdev = NULL;
4bbf4d56
JB
3104 }
3105
f444de05 3106 if (!netdev) {
878d9ec7
JB
3107 rdev = __cfg80211_rdev_from_attrs(genl_info_net(info),
3108 info->attrs);
5fe231e8 3109 if (IS_ERR(rdev))
4c476991 3110 return PTR_ERR(rdev);
f444de05
JB
3111 wdev = NULL;
3112 netdev = NULL;
3113 result = 0;
71fe96bf 3114 } else
f444de05 3115 wdev = netdev->ieee80211_ptr;
f444de05
JB
3116
3117 /*
3118 * end workaround code, by now the rdev is available
3119 * and locked, and wdev may or may not be NULL.
3120 */
4bbf4d56
JB
3121
3122 if (info->attrs[NL80211_ATTR_WIPHY_NAME])
31888487
JM
3123 result = cfg80211_dev_rename(
3124 rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME]));
4bbf4d56 3125
4bbf4d56 3126 if (result)
7f2b8562 3127 return result;
31888487
JM
3128
3129 if (info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS]) {
3130 struct ieee80211_txq_params txq_params;
3131 struct nlattr *tb[NL80211_TXQ_ATTR_MAX + 1];
3132
7f2b8562
YX
3133 if (!rdev->ops->set_txq_params)
3134 return -EOPNOTSUPP;
31888487 3135
7f2b8562
YX
3136 if (!netdev)
3137 return -EINVAL;
f70f01c2 3138
133a3ff2 3139 if (netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
7f2b8562
YX
3140 netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
3141 return -EINVAL;
133a3ff2 3142
7f2b8562
YX
3143 if (!netif_running(netdev))
3144 return -ENETDOWN;
2b5f8b0b 3145
31888487
JM
3146 nla_for_each_nested(nl_txq_params,
3147 info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS],
3148 rem_txq_params) {
8cb08174
JB
3149 result = nla_parse_nested_deprecated(tb,
3150 NL80211_TXQ_ATTR_MAX,
3151 nl_txq_params,
3152 txq_params_policy,
3153 info->extack);
ae811e21
JB
3154 if (result)
3155 return result;
31888487
JM
3156 result = parse_txq_params(tb, &txq_params);
3157 if (result)
7f2b8562 3158 return result;
31888487 3159
e35e4d28
HG
3160 result = rdev_set_txq_params(rdev, netdev,
3161 &txq_params);
31888487 3162 if (result)
7f2b8562 3163 return result;
31888487
JM
3164 }
3165 }
55682965 3166
72bdcf34 3167 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
e16821bc
JM
3168 result = __nl80211_set_channel(
3169 rdev,
3170 nl80211_can_set_dev_channel(wdev) ? netdev : NULL,
3171 info);
72bdcf34 3172 if (result)
7f2b8562 3173 return result;
72bdcf34
JM
3174 }
3175
98d2ff8b 3176 if (info->attrs[NL80211_ATTR_WIPHY_TX_POWER_SETTING]) {
c8442118 3177 struct wireless_dev *txp_wdev = wdev;
98d2ff8b
JO
3178 enum nl80211_tx_power_setting type;
3179 int idx, mbm = 0;
3180
c8442118
JB
3181 if (!(rdev->wiphy.features & NL80211_FEATURE_VIF_TXPOWER))
3182 txp_wdev = NULL;
3183
7f2b8562
YX
3184 if (!rdev->ops->set_tx_power)
3185 return -EOPNOTSUPP;
98d2ff8b
JO
3186
3187 idx = NL80211_ATTR_WIPHY_TX_POWER_SETTING;
3188 type = nla_get_u32(info->attrs[idx]);
3189
3190 if (!info->attrs[NL80211_ATTR_WIPHY_TX_POWER_LEVEL] &&
7f2b8562
YX
3191 (type != NL80211_TX_POWER_AUTOMATIC))
3192 return -EINVAL;
98d2ff8b
JO
3193
3194 if (type != NL80211_TX_POWER_AUTOMATIC) {
3195 idx = NL80211_ATTR_WIPHY_TX_POWER_LEVEL;
3196 mbm = nla_get_u32(info->attrs[idx]);
3197 }
3198
c8442118 3199 result = rdev_set_tx_power(rdev, txp_wdev, type, mbm);
98d2ff8b 3200 if (result)
7f2b8562 3201 return result;
98d2ff8b
JO
3202 }
3203
afe0cbf8
BR
3204 if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX] &&
3205 info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]) {
3206 u32 tx_ant, rx_ant;
7a087e74 3207
7f531e03
BR
3208 if ((!rdev->wiphy.available_antennas_tx &&
3209 !rdev->wiphy.available_antennas_rx) ||
7f2b8562
YX
3210 !rdev->ops->set_antenna)
3211 return -EOPNOTSUPP;
afe0cbf8
BR
3212
3213 tx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX]);
3214 rx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]);
3215
a7ffac95 3216 /* reject antenna configurations which don't match the
7f531e03
BR
3217 * available antenna masks, except for the "all" mask */
3218 if ((~tx_ant && (tx_ant & ~rdev->wiphy.available_antennas_tx)) ||
7f2b8562
YX
3219 (~rx_ant && (rx_ant & ~rdev->wiphy.available_antennas_rx)))
3220 return -EINVAL;
a7ffac95 3221
7f531e03
BR
3222 tx_ant = tx_ant & rdev->wiphy.available_antennas_tx;
3223 rx_ant = rx_ant & rdev->wiphy.available_antennas_rx;
a7ffac95 3224
e35e4d28 3225 result = rdev_set_antenna(rdev, tx_ant, rx_ant);
afe0cbf8 3226 if (result)
7f2b8562 3227 return result;
afe0cbf8
BR
3228 }
3229
b9a5f8ca
JM
3230 changed = 0;
3231
3232 if (info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]) {
3233 retry_short = nla_get_u8(
3234 info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]);
7f2b8562 3235
b9a5f8ca
JM
3236 changed |= WIPHY_PARAM_RETRY_SHORT;
3237 }
3238
3239 if (info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]) {
3240 retry_long = nla_get_u8(
3241 info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]);
7f2b8562 3242
b9a5f8ca
JM
3243 changed |= WIPHY_PARAM_RETRY_LONG;
3244 }
3245
3246 if (info->attrs[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]) {
3247 frag_threshold = nla_get_u32(
3248 info->attrs[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]);
7f2b8562
YX
3249 if (frag_threshold < 256)
3250 return -EINVAL;
3251
b9a5f8ca
JM
3252 if (frag_threshold != (u32) -1) {
3253 /*
3254 * Fragments (apart from the last one) are required to
3255 * have even length. Make the fragmentation code
3256 * simpler by stripping LSB should someone try to use
3257 * odd threshold value.
3258 */
3259 frag_threshold &= ~0x1;
3260 }
3261 changed |= WIPHY_PARAM_FRAG_THRESHOLD;
3262 }
3263
3264 if (info->attrs[NL80211_ATTR_WIPHY_RTS_THRESHOLD]) {
3265 rts_threshold = nla_get_u32(
3266 info->attrs[NL80211_ATTR_WIPHY_RTS_THRESHOLD]);
3267 changed |= WIPHY_PARAM_RTS_THRESHOLD;
3268 }
3269
81077e82 3270 if (info->attrs[NL80211_ATTR_WIPHY_COVERAGE_CLASS]) {
3057dbfd
LB
3271 if (info->attrs[NL80211_ATTR_WIPHY_DYN_ACK])
3272 return -EINVAL;
3273
81077e82
LT
3274 coverage_class = nla_get_u8(
3275 info->attrs[NL80211_ATTR_WIPHY_COVERAGE_CLASS]);
3276 changed |= WIPHY_PARAM_COVERAGE_CLASS;
3277 }
3278
3057dbfd
LB
3279 if (info->attrs[NL80211_ATTR_WIPHY_DYN_ACK]) {
3280 if (!(rdev->wiphy.features & NL80211_FEATURE_ACKTO_ESTIMATION))
3281 return -EOPNOTSUPP;
3282
3283 changed |= WIPHY_PARAM_DYN_ACK;
81077e82
LT
3284 }
3285
52539ca8
THJ
3286 if (info->attrs[NL80211_ATTR_TXQ_LIMIT]) {
3287 if (!wiphy_ext_feature_isset(&rdev->wiphy,
3288 NL80211_EXT_FEATURE_TXQS))
3289 return -EOPNOTSUPP;
3290 txq_limit = nla_get_u32(
3291 info->attrs[NL80211_ATTR_TXQ_LIMIT]);
3292 changed |= WIPHY_PARAM_TXQ_LIMIT;
3293 }
3294
3295 if (info->attrs[NL80211_ATTR_TXQ_MEMORY_LIMIT]) {
3296 if (!wiphy_ext_feature_isset(&rdev->wiphy,
3297 NL80211_EXT_FEATURE_TXQS))
3298 return -EOPNOTSUPP;
3299 txq_memory_limit = nla_get_u32(
3300 info->attrs[NL80211_ATTR_TXQ_MEMORY_LIMIT]);
3301 changed |= WIPHY_PARAM_TXQ_MEMORY_LIMIT;
3302 }
3303
3304 if (info->attrs[NL80211_ATTR_TXQ_QUANTUM]) {
3305 if (!wiphy_ext_feature_isset(&rdev->wiphy,
3306 NL80211_EXT_FEATURE_TXQS))
3307 return -EOPNOTSUPP;
3308 txq_quantum = nla_get_u32(
3309 info->attrs[NL80211_ATTR_TXQ_QUANTUM]);
3310 changed |= WIPHY_PARAM_TXQ_QUANTUM;
3311 }
3312
b9a5f8ca
JM
3313 if (changed) {
3314 u8 old_retry_short, old_retry_long;
3315 u32 old_frag_threshold, old_rts_threshold;
81077e82 3316 u8 old_coverage_class;
52539ca8 3317 u32 old_txq_limit, old_txq_memory_limit, old_txq_quantum;
b9a5f8ca 3318
7f2b8562
YX
3319 if (!rdev->ops->set_wiphy_params)
3320 return -EOPNOTSUPP;
b9a5f8ca
JM
3321
3322 old_retry_short = rdev->wiphy.retry_short;
3323 old_retry_long = rdev->wiphy.retry_long;
3324 old_frag_threshold = rdev->wiphy.frag_threshold;
3325 old_rts_threshold = rdev->wiphy.rts_threshold;
81077e82 3326 old_coverage_class = rdev->wiphy.coverage_class;
52539ca8
THJ
3327 old_txq_limit = rdev->wiphy.txq_limit;
3328 old_txq_memory_limit = rdev->wiphy.txq_memory_limit;
3329 old_txq_quantum = rdev->wiphy.txq_quantum;
b9a5f8ca
JM
3330
3331 if (changed & WIPHY_PARAM_RETRY_SHORT)
3332 rdev->wiphy.retry_short = retry_short;
3333 if (changed & WIPHY_PARAM_RETRY_LONG)
3334 rdev->wiphy.retry_long = retry_long;
3335 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
3336 rdev->wiphy.frag_threshold = frag_threshold;
3337 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
3338 rdev->wiphy.rts_threshold = rts_threshold;
81077e82
LT
3339 if (changed & WIPHY_PARAM_COVERAGE_CLASS)
3340 rdev->wiphy.coverage_class = coverage_class;
52539ca8
THJ
3341 if (changed & WIPHY_PARAM_TXQ_LIMIT)
3342 rdev->wiphy.txq_limit = txq_limit;
3343 if (changed & WIPHY_PARAM_TXQ_MEMORY_LIMIT)
3344 rdev->wiphy.txq_memory_limit = txq_memory_limit;
3345 if (changed & WIPHY_PARAM_TXQ_QUANTUM)
3346 rdev->wiphy.txq_quantum = txq_quantum;
b9a5f8ca 3347
e35e4d28 3348 result = rdev_set_wiphy_params(rdev, changed);
b9a5f8ca
JM
3349 if (result) {
3350 rdev->wiphy.retry_short = old_retry_short;
3351 rdev->wiphy.retry_long = old_retry_long;
3352 rdev->wiphy.frag_threshold = old_frag_threshold;
3353 rdev->wiphy.rts_threshold = old_rts_threshold;
81077e82 3354 rdev->wiphy.coverage_class = old_coverage_class;
52539ca8
THJ
3355 rdev->wiphy.txq_limit = old_txq_limit;
3356 rdev->wiphy.txq_memory_limit = old_txq_memory_limit;
3357 rdev->wiphy.txq_quantum = old_txq_quantum;
9189ee31 3358 return result;
b9a5f8ca
JM
3359 }
3360 }
7f2b8562 3361 return 0;
55682965
JB
3362}
3363
683b6d3b 3364static int nl80211_send_chandef(struct sk_buff *msg,
d2859df5 3365 const struct cfg80211_chan_def *chandef)
683b6d3b 3366{
601555cd
JB
3367 if (WARN_ON(!cfg80211_chandef_valid(chandef)))
3368 return -EINVAL;
3d9d1d66 3369
683b6d3b
JB
3370 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
3371 chandef->chan->center_freq))
3372 return -ENOBUFS;
942ba88b
TP
3373 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ_OFFSET,
3374 chandef->chan->freq_offset))
3375 return -ENOBUFS;
3d9d1d66
JB
3376 switch (chandef->width) {
3377 case NL80211_CHAN_WIDTH_20_NOHT:
3378 case NL80211_CHAN_WIDTH_20:
3379 case NL80211_CHAN_WIDTH_40:
3380 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
3381 cfg80211_get_chandef_type(chandef)))
3382 return -ENOBUFS;
3383 break;
3384 default:
3385 break;
3386 }
3387 if (nla_put_u32(msg, NL80211_ATTR_CHANNEL_WIDTH, chandef->width))
3388 return -ENOBUFS;
3389 if (nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ1, chandef->center_freq1))
3390 return -ENOBUFS;
3391 if (chandef->center_freq2 &&
3392 nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ2, chandef->center_freq2))
683b6d3b
JB
3393 return -ENOBUFS;
3394 return 0;
3395}
3396
15e47304 3397static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flags,
d726405a 3398 struct cfg80211_registered_device *rdev,
3d1a5bbf
AZ
3399 struct wireless_dev *wdev,
3400 enum nl80211_commands cmd)
55682965 3401{
72fb2abc 3402 struct net_device *dev = wdev->netdev;
55682965
JB
3403 void *hdr;
3404
3d1a5bbf
AZ
3405 WARN_ON(cmd != NL80211_CMD_NEW_INTERFACE &&
3406 cmd != NL80211_CMD_DEL_INTERFACE &&
3407 cmd != NL80211_CMD_SET_INTERFACE);
8f894be2
TB
3408
3409 hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
55682965
JB
3410 if (!hdr)
3411 return -1;
3412
72fb2abc
JB
3413 if (dev &&
3414 (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
98104fde 3415 nla_put_string(msg, NL80211_ATTR_IFNAME, dev->name)))
72fb2abc
JB
3416 goto nla_put_failure;
3417
3418 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
3419 nla_put_u32(msg, NL80211_ATTR_IFTYPE, wdev->iftype) ||
2dad624e
ND
3420 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
3421 NL80211_ATTR_PAD) ||
98104fde 3422 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, wdev_address(wdev)) ||
9360ffd1
DM
3423 nla_put_u32(msg, NL80211_ATTR_GENERATION,
3424 rdev->devlist_generation ^
446faa15
AQ
3425 (cfg80211_rdev_list_generation << 2)) ||
3426 nla_put_u8(msg, NL80211_ATTR_4ADDR, wdev->use_4addr))
9360ffd1 3427 goto nla_put_failure;
f5ea9120 3428
5b7ccaf3 3429 if (rdev->ops->get_channel) {
683b6d3b 3430 int ret;
f43e5210 3431 struct cfg80211_chan_def chandef = {};
683b6d3b
JB
3432
3433 ret = rdev_get_channel(rdev, wdev, &chandef);
3434 if (ret == 0) {
3435 if (nl80211_send_chandef(msg, &chandef))
3436 goto nla_put_failure;
3437 }
d91df0e3
PF
3438 }
3439
d55d0d59
RM
3440 if (rdev->ops->get_tx_power) {
3441 int dbm, ret;
3442
3443 ret = rdev_get_tx_power(rdev, wdev, &dbm);
3444 if (ret == 0 &&
3445 nla_put_u32(msg, NL80211_ATTR_WIPHY_TX_POWER_LEVEL,
3446 DBM_TO_MBM(dbm)))
3447 goto nla_put_failure;
3448 }
3449
44905265
JB
3450 wdev_lock(wdev);
3451 switch (wdev->iftype) {
3452 case NL80211_IFTYPE_AP:
3453 if (wdev->ssid_len &&
3454 nla_put(msg, NL80211_ATTR_SSID, wdev->ssid_len, wdev->ssid))
4564b187 3455 goto nla_put_failure_locked;
44905265
JB
3456 break;
3457 case NL80211_IFTYPE_STATION:
3458 case NL80211_IFTYPE_P2P_CLIENT:
3459 case NL80211_IFTYPE_ADHOC: {
3460 const u8 *ssid_ie;
3461 if (!wdev->current_bss)
3462 break;
7a94b8c2 3463 rcu_read_lock();
44905265
JB
3464 ssid_ie = ieee80211_bss_get_ie(&wdev->current_bss->pub,
3465 WLAN_EID_SSID);
7a94b8c2
DB
3466 if (ssid_ie &&
3467 nla_put(msg, NL80211_ATTR_SSID, ssid_ie[1], ssid_ie + 2))
3468 goto nla_put_failure_rcu_locked;
3469 rcu_read_unlock();
44905265
JB
3470 break;
3471 }
3472 default:
3473 /* nothing */
3474 break;
b84e7a05 3475 }
44905265 3476 wdev_unlock(wdev);
b84e7a05 3477
52539ca8
THJ
3478 if (rdev->ops->get_txq_stats) {
3479 struct cfg80211_txq_stats txqstats = {};
3480 int ret = rdev_get_txq_stats(rdev, wdev, &txqstats);
3481
3482 if (ret == 0 &&
3483 !nl80211_put_txq_stats(msg, &txqstats,
3484 NL80211_ATTR_TXQ_STATS))
3485 goto nla_put_failure;
3486 }
3487
053c095a
JB
3488 genlmsg_end(msg, hdr);
3489 return 0;
55682965 3490
7a94b8c2
DB
3491 nla_put_failure_rcu_locked:
3492 rcu_read_unlock();
4564b187
JB
3493 nla_put_failure_locked:
3494 wdev_unlock(wdev);
55682965 3495 nla_put_failure:
bc3ed28c
TG
3496 genlmsg_cancel(msg, hdr);
3497 return -EMSGSIZE;
55682965
JB
3498}
3499
3500static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *cb)
3501{
3502 int wp_idx = 0;
3503 int if_idx = 0;
3504 int wp_start = cb->args[0];
3505 int if_start = cb->args[1];
b7fb44da 3506 int filter_wiphy = -1;
f5ea9120 3507 struct cfg80211_registered_device *rdev;
55682965 3508 struct wireless_dev *wdev;
ea90e0dc 3509 int ret;
55682965 3510
5fe231e8 3511 rtnl_lock();
b7fb44da
DK
3512 if (!cb->args[2]) {
3513 struct nl80211_dump_wiphy_state state = {
3514 .filter_wiphy = -1,
3515 };
b7fb44da
DK
3516
3517 ret = nl80211_dump_wiphy_parse(skb, cb, &state);
3518 if (ret)
ea90e0dc 3519 goto out_unlock;
b7fb44da
DK
3520
3521 filter_wiphy = state.filter_wiphy;
3522
3523 /*
3524 * if filtering, set cb->args[2] to +1 since 0 is the default
3525 * value needed to determine that parsing is necessary.
3526 */
3527 if (filter_wiphy >= 0)
3528 cb->args[2] = filter_wiphy + 1;
3529 else
3530 cb->args[2] = -1;
3531 } else if (cb->args[2] > 0) {
3532 filter_wiphy = cb->args[2] - 1;
3533 }
3534
f5ea9120
JB
3535 list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
3536 if (!net_eq(wiphy_net(&rdev->wiphy), sock_net(skb->sk)))
463d0183 3537 continue;
bba95fef
JB
3538 if (wp_idx < wp_start) {
3539 wp_idx++;
55682965 3540 continue;
bba95fef 3541 }
b7fb44da
DK
3542
3543 if (filter_wiphy >= 0 && filter_wiphy != rdev->wiphy_idx)
3544 continue;
3545
55682965
JB
3546 if_idx = 0;
3547
53873f13 3548 list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
bba95fef
JB
3549 if (if_idx < if_start) {
3550 if_idx++;
55682965 3551 continue;
bba95fef 3552 }
15e47304 3553 if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).portid,
55682965 3554 cb->nlh->nlmsg_seq, NLM_F_MULTI,
3d1a5bbf
AZ
3555 rdev, wdev,
3556 NL80211_CMD_NEW_INTERFACE) < 0) {
bba95fef
JB
3557 goto out;
3558 }
3559 if_idx++;
55682965 3560 }
bba95fef
JB
3561
3562 wp_idx++;
55682965 3563 }
bba95fef 3564 out:
55682965
JB
3565 cb->args[0] = wp_idx;
3566 cb->args[1] = if_idx;
3567
ea90e0dc
JB
3568 ret = skb->len;
3569 out_unlock:
3570 rtnl_unlock();
3571
3572 return ret;
55682965
JB
3573}
3574
3575static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info)
3576{
3577 struct sk_buff *msg;
1b8ec87a 3578 struct cfg80211_registered_device *rdev = info->user_ptr[0];
72fb2abc 3579 struct wireless_dev *wdev = info->user_ptr[1];
55682965 3580
fd2120ca 3581 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
55682965 3582 if (!msg)
4c476991 3583 return -ENOMEM;
55682965 3584
15e47304 3585 if (nl80211_send_iface(msg, info->snd_portid, info->snd_seq, 0,
3d1a5bbf 3586 rdev, wdev, NL80211_CMD_NEW_INTERFACE) < 0) {
4c476991
JB
3587 nlmsg_free(msg);
3588 return -ENOBUFS;
3589 }
55682965 3590
134e6375 3591 return genlmsg_reply(msg, info);
55682965
JB
3592}
3593
66f7ac50
MW
3594static const struct nla_policy mntr_flags_policy[NL80211_MNTR_FLAG_MAX + 1] = {
3595 [NL80211_MNTR_FLAG_FCSFAIL] = { .type = NLA_FLAG },
3596 [NL80211_MNTR_FLAG_PLCPFAIL] = { .type = NLA_FLAG },
3597 [NL80211_MNTR_FLAG_CONTROL] = { .type = NLA_FLAG },
3598 [NL80211_MNTR_FLAG_OTHER_BSS] = { .type = NLA_FLAG },
3599 [NL80211_MNTR_FLAG_COOK_FRAMES] = { .type = NLA_FLAG },
e057d3c3 3600 [NL80211_MNTR_FLAG_ACTIVE] = { .type = NLA_FLAG },
66f7ac50
MW
3601};
3602
3603static int parse_monitor_flags(struct nlattr *nla, u32 *mntrflags)
3604{
3605 struct nlattr *flags[NL80211_MNTR_FLAG_MAX + 1];
3606 int flag;
3607
3608 *mntrflags = 0;
3609
3610 if (!nla)
3611 return -EINVAL;
3612
8cb08174 3613 if (nla_parse_nested_deprecated(flags, NL80211_MNTR_FLAG_MAX, nla, mntr_flags_policy, NULL))
66f7ac50
MW
3614 return -EINVAL;
3615
3616 for (flag = 1; flag <= NL80211_MNTR_FLAG_MAX; flag++)
3617 if (flags[flag])
3618 *mntrflags |= (1<<flag);
3619
818a986e
JB
3620 *mntrflags |= MONITOR_FLAG_CHANGED;
3621
66f7ac50
MW
3622 return 0;
3623}
3624
1db77596
JB
3625static int nl80211_parse_mon_options(struct cfg80211_registered_device *rdev,
3626 enum nl80211_iftype type,
3627 struct genl_info *info,
3628 struct vif_params *params)
3629{
3630 bool change = false;
3631 int err;
3632
3633 if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) {
3634 if (type != NL80211_IFTYPE_MONITOR)
3635 return -EINVAL;
3636
3637 err = parse_monitor_flags(info->attrs[NL80211_ATTR_MNTR_FLAGS],
3638 &params->flags);
3639 if (err)
3640 return err;
3641
3642 change = true;
3643 }
3644
3645 if (params->flags & MONITOR_FLAG_ACTIVE &&
3646 !(rdev->wiphy.features & NL80211_FEATURE_ACTIVE_MONITOR))
3647 return -EOPNOTSUPP;
3648
3649 if (info->attrs[NL80211_ATTR_MU_MIMO_GROUP_DATA]) {
3650 const u8 *mumimo_groups;
3651 u32 cap_flag = NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER;
3652
3653 if (type != NL80211_IFTYPE_MONITOR)
3654 return -EINVAL;
3655
3656 if (!wiphy_ext_feature_isset(&rdev->wiphy, cap_flag))
3657 return -EOPNOTSUPP;
3658
3659 mumimo_groups =
3660 nla_data(info->attrs[NL80211_ATTR_MU_MIMO_GROUP_DATA]);
3661
3662 /* bits 0 and 63 are reserved and must be zero */
4954601f
JB
3663 if ((mumimo_groups[0] & BIT(0)) ||
3664 (mumimo_groups[VHT_MUMIMO_GROUPS_DATA_LEN - 1] & BIT(7)))
1db77596
JB
3665 return -EINVAL;
3666
3667 params->vht_mumimo_groups = mumimo_groups;
3668 change = true;
3669 }
3670
3671 if (info->attrs[NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR]) {
3672 u32 cap_flag = NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER;
3673
3674 if (type != NL80211_IFTYPE_MONITOR)
3675 return -EINVAL;
3676
3677 if (!wiphy_ext_feature_isset(&rdev->wiphy, cap_flag))
3678 return -EOPNOTSUPP;
3679
3680 params->vht_mumimo_follow_addr =
3681 nla_data(info->attrs[NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR]);
3682 change = true;
3683 }
3684
3685 return change ? 1 : 0;
3686}
3687
9bc383de 3688static int nl80211_valid_4addr(struct cfg80211_registered_device *rdev,
ad4bb6f8
JB
3689 struct net_device *netdev, u8 use_4addr,
3690 enum nl80211_iftype iftype)
9bc383de 3691{
ad4bb6f8 3692 if (!use_4addr) {
2e92a2d0 3693 if (netdev && netif_is_bridge_port(netdev))
ad4bb6f8 3694 return -EBUSY;
9bc383de 3695 return 0;
ad4bb6f8 3696 }
9bc383de
JB
3697
3698 switch (iftype) {
3699 case NL80211_IFTYPE_AP_VLAN:
3700 if (rdev->wiphy.flags & WIPHY_FLAG_4ADDR_AP)
3701 return 0;
3702 break;
3703 case NL80211_IFTYPE_STATION:
3704 if (rdev->wiphy.flags & WIPHY_FLAG_4ADDR_STATION)
3705 return 0;
3706 break;
3707 default:
3708 break;
3709 }
3710
3711 return -EOPNOTSUPP;
3712}
3713
55682965
JB
3714static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
3715{
4c476991 3716 struct cfg80211_registered_device *rdev = info->user_ptr[0];
2ec600d6 3717 struct vif_params params;
e36d56b6 3718 int err;
04a773ad 3719 enum nl80211_iftype otype, ntype;
4c476991 3720 struct net_device *dev = info->user_ptr[1];
ac7f9cfa 3721 bool change = false;
55682965 3722
2ec600d6
LCC
3723 memset(&params, 0, sizeof(params));
3724
04a773ad 3725 otype = ntype = dev->ieee80211_ptr->iftype;
55682965 3726
723b038d 3727 if (info->attrs[NL80211_ATTR_IFTYPE]) {
ac7f9cfa 3728 ntype = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
04a773ad 3729 if (otype != ntype)
ac7f9cfa 3730 change = true;
723b038d
JB
3731 }
3732
92ffe055 3733 if (info->attrs[NL80211_ATTR_MESH_ID]) {
29cbe68c
JB
3734 struct wireless_dev *wdev = dev->ieee80211_ptr;
3735
4c476991
JB
3736 if (ntype != NL80211_IFTYPE_MESH_POINT)
3737 return -EINVAL;
29cbe68c
JB
3738 if (netif_running(dev))
3739 return -EBUSY;
3740
3741 wdev_lock(wdev);
3742 BUILD_BUG_ON(IEEE80211_MAX_SSID_LEN !=
3743 IEEE80211_MAX_MESH_ID_LEN);
3744 wdev->mesh_id_up_len =
3745 nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
3746 memcpy(wdev->ssid, nla_data(info->attrs[NL80211_ATTR_MESH_ID]),
3747 wdev->mesh_id_up_len);
3748 wdev_unlock(wdev);
2ec600d6
LCC
3749 }
3750
8b787643
FF
3751 if (info->attrs[NL80211_ATTR_4ADDR]) {
3752 params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]);
3753 change = true;
ad4bb6f8 3754 err = nl80211_valid_4addr(rdev, dev, params.use_4addr, ntype);
9bc383de 3755 if (err)
4c476991 3756 return err;
8b787643
FF
3757 } else {
3758 params.use_4addr = -1;
3759 }
3760
1db77596
JB
3761 err = nl80211_parse_mon_options(rdev, ntype, info, &params);
3762 if (err < 0)
3763 return err;
3764 if (err > 0)
c6e6a0c8 3765 change = true;
e057d3c3 3766
ac7f9cfa 3767 if (change)
818a986e 3768 err = cfg80211_change_iface(rdev, dev, ntype, &params);
ac7f9cfa
JB
3769 else
3770 err = 0;
60719ffd 3771
9bc383de
JB
3772 if (!err && params.use_4addr != -1)
3773 dev->ieee80211_ptr->use_4addr = params.use_4addr;
3774
3d1a5bbf
AZ
3775 if (change && !err) {
3776 struct wireless_dev *wdev = dev->ieee80211_ptr;
3777
3778 nl80211_notify_iface(rdev, wdev, NL80211_CMD_SET_INTERFACE);
3779 }
3780
55682965
JB
3781 return err;
3782}
3783
3784static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
3785{
4c476991 3786 struct cfg80211_registered_device *rdev = info->user_ptr[0];
2ec600d6 3787 struct vif_params params;
84efbb84 3788 struct wireless_dev *wdev;
896ff063 3789 struct sk_buff *msg;
55682965
JB
3790 int err;
3791 enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED;
3792
78f22b6a
JB
3793 /* to avoid failing a new interface creation due to pending removal */
3794 cfg80211_destroy_ifaces(rdev);
3795
2ec600d6
LCC
3796 memset(&params, 0, sizeof(params));
3797
55682965
JB
3798 if (!info->attrs[NL80211_ATTR_IFNAME])
3799 return -EINVAL;
3800
ab0d76f6 3801 if (info->attrs[NL80211_ATTR_IFTYPE])
55682965 3802 type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
55682965 3803
33d915d9 3804 if (!rdev->ops->add_virtual_intf)
4c476991 3805 return -EOPNOTSUPP;
55682965 3806
cb3b7d87 3807 if ((type == NL80211_IFTYPE_P2P_DEVICE || type == NL80211_IFTYPE_NAN ||
e8f479b1
BG
3808 rdev->wiphy.features & NL80211_FEATURE_MAC_ON_CREATE) &&
3809 info->attrs[NL80211_ATTR_MAC]) {
1c18f145
AS
3810 nla_memcpy(params.macaddr, info->attrs[NL80211_ATTR_MAC],
3811 ETH_ALEN);
3812 if (!is_valid_ether_addr(params.macaddr))
3813 return -EADDRNOTAVAIL;
3814 }
3815
9bc383de 3816 if (info->attrs[NL80211_ATTR_4ADDR]) {
8b787643 3817 params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]);
ad4bb6f8 3818 err = nl80211_valid_4addr(rdev, NULL, params.use_4addr, type);
9bc383de 3819 if (err)
4c476991 3820 return err;
9bc383de 3821 }
8b787643 3822
e6f40511 3823 if (!cfg80211_iftype_allowed(&rdev->wiphy, type, params.use_4addr, 0))
33d915d9
MP
3824 return -EOPNOTSUPP;
3825
1db77596
JB
3826 err = nl80211_parse_mon_options(rdev, type, info, &params);
3827 if (err < 0)
3828 return err;
e057d3c3 3829
a18c7192
JB
3830 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3831 if (!msg)
3832 return -ENOMEM;
3833
e35e4d28
HG
3834 wdev = rdev_add_virtual_intf(rdev,
3835 nla_data(info->attrs[NL80211_ATTR_IFNAME]),
818a986e 3836 NET_NAME_USER, type, &params);
d687cbb7
RM
3837 if (WARN_ON(!wdev)) {
3838 nlmsg_free(msg);
3839 return -EPROTO;
3840 } else if (IS_ERR(wdev)) {
1c90f9d4 3841 nlmsg_free(msg);
84efbb84 3842 return PTR_ERR(wdev);
1c90f9d4 3843 }
2ec600d6 3844
18e5ca65 3845 if (info->attrs[NL80211_ATTR_SOCKET_OWNER])
78f22b6a
JB
3846 wdev->owner_nlportid = info->snd_portid;
3847
98104fde
JB
3848 switch (type) {
3849 case NL80211_IFTYPE_MESH_POINT:
3850 if (!info->attrs[NL80211_ATTR_MESH_ID])
3851 break;
29cbe68c
JB
3852 wdev_lock(wdev);
3853 BUILD_BUG_ON(IEEE80211_MAX_SSID_LEN !=
3854 IEEE80211_MAX_MESH_ID_LEN);
3855 wdev->mesh_id_up_len =
3856 nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
3857 memcpy(wdev->ssid, nla_data(info->attrs[NL80211_ATTR_MESH_ID]),
3858 wdev->mesh_id_up_len);
3859 wdev_unlock(wdev);
98104fde 3860 break;
cb3b7d87 3861 case NL80211_IFTYPE_NAN:
98104fde
JB
3862 case NL80211_IFTYPE_P2P_DEVICE:
3863 /*
cb3b7d87 3864 * P2P Device and NAN do not have a netdev, so don't go
98104fde
JB
3865 * through the netdev notifier and must be added here
3866 */
e4d4216e 3867 cfg80211_init_wdev(rdev, wdev);
98104fde
JB
3868 break;
3869 default:
3870 break;
29cbe68c
JB
3871 }
3872
15e47304 3873 if (nl80211_send_iface(msg, info->snd_portid, info->snd_seq, 0,
3d1a5bbf 3874 rdev, wdev, NL80211_CMD_NEW_INTERFACE) < 0) {
1c90f9d4
JB
3875 nlmsg_free(msg);
3876 return -ENOBUFS;
3877 }
3878
3879 return genlmsg_reply(msg, info);
55682965
JB
3880}
3881
3882static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
3883{
4c476991 3884 struct cfg80211_registered_device *rdev = info->user_ptr[0];
84efbb84 3885 struct wireless_dev *wdev = info->user_ptr[1];
55682965 3886
4c476991
JB
3887 if (!rdev->ops->del_virtual_intf)
3888 return -EOPNOTSUPP;
55682965 3889
84efbb84
JB
3890 /*
3891 * If we remove a wireless device without a netdev then clear
3892 * user_ptr[1] so that nl80211_post_doit won't dereference it
3893 * to check if it needs to do dev_put(). Otherwise it crashes
3894 * since the wdev has been freed, unlike with a netdev where
3895 * we need the dev_put() for the netdev to really be freed.
3896 */
3897 if (!wdev->netdev)
3898 info->user_ptr[1] = NULL;
3899
7f8ed01e 3900 return rdev_del_virtual_intf(rdev, wdev);
55682965
JB
3901}
3902
1d9d9213
SW
3903static int nl80211_set_noack_map(struct sk_buff *skb, struct genl_info *info)
3904{
3905 struct cfg80211_registered_device *rdev = info->user_ptr[0];
3906 struct net_device *dev = info->user_ptr[1];
3907 u16 noack_map;
3908
3909 if (!info->attrs[NL80211_ATTR_NOACK_MAP])
3910 return -EINVAL;
3911
3912 if (!rdev->ops->set_noack_map)
3913 return -EOPNOTSUPP;
3914
3915 noack_map = nla_get_u16(info->attrs[NL80211_ATTR_NOACK_MAP]);
3916
e35e4d28 3917 return rdev_set_noack_map(rdev, dev, noack_map);
1d9d9213
SW
3918}
3919
41ade00f
JB
3920struct get_key_cookie {
3921 struct sk_buff *msg;
3922 int error;
b9454e83 3923 int idx;
41ade00f
JB
3924};
3925
3926static void get_key_callback(void *c, struct key_params *params)
3927{
b9454e83 3928 struct nlattr *key;
41ade00f
JB
3929 struct get_key_cookie *cookie = c;
3930
9360ffd1
DM
3931 if ((params->key &&
3932 nla_put(cookie->msg, NL80211_ATTR_KEY_DATA,
3933 params->key_len, params->key)) ||
3934 (params->seq &&
3935 nla_put(cookie->msg, NL80211_ATTR_KEY_SEQ,
3936 params->seq_len, params->seq)) ||
3937 (params->cipher &&
3938 nla_put_u32(cookie->msg, NL80211_ATTR_KEY_CIPHER,
3939 params->cipher)))
3940 goto nla_put_failure;
41ade00f 3941
ae0be8de 3942 key = nla_nest_start_noflag(cookie->msg, NL80211_ATTR_KEY);
b9454e83
JB
3943 if (!key)
3944 goto nla_put_failure;
3945
9360ffd1
DM
3946 if ((params->key &&
3947 nla_put(cookie->msg, NL80211_KEY_DATA,
3948 params->key_len, params->key)) ||
3949 (params->seq &&
3950 nla_put(cookie->msg, NL80211_KEY_SEQ,
3951 params->seq_len, params->seq)) ||
3952 (params->cipher &&
3953 nla_put_u32(cookie->msg, NL80211_KEY_CIPHER,
3954 params->cipher)))
3955 goto nla_put_failure;
b9454e83 3956
efdfce72 3957 if (nla_put_u8(cookie->msg, NL80211_KEY_IDX, cookie->idx))
9360ffd1 3958 goto nla_put_failure;
b9454e83
JB
3959
3960 nla_nest_end(cookie->msg, key);
3961
41ade00f
JB
3962 return;
3963 nla_put_failure:
3964 cookie->error = 1;
3965}
3966
3967static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
3968{
4c476991 3969 struct cfg80211_registered_device *rdev = info->user_ptr[0];
41ade00f 3970 int err;
4c476991 3971 struct net_device *dev = info->user_ptr[1];
41ade00f 3972 u8 key_idx = 0;
e31b8213
JB
3973 const u8 *mac_addr = NULL;
3974 bool pairwise;
41ade00f
JB
3975 struct get_key_cookie cookie = {
3976 .error = 0,
3977 };
3978 void *hdr;
3979 struct sk_buff *msg;
155d7c73
JB
3980 bool bigtk_support = false;
3981
3982 if (wiphy_ext_feature_isset(&rdev->wiphy,
3983 NL80211_EXT_FEATURE_BEACON_PROTECTION))
3984 bigtk_support = true;
3985
3986 if ((dev->ieee80211_ptr->iftype == NL80211_IFTYPE_STATION ||
3987 dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_CLIENT) &&
3988 wiphy_ext_feature_isset(&rdev->wiphy,
3989 NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT))
3990 bigtk_support = true;
41ade00f 3991
56be393f 3992 if (info->attrs[NL80211_ATTR_KEY_IDX]) {
41ade00f 3993 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
155d7c73
JB
3994
3995 if (key_idx >= 6 && key_idx <= 7 && !bigtk_support) {
3996 GENL_SET_ERR_MSG(info, "BIGTK not supported");
56be393f 3997 return -EINVAL;
155d7c73 3998 }
56be393f 3999 }
41ade00f 4000
41ade00f
JB
4001 if (info->attrs[NL80211_ATTR_MAC])
4002 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
4003
e31b8213
JB
4004 pairwise = !!mac_addr;
4005 if (info->attrs[NL80211_ATTR_KEY_TYPE]) {
4006 u32 kt = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]);
7a087e74 4007
e31b8213
JB
4008 if (kt != NL80211_KEYTYPE_GROUP &&
4009 kt != NL80211_KEYTYPE_PAIRWISE)
4010 return -EINVAL;
4011 pairwise = kt == NL80211_KEYTYPE_PAIRWISE;
4012 }
4013
4c476991
JB
4014 if (!rdev->ops->get_key)
4015 return -EOPNOTSUPP;
41ade00f 4016
0fa7b391
JB
4017 if (!pairwise && mac_addr && !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
4018 return -ENOENT;
4019
fd2120ca 4020 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4c476991
JB
4021 if (!msg)
4022 return -ENOMEM;
41ade00f 4023
15e47304 4024 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
41ade00f 4025 NL80211_CMD_NEW_KEY);
cb35fba3 4026 if (!hdr)
9fe271af 4027 goto nla_put_failure;
41ade00f
JB
4028
4029 cookie.msg = msg;
b9454e83 4030 cookie.idx = key_idx;
41ade00f 4031
9360ffd1
DM
4032 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
4033 nla_put_u8(msg, NL80211_ATTR_KEY_IDX, key_idx))
4034 goto nla_put_failure;
4035 if (mac_addr &&
4036 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr))
4037 goto nla_put_failure;
41ade00f 4038
e35e4d28
HG
4039 err = rdev_get_key(rdev, dev, key_idx, pairwise, mac_addr, &cookie,
4040 get_key_callback);
41ade00f
JB
4041
4042 if (err)
6c95e2a2 4043 goto free_msg;
41ade00f
JB
4044
4045 if (cookie.error)
4046 goto nla_put_failure;
4047
4048 genlmsg_end(msg, hdr);
4c476991 4049 return genlmsg_reply(msg, info);
41ade00f
JB
4050
4051 nla_put_failure:
4052 err = -ENOBUFS;
6c95e2a2 4053 free_msg:
41ade00f 4054 nlmsg_free(msg);
41ade00f
JB
4055 return err;
4056}
4057
4058static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
4059{
4c476991 4060 struct cfg80211_registered_device *rdev = info->user_ptr[0];
b9454e83 4061 struct key_parse key;
41ade00f 4062 int err;
4c476991 4063 struct net_device *dev = info->user_ptr[1];
41ade00f 4064
b9454e83
JB
4065 err = nl80211_parse_key(info, &key);
4066 if (err)
4067 return err;
41ade00f 4068
b9454e83 4069 if (key.idx < 0)
41ade00f
JB
4070 return -EINVAL;
4071
6cdd3979
AW
4072 /* Only support setting default key and
4073 * Extended Key ID action NL80211_KEY_SET_TX.
4074 */
56be393f 4075 if (!key.def && !key.defmgmt && !key.defbeacon &&
6cdd3979 4076 !(key.p.mode == NL80211_KEY_SET_TX))
41ade00f
JB
4077 return -EINVAL;
4078
dbd2fd65 4079 wdev_lock(dev->ieee80211_ptr);
3cfcf6ac 4080
dbd2fd65
JB
4081 if (key.def) {
4082 if (!rdev->ops->set_default_key) {
4083 err = -EOPNOTSUPP;
4084 goto out;
4085 }
41ade00f 4086
dbd2fd65
JB
4087 err = nl80211_key_allowed(dev->ieee80211_ptr);
4088 if (err)
4089 goto out;
4090
e35e4d28 4091 err = rdev_set_default_key(rdev, dev, key.idx,
dbd2fd65
JB
4092 key.def_uni, key.def_multi);
4093
4094 if (err)
4095 goto out;
fffd0934 4096
3d23e349 4097#ifdef CONFIG_CFG80211_WEXT
dbd2fd65
JB
4098 dev->ieee80211_ptr->wext.default_key = key.idx;
4099#endif
6cdd3979 4100 } else if (key.defmgmt) {
dbd2fd65
JB
4101 if (key.def_uni || !key.def_multi) {
4102 err = -EINVAL;
4103 goto out;
4104 }
4105
4106 if (!rdev->ops->set_default_mgmt_key) {
4107 err = -EOPNOTSUPP;
4108 goto out;
4109 }
4110
4111 err = nl80211_key_allowed(dev->ieee80211_ptr);
4112 if (err)
4113 goto out;
4114
e35e4d28 4115 err = rdev_set_default_mgmt_key(rdev, dev, key.idx);
dbd2fd65
JB
4116 if (err)
4117 goto out;
4118
4119#ifdef CONFIG_CFG80211_WEXT
4120 dev->ieee80211_ptr->wext.default_mgmt_key = key.idx;
08645126 4121#endif
56be393f
JM
4122 } else if (key.defbeacon) {
4123 if (key.def_uni || !key.def_multi) {
4124 err = -EINVAL;
4125 goto out;
4126 }
4127
4128 if (!rdev->ops->set_default_beacon_key) {
4129 err = -EOPNOTSUPP;
4130 goto out;
4131 }
4132
4133 err = nl80211_key_allowed(dev->ieee80211_ptr);
4134 if (err)
4135 goto out;
4136
4137 err = rdev_set_default_beacon_key(rdev, dev, key.idx);
4138 if (err)
4139 goto out;
6cdd3979
AW
4140 } else if (key.p.mode == NL80211_KEY_SET_TX &&
4141 wiphy_ext_feature_isset(&rdev->wiphy,
4142 NL80211_EXT_FEATURE_EXT_KEY_ID)) {
4143 u8 *mac_addr = NULL;
4144
4145 if (info->attrs[NL80211_ATTR_MAC])
4146 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
4147
4148 if (!mac_addr || key.idx < 0 || key.idx > 1) {
4149 err = -EINVAL;
4150 goto out;
4151 }
dbd2fd65 4152
6cdd3979
AW
4153 err = rdev_add_key(rdev, dev, key.idx,
4154 NL80211_KEYTYPE_PAIRWISE,
4155 mac_addr, &key.p);
4156 } else {
4157 err = -EINVAL;
4158 }
dbd2fd65 4159 out:
fffd0934 4160 wdev_unlock(dev->ieee80211_ptr);
41ade00f 4161
41ade00f
JB
4162 return err;
4163}
4164
4165static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
4166{
4c476991 4167 struct cfg80211_registered_device *rdev = info->user_ptr[0];
fffd0934 4168 int err;
4c476991 4169 struct net_device *dev = info->user_ptr[1];
b9454e83 4170 struct key_parse key;
e31b8213 4171 const u8 *mac_addr = NULL;
41ade00f 4172
b9454e83
JB
4173 err = nl80211_parse_key(info, &key);
4174 if (err)
4175 return err;
41ade00f 4176
f8af764b
JM
4177 if (!key.p.key) {
4178 GENL_SET_ERR_MSG(info, "no key");
41ade00f 4179 return -EINVAL;
f8af764b 4180 }
41ade00f 4181
41ade00f
JB
4182 if (info->attrs[NL80211_ATTR_MAC])
4183 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
4184
e31b8213
JB
4185 if (key.type == -1) {
4186 if (mac_addr)
4187 key.type = NL80211_KEYTYPE_PAIRWISE;
4188 else
4189 key.type = NL80211_KEYTYPE_GROUP;
4190 }
4191
4192 /* for now */
4193 if (key.type != NL80211_KEYTYPE_PAIRWISE &&
f8af764b
JM
4194 key.type != NL80211_KEYTYPE_GROUP) {
4195 GENL_SET_ERR_MSG(info, "key type not pairwise or group");
e31b8213 4196 return -EINVAL;
f8af764b 4197 }
e31b8213 4198
14f34e36
GG
4199 if (key.type == NL80211_KEYTYPE_GROUP &&
4200 info->attrs[NL80211_ATTR_VLAN_ID])
4201 key.p.vlan_id = nla_get_u16(info->attrs[NL80211_ATTR_VLAN_ID]);
4202
4c476991
JB
4203 if (!rdev->ops->add_key)
4204 return -EOPNOTSUPP;
25e47c18 4205
e31b8213
JB
4206 if (cfg80211_validate_key_settings(rdev, &key.p, key.idx,
4207 key.type == NL80211_KEYTYPE_PAIRWISE,
f8af764b
JM
4208 mac_addr)) {
4209 GENL_SET_ERR_MSG(info, "key setting validation failed");
4c476991 4210 return -EINVAL;
f8af764b 4211 }
41ade00f 4212
fffd0934
JB
4213 wdev_lock(dev->ieee80211_ptr);
4214 err = nl80211_key_allowed(dev->ieee80211_ptr);
f8af764b
JM
4215 if (err)
4216 GENL_SET_ERR_MSG(info, "key not allowed");
4217 if (!err) {
e35e4d28
HG
4218 err = rdev_add_key(rdev, dev, key.idx,
4219 key.type == NL80211_KEYTYPE_PAIRWISE,
4220 mac_addr, &key.p);
f8af764b
JM
4221 if (err)
4222 GENL_SET_ERR_MSG(info, "key addition failed");
4223 }
fffd0934 4224 wdev_unlock(dev->ieee80211_ptr);
41ade00f 4225
41ade00f
JB
4226 return err;
4227}
4228
4229static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
4230{
4c476991 4231 struct cfg80211_registered_device *rdev = info->user_ptr[0];
41ade00f 4232 int err;
4c476991 4233 struct net_device *dev = info->user_ptr[1];
41ade00f 4234 u8 *mac_addr = NULL;
b9454e83 4235 struct key_parse key;
41ade00f 4236
b9454e83
JB
4237 err = nl80211_parse_key(info, &key);
4238 if (err)
4239 return err;
41ade00f
JB
4240
4241 if (info->attrs[NL80211_ATTR_MAC])
4242 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
4243
e31b8213
JB
4244 if (key.type == -1) {
4245 if (mac_addr)
4246 key.type = NL80211_KEYTYPE_PAIRWISE;
4247 else
4248 key.type = NL80211_KEYTYPE_GROUP;
4249 }
4250
4251 /* for now */
4252 if (key.type != NL80211_KEYTYPE_PAIRWISE &&
4253 key.type != NL80211_KEYTYPE_GROUP)
4254 return -EINVAL;
4255
4c476991
JB
4256 if (!rdev->ops->del_key)
4257 return -EOPNOTSUPP;
41ade00f 4258
fffd0934
JB
4259 wdev_lock(dev->ieee80211_ptr);
4260 err = nl80211_key_allowed(dev->ieee80211_ptr);
e31b8213 4261
0fa7b391 4262 if (key.type == NL80211_KEYTYPE_GROUP && mac_addr &&
e31b8213
JB
4263 !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
4264 err = -ENOENT;
4265
fffd0934 4266 if (!err)
e35e4d28
HG
4267 err = rdev_del_key(rdev, dev, key.idx,
4268 key.type == NL80211_KEYTYPE_PAIRWISE,
4269 mac_addr);
41ade00f 4270
3d23e349 4271#ifdef CONFIG_CFG80211_WEXT
08645126 4272 if (!err) {
b9454e83 4273 if (key.idx == dev->ieee80211_ptr->wext.default_key)
08645126 4274 dev->ieee80211_ptr->wext.default_key = -1;
b9454e83 4275 else if (key.idx == dev->ieee80211_ptr->wext.default_mgmt_key)
08645126
JB
4276 dev->ieee80211_ptr->wext.default_mgmt_key = -1;
4277 }
4278#endif
fffd0934 4279 wdev_unlock(dev->ieee80211_ptr);
08645126 4280
41ade00f
JB
4281 return err;
4282}
4283
77765eaf
VT
4284/* This function returns an error or the number of nested attributes */
4285static int validate_acl_mac_addrs(struct nlattr *nl_attr)
4286{
4287 struct nlattr *attr;
4288 int n_entries = 0, tmp;
4289
4290 nla_for_each_nested(attr, nl_attr, tmp) {
4291 if (nla_len(attr) != ETH_ALEN)
4292 return -EINVAL;
4293
4294 n_entries++;
4295 }
4296
4297 return n_entries;
4298}
4299
4300/*
4301 * This function parses ACL information and allocates memory for ACL data.
4302 * On successful return, the calling function is responsible to free the
4303 * ACL buffer returned by this function.
4304 */
4305static struct cfg80211_acl_data *parse_acl_data(struct wiphy *wiphy,
4306 struct genl_info *info)
4307{
4308 enum nl80211_acl_policy acl_policy;
4309 struct nlattr *attr;
4310 struct cfg80211_acl_data *acl;
4311 int i = 0, n_entries, tmp;
4312
4313 if (!wiphy->max_acl_mac_addrs)
4314 return ERR_PTR(-EOPNOTSUPP);
4315
4316 if (!info->attrs[NL80211_ATTR_ACL_POLICY])
4317 return ERR_PTR(-EINVAL);
4318
4319 acl_policy = nla_get_u32(info->attrs[NL80211_ATTR_ACL_POLICY]);
4320 if (acl_policy != NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED &&
4321 acl_policy != NL80211_ACL_POLICY_DENY_UNLESS_LISTED)
4322 return ERR_PTR(-EINVAL);
4323
4324 if (!info->attrs[NL80211_ATTR_MAC_ADDRS])
4325 return ERR_PTR(-EINVAL);
4326
4327 n_entries = validate_acl_mac_addrs(info->attrs[NL80211_ATTR_MAC_ADDRS]);
4328 if (n_entries < 0)
4329 return ERR_PTR(n_entries);
4330
4331 if (n_entries > wiphy->max_acl_mac_addrs)
4332 return ERR_PTR(-ENOTSUPP);
4333
391d132c 4334 acl = kzalloc(struct_size(acl, mac_addrs, n_entries), GFP_KERNEL);
77765eaf
VT
4335 if (!acl)
4336 return ERR_PTR(-ENOMEM);
4337
4338 nla_for_each_nested(attr, info->attrs[NL80211_ATTR_MAC_ADDRS], tmp) {
4339 memcpy(acl->mac_addrs[i].addr, nla_data(attr), ETH_ALEN);
4340 i++;
4341 }
4342
4343 acl->n_acl_entries = n_entries;
4344 acl->acl_policy = acl_policy;
4345
4346 return acl;
4347}
4348
4349static int nl80211_set_mac_acl(struct sk_buff *skb, struct genl_info *info)
4350{
4351 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4352 struct net_device *dev = info->user_ptr[1];
4353 struct cfg80211_acl_data *acl;
4354 int err;
4355
4356 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
4357 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
4358 return -EOPNOTSUPP;
4359
4360 if (!dev->ieee80211_ptr->beacon_interval)
4361 return -EINVAL;
4362
4363 acl = parse_acl_data(&rdev->wiphy, info);
4364 if (IS_ERR(acl))
4365 return PTR_ERR(acl);
4366
4367 err = rdev_set_mac_acl(rdev, dev, acl);
4368
4369 kfree(acl);
4370
4371 return err;
4372}
4373
a7c7fbff
PK
4374static u32 rateset_to_mask(struct ieee80211_supported_band *sband,
4375 u8 *rates, u8 rates_len)
4376{
4377 u8 i;
4378 u32 mask = 0;
4379
4380 for (i = 0; i < rates_len; i++) {
4381 int rate = (rates[i] & 0x7f) * 5;
4382 int ridx;
4383
4384 for (ridx = 0; ridx < sband->n_bitrates; ridx++) {
4385 struct ieee80211_rate *srate =
4386 &sband->bitrates[ridx];
4387 if (rate == srate->bitrate) {
4388 mask |= 1 << ridx;
4389 break;
4390 }
4391 }
4392 if (ridx == sband->n_bitrates)
4393 return 0; /* rate not found */
4394 }
4395
4396 return mask;
4397}
4398
4399static bool ht_rateset_to_mask(struct ieee80211_supported_band *sband,
4400 u8 *rates, u8 rates_len,
4401 u8 mcs[IEEE80211_HT_MCS_MASK_LEN])
4402{
4403 u8 i;
4404
4405 memset(mcs, 0, IEEE80211_HT_MCS_MASK_LEN);
4406
4407 for (i = 0; i < rates_len; i++) {
4408 int ridx, rbit;
4409
4410 ridx = rates[i] / 8;
4411 rbit = BIT(rates[i] % 8);
4412
4413 /* check validity */
4414 if ((ridx < 0) || (ridx >= IEEE80211_HT_MCS_MASK_LEN))
4415 return false;
4416
4417 /* check availability */
30fe6d50 4418 ridx = array_index_nospec(ridx, IEEE80211_HT_MCS_MASK_LEN);
a7c7fbff
PK
4419 if (sband->ht_cap.mcs.rx_mask[ridx] & rbit)
4420 mcs[ridx] |= rbit;
4421 else
4422 return false;
4423 }
4424
4425 return true;
4426}
4427
4428static u16 vht_mcs_map_to_mcs_mask(u8 vht_mcs_map)
4429{
4430 u16 mcs_mask = 0;
4431
4432 switch (vht_mcs_map) {
4433 case IEEE80211_VHT_MCS_NOT_SUPPORTED:
4434 break;
4435 case IEEE80211_VHT_MCS_SUPPORT_0_7:
4436 mcs_mask = 0x00FF;
4437 break;
4438 case IEEE80211_VHT_MCS_SUPPORT_0_8:
4439 mcs_mask = 0x01FF;
4440 break;
4441 case IEEE80211_VHT_MCS_SUPPORT_0_9:
4442 mcs_mask = 0x03FF;
4443 break;
4444 default:
4445 break;
4446 }
4447
4448 return mcs_mask;
4449}
4450
4451static void vht_build_mcs_mask(u16 vht_mcs_map,
4452 u16 vht_mcs_mask[NL80211_VHT_NSS_MAX])
4453{
4454 u8 nss;
4455
4456 for (nss = 0; nss < NL80211_VHT_NSS_MAX; nss++) {
4457 vht_mcs_mask[nss] = vht_mcs_map_to_mcs_mask(vht_mcs_map & 0x03);
4458 vht_mcs_map >>= 2;
4459 }
4460}
4461
4462static bool vht_set_mcs_mask(struct ieee80211_supported_band *sband,
4463 struct nl80211_txrate_vht *txrate,
4464 u16 mcs[NL80211_VHT_NSS_MAX])
4465{
4466 u16 tx_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map);
4467 u16 tx_mcs_mask[NL80211_VHT_NSS_MAX] = {};
4468 u8 i;
4469
4470 if (!sband->vht_cap.vht_supported)
4471 return false;
4472
4473 memset(mcs, 0, sizeof(u16) * NL80211_VHT_NSS_MAX);
4474
4475 /* Build vht_mcs_mask from VHT capabilities */
4476 vht_build_mcs_mask(tx_mcs_map, tx_mcs_mask);
4477
4478 for (i = 0; i < NL80211_VHT_NSS_MAX; i++) {
4479 if ((tx_mcs_mask[i] & txrate->mcs[i]) == txrate->mcs[i])
4480 mcs[i] = txrate->mcs[i];
4481 else
4482 return false;
4483 }
4484
4485 return true;
4486}
4487
eb89a6a6
MH
4488static u16 he_mcs_map_to_mcs_mask(u8 he_mcs_map)
4489{
4490 switch (he_mcs_map) {
4491 case IEEE80211_HE_MCS_NOT_SUPPORTED:
4492 return 0;
4493 case IEEE80211_HE_MCS_SUPPORT_0_7:
4494 return 0x00FF;
4495 case IEEE80211_HE_MCS_SUPPORT_0_9:
4496 return 0x03FF;
4497 case IEEE80211_HE_MCS_SUPPORT_0_11:
4498 return 0xFFF;
4499 default:
4500 break;
4501 }
4502 return 0;
4503}
4504
4505static void he_build_mcs_mask(u16 he_mcs_map,
4506 u16 he_mcs_mask[NL80211_HE_NSS_MAX])
4507{
4508 u8 nss;
4509
4510 for (nss = 0; nss < NL80211_HE_NSS_MAX; nss++) {
4511 he_mcs_mask[nss] = he_mcs_map_to_mcs_mask(he_mcs_map & 0x03);
4512 he_mcs_map >>= 2;
4513 }
4514}
4515
4516static u16 he_get_txmcsmap(struct genl_info *info,
4517 const struct ieee80211_sta_he_cap *he_cap)
4518{
4519 struct net_device *dev = info->user_ptr[1];
4520 struct wireless_dev *wdev = dev->ieee80211_ptr;
4521 __le16 tx_mcs;
4522
4523 switch (wdev->chandef.width) {
4524 case NL80211_CHAN_WIDTH_80P80:
4525 tx_mcs = he_cap->he_mcs_nss_supp.tx_mcs_80p80;
4526 break;
4527 case NL80211_CHAN_WIDTH_160:
4528 tx_mcs = he_cap->he_mcs_nss_supp.tx_mcs_160;
4529 break;
4530 default:
4531 tx_mcs = he_cap->he_mcs_nss_supp.tx_mcs_80;
4532 break;
4533 }
4534 return le16_to_cpu(tx_mcs);
4535}
4536
4537static bool he_set_mcs_mask(struct genl_info *info,
4538 struct wireless_dev *wdev,
4539 struct ieee80211_supported_band *sband,
4540 struct nl80211_txrate_he *txrate,
4541 u16 mcs[NL80211_HE_NSS_MAX])
4542{
4543 const struct ieee80211_sta_he_cap *he_cap;
4544 u16 tx_mcs_mask[NL80211_HE_NSS_MAX] = {};
4545 u16 tx_mcs_map = 0;
4546 u8 i;
4547
4548 he_cap = ieee80211_get_he_iftype_cap(sband, wdev->iftype);
4549 if (!he_cap)
4550 return false;
4551
4552 memset(mcs, 0, sizeof(u16) * NL80211_HE_NSS_MAX);
4553
4554 tx_mcs_map = he_get_txmcsmap(info, he_cap);
4555
4556 /* Build he_mcs_mask from HE capabilities */
4557 he_build_mcs_mask(tx_mcs_map, tx_mcs_mask);
4558
4559 for (i = 0; i < NL80211_HE_NSS_MAX; i++) {
4560 if ((tx_mcs_mask[i] & txrate->mcs[i]) == txrate->mcs[i])
4561 mcs[i] = txrate->mcs[i];
4562 else
4563 return false;
4564 }
4565
4566 return true;
4567}
4568
a7c7fbff 4569static int nl80211_parse_tx_bitrate_mask(struct genl_info *info,
9a5f6488
TC
4570 struct nlattr *attrs[],
4571 enum nl80211_attrs attr,
eb89a6a6
MH
4572 struct cfg80211_bitrate_mask *mask,
4573 struct net_device *dev)
a7c7fbff
PK
4574{
4575 struct nlattr *tb[NL80211_TXRATE_MAX + 1];
4576 struct cfg80211_registered_device *rdev = info->user_ptr[0];
eb89a6a6 4577 struct wireless_dev *wdev = dev->ieee80211_ptr;
a7c7fbff
PK
4578 int rem, i;
4579 struct nlattr *tx_rates;
4580 struct ieee80211_supported_band *sband;
eb89a6a6 4581 u16 vht_tx_mcs_map, he_tx_mcs_map;
a7c7fbff
PK
4582
4583 memset(mask, 0, sizeof(*mask));
4584 /* Default to all rates enabled */
4585 for (i = 0; i < NUM_NL80211_BANDS; i++) {
eb89a6a6
MH
4586 const struct ieee80211_sta_he_cap *he_cap;
4587
a7c7fbff
PK
4588 sband = rdev->wiphy.bands[i];
4589
4590 if (!sband)
4591 continue;
4592
4593 mask->control[i].legacy = (1 << sband->n_bitrates) - 1;
4594 memcpy(mask->control[i].ht_mcs,
4595 sband->ht_cap.mcs.rx_mask,
4596 sizeof(mask->control[i].ht_mcs));
4597
4598 if (!sband->vht_cap.vht_supported)
4599 continue;
4600
4601 vht_tx_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map);
4602 vht_build_mcs_mask(vht_tx_mcs_map, mask->control[i].vht_mcs);
eb89a6a6
MH
4603
4604 he_cap = ieee80211_get_he_iftype_cap(sband, wdev->iftype);
4605 if (!he_cap)
4606 continue;
4607
4608 he_tx_mcs_map = he_get_txmcsmap(info, he_cap);
4609 he_build_mcs_mask(he_tx_mcs_map, mask->control[i].he_mcs);
4610
4611 mask->control[i].he_gi = 0xFF;
4612 mask->control[i].he_ltf = 0xFF;
a7c7fbff
PK
4613 }
4614
4615 /* if no rates are given set it back to the defaults */
9a5f6488 4616 if (!attrs[attr])
a7c7fbff
PK
4617 goto out;
4618
4619 /* The nested attribute uses enum nl80211_band as the index. This maps
4620 * directly to the enum nl80211_band values used in cfg80211.
4621 */
4622 BUILD_BUG_ON(NL80211_MAX_SUPP_HT_RATES > IEEE80211_HT_MCS_MASK_LEN * 8);
9a5f6488 4623 nla_for_each_nested(tx_rates, attrs[attr], rem) {
a7c7fbff
PK
4624 enum nl80211_band band = nla_type(tx_rates);
4625 int err;
4626
4627 if (band < 0 || band >= NUM_NL80211_BANDS)
4628 return -EINVAL;
4629 sband = rdev->wiphy.bands[band];
4630 if (sband == NULL)
4631 return -EINVAL;
8cb08174
JB
4632 err = nla_parse_nested_deprecated(tb, NL80211_TXRATE_MAX,
4633 tx_rates,
4634 nl80211_txattr_policy,
4635 info->extack);
a7c7fbff
PK
4636 if (err)
4637 return err;
4638 if (tb[NL80211_TXRATE_LEGACY]) {
4639 mask->control[band].legacy = rateset_to_mask(
4640 sband,
4641 nla_data(tb[NL80211_TXRATE_LEGACY]),
4642 nla_len(tb[NL80211_TXRATE_LEGACY]));
4643 if ((mask->control[band].legacy == 0) &&
4644 nla_len(tb[NL80211_TXRATE_LEGACY]))
4645 return -EINVAL;
4646 }
4647 if (tb[NL80211_TXRATE_HT]) {
4648 if (!ht_rateset_to_mask(
4649 sband,
4650 nla_data(tb[NL80211_TXRATE_HT]),
4651 nla_len(tb[NL80211_TXRATE_HT]),
4652 mask->control[band].ht_mcs))
4653 return -EINVAL;
4654 }
4655 if (tb[NL80211_TXRATE_VHT]) {
4656 if (!vht_set_mcs_mask(
4657 sband,
4658 nla_data(tb[NL80211_TXRATE_VHT]),
4659 mask->control[band].vht_mcs))
4660 return -EINVAL;
4661 }
4662 if (tb[NL80211_TXRATE_GI]) {
4663 mask->control[band].gi =
4664 nla_get_u8(tb[NL80211_TXRATE_GI]);
4665 if (mask->control[band].gi > NL80211_TXRATE_FORCE_LGI)
4666 return -EINVAL;
4667 }
eb89a6a6
MH
4668 if (tb[NL80211_TXRATE_HE] &&
4669 !he_set_mcs_mask(info, wdev, sband,
4670 nla_data(tb[NL80211_TXRATE_HE]),
4671 mask->control[band].he_mcs))
4672 return -EINVAL;
4673 if (tb[NL80211_TXRATE_HE_GI])
4674 mask->control[band].he_gi =
4675 nla_get_u8(tb[NL80211_TXRATE_HE_GI]);
4676 if (tb[NL80211_TXRATE_HE_LTF])
4677 mask->control[band].he_ltf =
4678 nla_get_u8(tb[NL80211_TXRATE_HE_LTF]);
a7c7fbff
PK
4679
4680 if (mask->control[band].legacy == 0) {
eb89a6a6 4681 /* don't allow empty legacy rates if HT, VHT or HE
a7c7fbff
PK
4682 * are not even supported.
4683 */
4684 if (!(rdev->wiphy.bands[band]->ht_cap.ht_supported ||
eb89a6a6
MH
4685 rdev->wiphy.bands[band]->vht_cap.vht_supported ||
4686 ieee80211_get_he_iftype_cap(sband, wdev->iftype)))
a7c7fbff
PK
4687 return -EINVAL;
4688
4689 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++)
4690 if (mask->control[band].ht_mcs[i])
4691 goto out;
4692
4693 for (i = 0; i < NL80211_VHT_NSS_MAX; i++)
4694 if (mask->control[band].vht_mcs[i])
4695 goto out;
4696
eb89a6a6
MH
4697 for (i = 0; i < NL80211_HE_NSS_MAX; i++)
4698 if (mask->control[band].he_mcs[i])
4699 goto out;
4700
a7c7fbff
PK
4701 /* legacy and mcs rates may not be both empty */
4702 return -EINVAL;
4703 }
4704 }
4705
4706out:
4707 return 0;
4708}
4709
8564e382
JB
4710static int validate_beacon_tx_rate(struct cfg80211_registered_device *rdev,
4711 enum nl80211_band band,
4712 struct cfg80211_bitrate_mask *beacon_rate)
a7c7fbff 4713{
8564e382
JB
4714 u32 count_ht, count_vht, i;
4715 u32 rate = beacon_rate->control[band].legacy;
a7c7fbff
PK
4716
4717 /* Allow only one rate */
4718 if (hweight32(rate) > 1)
4719 return -EINVAL;
4720
4721 count_ht = 0;
4722 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
8564e382 4723 if (hweight8(beacon_rate->control[band].ht_mcs[i]) > 1) {
a7c7fbff 4724 return -EINVAL;
8564e382 4725 } else if (beacon_rate->control[band].ht_mcs[i]) {
a7c7fbff
PK
4726 count_ht++;
4727 if (count_ht > 1)
4728 return -EINVAL;
4729 }
4730 if (count_ht && rate)
4731 return -EINVAL;
4732 }
4733
4734 count_vht = 0;
4735 for (i = 0; i < NL80211_VHT_NSS_MAX; i++) {
8564e382 4736 if (hweight16(beacon_rate->control[band].vht_mcs[i]) > 1) {
a7c7fbff 4737 return -EINVAL;
8564e382 4738 } else if (beacon_rate->control[band].vht_mcs[i]) {
a7c7fbff
PK
4739 count_vht++;
4740 if (count_vht > 1)
4741 return -EINVAL;
4742 }
4743 if (count_vht && rate)
4744 return -EINVAL;
4745 }
4746
4747 if ((count_ht && count_vht) || (!rate && !count_ht && !count_vht))
4748 return -EINVAL;
4749
8564e382
JB
4750 if (rate &&
4751 !wiphy_ext_feature_isset(&rdev->wiphy,
4752 NL80211_EXT_FEATURE_BEACON_RATE_LEGACY))
4753 return -EINVAL;
4754 if (count_ht &&
4755 !wiphy_ext_feature_isset(&rdev->wiphy,
4756 NL80211_EXT_FEATURE_BEACON_RATE_HT))
4757 return -EINVAL;
4758 if (count_vht &&
4759 !wiphy_ext_feature_isset(&rdev->wiphy,
4760 NL80211_EXT_FEATURE_BEACON_RATE_VHT))
4761 return -EINVAL;
4762
a7c7fbff
PK
4763 return 0;
4764}
4765
81e54d08
PKC
4766static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev,
4767 struct nlattr *attrs[],
8860020e 4768 struct cfg80211_beacon_data *bcn)
ed1b6cc7 4769{
8860020e 4770 bool haveinfo = false;
81e54d08 4771 int err;
ed1b6cc7 4772
8860020e 4773 memset(bcn, 0, sizeof(*bcn));
ed1b6cc7 4774
a1193be8
SW
4775 if (attrs[NL80211_ATTR_BEACON_HEAD]) {
4776 bcn->head = nla_data(attrs[NL80211_ATTR_BEACON_HEAD]);
4777 bcn->head_len = nla_len(attrs[NL80211_ATTR_BEACON_HEAD]);
8860020e
JB
4778 if (!bcn->head_len)
4779 return -EINVAL;
4780 haveinfo = true;
ed1b6cc7
JB
4781 }
4782
a1193be8
SW
4783 if (attrs[NL80211_ATTR_BEACON_TAIL]) {
4784 bcn->tail = nla_data(attrs[NL80211_ATTR_BEACON_TAIL]);
4785 bcn->tail_len = nla_len(attrs[NL80211_ATTR_BEACON_TAIL]);
8860020e 4786 haveinfo = true;
ed1b6cc7
JB
4787 }
4788
4c476991
JB
4789 if (!haveinfo)
4790 return -EINVAL;
3b85875a 4791
a1193be8
SW
4792 if (attrs[NL80211_ATTR_IE]) {
4793 bcn->beacon_ies = nla_data(attrs[NL80211_ATTR_IE]);
4794 bcn->beacon_ies_len = nla_len(attrs[NL80211_ATTR_IE]);
9946ecfb
JM
4795 }
4796
a1193be8 4797 if (attrs[NL80211_ATTR_IE_PROBE_RESP]) {
8860020e 4798 bcn->proberesp_ies =
a1193be8 4799 nla_data(attrs[NL80211_ATTR_IE_PROBE_RESP]);
8860020e 4800 bcn->proberesp_ies_len =
a1193be8 4801 nla_len(attrs[NL80211_ATTR_IE_PROBE_RESP]);
9946ecfb
JM
4802 }
4803
a1193be8 4804 if (attrs[NL80211_ATTR_IE_ASSOC_RESP]) {
8860020e 4805 bcn->assocresp_ies =
a1193be8 4806 nla_data(attrs[NL80211_ATTR_IE_ASSOC_RESP]);
8860020e 4807 bcn->assocresp_ies_len =
a1193be8 4808 nla_len(attrs[NL80211_ATTR_IE_ASSOC_RESP]);
9946ecfb
JM
4809 }
4810
a1193be8
SW
4811 if (attrs[NL80211_ATTR_PROBE_RESP]) {
4812 bcn->probe_resp = nla_data(attrs[NL80211_ATTR_PROBE_RESP]);
4813 bcn->probe_resp_len = nla_len(attrs[NL80211_ATTR_PROBE_RESP]);
00f740e1
AN
4814 }
4815
81e54d08
PKC
4816 if (attrs[NL80211_ATTR_FTM_RESPONDER]) {
4817 struct nlattr *tb[NL80211_FTM_RESP_ATTR_MAX + 1];
4818
8cb08174
JB
4819 err = nla_parse_nested_deprecated(tb,
4820 NL80211_FTM_RESP_ATTR_MAX,
4821 attrs[NL80211_ATTR_FTM_RESPONDER],
4822 NULL, NULL);
81e54d08
PKC
4823 if (err)
4824 return err;
4825
4826 if (tb[NL80211_FTM_RESP_ATTR_ENABLED] &&
4827 wiphy_ext_feature_isset(&rdev->wiphy,
4828 NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER))
4829 bcn->ftm_responder = 1;
4830 else
4831 return -EOPNOTSUPP;
4832
4833 if (tb[NL80211_FTM_RESP_ATTR_LCI]) {
4834 bcn->lci = nla_data(tb[NL80211_FTM_RESP_ATTR_LCI]);
4835 bcn->lci_len = nla_len(tb[NL80211_FTM_RESP_ATTR_LCI]);
4836 }
4837
4838 if (tb[NL80211_FTM_RESP_ATTR_CIVICLOC]) {
4839 bcn->civicloc = nla_data(tb[NL80211_FTM_RESP_ATTR_CIVICLOC]);
4840 bcn->civicloc_len = nla_len(tb[NL80211_FTM_RESP_ATTR_CIVICLOC]);
4841 }
4842 } else {
4843 bcn->ftm_responder = -1;
4844 }
4845
8860020e
JB
4846 return 0;
4847}
4848
796e90f4
JC
4849static int nl80211_parse_he_obss_pd(struct nlattr *attrs,
4850 struct ieee80211_he_obss_pd *he_obss_pd)
4851{
4852 struct nlattr *tb[NL80211_HE_OBSS_PD_ATTR_MAX + 1];
4853 int err;
4854
4855 err = nla_parse_nested(tb, NL80211_HE_OBSS_PD_ATTR_MAX, attrs,
4856 he_obss_pd_policy, NULL);
4857 if (err)
4858 return err;
4859
4860 if (!tb[NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET] ||
4861 !tb[NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET])
4862 return -EINVAL;
4863
4864 he_obss_pd->min_offset =
4865 nla_get_u32(tb[NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET]);
4866 he_obss_pd->max_offset =
4867 nla_get_u32(tb[NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET]);
4868
4869 if (he_obss_pd->min_offset >= he_obss_pd->max_offset)
4870 return -EINVAL;
4871
4872 he_obss_pd->enable = true;
4873
4874 return 0;
4875}
4876
5c5e52d1
JC
4877static int nl80211_parse_he_bss_color(struct nlattr *attrs,
4878 struct cfg80211_he_bss_color *he_bss_color)
4879{
4880 struct nlattr *tb[NL80211_HE_BSS_COLOR_ATTR_MAX + 1];
4881 int err;
4882
4883 err = nla_parse_nested(tb, NL80211_HE_BSS_COLOR_ATTR_MAX, attrs,
4884 he_bss_color_policy, NULL);
4885 if (err)
4886 return err;
4887
4888 if (!tb[NL80211_HE_BSS_COLOR_ATTR_COLOR])
4889 return -EINVAL;
4890
4891 he_bss_color->color =
4892 nla_get_u8(tb[NL80211_HE_BSS_COLOR_ATTR_COLOR]);
75e6b594
JB
4893 he_bss_color->enabled =
4894 !nla_get_flag(tb[NL80211_HE_BSS_COLOR_ATTR_DISABLED]);
5c5e52d1
JC
4895 he_bss_color->partial =
4896 nla_get_flag(tb[NL80211_HE_BSS_COLOR_ATTR_PARTIAL]);
4897
4898 return 0;
4899}
4900
291c49de
AD
4901static int nl80211_parse_fils_discovery(struct cfg80211_registered_device *rdev,
4902 struct nlattr *attrs,
4903 struct cfg80211_ap_settings *params)
4904{
4905 struct nlattr *tb[NL80211_FILS_DISCOVERY_ATTR_MAX + 1];
4906 int ret;
4907 struct cfg80211_fils_discovery *fd = &params->fils_discovery;
4908
4909 if (!wiphy_ext_feature_isset(&rdev->wiphy,
4910 NL80211_EXT_FEATURE_FILS_DISCOVERY))
4911 return -EINVAL;
4912
4913 ret = nla_parse_nested(tb, NL80211_FILS_DISCOVERY_ATTR_MAX, attrs,
4914 NULL, NULL);
4915 if (ret)
4916 return ret;
4917
4918 if (!tb[NL80211_FILS_DISCOVERY_ATTR_INT_MIN] ||
4919 !tb[NL80211_FILS_DISCOVERY_ATTR_INT_MAX] ||
4920 !tb[NL80211_FILS_DISCOVERY_ATTR_TMPL])
4921 return -EINVAL;
4922
4923 fd->tmpl_len = nla_len(tb[NL80211_FILS_DISCOVERY_ATTR_TMPL]);
4924 fd->tmpl = nla_data(tb[NL80211_FILS_DISCOVERY_ATTR_TMPL]);
4925 fd->min_interval = nla_get_u32(tb[NL80211_FILS_DISCOVERY_ATTR_INT_MIN]);
4926 fd->max_interval = nla_get_u32(tb[NL80211_FILS_DISCOVERY_ATTR_INT_MAX]);
4927
4928 return 0;
4929}
4930
7443dcd1
AD
4931static int
4932nl80211_parse_unsol_bcast_probe_resp(struct cfg80211_registered_device *rdev,
4933 struct nlattr *attrs,
4934 struct cfg80211_ap_settings *params)
4935{
4936 struct nlattr *tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_MAX + 1];
4937 int ret;
4938 struct cfg80211_unsol_bcast_probe_resp *presp =
4939 &params->unsol_bcast_probe_resp;
4940
4941 if (!wiphy_ext_feature_isset(&rdev->wiphy,
4942 NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP))
4943 return -EINVAL;
4944
4945 ret = nla_parse_nested(tb, NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_MAX,
4946 attrs, NULL, NULL);
4947 if (ret)
4948 return ret;
4949
4950 if (!tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INT] ||
4951 !tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL])
4952 return -EINVAL;
4953
4954 presp->tmpl = nla_data(tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL]);
4955 presp->tmpl_len = nla_len(tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL]);
4956 presp->interval = nla_get_u32(tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INT]);
4957 return 0;
4958}
4959
66cd794e
JB
4960static void nl80211_check_ap_rate_selectors(struct cfg80211_ap_settings *params,
4961 const u8 *rates)
4962{
4963 int i;
4964
4965 if (!rates)
4966 return;
4967
4968 for (i = 0; i < rates[1]; i++) {
4969 if (rates[2 + i] == BSS_MEMBERSHIP_SELECTOR_HT_PHY)
4970 params->ht_required = true;
4971 if (rates[2 + i] == BSS_MEMBERSHIP_SELECTOR_VHT_PHY)
4972 params->vht_required = true;
2a392596
IP
4973 if (rates[2 + i] == BSS_MEMBERSHIP_SELECTOR_HE_PHY)
4974 params->he_required = true;
66cd794e
JB
4975 }
4976}
4977
4978/*
4979 * Since the nl80211 API didn't include, from the beginning, attributes about
4980 * HT/VHT requirements/capabilities, we parse them out of the IEs for the
4981 * benefit of drivers that rebuild IEs in the firmware.
4982 */
4983static void nl80211_calculate_ap_params(struct cfg80211_ap_settings *params)
4984{
4985 const struct cfg80211_beacon_data *bcn = &params->beacon;
ba83bfb1
IM
4986 size_t ies_len = bcn->tail_len;
4987 const u8 *ies = bcn->tail;
66cd794e
JB
4988 const u8 *rates;
4989 const u8 *cap;
4990
4991 rates = cfg80211_find_ie(WLAN_EID_SUPP_RATES, ies, ies_len);
4992 nl80211_check_ap_rate_selectors(params, rates);
4993
4994 rates = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, ies, ies_len);
4995 nl80211_check_ap_rate_selectors(params, rates);
4996
4997 cap = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, ies, ies_len);
4998 if (cap && cap[1] >= sizeof(*params->ht_cap))
4999 params->ht_cap = (void *)(cap + 2);
5000 cap = cfg80211_find_ie(WLAN_EID_VHT_CAPABILITY, ies, ies_len);
5001 if (cap && cap[1] >= sizeof(*params->vht_cap))
5002 params->vht_cap = (void *)(cap + 2);
244eb9ae
ST
5003 cap = cfg80211_find_ext_ie(WLAN_EID_EXT_HE_CAPABILITY, ies, ies_len);
5004 if (cap && cap[1] >= sizeof(*params->he_cap) + 1)
5005 params->he_cap = (void *)(cap + 3);
7e8d6f12
ST
5006 cap = cfg80211_find_ext_ie(WLAN_EID_EXT_HE_OPERATION, ies, ies_len);
5007 if (cap && cap[1] >= sizeof(*params->he_oper) + 1)
5008 params->he_oper = (void *)(cap + 3);
66cd794e
JB
5009}
5010
46c1dd0c
FF
5011static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev,
5012 struct cfg80211_ap_settings *params)
5013{
5014 struct wireless_dev *wdev;
5015 bool ret = false;
5016
53873f13 5017 list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
46c1dd0c
FF
5018 if (wdev->iftype != NL80211_IFTYPE_AP &&
5019 wdev->iftype != NL80211_IFTYPE_P2P_GO)
5020 continue;
5021
683b6d3b 5022 if (!wdev->preset_chandef.chan)
46c1dd0c
FF
5023 continue;
5024
683b6d3b 5025 params->chandef = wdev->preset_chandef;
46c1dd0c
FF
5026 ret = true;
5027 break;
5028 }
5029
46c1dd0c
FF
5030 return ret;
5031}
5032
e39e5b5e
JM
5033static bool nl80211_valid_auth_type(struct cfg80211_registered_device *rdev,
5034 enum nl80211_auth_type auth_type,
5035 enum nl80211_commands cmd)
5036{
5037 if (auth_type > NL80211_AUTHTYPE_MAX)
5038 return false;
5039
5040 switch (cmd) {
5041 case NL80211_CMD_AUTHENTICATE:
5042 if (!(rdev->wiphy.features & NL80211_FEATURE_SAE) &&
5043 auth_type == NL80211_AUTHTYPE_SAE)
5044 return false;
63181060
JM
5045 if (!wiphy_ext_feature_isset(&rdev->wiphy,
5046 NL80211_EXT_FEATURE_FILS_STA) &&
5047 (auth_type == NL80211_AUTHTYPE_FILS_SK ||
5048 auth_type == NL80211_AUTHTYPE_FILS_SK_PFS ||
5049 auth_type == NL80211_AUTHTYPE_FILS_PK))
5050 return false;
e39e5b5e
JM
5051 return true;
5052 case NL80211_CMD_CONNECT:
10773a7c 5053 if (!(rdev->wiphy.features & NL80211_FEATURE_SAE) &&
26f7044e
CHH
5054 !wiphy_ext_feature_isset(&rdev->wiphy,
5055 NL80211_EXT_FEATURE_SAE_OFFLOAD) &&
10773a7c 5056 auth_type == NL80211_AUTHTYPE_SAE)
a3caf744 5057 return false;
10773a7c 5058
a3caf744
VK
5059 /* FILS with SK PFS or PK not supported yet */
5060 if (auth_type == NL80211_AUTHTYPE_FILS_SK_PFS ||
5061 auth_type == NL80211_AUTHTYPE_FILS_PK)
5062 return false;
5063 if (!wiphy_ext_feature_isset(
5064 &rdev->wiphy,
5065 NL80211_EXT_FEATURE_FILS_SK_OFFLOAD) &&
5066 auth_type == NL80211_AUTHTYPE_FILS_SK)
5067 return false;
5068 return true;
e39e5b5e 5069 case NL80211_CMD_START_AP:
2831a631
CHH
5070 if (!wiphy_ext_feature_isset(&rdev->wiphy,
5071 NL80211_EXT_FEATURE_SAE_OFFLOAD_AP) &&
5072 auth_type == NL80211_AUTHTYPE_SAE)
e39e5b5e 5073 return false;
63181060
JM
5074 /* FILS not supported yet */
5075 if (auth_type == NL80211_AUTHTYPE_FILS_SK ||
5076 auth_type == NL80211_AUTHTYPE_FILS_SK_PFS ||
5077 auth_type == NL80211_AUTHTYPE_FILS_PK)
5078 return false;
e39e5b5e
JM
5079 return true;
5080 default:
5081 return false;
5082 }
5083}
5084
8860020e
JB
5085static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
5086{
5087 struct cfg80211_registered_device *rdev = info->user_ptr[0];
5088 struct net_device *dev = info->user_ptr[1];
5089 struct wireless_dev *wdev = dev->ieee80211_ptr;
5090 struct cfg80211_ap_settings params;
5091 int err;
5092
5093 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
5094 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
5095 return -EOPNOTSUPP;
5096
5097 if (!rdev->ops->start_ap)
5098 return -EOPNOTSUPP;
5099
5100 if (wdev->beacon_interval)
5101 return -EALREADY;
5102
5103 memset(&params, 0, sizeof(params));
5104
5105 /* these are required for START_AP */
5106 if (!info->attrs[NL80211_ATTR_BEACON_INTERVAL] ||
5107 !info->attrs[NL80211_ATTR_DTIM_PERIOD] ||
5108 !info->attrs[NL80211_ATTR_BEACON_HEAD])
5109 return -EINVAL;
5110
81e54d08 5111 err = nl80211_parse_beacon(rdev, info->attrs, &params.beacon);
8860020e
JB
5112 if (err)
5113 return err;
5114
5115 params.beacon_interval =
5116 nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
5117 params.dtim_period =
5118 nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);
5119
0c317a02
PK
5120 err = cfg80211_validate_beacon_int(rdev, dev->ieee80211_ptr->iftype,
5121 params.beacon_interval);
8860020e
JB
5122 if (err)
5123 return err;
5124
5125 /*
5126 * In theory, some of these attributes should be required here
5127 * but since they were not used when the command was originally
5128 * added, keep them optional for old user space programs to let
5129 * them continue to work with drivers that do not need the
5130 * additional information -- drivers must check!
5131 */
5132 if (info->attrs[NL80211_ATTR_SSID]) {
5133 params.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
5134 params.ssid_len =
5135 nla_len(info->attrs[NL80211_ATTR_SSID]);
cb9abd48 5136 if (params.ssid_len == 0)
8860020e
JB
5137 return -EINVAL;
5138 }
5139
ab0d76f6 5140 if (info->attrs[NL80211_ATTR_HIDDEN_SSID])
8860020e
JB
5141 params.hidden_ssid = nla_get_u32(
5142 info->attrs[NL80211_ATTR_HIDDEN_SSID]);
8860020e
JB
5143
5144 params.privacy = !!info->attrs[NL80211_ATTR_PRIVACY];
5145
5146 if (info->attrs[NL80211_ATTR_AUTH_TYPE]) {
5147 params.auth_type = nla_get_u32(
5148 info->attrs[NL80211_ATTR_AUTH_TYPE]);
e39e5b5e
JM
5149 if (!nl80211_valid_auth_type(rdev, params.auth_type,
5150 NL80211_CMD_START_AP))
8860020e
JB
5151 return -EINVAL;
5152 } else
5153 params.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
5154
5155 err = nl80211_crypto_settings(rdev, info, &params.crypto,
5156 NL80211_MAX_NR_CIPHER_SUITES);
5157 if (err)
5158 return err;
5159
1b658f11
VT
5160 if (info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]) {
5161 if (!(rdev->wiphy.features & NL80211_FEATURE_INACTIVITY_TIMER))
5162 return -EOPNOTSUPP;
5163 params.inactivity_timeout = nla_get_u16(
5164 info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]);
5165 }
5166
53cabad7
JB
5167 if (info->attrs[NL80211_ATTR_P2P_CTWINDOW]) {
5168 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
5169 return -EINVAL;
5170 params.p2p_ctwindow =
5171 nla_get_u8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]);
53cabad7
JB
5172 if (params.p2p_ctwindow != 0 &&
5173 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN))
5174 return -EINVAL;
5175 }
5176
5177 if (info->attrs[NL80211_ATTR_P2P_OPPPS]) {
5178 u8 tmp;
5179
5180 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
5181 return -EINVAL;
5182 tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]);
53cabad7
JB
5183 params.p2p_opp_ps = tmp;
5184 if (params.p2p_opp_ps != 0 &&
5185 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS))
5186 return -EINVAL;
5187 }
5188
aa430da4 5189 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
683b6d3b
JB
5190 err = nl80211_parse_chandef(rdev, info, &params.chandef);
5191 if (err)
5192 return err;
5193 } else if (wdev->preset_chandef.chan) {
5194 params.chandef = wdev->preset_chandef;
46c1dd0c 5195 } else if (!nl80211_get_ap_channel(rdev, &params))
aa430da4
JB
5196 return -EINVAL;
5197
923b352f
AN
5198 if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &params.chandef,
5199 wdev->iftype))
aa430da4
JB
5200 return -EINVAL;
5201
a7c7fbff 5202 if (info->attrs[NL80211_ATTR_TX_RATES]) {
9a5f6488
TC
5203 err = nl80211_parse_tx_bitrate_mask(info, info->attrs,
5204 NL80211_ATTR_TX_RATES,
eb89a6a6
MH
5205 &params.beacon_rate,
5206 dev);
a7c7fbff
PK
5207 if (err)
5208 return err;
5209
8564e382
JB
5210 err = validate_beacon_tx_rate(rdev, params.chandef.chan->band,
5211 &params.beacon_rate);
a7c7fbff
PK
5212 if (err)
5213 return err;
5214 }
5215
18998c38
EP
5216 if (info->attrs[NL80211_ATTR_SMPS_MODE]) {
5217 params.smps_mode =
5218 nla_get_u8(info->attrs[NL80211_ATTR_SMPS_MODE]);
5219 switch (params.smps_mode) {
5220 case NL80211_SMPS_OFF:
5221 break;
5222 case NL80211_SMPS_STATIC:
5223 if (!(rdev->wiphy.features &
5224 NL80211_FEATURE_STATIC_SMPS))
5225 return -EINVAL;
5226 break;
5227 case NL80211_SMPS_DYNAMIC:
5228 if (!(rdev->wiphy.features &
5229 NL80211_FEATURE_DYNAMIC_SMPS))
5230 return -EINVAL;
5231 break;
5232 default:
5233 return -EINVAL;
5234 }
5235 } else {
5236 params.smps_mode = NL80211_SMPS_OFF;
5237 }
5238
6e8ef842
PK
5239 params.pbss = nla_get_flag(info->attrs[NL80211_ATTR_PBSS]);
5240 if (params.pbss && !rdev->wiphy.bands[NL80211_BAND_60GHZ])
5241 return -EOPNOTSUPP;
5242
4baf6bea
OO
5243 if (info->attrs[NL80211_ATTR_ACL_POLICY]) {
5244 params.acl = parse_acl_data(&rdev->wiphy, info);
5245 if (IS_ERR(params.acl))
5246 return PTR_ERR(params.acl);
5247 }
5248
a0de1ca3
JC
5249 params.twt_responder =
5250 nla_get_flag(info->attrs[NL80211_ATTR_TWT_RESPONDER]);
5251
796e90f4
JC
5252 if (info->attrs[NL80211_ATTR_HE_OBSS_PD]) {
5253 err = nl80211_parse_he_obss_pd(
5254 info->attrs[NL80211_ATTR_HE_OBSS_PD],
5255 &params.he_obss_pd);
bc7a39b4
LC
5256 if (err)
5257 goto out;
796e90f4
JC
5258 }
5259
5c5e52d1
JC
5260 if (info->attrs[NL80211_ATTR_HE_BSS_COLOR]) {
5261 err = nl80211_parse_he_bss_color(
5262 info->attrs[NL80211_ATTR_HE_BSS_COLOR],
5263 &params.he_bss_color);
5264 if (err)
60a0121f 5265 goto out;
5c5e52d1
JC
5266 }
5267
291c49de
AD
5268 if (info->attrs[NL80211_ATTR_FILS_DISCOVERY]) {
5269 err = nl80211_parse_fils_discovery(rdev,
5270 info->attrs[NL80211_ATTR_FILS_DISCOVERY],
5271 &params);
5272 if (err)
5273 goto out;
5274 }
5275
7443dcd1
AD
5276 if (info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP]) {
5277 err = nl80211_parse_unsol_bcast_probe_resp(
5278 rdev, info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP],
5279 &params);
5280 if (err)
5281 return err;
5282 }
5283
66cd794e
JB
5284 nl80211_calculate_ap_params(&params);
5285
fe494370
SD
5286 if (info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])
5287 params.flags |= AP_SETTINGS_EXTERNAL_AUTH_SUPPORT;
5288
c56589ed 5289 wdev_lock(wdev);
e35e4d28 5290 err = rdev_start_ap(rdev, dev, &params);
46c1dd0c 5291 if (!err) {
683b6d3b 5292 wdev->preset_chandef = params.chandef;
8860020e 5293 wdev->beacon_interval = params.beacon_interval;
9e0e2961 5294 wdev->chandef = params.chandef;
06e191e2
AQ
5295 wdev->ssid_len = params.ssid_len;
5296 memcpy(wdev->ssid, params.ssid, wdev->ssid_len);
466a3061
DK
5297
5298 if (info->attrs[NL80211_ATTR_SOCKET_OWNER])
5299 wdev->conn_owner_nlportid = info->snd_portid;
46c1dd0c 5300 }
c56589ed 5301 wdev_unlock(wdev);
77765eaf 5302
9951ebfc 5303out:
77765eaf
VT
5304 kfree(params.acl);
5305
56d1893d 5306 return err;
ed1b6cc7
JB
5307}
5308
8860020e
JB
5309static int nl80211_set_beacon(struct sk_buff *skb, struct genl_info *info)
5310{
5311 struct cfg80211_registered_device *rdev = info->user_ptr[0];
5312 struct net_device *dev = info->user_ptr[1];
5313 struct wireless_dev *wdev = dev->ieee80211_ptr;
5314 struct cfg80211_beacon_data params;
5315 int err;
5316
5317 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
5318 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
5319 return -EOPNOTSUPP;
5320
5321 if (!rdev->ops->change_beacon)
5322 return -EOPNOTSUPP;
5323
5324 if (!wdev->beacon_interval)
5325 return -EINVAL;
5326
81e54d08 5327 err = nl80211_parse_beacon(rdev, info->attrs, &params);
8860020e
JB
5328 if (err)
5329 return err;
5330
c56589ed
SW
5331 wdev_lock(wdev);
5332 err = rdev_change_beacon(rdev, dev, &params);
5333 wdev_unlock(wdev);
5334
5335 return err;
8860020e
JB
5336}
5337
5338static int nl80211_stop_ap(struct sk_buff *skb, struct genl_info *info)
ed1b6cc7 5339{
4c476991
JB
5340 struct cfg80211_registered_device *rdev = info->user_ptr[0];
5341 struct net_device *dev = info->user_ptr[1];
ed1b6cc7 5342
7c8d5e03 5343 return cfg80211_stop_ap(rdev, dev, false);
ed1b6cc7
JB
5344}
5345
5727ef1b
JB
5346static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = {
5347 [NL80211_STA_FLAG_AUTHORIZED] = { .type = NLA_FLAG },
5348 [NL80211_STA_FLAG_SHORT_PREAMBLE] = { .type = NLA_FLAG },
5349 [NL80211_STA_FLAG_WME] = { .type = NLA_FLAG },
0e46724a 5350 [NL80211_STA_FLAG_MFP] = { .type = NLA_FLAG },
b39c48fa 5351 [NL80211_STA_FLAG_AUTHENTICATED] = { .type = NLA_FLAG },
d83023da 5352 [NL80211_STA_FLAG_TDLS_PEER] = { .type = NLA_FLAG },
5727ef1b
JB
5353};
5354
eccb8e8f 5355static int parse_station_flags(struct genl_info *info,
bdd3ae3d 5356 enum nl80211_iftype iftype,
eccb8e8f 5357 struct station_parameters *params)
5727ef1b
JB
5358{
5359 struct nlattr *flags[NL80211_STA_FLAG_MAX + 1];
eccb8e8f 5360 struct nlattr *nla;
5727ef1b
JB
5361 int flag;
5362
eccb8e8f
JB
5363 /*
5364 * Try parsing the new attribute first so userspace
5365 * can specify both for older kernels.
5366 */
5367 nla = info->attrs[NL80211_ATTR_STA_FLAGS2];
5368 if (nla) {
5369 struct nl80211_sta_flag_update *sta_flags;
5370
5371 sta_flags = nla_data(nla);
5372 params->sta_flags_mask = sta_flags->mask;
5373 params->sta_flags_set = sta_flags->set;
77ee7c89 5374 params->sta_flags_set &= params->sta_flags_mask;
eccb8e8f
JB
5375 if ((params->sta_flags_mask |
5376 params->sta_flags_set) & BIT(__NL80211_STA_FLAG_INVALID))
5377 return -EINVAL;
5378 return 0;
5379 }
5380
5381 /* if present, parse the old attribute */
5727ef1b 5382
eccb8e8f 5383 nla = info->attrs[NL80211_ATTR_STA_FLAGS];
5727ef1b
JB
5384 if (!nla)
5385 return 0;
5386
8cb08174 5387 if (nla_parse_nested_deprecated(flags, NL80211_STA_FLAG_MAX, nla, sta_flags_policy, info->extack))
5727ef1b
JB
5388 return -EINVAL;
5389
bdd3ae3d
JB
5390 /*
5391 * Only allow certain flags for interface types so that
5392 * other attributes are silently ignored. Remember that
5393 * this is backward compatibility code with old userspace
5394 * and shouldn't be hit in other cases anyway.
5395 */
5396 switch (iftype) {
5397 case NL80211_IFTYPE_AP:
5398 case NL80211_IFTYPE_AP_VLAN:
5399 case NL80211_IFTYPE_P2P_GO:
5400 params->sta_flags_mask = BIT(NL80211_STA_FLAG_AUTHORIZED) |
5401 BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) |
5402 BIT(NL80211_STA_FLAG_WME) |
5403 BIT(NL80211_STA_FLAG_MFP);
5404 break;
5405 case NL80211_IFTYPE_P2P_CLIENT:
5406 case NL80211_IFTYPE_STATION:
5407 params->sta_flags_mask = BIT(NL80211_STA_FLAG_AUTHORIZED) |
5408 BIT(NL80211_STA_FLAG_TDLS_PEER);
5409 break;
5410 case NL80211_IFTYPE_MESH_POINT:
5411 params->sta_flags_mask = BIT(NL80211_STA_FLAG_AUTHENTICATED) |
5412 BIT(NL80211_STA_FLAG_MFP) |
5413 BIT(NL80211_STA_FLAG_AUTHORIZED);
5cf3006c 5414 break;
bdd3ae3d
JB
5415 default:
5416 return -EINVAL;
5417 }
5727ef1b 5418
3383b5a6
JB
5419 for (flag = 1; flag <= NL80211_STA_FLAG_MAX; flag++) {
5420 if (flags[flag]) {
eccb8e8f 5421 params->sta_flags_set |= (1<<flag);
5727ef1b 5422
3383b5a6
JB
5423 /* no longer support new API additions in old API */
5424 if (flag > NL80211_STA_FLAG_MAX_OLD_API)
5425 return -EINVAL;
5426 }
5427 }
5428
5727ef1b
JB
5429 return 0;
5430}
5431
9bb7e0f2 5432bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, int attr)
c8dcfd8a
FF
5433{
5434 struct nlattr *rate;
8eb41c8d
VK
5435 u32 bitrate;
5436 u16 bitrate_compat;
bbf67e45 5437 enum nl80211_rate_info rate_flg;
c8dcfd8a 5438
ae0be8de 5439 rate = nla_nest_start_noflag(msg, attr);
c8dcfd8a 5440 if (!rate)
db9c64cf 5441 return false;
c8dcfd8a
FF
5442
5443 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
5444 bitrate = cfg80211_calculate_bitrate(info);
8eb41c8d
VK
5445 /* report 16-bit bitrate only if we can */
5446 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
db9c64cf
JB
5447 if (bitrate > 0 &&
5448 nla_put_u32(msg, NL80211_RATE_INFO_BITRATE32, bitrate))
5449 return false;
5450 if (bitrate_compat > 0 &&
5451 nla_put_u16(msg, NL80211_RATE_INFO_BITRATE, bitrate_compat))
5452 return false;
5453
b51f3bee
JB
5454 switch (info->bw) {
5455 case RATE_INFO_BW_5:
5456 rate_flg = NL80211_RATE_INFO_5_MHZ_WIDTH;
5457 break;
5458 case RATE_INFO_BW_10:
5459 rate_flg = NL80211_RATE_INFO_10_MHZ_WIDTH;
5460 break;
5461 default:
5462 WARN_ON(1);
7b506ff6 5463 fallthrough;
b51f3bee
JB
5464 case RATE_INFO_BW_20:
5465 rate_flg = 0;
5466 break;
5467 case RATE_INFO_BW_40:
5468 rate_flg = NL80211_RATE_INFO_40_MHZ_WIDTH;
5469 break;
5470 case RATE_INFO_BW_80:
5471 rate_flg = NL80211_RATE_INFO_80_MHZ_WIDTH;
5472 break;
5473 case RATE_INFO_BW_160:
5474 rate_flg = NL80211_RATE_INFO_160_MHZ_WIDTH;
5475 break;
c4cbaf79
LC
5476 case RATE_INFO_BW_HE_RU:
5477 rate_flg = 0;
5478 WARN_ON(!(info->flags & RATE_INFO_FLAGS_HE_MCS));
b51f3bee
JB
5479 }
5480
5481 if (rate_flg && nla_put_flag(msg, rate_flg))
5482 return false;
5483
db9c64cf
JB
5484 if (info->flags & RATE_INFO_FLAGS_MCS) {
5485 if (nla_put_u8(msg, NL80211_RATE_INFO_MCS, info->mcs))
5486 return false;
db9c64cf
JB
5487 if (info->flags & RATE_INFO_FLAGS_SHORT_GI &&
5488 nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI))
5489 return false;
5490 } else if (info->flags & RATE_INFO_FLAGS_VHT_MCS) {
5491 if (nla_put_u8(msg, NL80211_RATE_INFO_VHT_MCS, info->mcs))
5492 return false;
5493 if (nla_put_u8(msg, NL80211_RATE_INFO_VHT_NSS, info->nss))
5494 return false;
db9c64cf
JB
5495 if (info->flags & RATE_INFO_FLAGS_SHORT_GI &&
5496 nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI))
5497 return false;
c4cbaf79
LC
5498 } else if (info->flags & RATE_INFO_FLAGS_HE_MCS) {
5499 if (nla_put_u8(msg, NL80211_RATE_INFO_HE_MCS, info->mcs))
5500 return false;
5501 if (nla_put_u8(msg, NL80211_RATE_INFO_HE_NSS, info->nss))
5502 return false;
5503 if (nla_put_u8(msg, NL80211_RATE_INFO_HE_GI, info->he_gi))
5504 return false;
5505 if (nla_put_u8(msg, NL80211_RATE_INFO_HE_DCM, info->he_dcm))
5506 return false;
5507 if (info->bw == RATE_INFO_BW_HE_RU &&
5508 nla_put_u8(msg, NL80211_RATE_INFO_HE_RU_ALLOC,
5509 info->he_ru_alloc))
5510 return false;
db9c64cf 5511 }
c8dcfd8a
FF
5512
5513 nla_nest_end(msg, rate);
5514 return true;
c8dcfd8a
FF
5515}
5516
119363c7
FF
5517static bool nl80211_put_signal(struct sk_buff *msg, u8 mask, s8 *signal,
5518 int id)
5519{
5520 void *attr;
5521 int i = 0;
5522
5523 if (!mask)
5524 return true;
5525
ae0be8de 5526 attr = nla_nest_start_noflag(msg, id);
119363c7
FF
5527 if (!attr)
5528 return false;
5529
5530 for (i = 0; i < IEEE80211_MAX_CHAINS; i++) {
5531 if (!(mask & BIT(i)))
5532 continue;
5533
5534 if (nla_put_u8(msg, i, signal[i]))
5535 return false;
5536 }
5537
5538 nla_nest_end(msg, attr);
5539
5540 return true;
5541}
5542
cf5ead82
JB
5543static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
5544 u32 seq, int flags,
66266b3a
JL
5545 struct cfg80211_registered_device *rdev,
5546 struct net_device *dev,
98b62183 5547 const u8 *mac_addr, struct station_info *sinfo)
fd5b74dc
JB
5548{
5549 void *hdr;
f4263c98 5550 struct nlattr *sinfoattr, *bss_param;
fd5b74dc 5551
cf5ead82 5552 hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
f77bf486
AS
5553 if (!hdr) {
5554 cfg80211_sinfo_release_content(sinfo);
fd5b74dc 5555 return -1;
f77bf486 5556 }
fd5b74dc 5557
9360ffd1
DM
5558 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
5559 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr) ||
5560 nla_put_u32(msg, NL80211_ATTR_GENERATION, sinfo->generation))
5561 goto nla_put_failure;
f5ea9120 5562
ae0be8de 5563 sinfoattr = nla_nest_start_noflag(msg, NL80211_ATTR_STA_INFO);
2ec600d6 5564 if (!sinfoattr)
fd5b74dc 5565 goto nla_put_failure;
319090bf
JB
5566
5567#define PUT_SINFO(attr, memb, type) do { \
d686b920 5568 BUILD_BUG_ON(sizeof(type) == sizeof(u64)); \
397c657a 5569 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_ ## attr) && \
319090bf
JB
5570 nla_put_ ## type(msg, NL80211_STA_INFO_ ## attr, \
5571 sinfo->memb)) \
5572 goto nla_put_failure; \
5573 } while (0)
d686b920 5574#define PUT_SINFO_U64(attr, memb) do { \
397c657a 5575 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_ ## attr) && \
d686b920
JB
5576 nla_put_u64_64bit(msg, NL80211_STA_INFO_ ## attr, \
5577 sinfo->memb, NL80211_STA_INFO_PAD)) \
5578 goto nla_put_failure; \
5579 } while (0)
319090bf
JB
5580
5581 PUT_SINFO(CONNECTED_TIME, connected_time, u32);
5582 PUT_SINFO(INACTIVE_TIME, inactive_time, u32);
6c7a0033 5583 PUT_SINFO_U64(ASSOC_AT_BOOTTIME, assoc_at);
319090bf 5584
397c657a
OE
5585 if (sinfo->filled & (BIT_ULL(NL80211_STA_INFO_RX_BYTES) |
5586 BIT_ULL(NL80211_STA_INFO_RX_BYTES64)) &&
9360ffd1 5587 nla_put_u32(msg, NL80211_STA_INFO_RX_BYTES,
42745e03 5588 (u32)sinfo->rx_bytes))
9360ffd1 5589 goto nla_put_failure;
319090bf 5590
397c657a
OE
5591 if (sinfo->filled & (BIT_ULL(NL80211_STA_INFO_TX_BYTES) |
5592 BIT_ULL(NL80211_STA_INFO_TX_BYTES64)) &&
9360ffd1 5593 nla_put_u32(msg, NL80211_STA_INFO_TX_BYTES,
42745e03
VK
5594 (u32)sinfo->tx_bytes))
5595 goto nla_put_failure;
319090bf 5596
d686b920
JB
5597 PUT_SINFO_U64(RX_BYTES64, rx_bytes);
5598 PUT_SINFO_U64(TX_BYTES64, tx_bytes);
319090bf
JB
5599 PUT_SINFO(LLID, llid, u16);
5600 PUT_SINFO(PLID, plid, u16);
5601 PUT_SINFO(PLINK_STATE, plink_state, u8);
d686b920 5602 PUT_SINFO_U64(RX_DURATION, rx_duration);
36647055
THJ
5603 PUT_SINFO_U64(TX_DURATION, tx_duration);
5604
5605 if (wiphy_ext_feature_isset(&rdev->wiphy,
5606 NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))
5607 PUT_SINFO(AIRTIME_WEIGHT, airtime_weight, u16);
319090bf 5608
66266b3a
JL
5609 switch (rdev->wiphy.signal_type) {
5610 case CFG80211_SIGNAL_TYPE_MBM:
319090bf
JB
5611 PUT_SINFO(SIGNAL, signal, u8);
5612 PUT_SINFO(SIGNAL_AVG, signal_avg, u8);
66266b3a
JL
5613 break;
5614 default:
5615 break;
5616 }
397c657a 5617 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL)) {
119363c7
FF
5618 if (!nl80211_put_signal(msg, sinfo->chains,
5619 sinfo->chain_signal,
5620 NL80211_STA_INFO_CHAIN_SIGNAL))
5621 goto nla_put_failure;
5622 }
397c657a 5623 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL_AVG)) {
119363c7
FF
5624 if (!nl80211_put_signal(msg, sinfo->chains,
5625 sinfo->chain_signal_avg,
5626 NL80211_STA_INFO_CHAIN_SIGNAL_AVG))
5627 goto nla_put_failure;
5628 }
397c657a 5629 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_BITRATE)) {
c8dcfd8a
FF
5630 if (!nl80211_put_sta_rate(msg, &sinfo->txrate,
5631 NL80211_STA_INFO_TX_BITRATE))
5632 goto nla_put_failure;
5633 }
397c657a 5634 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_RX_BITRATE)) {
c8dcfd8a
FF
5635 if (!nl80211_put_sta_rate(msg, &sinfo->rxrate,
5636 NL80211_STA_INFO_RX_BITRATE))
420e7fab 5637 goto nla_put_failure;
420e7fab 5638 }
319090bf
JB
5639
5640 PUT_SINFO(RX_PACKETS, rx_packets, u32);
5641 PUT_SINFO(TX_PACKETS, tx_packets, u32);
5642 PUT_SINFO(TX_RETRIES, tx_retries, u32);
5643 PUT_SINFO(TX_FAILED, tx_failed, u32);
5644 PUT_SINFO(EXPECTED_THROUGHPUT, expected_throughput, u32);
ab60633c 5645 PUT_SINFO(AIRTIME_LINK_METRIC, airtime_link_metric, u32);
319090bf
JB
5646 PUT_SINFO(BEACON_LOSS, beacon_loss_count, u32);
5647 PUT_SINFO(LOCAL_PM, local_pm, u32);
5648 PUT_SINFO(PEER_PM, peer_pm, u32);
5649 PUT_SINFO(NONPEER_PM, nonpeer_pm, u32);
dbdaee7a 5650 PUT_SINFO(CONNECTED_TO_GATE, connected_to_gate, u8);
1303a51c 5651 PUT_SINFO(CONNECTED_TO_AS, connected_to_as, u8);
319090bf 5652
397c657a 5653 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_BSS_PARAM)) {
ae0be8de
MK
5654 bss_param = nla_nest_start_noflag(msg,
5655 NL80211_STA_INFO_BSS_PARAM);
f4263c98
PS
5656 if (!bss_param)
5657 goto nla_put_failure;
5658
9360ffd1
DM
5659 if (((sinfo->bss_param.flags & BSS_PARAM_FLAGS_CTS_PROT) &&
5660 nla_put_flag(msg, NL80211_STA_BSS_PARAM_CTS_PROT)) ||
5661 ((sinfo->bss_param.flags & BSS_PARAM_FLAGS_SHORT_PREAMBLE) &&
5662 nla_put_flag(msg, NL80211_STA_BSS_PARAM_SHORT_PREAMBLE)) ||
5663 ((sinfo->bss_param.flags & BSS_PARAM_FLAGS_SHORT_SLOT_TIME) &&
5664 nla_put_flag(msg, NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME)) ||
5665 nla_put_u8(msg, NL80211_STA_BSS_PARAM_DTIM_PERIOD,
5666 sinfo->bss_param.dtim_period) ||
5667 nla_put_u16(msg, NL80211_STA_BSS_PARAM_BEACON_INTERVAL,
5668 sinfo->bss_param.beacon_interval))
5669 goto nla_put_failure;
f4263c98
PS
5670
5671 nla_nest_end(msg, bss_param);
5672 }
397c657a 5673 if ((sinfo->filled & BIT_ULL(NL80211_STA_INFO_STA_FLAGS)) &&
9360ffd1
DM
5674 nla_put(msg, NL80211_STA_INFO_STA_FLAGS,
5675 sizeof(struct nl80211_sta_flag_update),
5676 &sinfo->sta_flags))
5677 goto nla_put_failure;
319090bf 5678
d686b920
JB
5679 PUT_SINFO_U64(T_OFFSET, t_offset);
5680 PUT_SINFO_U64(RX_DROP_MISC, rx_dropped_misc);
5681 PUT_SINFO_U64(BEACON_RX, rx_beacon);
a76b1942 5682 PUT_SINFO(BEACON_SIGNAL_AVG, rx_beacon_signal_avg, u8);
0d4e14a3
AB
5683 PUT_SINFO(RX_MPDUS, rx_mpdu_count, u32);
5684 PUT_SINFO(FCS_ERROR_COUNT, fcs_err_count, u32);
81d5439d 5685 if (wiphy_ext_feature_isset(&rdev->wiphy,
9c06602b
BP
5686 NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT)) {
5687 PUT_SINFO(ACK_SIGNAL, ack_signal, u8);
5688 PUT_SINFO(ACK_SIGNAL_AVG, avg_ack_signal, s8);
5689 }
319090bf
JB
5690
5691#undef PUT_SINFO
d686b920 5692#undef PUT_SINFO_U64
6de39808 5693
8689c051 5694 if (sinfo->pertid) {
6de39808
JB
5695 struct nlattr *tidsattr;
5696 int tid;
5697
ae0be8de
MK
5698 tidsattr = nla_nest_start_noflag(msg,
5699 NL80211_STA_INFO_TID_STATS);
6de39808
JB
5700 if (!tidsattr)
5701 goto nla_put_failure;
5702
5703 for (tid = 0; tid < IEEE80211_NUM_TIDS + 1; tid++) {
5704 struct cfg80211_tid_stats *tidstats;
5705 struct nlattr *tidattr;
5706
5707 tidstats = &sinfo->pertid[tid];
5708
5709 if (!tidstats->filled)
5710 continue;
5711
ae0be8de 5712 tidattr = nla_nest_start_noflag(msg, tid + 1);
6de39808
JB
5713 if (!tidattr)
5714 goto nla_put_failure;
5715
d686b920 5716#define PUT_TIDVAL_U64(attr, memb) do { \
6de39808 5717 if (tidstats->filled & BIT(NL80211_TID_STATS_ ## attr) && \
d686b920
JB
5718 nla_put_u64_64bit(msg, NL80211_TID_STATS_ ## attr, \
5719 tidstats->memb, NL80211_TID_STATS_PAD)) \
6de39808
JB
5720 goto nla_put_failure; \
5721 } while (0)
5722
d686b920
JB
5723 PUT_TIDVAL_U64(RX_MSDU, rx_msdu);
5724 PUT_TIDVAL_U64(TX_MSDU, tx_msdu);
5725 PUT_TIDVAL_U64(TX_MSDU_RETRIES, tx_msdu_retries);
5726 PUT_TIDVAL_U64(TX_MSDU_FAILED, tx_msdu_failed);
6de39808 5727
d686b920 5728#undef PUT_TIDVAL_U64
52539ca8
THJ
5729 if ((tidstats->filled &
5730 BIT(NL80211_TID_STATS_TXQ_STATS)) &&
5731 !nl80211_put_txq_stats(msg, &tidstats->txq_stats,
5732 NL80211_TID_STATS_TXQ_STATS))
5733 goto nla_put_failure;
5734
6de39808
JB
5735 nla_nest_end(msg, tidattr);
5736 }
5737
5738 nla_nest_end(msg, tidsattr);
5739 }
5740
2ec600d6 5741 nla_nest_end(msg, sinfoattr);
fd5b74dc 5742
319090bf 5743 if (sinfo->assoc_req_ies_len &&
9360ffd1
DM
5744 nla_put(msg, NL80211_ATTR_IE, sinfo->assoc_req_ies_len,
5745 sinfo->assoc_req_ies))
5746 goto nla_put_failure;
50d3dfb7 5747
7ea3e110 5748 cfg80211_sinfo_release_content(sinfo);
053c095a
JB
5749 genlmsg_end(msg, hdr);
5750 return 0;
fd5b74dc
JB
5751
5752 nla_put_failure:
7ea3e110 5753 cfg80211_sinfo_release_content(sinfo);
bc3ed28c
TG
5754 genlmsg_cancel(msg, hdr);
5755 return -EMSGSIZE;
fd5b74dc
JB
5756}
5757
2ec600d6 5758static int nl80211_dump_station(struct sk_buff *skb,
bba95fef 5759 struct netlink_callback *cb)
2ec600d6 5760{
73887fd9 5761 struct station_info sinfo;
1b8ec87a 5762 struct cfg80211_registered_device *rdev;
97990a06 5763 struct wireless_dev *wdev;
2ec600d6 5764 u8 mac_addr[ETH_ALEN];
97990a06 5765 int sta_idx = cb->args[2];
2ec600d6 5766 int err;
2ec600d6 5767
ea90e0dc 5768 rtnl_lock();
5297c65c 5769 err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev);
67748893 5770 if (err)
ea90e0dc 5771 goto out_err;
bba95fef 5772
97990a06
JB
5773 if (!wdev->netdev) {
5774 err = -EINVAL;
5775 goto out_err;
5776 }
5777
1b8ec87a 5778 if (!rdev->ops->dump_station) {
eec60b03 5779 err = -EOPNOTSUPP;
bba95fef
JB
5780 goto out_err;
5781 }
5782
bba95fef 5783 while (1) {
73887fd9 5784 memset(&sinfo, 0, sizeof(sinfo));
1b8ec87a 5785 err = rdev_dump_station(rdev, wdev->netdev, sta_idx,
73887fd9 5786 mac_addr, &sinfo);
bba95fef
JB
5787 if (err == -ENOENT)
5788 break;
5789 if (err)
3b85875a 5790 goto out_err;
bba95fef 5791
cf5ead82 5792 if (nl80211_send_station(skb, NL80211_CMD_NEW_STATION,
15e47304 5793 NETLINK_CB(cb->skb).portid,
bba95fef 5794 cb->nlh->nlmsg_seq, NLM_F_MULTI,
1b8ec87a 5795 rdev, wdev->netdev, mac_addr,
73887fd9 5796 &sinfo) < 0)
bba95fef
JB
5797 goto out;
5798
5799 sta_idx++;
5800 }
5801
bba95fef 5802 out:
97990a06 5803 cb->args[2] = sta_idx;
bba95fef 5804 err = skb->len;
bba95fef 5805 out_err:
ea90e0dc 5806 rtnl_unlock();
bba95fef
JB
5807
5808 return err;
2ec600d6 5809}
fd5b74dc 5810
5727ef1b
JB
5811static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
5812{
4c476991
JB
5813 struct cfg80211_registered_device *rdev = info->user_ptr[0];
5814 struct net_device *dev = info->user_ptr[1];
73887fd9 5815 struct station_info sinfo;
fd5b74dc
JB
5816 struct sk_buff *msg;
5817 u8 *mac_addr = NULL;
4c476991 5818 int err;
fd5b74dc 5819
73887fd9 5820 memset(&sinfo, 0, sizeof(sinfo));
fd5b74dc 5821
73887fd9
JB
5822 if (!info->attrs[NL80211_ATTR_MAC])
5823 return -EINVAL;
fd5b74dc
JB
5824
5825 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
5826
73887fd9
JB
5827 if (!rdev->ops->get_station)
5828 return -EOPNOTSUPP;
3b85875a 5829
73887fd9 5830 err = rdev_get_station(rdev, dev, mac_addr, &sinfo);
fd5b74dc 5831 if (err)
73887fd9 5832 return err;
2ec600d6 5833
fd2120ca 5834 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
7ea3e110 5835 if (!msg) {
ba8f566a 5836 cfg80211_sinfo_release_content(&sinfo);
73887fd9 5837 return -ENOMEM;
7ea3e110 5838 }
fd5b74dc 5839
cf5ead82
JB
5840 if (nl80211_send_station(msg, NL80211_CMD_NEW_STATION,
5841 info->snd_portid, info->snd_seq, 0,
73887fd9 5842 rdev, dev, mac_addr, &sinfo) < 0) {
4c476991 5843 nlmsg_free(msg);
73887fd9 5844 return -ENOBUFS;
4c476991 5845 }
3b85875a 5846
73887fd9 5847 return genlmsg_reply(msg, info);
5727ef1b
JB
5848}
5849
77ee7c89
JB
5850int cfg80211_check_station_change(struct wiphy *wiphy,
5851 struct station_parameters *params,
5852 enum cfg80211_station_type statype)
5853{
e4208427
AB
5854 if (params->listen_interval != -1 &&
5855 statype != CFG80211_STA_AP_CLIENT_UNASSOC)
77ee7c89 5856 return -EINVAL;
e4208427 5857
17b94247
AB
5858 if (params->support_p2p_ps != -1 &&
5859 statype != CFG80211_STA_AP_CLIENT_UNASSOC)
5860 return -EINVAL;
5861
c72e1140 5862 if (params->aid &&
e4208427
AB
5863 !(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) &&
5864 statype != CFG80211_STA_AP_CLIENT_UNASSOC)
77ee7c89
JB
5865 return -EINVAL;
5866
5867 /* When you run into this, adjust the code below for the new flag */
5868 BUILD_BUG_ON(NL80211_STA_FLAG_MAX != 7);
5869
5870 switch (statype) {
eef941e6
TP
5871 case CFG80211_STA_MESH_PEER_KERNEL:
5872 case CFG80211_STA_MESH_PEER_USER:
77ee7c89
JB
5873 /*
5874 * No ignoring the TDLS flag here -- the userspace mesh
5875 * code doesn't have the bug of including TDLS in the
5876 * mask everywhere.
5877 */
5878 if (params->sta_flags_mask &
5879 ~(BIT(NL80211_STA_FLAG_AUTHENTICATED) |
5880 BIT(NL80211_STA_FLAG_MFP) |
5881 BIT(NL80211_STA_FLAG_AUTHORIZED)))
5882 return -EINVAL;
5883 break;
5884 case CFG80211_STA_TDLS_PEER_SETUP:
5885 case CFG80211_STA_TDLS_PEER_ACTIVE:
5886 if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))
5887 return -EINVAL;
5888 /* ignore since it can't change */
5889 params->sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
5890 break;
5891 default:
5892 /* disallow mesh-specific things */
5893 if (params->plink_action != NL80211_PLINK_ACTION_NO_ACTION)
5894 return -EINVAL;
5895 if (params->local_pm)
5896 return -EINVAL;
5897 if (params->sta_modify_mask & STATION_PARAM_APPLY_PLINK_STATE)
5898 return -EINVAL;
5899 }
5900
5901 if (statype != CFG80211_STA_TDLS_PEER_SETUP &&
5902 statype != CFG80211_STA_TDLS_PEER_ACTIVE) {
5903 /* TDLS can't be set, ... */
5904 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))
5905 return -EINVAL;
5906 /*
5907 * ... but don't bother the driver with it. This works around
5908 * a hostapd/wpa_supplicant issue -- it always includes the
5909 * TLDS_PEER flag in the mask even for AP mode.
5910 */
5911 params->sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
5912 }
5913
47edb11b
AB
5914 if (statype != CFG80211_STA_TDLS_PEER_SETUP &&
5915 statype != CFG80211_STA_AP_CLIENT_UNASSOC) {
77ee7c89
JB
5916 /* reject other things that can't change */
5917 if (params->sta_modify_mask & STATION_PARAM_APPLY_UAPSD)
5918 return -EINVAL;
5919 if (params->sta_modify_mask & STATION_PARAM_APPLY_CAPABILITY)
5920 return -EINVAL;
5921 if (params->supported_rates)
5922 return -EINVAL;
c4cbaf79
LC
5923 if (params->ext_capab || params->ht_capa || params->vht_capa ||
5924 params->he_capa)
77ee7c89
JB
5925 return -EINVAL;
5926 }
5927
47edb11b
AB
5928 if (statype != CFG80211_STA_AP_CLIENT &&
5929 statype != CFG80211_STA_AP_CLIENT_UNASSOC) {
77ee7c89
JB
5930 if (params->vlan)
5931 return -EINVAL;
5932 }
5933
5934 switch (statype) {
5935 case CFG80211_STA_AP_MLME_CLIENT:
5936 /* Use this only for authorizing/unauthorizing a station */
5937 if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)))
5938 return -EOPNOTSUPP;
5939 break;
5940 case CFG80211_STA_AP_CLIENT:
47edb11b 5941 case CFG80211_STA_AP_CLIENT_UNASSOC:
77ee7c89
JB
5942 /* accept only the listed bits */
5943 if (params->sta_flags_mask &
5944 ~(BIT(NL80211_STA_FLAG_AUTHORIZED) |
5945 BIT(NL80211_STA_FLAG_AUTHENTICATED) |
5946 BIT(NL80211_STA_FLAG_ASSOCIATED) |
5947 BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) |
5948 BIT(NL80211_STA_FLAG_WME) |
5949 BIT(NL80211_STA_FLAG_MFP)))
5950 return -EINVAL;
5951
5952 /* but authenticated/associated only if driver handles it */
5953 if (!(wiphy->features & NL80211_FEATURE_FULL_AP_CLIENT_STATE) &&
5954 params->sta_flags_mask &
5955 (BIT(NL80211_STA_FLAG_AUTHENTICATED) |
5956 BIT(NL80211_STA_FLAG_ASSOCIATED)))
5957 return -EINVAL;
5958 break;
5959 case CFG80211_STA_IBSS:
5960 case CFG80211_STA_AP_STA:
5961 /* reject any changes other than AUTHORIZED */
5962 if (params->sta_flags_mask & ~BIT(NL80211_STA_FLAG_AUTHORIZED))
5963 return -EINVAL;
5964 break;
5965 case CFG80211_STA_TDLS_PEER_SETUP:
5966 /* reject any changes other than AUTHORIZED or WME */
5967 if (params->sta_flags_mask & ~(BIT(NL80211_STA_FLAG_AUTHORIZED) |
5968 BIT(NL80211_STA_FLAG_WME)))
5969 return -EINVAL;
5970 /* force (at least) rates when authorizing */
5971 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED) &&
5972 !params->supported_rates)
5973 return -EINVAL;
5974 break;
5975 case CFG80211_STA_TDLS_PEER_ACTIVE:
5976 /* reject any changes */
5977 return -EINVAL;
eef941e6 5978 case CFG80211_STA_MESH_PEER_KERNEL:
77ee7c89
JB
5979 if (params->sta_modify_mask & STATION_PARAM_APPLY_PLINK_STATE)
5980 return -EINVAL;
5981 break;
eef941e6 5982 case CFG80211_STA_MESH_PEER_USER:
42925040
CYY
5983 if (params->plink_action != NL80211_PLINK_ACTION_NO_ACTION &&
5984 params->plink_action != NL80211_PLINK_ACTION_BLOCK)
77ee7c89
JB
5985 return -EINVAL;
5986 break;
5987 }
5988
06f7c88c
BL
5989 /*
5990 * Older kernel versions ignored this attribute entirely, so don't
5991 * reject attempts to update it but mark it as unused instead so the
5992 * driver won't look at the data.
5993 */
5994 if (statype != CFG80211_STA_AP_CLIENT_UNASSOC &&
5995 statype != CFG80211_STA_TDLS_PEER_SETUP)
5996 params->opmode_notif_used = false;
5997
77ee7c89
JB
5998 return 0;
5999}
6000EXPORT_SYMBOL(cfg80211_check_station_change);
6001
5727ef1b 6002/*
c258d2de 6003 * Get vlan interface making sure it is running and on the right wiphy.
5727ef1b 6004 */
80b99899
JB
6005static struct net_device *get_vlan(struct genl_info *info,
6006 struct cfg80211_registered_device *rdev)
5727ef1b 6007{
463d0183 6008 struct nlattr *vlanattr = info->attrs[NL80211_ATTR_STA_VLAN];
80b99899
JB
6009 struct net_device *v;
6010 int ret;
6011
6012 if (!vlanattr)
6013 return NULL;
6014
6015 v = dev_get_by_index(genl_info_net(info), nla_get_u32(vlanattr));
6016 if (!v)
6017 return ERR_PTR(-ENODEV);
6018
6019 if (!v->ieee80211_ptr || v->ieee80211_ptr->wiphy != &rdev->wiphy) {
6020 ret = -EINVAL;
6021 goto error;
5727ef1b 6022 }
80b99899 6023
77ee7c89
JB
6024 if (v->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
6025 v->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
6026 v->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
6027 ret = -EINVAL;
6028 goto error;
6029 }
6030
80b99899
JB
6031 if (!netif_running(v)) {
6032 ret = -ENETDOWN;
6033 goto error;
6034 }
6035
6036 return v;
6037 error:
6038 dev_put(v);
6039 return ERR_PTR(ret);
5727ef1b
JB
6040}
6041
94e860f1
JB
6042static const struct nla_policy
6043nl80211_sta_wme_policy[NL80211_STA_WME_MAX + 1] = {
df881293
JM
6044 [NL80211_STA_WME_UAPSD_QUEUES] = { .type = NLA_U8 },
6045 [NL80211_STA_WME_MAX_SP] = { .type = NLA_U8 },
6046};
6047
ff276691
JB
6048static int nl80211_parse_sta_wme(struct genl_info *info,
6049 struct station_parameters *params)
df881293 6050{
df881293
JM
6051 struct nlattr *tb[NL80211_STA_WME_MAX + 1];
6052 struct nlattr *nla;
6053 int err;
6054
df881293
JM
6055 /* parse WME attributes if present */
6056 if (!info->attrs[NL80211_ATTR_STA_WME])
6057 return 0;
6058
6059 nla = info->attrs[NL80211_ATTR_STA_WME];
8cb08174
JB
6060 err = nla_parse_nested_deprecated(tb, NL80211_STA_WME_MAX, nla,
6061 nl80211_sta_wme_policy,
6062 info->extack);
df881293
JM
6063 if (err)
6064 return err;
6065
6066 if (tb[NL80211_STA_WME_UAPSD_QUEUES])
6067 params->uapsd_queues = nla_get_u8(
6068 tb[NL80211_STA_WME_UAPSD_QUEUES]);
6069 if (params->uapsd_queues & ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK)
6070 return -EINVAL;
6071
6072 if (tb[NL80211_STA_WME_MAX_SP])
6073 params->max_sp = nla_get_u8(tb[NL80211_STA_WME_MAX_SP]);
6074
6075 if (params->max_sp & ~IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK)
6076 return -EINVAL;
6077
6078 params->sta_modify_mask |= STATION_PARAM_APPLY_UAPSD;
6079
6080 return 0;
6081}
6082
c01fc9ad
SD
6083static int nl80211_parse_sta_channel_info(struct genl_info *info,
6084 struct station_parameters *params)
6085{
6086 if (info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]) {
6087 params->supported_channels =
6088 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]);
6089 params->supported_channels_len =
6090 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]);
6091 /*
6092 * Need to include at least one (first channel, number of
cb9abd48
JB
6093 * channels) tuple for each subband (checked in policy),
6094 * and must have proper tuples for the rest of the data as well.
c01fc9ad 6095 */
c01fc9ad
SD
6096 if (params->supported_channels_len % 2)
6097 return -EINVAL;
6098 }
6099
6100 if (info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]) {
6101 params->supported_oper_classes =
6102 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]);
6103 params->supported_oper_classes_len =
6104 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]);
c01fc9ad
SD
6105 }
6106 return 0;
6107}
6108
ff276691
JB
6109static int nl80211_set_station_tdls(struct genl_info *info,
6110 struct station_parameters *params)
6111{
c01fc9ad 6112 int err;
ff276691 6113 /* Dummy STA entry gets updated once the peer capabilities are known */
5e4b6f56
JM
6114 if (info->attrs[NL80211_ATTR_PEER_AID])
6115 params->aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]);
ff276691
JB
6116 if (info->attrs[NL80211_ATTR_HT_CAPABILITY])
6117 params->ht_capa =
6118 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
6119 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY])
6120 params->vht_capa =
6121 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);
c4cbaf79
LC
6122 if (info->attrs[NL80211_ATTR_HE_CAPABILITY]) {
6123 params->he_capa =
6124 nla_data(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
6125 params->he_capa_len =
6126 nla_len(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
c4cbaf79 6127 }
ff276691 6128
c01fc9ad
SD
6129 err = nl80211_parse_sta_channel_info(info, params);
6130 if (err)
6131 return err;
6132
ff276691
JB
6133 return nl80211_parse_sta_wme(info, params);
6134}
6135
e96d1cd2
ARN
6136static int nl80211_parse_sta_txpower_setting(struct genl_info *info,
6137 struct station_parameters *params)
6138{
6139 struct cfg80211_registered_device *rdev = info->user_ptr[0];
6140 int idx;
6141
6142 if (info->attrs[NL80211_ATTR_STA_TX_POWER_SETTING]) {
6143 if (!rdev->ops->set_tx_power ||
6144 !wiphy_ext_feature_isset(&rdev->wiphy,
6145 NL80211_EXT_FEATURE_STA_TX_PWR))
6146 return -EOPNOTSUPP;
6147
6148 idx = NL80211_ATTR_STA_TX_POWER_SETTING;
6149 params->txpwr.type = nla_get_u8(info->attrs[idx]);
6150
6151 if (params->txpwr.type == NL80211_TX_POWER_LIMITED) {
6152 idx = NL80211_ATTR_STA_TX_POWER;
6153
6154 if (info->attrs[idx])
6155 params->txpwr.power =
6156 nla_get_s16(info->attrs[idx]);
6157 else
6158 return -EINVAL;
6159 }
6160 params->sta_modify_mask |= STATION_PARAM_APPLY_STA_TXPOWER;
6161 }
6162
6163 return 0;
6164}
6165
5727ef1b
JB
6166static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
6167{
4c476991 6168 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4c476991 6169 struct net_device *dev = info->user_ptr[1];
5727ef1b 6170 struct station_parameters params;
77ee7c89
JB
6171 u8 *mac_addr;
6172 int err;
5727ef1b
JB
6173
6174 memset(&params, 0, sizeof(params));
6175
77ee7c89
JB
6176 if (!rdev->ops->change_station)
6177 return -EOPNOTSUPP;
6178
e4208427
AB
6179 /*
6180 * AID and listen_interval properties can be set only for unassociated
6181 * station. Include these parameters here and will check them in
6182 * cfg80211_check_station_change().
6183 */
a9bc31e4
AB
6184 if (info->attrs[NL80211_ATTR_STA_AID])
6185 params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
e4208427 6186
14f34e36
GG
6187 if (info->attrs[NL80211_ATTR_VLAN_ID])
6188 params.vlan_id = nla_get_u16(info->attrs[NL80211_ATTR_VLAN_ID]);
6189
e4208427
AB
6190 if (info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
6191 params.listen_interval =
6192 nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
6193 else
6194 params.listen_interval = -1;
5727ef1b 6195
ab0d76f6
JB
6196 if (info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS])
6197 params.support_p2p_ps =
6198 nla_get_u8(info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]);
6199 else
17b94247 6200 params.support_p2p_ps = -1;
17b94247 6201
5727ef1b
JB
6202 if (!info->attrs[NL80211_ATTR_MAC])
6203 return -EINVAL;
6204
6205 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
6206
6207 if (info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]) {
6208 params.supported_rates =
6209 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
6210 params.supported_rates_len =
6211 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
6212 }
6213
9d62a986
JM
6214 if (info->attrs[NL80211_ATTR_STA_CAPABILITY]) {
6215 params.capability =
6216 nla_get_u16(info->attrs[NL80211_ATTR_STA_CAPABILITY]);
6217 params.sta_modify_mask |= STATION_PARAM_APPLY_CAPABILITY;
6218 }
6219
6220 if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]) {
6221 params.ext_capab =
6222 nla_data(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]);
6223 params.ext_capab_len =
6224 nla_len(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]);
6225 }
6226
bdd3ae3d 6227 if (parse_station_flags(info, dev->ieee80211_ptr->iftype, &params))
5727ef1b
JB
6228 return -EINVAL;
6229
ab0d76f6 6230 if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION])
2ec600d6 6231 params.plink_action =
f8bacc21 6232 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
2ec600d6 6233
f8bacc21 6234 if (info->attrs[NL80211_ATTR_STA_PLINK_STATE]) {
9c3990aa 6235 params.plink_state =
f8bacc21 6236 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_STATE]);
ab0d76f6 6237 if (info->attrs[NL80211_ATTR_MESH_PEER_AID])
7d27a0ba
MH
6238 params.peer_aid = nla_get_u16(
6239 info->attrs[NL80211_ATTR_MESH_PEER_AID]);
f8bacc21
JB
6240 params.sta_modify_mask |= STATION_PARAM_APPLY_PLINK_STATE;
6241 }
9c3990aa 6242
ab0d76f6
JB
6243 if (info->attrs[NL80211_ATTR_LOCAL_MESH_POWER_MODE])
6244 params.local_pm = nla_get_u32(
3b1c5a53
MP
6245 info->attrs[NL80211_ATTR_LOCAL_MESH_POWER_MODE]);
6246
06f7c88c
BL
6247 if (info->attrs[NL80211_ATTR_OPMODE_NOTIF]) {
6248 params.opmode_notif_used = true;
6249 params.opmode_notif =
6250 nla_get_u8(info->attrs[NL80211_ATTR_OPMODE_NOTIF]);
6251 }
6252
43e64bf3
RM
6253 if (info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY])
6254 params.he_6ghz_capa =
fce2ff72 6255 nla_data(info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY]);
43e64bf3 6256
36647055
THJ
6257 if (info->attrs[NL80211_ATTR_AIRTIME_WEIGHT])
6258 params.airtime_weight =
6259 nla_get_u16(info->attrs[NL80211_ATTR_AIRTIME_WEIGHT]);
6260
6261 if (params.airtime_weight &&
6262 !wiphy_ext_feature_isset(&rdev->wiphy,
6263 NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))
6264 return -EOPNOTSUPP;
6265
e96d1cd2
ARN
6266 err = nl80211_parse_sta_txpower_setting(info, &params);
6267 if (err)
6268 return err;
6269
77ee7c89
JB
6270 /* Include parameters for TDLS peer (will check later) */
6271 err = nl80211_set_station_tdls(info, &params);
6272 if (err)
6273 return err;
6274
6275 params.vlan = get_vlan(info, rdev);
6276 if (IS_ERR(params.vlan))
6277 return PTR_ERR(params.vlan);
6278
a97f4424
JB
6279 switch (dev->ieee80211_ptr->iftype) {
6280 case NL80211_IFTYPE_AP:
6281 case NL80211_IFTYPE_AP_VLAN:
074ac8df 6282 case NL80211_IFTYPE_P2P_GO:
074ac8df 6283 case NL80211_IFTYPE_P2P_CLIENT:
a97f4424 6284 case NL80211_IFTYPE_STATION:
267335d6 6285 case NL80211_IFTYPE_ADHOC:
a97f4424 6286 case NL80211_IFTYPE_MESH_POINT:
a97f4424
JB
6287 break;
6288 default:
77ee7c89
JB
6289 err = -EOPNOTSUPP;
6290 goto out_put_vlan;
034d655e
JB
6291 }
6292
77ee7c89 6293 /* driver will call cfg80211_check_station_change() */
e35e4d28 6294 err = rdev_change_station(rdev, dev, mac_addr, &params);
5727ef1b 6295
77ee7c89 6296 out_put_vlan:
5727ef1b
JB
6297 if (params.vlan)
6298 dev_put(params.vlan);
3b85875a 6299
5727ef1b
JB
6300 return err;
6301}
6302
6303static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
6304{
4c476991 6305 struct cfg80211_registered_device *rdev = info->user_ptr[0];
5727ef1b 6306 int err;
4c476991 6307 struct net_device *dev = info->user_ptr[1];
5727ef1b
JB
6308 struct station_parameters params;
6309 u8 *mac_addr = NULL;
bda95eb1
JB
6310 u32 auth_assoc = BIT(NL80211_STA_FLAG_AUTHENTICATED) |
6311 BIT(NL80211_STA_FLAG_ASSOCIATED);
5727ef1b
JB
6312
6313 memset(&params, 0, sizeof(params));
6314
984c311b
JB
6315 if (!rdev->ops->add_station)
6316 return -EOPNOTSUPP;
6317
5727ef1b
JB
6318 if (!info->attrs[NL80211_ATTR_MAC])
6319 return -EINVAL;
6320
5727ef1b
JB
6321 if (!info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
6322 return -EINVAL;
6323
6324 if (!info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES])
6325 return -EINVAL;
6326
5e4b6f56
JM
6327 if (!info->attrs[NL80211_ATTR_STA_AID] &&
6328 !info->attrs[NL80211_ATTR_PEER_AID])
0e956c13
TLSC
6329 return -EINVAL;
6330
5727ef1b
JB
6331 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
6332 params.supported_rates =
6333 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
6334 params.supported_rates_len =
6335 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
6336 params.listen_interval =
6337 nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
51b50fbe 6338
14f34e36
GG
6339 if (info->attrs[NL80211_ATTR_VLAN_ID])
6340 params.vlan_id = nla_get_u16(info->attrs[NL80211_ATTR_VLAN_ID]);
6341
17b94247 6342 if (info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]) {
ab0d76f6
JB
6343 params.support_p2p_ps =
6344 nla_get_u8(info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]);
17b94247
AB
6345 } else {
6346 /*
6347 * if not specified, assume it's supported for P2P GO interface,
6348 * and is NOT supported for AP interface
6349 */
6350 params.support_p2p_ps =
6351 dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO;
6352 }
6353
3d124ea2 6354 if (info->attrs[NL80211_ATTR_PEER_AID])
5e4b6f56 6355 params.aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]);
3d124ea2
JM
6356 else
6357 params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
51b50fbe 6358
9d62a986
JM
6359 if (info->attrs[NL80211_ATTR_STA_CAPABILITY]) {
6360 params.capability =
6361 nla_get_u16(info->attrs[NL80211_ATTR_STA_CAPABILITY]);
6362 params.sta_modify_mask |= STATION_PARAM_APPLY_CAPABILITY;
6363 }
6364
6365 if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]) {
6366 params.ext_capab =
6367 nla_data(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]);
6368 params.ext_capab_len =
6369 nla_len(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]);
6370 }
6371
36aedc90
JM
6372 if (info->attrs[NL80211_ATTR_HT_CAPABILITY])
6373 params.ht_capa =
6374 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
5727ef1b 6375
f461be3e
MP
6376 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY])
6377 params.vht_capa =
6378 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);
6379
c4cbaf79
LC
6380 if (info->attrs[NL80211_ATTR_HE_CAPABILITY]) {
6381 params.he_capa =
6382 nla_data(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
6383 params.he_capa_len =
6384 nla_len(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
c4cbaf79
LC
6385 }
6386
43e64bf3
RM
6387 if (info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY])
6388 params.he_6ghz_capa =
6389 nla_data(info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY]);
6390
60f4a7b1
MK
6391 if (info->attrs[NL80211_ATTR_OPMODE_NOTIF]) {
6392 params.opmode_notif_used = true;
6393 params.opmode_notif =
6394 nla_get_u8(info->attrs[NL80211_ATTR_OPMODE_NOTIF]);
6395 }
6396
ab0d76f6 6397 if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION])
96b78dff 6398 params.plink_action =
f8bacc21 6399 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
96b78dff 6400
36647055
THJ
6401 if (info->attrs[NL80211_ATTR_AIRTIME_WEIGHT])
6402 params.airtime_weight =
6403 nla_get_u16(info->attrs[NL80211_ATTR_AIRTIME_WEIGHT]);
6404
6405 if (params.airtime_weight &&
6406 !wiphy_ext_feature_isset(&rdev->wiphy,
6407 NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))
6408 return -EOPNOTSUPP;
6409
e96d1cd2
ARN
6410 err = nl80211_parse_sta_txpower_setting(info, &params);
6411 if (err)
6412 return err;
6413
c01fc9ad
SD
6414 err = nl80211_parse_sta_channel_info(info, &params);
6415 if (err)
6416 return err;
6417
ff276691
JB
6418 err = nl80211_parse_sta_wme(info, &params);
6419 if (err)
6420 return err;
bdd90d5e 6421
bdd3ae3d 6422 if (parse_station_flags(info, dev->ieee80211_ptr->iftype, &params))
5727ef1b
JB
6423 return -EINVAL;
6424
496fcc29
JB
6425 /* HT/VHT requires QoS, but if we don't have that just ignore HT/VHT
6426 * as userspace might just pass through the capabilities from the IEs
6427 * directly, rather than enforcing this restriction and returning an
6428 * error in this case.
6429 */
6430 if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_WME))) {
6431 params.ht_capa = NULL;
6432 params.vht_capa = NULL;
c4cbaf79
LC
6433
6434 /* HE requires WME */
43e64bf3 6435 if (params.he_capa_len || params.he_6ghz_capa)
c4cbaf79 6436 return -EINVAL;
496fcc29
JB
6437 }
6438
43e64bf3
RM
6439 /* Ensure that HT/VHT capabilities are not set for 6 GHz HE STA */
6440 if (params.he_6ghz_capa && (params.ht_capa || params.vht_capa))
6441 return -EINVAL;
6442
77ee7c89
JB
6443 /* When you run into this, adjust the code below for the new flag */
6444 BUILD_BUG_ON(NL80211_STA_FLAG_MAX != 7);
6445
bdd90d5e
JB
6446 switch (dev->ieee80211_ptr->iftype) {
6447 case NL80211_IFTYPE_AP:
6448 case NL80211_IFTYPE_AP_VLAN:
6449 case NL80211_IFTYPE_P2P_GO:
984c311b
JB
6450 /* ignore WME attributes if iface/sta is not capable */
6451 if (!(rdev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) ||
6452 !(params.sta_flags_set & BIT(NL80211_STA_FLAG_WME)))
6453 params.sta_modify_mask &= ~STATION_PARAM_APPLY_UAPSD;
c75786c9 6454
bdd90d5e 6455 /* TDLS peers cannot be added */
3d124ea2
JM
6456 if ((params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) ||
6457 info->attrs[NL80211_ATTR_PEER_AID])
4319e193 6458 return -EINVAL;
bdd90d5e
JB
6459 /* but don't bother the driver with it */
6460 params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
3b9ce80c 6461
d582cffb
JB
6462 /* allow authenticated/associated only if driver handles it */
6463 if (!(rdev->wiphy.features &
6464 NL80211_FEATURE_FULL_AP_CLIENT_STATE) &&
bda95eb1 6465 params.sta_flags_mask & auth_assoc)
d582cffb
JB
6466 return -EINVAL;
6467
bda95eb1
JB
6468 /* Older userspace, or userspace wanting to be compatible with
6469 * !NL80211_FEATURE_FULL_AP_CLIENT_STATE, will not set the auth
6470 * and assoc flags in the mask, but assumes the station will be
6471 * added as associated anyway since this was the required driver
6472 * behaviour before NL80211_FEATURE_FULL_AP_CLIENT_STATE was
6473 * introduced.
6474 * In order to not bother drivers with this quirk in the API
6475 * set the flags in both the mask and set for new stations in
6476 * this case.
6477 */
6478 if (!(params.sta_flags_mask & auth_assoc)) {
6479 params.sta_flags_mask |= auth_assoc;
6480 params.sta_flags_set |= auth_assoc;
6481 }
6482
bdd90d5e
JB
6483 /* must be last in here for error handling */
6484 params.vlan = get_vlan(info, rdev);
6485 if (IS_ERR(params.vlan))
6486 return PTR_ERR(params.vlan);
6487 break;
6488 case NL80211_IFTYPE_MESH_POINT:
984c311b
JB
6489 /* ignore uAPSD data */
6490 params.sta_modify_mask &= ~STATION_PARAM_APPLY_UAPSD;
6491
d582cffb
JB
6492 /* associated is disallowed */
6493 if (params.sta_flags_mask & BIT(NL80211_STA_FLAG_ASSOCIATED))
6494 return -EINVAL;
bdd90d5e 6495 /* TDLS peers cannot be added */
3d124ea2
JM
6496 if ((params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) ||
6497 info->attrs[NL80211_ATTR_PEER_AID])
bdd90d5e
JB
6498 return -EINVAL;
6499 break;
6500 case NL80211_IFTYPE_STATION:
93d08f0b 6501 case NL80211_IFTYPE_P2P_CLIENT:
984c311b
JB
6502 /* ignore uAPSD data */
6503 params.sta_modify_mask &= ~STATION_PARAM_APPLY_UAPSD;
6504
77ee7c89
JB
6505 /* these are disallowed */
6506 if (params.sta_flags_mask &
6507 (BIT(NL80211_STA_FLAG_ASSOCIATED) |
6508 BIT(NL80211_STA_FLAG_AUTHENTICATED)))
d582cffb 6509 return -EINVAL;
bdd90d5e
JB
6510 /* Only TDLS peers can be added */
6511 if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))
6512 return -EINVAL;
6513 /* Can only add if TDLS ... */
6514 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS))
6515 return -EOPNOTSUPP;
6516 /* ... with external setup is supported */
6517 if (!(rdev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP))
6518 return -EOPNOTSUPP;
77ee7c89
JB
6519 /*
6520 * Older wpa_supplicant versions always mark the TDLS peer
6521 * as authorized, but it shouldn't yet be.
6522 */
6523 params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_AUTHORIZED);
bdd90d5e
JB
6524 break;
6525 default:
6526 return -EOPNOTSUPP;
c75786c9
EP
6527 }
6528
bdd90d5e 6529 /* be aware of params.vlan when changing code here */
5727ef1b 6530
e35e4d28 6531 err = rdev_add_station(rdev, dev, mac_addr, &params);
5727ef1b 6532
5727ef1b
JB
6533 if (params.vlan)
6534 dev_put(params.vlan);
5727ef1b
JB
6535 return err;
6536}
6537
6538static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info)
6539{
4c476991
JB
6540 struct cfg80211_registered_device *rdev = info->user_ptr[0];
6541 struct net_device *dev = info->user_ptr[1];
89c771e5
JM
6542 struct station_del_parameters params;
6543
6544 memset(&params, 0, sizeof(params));
5727ef1b
JB
6545
6546 if (info->attrs[NL80211_ATTR_MAC])
89c771e5 6547 params.mac = nla_data(info->attrs[NL80211_ATTR_MAC]);
5727ef1b 6548
306b79ea
JB
6549 switch (dev->ieee80211_ptr->iftype) {
6550 case NL80211_IFTYPE_AP:
6551 case NL80211_IFTYPE_AP_VLAN:
6552 case NL80211_IFTYPE_MESH_POINT:
6553 case NL80211_IFTYPE_P2P_GO:
6554 /* always accept these */
6555 break;
6556 case NL80211_IFTYPE_ADHOC:
6557 /* conditionally accept */
6558 if (wiphy_ext_feature_isset(&rdev->wiphy,
6559 NL80211_EXT_FEATURE_DEL_IBSS_STA))
6560 break;
edafcf42 6561 return -EINVAL;
306b79ea 6562 default:
4c476991 6563 return -EINVAL;
306b79ea 6564 }
5727ef1b 6565
4c476991
JB
6566 if (!rdev->ops->del_station)
6567 return -EOPNOTSUPP;
3b85875a 6568
98856866
JM
6569 if (info->attrs[NL80211_ATTR_MGMT_SUBTYPE]) {
6570 params.subtype =
6571 nla_get_u8(info->attrs[NL80211_ATTR_MGMT_SUBTYPE]);
6572 if (params.subtype != IEEE80211_STYPE_DISASSOC >> 4 &&
6573 params.subtype != IEEE80211_STYPE_DEAUTH >> 4)
6574 return -EINVAL;
6575 } else {
6576 /* Default to Deauthentication frame */
6577 params.subtype = IEEE80211_STYPE_DEAUTH >> 4;
6578 }
6579
6580 if (info->attrs[NL80211_ATTR_REASON_CODE]) {
6581 params.reason_code =
6582 nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
6583 if (params.reason_code == 0)
6584 return -EINVAL; /* 0 is reserved */
6585 } else {
6586 /* Default to reason code 2 */
6587 params.reason_code = WLAN_REASON_PREV_AUTH_NOT_VALID;
6588 }
6589
89c771e5 6590 return rdev_del_station(rdev, dev, &params);
5727ef1b
JB
6591}
6592
15e47304 6593static int nl80211_send_mpath(struct sk_buff *msg, u32 portid, u32 seq,
2ec600d6
LCC
6594 int flags, struct net_device *dev,
6595 u8 *dst, u8 *next_hop,
6596 struct mpath_info *pinfo)
6597{
6598 void *hdr;
6599 struct nlattr *pinfoattr;
6600
1ef4c850 6601 hdr = nl80211hdr_put(msg, portid, seq, flags, NL80211_CMD_NEW_MPATH);
2ec600d6
LCC
6602 if (!hdr)
6603 return -1;
6604
9360ffd1
DM
6605 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
6606 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, dst) ||
6607 nla_put(msg, NL80211_ATTR_MPATH_NEXT_HOP, ETH_ALEN, next_hop) ||
6608 nla_put_u32(msg, NL80211_ATTR_GENERATION, pinfo->generation))
6609 goto nla_put_failure;
f5ea9120 6610
ae0be8de 6611 pinfoattr = nla_nest_start_noflag(msg, NL80211_ATTR_MPATH_INFO);
2ec600d6
LCC
6612 if (!pinfoattr)
6613 goto nla_put_failure;
9360ffd1
DM
6614 if ((pinfo->filled & MPATH_INFO_FRAME_QLEN) &&
6615 nla_put_u32(msg, NL80211_MPATH_INFO_FRAME_QLEN,
6616 pinfo->frame_qlen))
6617 goto nla_put_failure;
6618 if (((pinfo->filled & MPATH_INFO_SN) &&
6619 nla_put_u32(msg, NL80211_MPATH_INFO_SN, pinfo->sn)) ||
6620 ((pinfo->filled & MPATH_INFO_METRIC) &&
6621 nla_put_u32(msg, NL80211_MPATH_INFO_METRIC,
6622 pinfo->metric)) ||
6623 ((pinfo->filled & MPATH_INFO_EXPTIME) &&
6624 nla_put_u32(msg, NL80211_MPATH_INFO_EXPTIME,
6625 pinfo->exptime)) ||
6626 ((pinfo->filled & MPATH_INFO_FLAGS) &&
6627 nla_put_u8(msg, NL80211_MPATH_INFO_FLAGS,
6628 pinfo->flags)) ||
6629 ((pinfo->filled & MPATH_INFO_DISCOVERY_TIMEOUT) &&
6630 nla_put_u32(msg, NL80211_MPATH_INFO_DISCOVERY_TIMEOUT,
6631 pinfo->discovery_timeout)) ||
6632 ((pinfo->filled & MPATH_INFO_DISCOVERY_RETRIES) &&
6633 nla_put_u8(msg, NL80211_MPATH_INFO_DISCOVERY_RETRIES,
cc241636
JH
6634 pinfo->discovery_retries)) ||
6635 ((pinfo->filled & MPATH_INFO_HOP_COUNT) &&
6636 nla_put_u8(msg, NL80211_MPATH_INFO_HOP_COUNT,
540bbcb9
JH
6637 pinfo->hop_count)) ||
6638 ((pinfo->filled & MPATH_INFO_PATH_CHANGE) &&
6639 nla_put_u32(msg, NL80211_MPATH_INFO_PATH_CHANGE,
6640 pinfo->path_change_count)))
9360ffd1 6641 goto nla_put_failure;
2ec600d6
LCC
6642
6643 nla_nest_end(msg, pinfoattr);
6644
053c095a
JB
6645 genlmsg_end(msg, hdr);
6646 return 0;
2ec600d6
LCC
6647
6648 nla_put_failure:
bc3ed28c
TG
6649 genlmsg_cancel(msg, hdr);
6650 return -EMSGSIZE;
2ec600d6
LCC
6651}
6652
6653static int nl80211_dump_mpath(struct sk_buff *skb,
bba95fef 6654 struct netlink_callback *cb)
2ec600d6 6655{
2ec600d6 6656 struct mpath_info pinfo;
1b8ec87a 6657 struct cfg80211_registered_device *rdev;
97990a06 6658 struct wireless_dev *wdev;
2ec600d6
LCC
6659 u8 dst[ETH_ALEN];
6660 u8 next_hop[ETH_ALEN];
97990a06 6661 int path_idx = cb->args[2];
2ec600d6 6662 int err;
2ec600d6 6663
ea90e0dc 6664 rtnl_lock();
5297c65c 6665 err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev);
67748893 6666 if (err)
ea90e0dc 6667 goto out_err;
bba95fef 6668
1b8ec87a 6669 if (!rdev->ops->dump_mpath) {
eec60b03 6670 err = -EOPNOTSUPP;
bba95fef
JB
6671 goto out_err;
6672 }
6673
97990a06 6674 if (wdev->iftype != NL80211_IFTYPE_MESH_POINT) {
eec60b03 6675 err = -EOPNOTSUPP;
0448b5fc 6676 goto out_err;
eec60b03
JM
6677 }
6678
bba95fef 6679 while (1) {
1b8ec87a 6680 err = rdev_dump_mpath(rdev, wdev->netdev, path_idx, dst,
97990a06 6681 next_hop, &pinfo);
bba95fef 6682 if (err == -ENOENT)
2ec600d6 6683 break;
bba95fef 6684 if (err)
3b85875a 6685 goto out_err;
2ec600d6 6686
15e47304 6687 if (nl80211_send_mpath(skb, NETLINK_CB(cb->skb).portid,
bba95fef 6688 cb->nlh->nlmsg_seq, NLM_F_MULTI,
97990a06 6689 wdev->netdev, dst, next_hop,
bba95fef
JB
6690 &pinfo) < 0)
6691 goto out;
2ec600d6 6692
bba95fef 6693 path_idx++;
2ec600d6 6694 }
2ec600d6 6695
bba95fef 6696 out:
97990a06 6697 cb->args[2] = path_idx;
bba95fef 6698 err = skb->len;
bba95fef 6699 out_err:
ea90e0dc 6700 rtnl_unlock();
bba95fef 6701 return err;
2ec600d6
LCC
6702}
6703
6704static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info)
6705{
4c476991 6706 struct cfg80211_registered_device *rdev = info->user_ptr[0];
2ec600d6 6707 int err;
4c476991 6708 struct net_device *dev = info->user_ptr[1];
2ec600d6
LCC
6709 struct mpath_info pinfo;
6710 struct sk_buff *msg;
6711 u8 *dst = NULL;
6712 u8 next_hop[ETH_ALEN];
6713
6714 memset(&pinfo, 0, sizeof(pinfo));
6715
6716 if (!info->attrs[NL80211_ATTR_MAC])
6717 return -EINVAL;
6718
6719 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
6720
4c476991
JB
6721 if (!rdev->ops->get_mpath)
6722 return -EOPNOTSUPP;
2ec600d6 6723
4c476991
JB
6724 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
6725 return -EOPNOTSUPP;
eec60b03 6726
e35e4d28 6727 err = rdev_get_mpath(rdev, dev, dst, next_hop, &pinfo);
2ec600d6 6728 if (err)
4c476991 6729 return err;
2ec600d6 6730
fd2120ca 6731 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2ec600d6 6732 if (!msg)
4c476991 6733 return -ENOMEM;
2ec600d6 6734
15e47304 6735 if (nl80211_send_mpath(msg, info->snd_portid, info->snd_seq, 0,
4c476991
JB
6736 dev, dst, next_hop, &pinfo) < 0) {
6737 nlmsg_free(msg);
6738 return -ENOBUFS;
6739 }
3b85875a 6740
4c476991 6741 return genlmsg_reply(msg, info);
2ec600d6
LCC
6742}
6743
6744static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info)
6745{
4c476991
JB
6746 struct cfg80211_registered_device *rdev = info->user_ptr[0];
6747 struct net_device *dev = info->user_ptr[1];
2ec600d6
LCC
6748 u8 *dst = NULL;
6749 u8 *next_hop = NULL;
6750
6751 if (!info->attrs[NL80211_ATTR_MAC])
6752 return -EINVAL;
6753
6754 if (!info->attrs[NL80211_ATTR_MPATH_NEXT_HOP])
6755 return -EINVAL;
6756
6757 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
6758 next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);
6759
4c476991
JB
6760 if (!rdev->ops->change_mpath)
6761 return -EOPNOTSUPP;
35a8efe1 6762
4c476991
JB
6763 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
6764 return -EOPNOTSUPP;
2ec600d6 6765
e35e4d28 6766 return rdev_change_mpath(rdev, dev, dst, next_hop);
2ec600d6 6767}
4c476991 6768
2ec600d6
LCC
6769static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info)
6770{
4c476991
JB
6771 struct cfg80211_registered_device *rdev = info->user_ptr[0];
6772 struct net_device *dev = info->user_ptr[1];
2ec600d6
LCC
6773 u8 *dst = NULL;
6774 u8 *next_hop = NULL;
6775
6776 if (!info->attrs[NL80211_ATTR_MAC])
6777 return -EINVAL;
6778
6779 if (!info->attrs[NL80211_ATTR_MPATH_NEXT_HOP])
6780 return -EINVAL;
6781
6782 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
6783 next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);
6784
4c476991
JB
6785 if (!rdev->ops->add_mpath)
6786 return -EOPNOTSUPP;
35a8efe1 6787
4c476991
JB
6788 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
6789 return -EOPNOTSUPP;
2ec600d6 6790
e35e4d28 6791 return rdev_add_mpath(rdev, dev, dst, next_hop);
2ec600d6
LCC
6792}
6793
6794static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info)
6795{
4c476991
JB
6796 struct cfg80211_registered_device *rdev = info->user_ptr[0];
6797 struct net_device *dev = info->user_ptr[1];
2ec600d6
LCC
6798 u8 *dst = NULL;
6799
6800 if (info->attrs[NL80211_ATTR_MAC])
6801 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
6802
4c476991
JB
6803 if (!rdev->ops->del_mpath)
6804 return -EOPNOTSUPP;
3b85875a 6805
b501426c
MP
6806 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
6807 return -EOPNOTSUPP;
6808
e35e4d28 6809 return rdev_del_mpath(rdev, dev, dst);
2ec600d6
LCC
6810}
6811
66be7d2b
HR
6812static int nl80211_get_mpp(struct sk_buff *skb, struct genl_info *info)
6813{
6814 struct cfg80211_registered_device *rdev = info->user_ptr[0];
6815 int err;
6816 struct net_device *dev = info->user_ptr[1];
6817 struct mpath_info pinfo;
6818 struct sk_buff *msg;
6819 u8 *dst = NULL;
6820 u8 mpp[ETH_ALEN];
6821
6822 memset(&pinfo, 0, sizeof(pinfo));
6823
6824 if (!info->attrs[NL80211_ATTR_MAC])
6825 return -EINVAL;
6826
6827 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
6828
6829 if (!rdev->ops->get_mpp)
6830 return -EOPNOTSUPP;
6831
6832 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
6833 return -EOPNOTSUPP;
6834
6835 err = rdev_get_mpp(rdev, dev, dst, mpp, &pinfo);
6836 if (err)
6837 return err;
6838
6839 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
6840 if (!msg)
6841 return -ENOMEM;
6842
6843 if (nl80211_send_mpath(msg, info->snd_portid, info->snd_seq, 0,
6844 dev, dst, mpp, &pinfo) < 0) {
6845 nlmsg_free(msg);
6846 return -ENOBUFS;
6847 }
6848
6849 return genlmsg_reply(msg, info);
6850}
6851
6852static int nl80211_dump_mpp(struct sk_buff *skb,
6853 struct netlink_callback *cb)
6854{
6855 struct mpath_info pinfo;
6856 struct cfg80211_registered_device *rdev;
6857 struct wireless_dev *wdev;
6858 u8 dst[ETH_ALEN];
6859 u8 mpp[ETH_ALEN];
6860 int path_idx = cb->args[2];
6861 int err;
6862
ea90e0dc 6863 rtnl_lock();
5297c65c 6864 err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev);
66be7d2b 6865 if (err)
ea90e0dc 6866 goto out_err;
66be7d2b
HR
6867
6868 if (!rdev->ops->dump_mpp) {
6869 err = -EOPNOTSUPP;
6870 goto out_err;
6871 }
6872
6873 if (wdev->iftype != NL80211_IFTYPE_MESH_POINT) {
6874 err = -EOPNOTSUPP;
6875 goto out_err;
6876 }
6877
6878 while (1) {
6879 err = rdev_dump_mpp(rdev, wdev->netdev, path_idx, dst,
6880 mpp, &pinfo);
6881 if (err == -ENOENT)
6882 break;
6883 if (err)
6884 goto out_err;
6885
6886 if (nl80211_send_mpath(skb, NETLINK_CB(cb->skb).portid,
6887 cb->nlh->nlmsg_seq, NLM_F_MULTI,
6888 wdev->netdev, dst, mpp,
6889 &pinfo) < 0)
6890 goto out;
6891
6892 path_idx++;
6893 }
6894
6895 out:
6896 cb->args[2] = path_idx;
6897 err = skb->len;
6898 out_err:
ea90e0dc 6899 rtnl_unlock();
66be7d2b
HR
6900 return err;
6901}
6902
9f1ba906
JM
6903static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
6904{
4c476991
JB
6905 struct cfg80211_registered_device *rdev = info->user_ptr[0];
6906 struct net_device *dev = info->user_ptr[1];
c56589ed 6907 struct wireless_dev *wdev = dev->ieee80211_ptr;
9f1ba906 6908 struct bss_parameters params;
c56589ed 6909 int err;
9f1ba906
JM
6910
6911 memset(&params, 0, sizeof(params));
6912 /* default to not changing parameters */
6913 params.use_cts_prot = -1;
6914 params.use_short_preamble = -1;
6915 params.use_short_slot_time = -1;
fd8aaaf3 6916 params.ap_isolate = -1;
50b12f59 6917 params.ht_opmode = -1;
53cabad7
JB
6918 params.p2p_ctwindow = -1;
6919 params.p2p_opp_ps = -1;
9f1ba906
JM
6920
6921 if (info->attrs[NL80211_ATTR_BSS_CTS_PROT])
6922 params.use_cts_prot =
6923 nla_get_u8(info->attrs[NL80211_ATTR_BSS_CTS_PROT]);
6924 if (info->attrs[NL80211_ATTR_BSS_SHORT_PREAMBLE])
6925 params.use_short_preamble =
6926 nla_get_u8(info->attrs[NL80211_ATTR_BSS_SHORT_PREAMBLE]);
6927 if (info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME])
6928 params.use_short_slot_time =
6929 nla_get_u8(info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME]);
90c97a04
JM
6930 if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) {
6931 params.basic_rates =
6932 nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
6933 params.basic_rates_len =
6934 nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
6935 }
fd8aaaf3
FF
6936 if (info->attrs[NL80211_ATTR_AP_ISOLATE])
6937 params.ap_isolate = !!nla_get_u8(info->attrs[NL80211_ATTR_AP_ISOLATE]);
50b12f59
HS
6938 if (info->attrs[NL80211_ATTR_BSS_HT_OPMODE])
6939 params.ht_opmode =
6940 nla_get_u16(info->attrs[NL80211_ATTR_BSS_HT_OPMODE]);
9f1ba906 6941
53cabad7
JB
6942 if (info->attrs[NL80211_ATTR_P2P_CTWINDOW]) {
6943 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
6944 return -EINVAL;
6945 params.p2p_ctwindow =
ab0d76f6 6946 nla_get_u8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]);
53cabad7
JB
6947 if (params.p2p_ctwindow != 0 &&
6948 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN))
6949 return -EINVAL;
6950 }
6951
6952 if (info->attrs[NL80211_ATTR_P2P_OPPPS]) {
6953 u8 tmp;
6954
6955 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
6956 return -EINVAL;
6957 tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]);
53cabad7
JB
6958 params.p2p_opp_ps = tmp;
6959 if (params.p2p_opp_ps &&
6960 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS))
6961 return -EINVAL;
6962 }
6963
4c476991
JB
6964 if (!rdev->ops->change_bss)
6965 return -EOPNOTSUPP;
9f1ba906 6966
074ac8df 6967 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
4c476991
JB
6968 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
6969 return -EOPNOTSUPP;
3b85875a 6970
c56589ed
SW
6971 wdev_lock(wdev);
6972 err = rdev_change_bss(rdev, dev, &params);
6973 wdev_unlock(wdev);
6974
6975 return err;
9f1ba906
JM
6976}
6977
b2e1b302
LR
6978static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info)
6979{
b2e1b302 6980 char *data = NULL;
05050753 6981 bool is_indoor;
57b5ce07 6982 enum nl80211_user_reg_hint_type user_reg_hint_type;
05050753
I
6983 u32 owner_nlportid;
6984
80778f18
LR
6985 /*
6986 * You should only get this when cfg80211 hasn't yet initialized
6987 * completely when built-in to the kernel right between the time
6988 * window between nl80211_init() and regulatory_init(), if that is
6989 * even possible.
6990 */
458f4f9e 6991 if (unlikely(!rcu_access_pointer(cfg80211_regdomain)))
fe33eb39 6992 return -EINPROGRESS;
80778f18 6993
57b5ce07
LR
6994 if (info->attrs[NL80211_ATTR_USER_REG_HINT_TYPE])
6995 user_reg_hint_type =
6996 nla_get_u32(info->attrs[NL80211_ATTR_USER_REG_HINT_TYPE]);
6997 else
6998 user_reg_hint_type = NL80211_USER_REG_HINT_USER;
6999
7000 switch (user_reg_hint_type) {
7001 case NL80211_USER_REG_HINT_USER:
7002 case NL80211_USER_REG_HINT_CELL_BASE:
52616f2b
IP
7003 if (!info->attrs[NL80211_ATTR_REG_ALPHA2])
7004 return -EINVAL;
7005
7006 data = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]);
7007 return regulatory_hint_user(data, user_reg_hint_type);
7008 case NL80211_USER_REG_HINT_INDOOR:
05050753
I
7009 if (info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
7010 owner_nlportid = info->snd_portid;
7011 is_indoor = !!info->attrs[NL80211_ATTR_REG_INDOOR];
7012 } else {
7013 owner_nlportid = 0;
7014 is_indoor = true;
7015 }
7016
7017 return regulatory_hint_indoor(is_indoor, owner_nlportid);
57b5ce07
LR
7018 default:
7019 return -EINVAL;
7020 }
b2e1b302
LR
7021}
7022
1ea4ff3e
JB
7023static int nl80211_reload_regdb(struct sk_buff *skb, struct genl_info *info)
7024{
7025 return reg_reload_regdb();
7026}
7027
24bdd9f4 7028static int nl80211_get_mesh_config(struct sk_buff *skb,
29cbe68c 7029 struct genl_info *info)
93da9cc1 7030{
4c476991 7031 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4c476991 7032 struct net_device *dev = info->user_ptr[1];
29cbe68c
JB
7033 struct wireless_dev *wdev = dev->ieee80211_ptr;
7034 struct mesh_config cur_params;
7035 int err = 0;
93da9cc1 7036 void *hdr;
7037 struct nlattr *pinfoattr;
7038 struct sk_buff *msg;
7039
29cbe68c
JB
7040 if (wdev->iftype != NL80211_IFTYPE_MESH_POINT)
7041 return -EOPNOTSUPP;
7042
24bdd9f4 7043 if (!rdev->ops->get_mesh_config)
4c476991 7044 return -EOPNOTSUPP;
f3f92586 7045
29cbe68c
JB
7046 wdev_lock(wdev);
7047 /* If not connected, get default parameters */
7048 if (!wdev->mesh_id_len)
7049 memcpy(&cur_params, &default_mesh_config, sizeof(cur_params));
7050 else
e35e4d28 7051 err = rdev_get_mesh_config(rdev, dev, &cur_params);
29cbe68c
JB
7052 wdev_unlock(wdev);
7053
93da9cc1 7054 if (err)
4c476991 7055 return err;
93da9cc1 7056
7057 /* Draw up a netlink message to send back */
fd2120ca 7058 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4c476991
JB
7059 if (!msg)
7060 return -ENOMEM;
15e47304 7061 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
24bdd9f4 7062 NL80211_CMD_GET_MESH_CONFIG);
93da9cc1 7063 if (!hdr)
efe1cf0c 7064 goto out;
ae0be8de 7065 pinfoattr = nla_nest_start_noflag(msg, NL80211_ATTR_MESH_CONFIG);
93da9cc1 7066 if (!pinfoattr)
7067 goto nla_put_failure;
9360ffd1
DM
7068 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
7069 nla_put_u16(msg, NL80211_MESHCONF_RETRY_TIMEOUT,
7070 cur_params.dot11MeshRetryTimeout) ||
7071 nla_put_u16(msg, NL80211_MESHCONF_CONFIRM_TIMEOUT,
7072 cur_params.dot11MeshConfirmTimeout) ||
7073 nla_put_u16(msg, NL80211_MESHCONF_HOLDING_TIMEOUT,
7074 cur_params.dot11MeshHoldingTimeout) ||
7075 nla_put_u16(msg, NL80211_MESHCONF_MAX_PEER_LINKS,
7076 cur_params.dot11MeshMaxPeerLinks) ||
7077 nla_put_u8(msg, NL80211_MESHCONF_MAX_RETRIES,
7078 cur_params.dot11MeshMaxRetries) ||
7079 nla_put_u8(msg, NL80211_MESHCONF_TTL,
7080 cur_params.dot11MeshTTL) ||
7081 nla_put_u8(msg, NL80211_MESHCONF_ELEMENT_TTL,
7082 cur_params.element_ttl) ||
7083 nla_put_u8(msg, NL80211_MESHCONF_AUTO_OPEN_PLINKS,
7084 cur_params.auto_open_plinks) ||
7eab0f64
JL
7085 nla_put_u32(msg, NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR,
7086 cur_params.dot11MeshNbrOffsetMaxNeighbor) ||
9360ffd1
DM
7087 nla_put_u8(msg, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES,
7088 cur_params.dot11MeshHWMPmaxPREQretries) ||
7089 nla_put_u32(msg, NL80211_MESHCONF_PATH_REFRESH_TIME,
7090 cur_params.path_refresh_time) ||
7091 nla_put_u16(msg, NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT,
7092 cur_params.min_discovery_timeout) ||
7093 nla_put_u32(msg, NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT,
7094 cur_params.dot11MeshHWMPactivePathTimeout) ||
7095 nla_put_u16(msg, NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL,
7096 cur_params.dot11MeshHWMPpreqMinInterval) ||
7097 nla_put_u16(msg, NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL,
7098 cur_params.dot11MeshHWMPperrMinInterval) ||
7099 nla_put_u16(msg, NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
7100 cur_params.dot11MeshHWMPnetDiameterTraversalTime) ||
7101 nla_put_u8(msg, NL80211_MESHCONF_HWMP_ROOTMODE,
7102 cur_params.dot11MeshHWMPRootMode) ||
7103 nla_put_u16(msg, NL80211_MESHCONF_HWMP_RANN_INTERVAL,
7104 cur_params.dot11MeshHWMPRannInterval) ||
7105 nla_put_u8(msg, NL80211_MESHCONF_GATE_ANNOUNCEMENTS,
7106 cur_params.dot11MeshGateAnnouncementProtocol) ||
7107 nla_put_u8(msg, NL80211_MESHCONF_FORWARDING,
7108 cur_params.dot11MeshForwarding) ||
335d5349 7109 nla_put_s32(msg, NL80211_MESHCONF_RSSI_THRESHOLD,
70c33eaa
AN
7110 cur_params.rssi_threshold) ||
7111 nla_put_u32(msg, NL80211_MESHCONF_HT_OPMODE,
ac1073a6
CYY
7112 cur_params.ht_opmode) ||
7113 nla_put_u32(msg, NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT,
7114 cur_params.dot11MeshHWMPactivePathToRootTimeout) ||
7115 nla_put_u16(msg, NL80211_MESHCONF_HWMP_ROOT_INTERVAL,
728b19e5
CYY
7116 cur_params.dot11MeshHWMProotInterval) ||
7117 nla_put_u16(msg, NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL,
3b1c5a53
MP
7118 cur_params.dot11MeshHWMPconfirmationInterval) ||
7119 nla_put_u32(msg, NL80211_MESHCONF_POWER_MODE,
7120 cur_params.power_mode) ||
7121 nla_put_u16(msg, NL80211_MESHCONF_AWAKE_WINDOW,
8e7c0538
CT
7122 cur_params.dot11MeshAwakeWindowDuration) ||
7123 nla_put_u32(msg, NL80211_MESHCONF_PLINK_TIMEOUT,
01d66fbd
BC
7124 cur_params.plink_timeout) ||
7125 nla_put_u8(msg, NL80211_MESHCONF_CONNECTED_TO_GATE,
e3718a61
LL
7126 cur_params.dot11MeshConnectedToMeshGate) ||
7127 nla_put_u8(msg, NL80211_MESHCONF_NOLEARN,
184eebe6
MT
7128 cur_params.dot11MeshNolearn) ||
7129 nla_put_u8(msg, NL80211_MESHCONF_CONNECTED_TO_AS,
7130 cur_params.dot11MeshConnectedToAuthServer))
9360ffd1 7131 goto nla_put_failure;
93da9cc1 7132 nla_nest_end(msg, pinfoattr);
7133 genlmsg_end(msg, hdr);
4c476991 7134 return genlmsg_reply(msg, info);
93da9cc1 7135
3b85875a 7136 nla_put_failure:
efe1cf0c 7137 out:
d080e275 7138 nlmsg_free(msg);
4c476991 7139 return -ENOBUFS;
93da9cc1 7140}
7141
ab0d76f6
JB
7142static const struct nla_policy
7143nl80211_meshconf_params_policy[NL80211_MESHCONF_ATTR_MAX+1] = {
7144 [NL80211_MESHCONF_RETRY_TIMEOUT] =
7145 NLA_POLICY_RANGE(NLA_U16, 1, 255),
7146 [NL80211_MESHCONF_CONFIRM_TIMEOUT] =
7147 NLA_POLICY_RANGE(NLA_U16, 1, 255),
7148 [NL80211_MESHCONF_HOLDING_TIMEOUT] =
7149 NLA_POLICY_RANGE(NLA_U16, 1, 255),
7150 [NL80211_MESHCONF_MAX_PEER_LINKS] =
7151 NLA_POLICY_RANGE(NLA_U16, 0, 255),
7152 [NL80211_MESHCONF_MAX_RETRIES] = NLA_POLICY_MAX(NLA_U8, 16),
7153 [NL80211_MESHCONF_TTL] = NLA_POLICY_MIN(NLA_U8, 1),
7154 [NL80211_MESHCONF_ELEMENT_TTL] = NLA_POLICY_MIN(NLA_U8, 1),
7155 [NL80211_MESHCONF_AUTO_OPEN_PLINKS] = NLA_POLICY_MAX(NLA_U8, 1),
7156 [NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR] =
7157 NLA_POLICY_RANGE(NLA_U32, 1, 255),
93da9cc1 7158 [NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES] = { .type = NLA_U8 },
7159 [NL80211_MESHCONF_PATH_REFRESH_TIME] = { .type = NLA_U32 },
ab0d76f6 7160 [NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT] = NLA_POLICY_MIN(NLA_U16, 1),
93da9cc1 7161 [NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT] = { .type = NLA_U32 },
ab0d76f6
JB
7162 [NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL] =
7163 NLA_POLICY_MIN(NLA_U16, 1),
7164 [NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL] =
7165 NLA_POLICY_MIN(NLA_U16, 1),
7166 [NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME] =
7167 NLA_POLICY_MIN(NLA_U16, 1),
7168 [NL80211_MESHCONF_HWMP_ROOTMODE] = NLA_POLICY_MAX(NLA_U8, 4),
7169 [NL80211_MESHCONF_HWMP_RANN_INTERVAL] =
7170 NLA_POLICY_MIN(NLA_U16, 1),
7171 [NL80211_MESHCONF_GATE_ANNOUNCEMENTS] = NLA_POLICY_MAX(NLA_U8, 1),
7172 [NL80211_MESHCONF_FORWARDING] = NLA_POLICY_MAX(NLA_U8, 1),
7173 [NL80211_MESHCONF_RSSI_THRESHOLD] =
7174 NLA_POLICY_RANGE(NLA_S32, -255, 0),
a4f606ea 7175 [NL80211_MESHCONF_HT_OPMODE] = { .type = NLA_U16 },
ac1073a6 7176 [NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT] = { .type = NLA_U32 },
ab0d76f6
JB
7177 [NL80211_MESHCONF_HWMP_ROOT_INTERVAL] =
7178 NLA_POLICY_MIN(NLA_U16, 1),
7179 [NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL] =
7180 NLA_POLICY_MIN(NLA_U16, 1),
7181 [NL80211_MESHCONF_POWER_MODE] =
7182 NLA_POLICY_RANGE(NLA_U32,
7183 NL80211_MESH_POWER_ACTIVE,
7184 NL80211_MESH_POWER_MAX),
3b1c5a53 7185 [NL80211_MESHCONF_AWAKE_WINDOW] = { .type = NLA_U16 },
8e7c0538 7186 [NL80211_MESHCONF_PLINK_TIMEOUT] = { .type = NLA_U32 },
01d66fbd 7187 [NL80211_MESHCONF_CONNECTED_TO_GATE] = NLA_POLICY_RANGE(NLA_U8, 0, 1),
e3718a61 7188 [NL80211_MESHCONF_NOLEARN] = NLA_POLICY_RANGE(NLA_U8, 0, 1),
184eebe6 7189 [NL80211_MESHCONF_CONNECTED_TO_AS] = NLA_POLICY_RANGE(NLA_U8, 0, 1),
93da9cc1 7190};
7191
c80d545d
JC
7192static const struct nla_policy
7193 nl80211_mesh_setup_params_policy[NL80211_MESH_SETUP_ATTR_MAX+1] = {
d299a1f2 7194 [NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC] = { .type = NLA_U8 },
c80d545d
JC
7195 [NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL] = { .type = NLA_U8 },
7196 [NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC] = { .type = NLA_U8 },
15d5dda6 7197 [NL80211_MESH_SETUP_USERSPACE_AUTH] = { .type = NLA_FLAG },
6e16d90b 7198 [NL80211_MESH_SETUP_AUTH_PROTOCOL] = { .type = NLA_U8 },
bb2798d4 7199 [NL80211_MESH_SETUP_USERSPACE_MPM] = { .type = NLA_FLAG },
3d7af878
JB
7200 [NL80211_MESH_SETUP_IE] =
7201 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr,
7202 IEEE80211_MAX_DATA_LEN),
b130e5ce 7203 [NL80211_MESH_SETUP_USERSPACE_AMPE] = { .type = NLA_FLAG },
c80d545d
JC
7204};
7205
24bdd9f4 7206static int nl80211_parse_mesh_config(struct genl_info *info,
bd90fdcc
JB
7207 struct mesh_config *cfg,
7208 u32 *mask_out)
93da9cc1 7209{
93da9cc1 7210 struct nlattr *tb[NL80211_MESHCONF_ATTR_MAX + 1];
bd90fdcc 7211 u32 mask = 0;
9757235f 7212 u16 ht_opmode;
93da9cc1 7213
ab0d76f6
JB
7214#define FILL_IN_MESH_PARAM_IF_SET(tb, cfg, param, mask, attr, fn) \
7215do { \
7216 if (tb[attr]) { \
7217 cfg->param = fn(tb[attr]); \
7218 mask |= BIT((attr) - 1); \
7219 } \
ea54fba2 7220} while (0)
bd90fdcc 7221
24bdd9f4 7222 if (!info->attrs[NL80211_ATTR_MESH_CONFIG])
93da9cc1 7223 return -EINVAL;
8cb08174 7224 if (nla_parse_nested_deprecated(tb, NL80211_MESHCONF_ATTR_MAX, info->attrs[NL80211_ATTR_MESH_CONFIG], nl80211_meshconf_params_policy, info->extack))
93da9cc1 7225 return -EINVAL;
7226
93da9cc1 7227 /* This makes sure that there aren't more than 32 mesh config
7228 * parameters (otherwise our bitfield scheme would not work.) */
7229 BUILD_BUG_ON(NL80211_MESHCONF_ATTR_MAX > 32);
7230
7231 /* Fill in the params struct */
ab0d76f6
JB
7232 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshRetryTimeout, mask,
7233 NL80211_MESHCONF_RETRY_TIMEOUT, nla_get_u16);
7234 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConfirmTimeout, mask,
7235 NL80211_MESHCONF_CONFIRM_TIMEOUT,
7236 nla_get_u16);
7237 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHoldingTimeout, mask,
7238 NL80211_MESHCONF_HOLDING_TIMEOUT,
7239 nla_get_u16);
7240 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxPeerLinks, mask,
7241 NL80211_MESHCONF_MAX_PEER_LINKS,
7242 nla_get_u16);
7243 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxRetries, mask,
7244 NL80211_MESHCONF_MAX_RETRIES, nla_get_u8);
7245 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshTTL, mask,
7246 NL80211_MESHCONF_TTL, nla_get_u8);
7247 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, element_ttl, mask,
7248 NL80211_MESHCONF_ELEMENT_TTL, nla_get_u8);
7249 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, auto_open_plinks, mask,
7250 NL80211_MESHCONF_AUTO_OPEN_PLINKS,
7251 nla_get_u8);
ea54fba2 7252 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshNbrOffsetMaxNeighbor,
ab0d76f6 7253 mask,
a4f606ea 7254 NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR,
ab0d76f6
JB
7255 nla_get_u32);
7256 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPmaxPREQretries, mask,
7257 NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES,
7258 nla_get_u8);
7259 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, path_refresh_time, mask,
7260 NL80211_MESHCONF_PATH_REFRESH_TIME,
7261 nla_get_u32);
7262 if (mask & BIT(NL80211_MESHCONF_PATH_REFRESH_TIME) &&
7263 (cfg->path_refresh_time < 1 || cfg->path_refresh_time > 65535))
7264 return -EINVAL;
7265 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, min_discovery_timeout, mask,
7266 NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT,
7267 nla_get_u16);
ea54fba2 7268 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathTimeout,
ab0d76f6 7269 mask,
a4f606ea 7270 NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT,
ab0d76f6
JB
7271 nla_get_u32);
7272 if (mask & BIT(NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT) &&
7273 (cfg->dot11MeshHWMPactivePathTimeout < 1 ||
7274 cfg->dot11MeshHWMPactivePathTimeout > 65535))
7275 return -EINVAL;
7276 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPpreqMinInterval, mask,
ea54fba2 7277 NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL,
ab0d76f6
JB
7278 nla_get_u16);
7279 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPperrMinInterval, mask,
ea54fba2 7280 NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL,
ab0d76f6 7281 nla_get_u16);
93da9cc1 7282 FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
ab0d76f6 7283 dot11MeshHWMPnetDiameterTraversalTime, mask,
a4f606ea 7284 NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
ab0d76f6
JB
7285 nla_get_u16);
7286 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRootMode, mask,
7287 NL80211_MESHCONF_HWMP_ROOTMODE, nla_get_u8);
7288 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRannInterval, mask,
7289 NL80211_MESHCONF_HWMP_RANN_INTERVAL,
7290 nla_get_u16);
7291 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshGateAnnouncementProtocol,
ea54fba2 7292 mask, NL80211_MESHCONF_GATE_ANNOUNCEMENTS,
ab0d76f6
JB
7293 nla_get_u8);
7294 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshForwarding, mask,
7295 NL80211_MESHCONF_FORWARDING, nla_get_u8);
7296 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, rssi_threshold, mask,
7297 NL80211_MESHCONF_RSSI_THRESHOLD,
7298 nla_get_s32);
01d66fbd
BC
7299 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConnectedToMeshGate, mask,
7300 NL80211_MESHCONF_CONNECTED_TO_GATE,
7301 nla_get_u8);
184eebe6
MT
7302 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConnectedToAuthServer, mask,
7303 NL80211_MESHCONF_CONNECTED_TO_AS,
7304 nla_get_u8);
9757235f
MH
7305 /*
7306 * Check HT operation mode based on
188f60ab 7307 * IEEE 802.11-2016 9.4.2.57 HT Operation element.
9757235f
MH
7308 */
7309 if (tb[NL80211_MESHCONF_HT_OPMODE]) {
7310 ht_opmode = nla_get_u16(tb[NL80211_MESHCONF_HT_OPMODE]);
7311
7312 if (ht_opmode & ~(IEEE80211_HT_OP_MODE_PROTECTION |
7313 IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT |
7314 IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT))
7315 return -EINVAL;
7316
188f60ab
BC
7317 /* NON_HT_STA bit is reserved, but some programs set it */
7318 ht_opmode &= ~IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT;
9757235f 7319
9757235f 7320 cfg->ht_opmode = ht_opmode;
fd551bac 7321 mask |= (1 << (NL80211_MESHCONF_HT_OPMODE - 1));
9757235f 7322 }
728b19e5 7323 FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
ab0d76f6
JB
7324 dot11MeshHWMPactivePathToRootTimeout, mask,
7325 NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT,
7326 nla_get_u32);
7327 if (mask & BIT(NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT) &&
7328 (cfg->dot11MeshHWMPactivePathToRootTimeout < 1 ||
7329 cfg->dot11MeshHWMPactivePathToRootTimeout > 65535))
7330 return -EINVAL;
7331 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMProotInterval, mask,
7332 NL80211_MESHCONF_HWMP_ROOT_INTERVAL,
7333 nla_get_u16);
7334 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPconfirmationInterval,
7335 mask,
728b19e5 7336 NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL,
ab0d76f6
JB
7337 nla_get_u16);
7338 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, power_mode, mask,
7339 NL80211_MESHCONF_POWER_MODE, nla_get_u32);
7340 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshAwakeWindowDuration, mask,
7341 NL80211_MESHCONF_AWAKE_WINDOW, nla_get_u16);
7342 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, plink_timeout, mask,
7343 NL80211_MESHCONF_PLINK_TIMEOUT, nla_get_u32);
e3718a61
LL
7344 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshNolearn, mask,
7345 NL80211_MESHCONF_NOLEARN, nla_get_u8);
bd90fdcc
JB
7346 if (mask_out)
7347 *mask_out = mask;
c80d545d 7348
bd90fdcc
JB
7349 return 0;
7350
7351#undef FILL_IN_MESH_PARAM_IF_SET
7352}
7353
c80d545d
JC
7354static int nl80211_parse_mesh_setup(struct genl_info *info,
7355 struct mesh_setup *setup)
7356{
bb2798d4 7357 struct cfg80211_registered_device *rdev = info->user_ptr[0];
c80d545d
JC
7358 struct nlattr *tb[NL80211_MESH_SETUP_ATTR_MAX + 1];
7359
7360 if (!info->attrs[NL80211_ATTR_MESH_SETUP])
7361 return -EINVAL;
8cb08174 7362 if (nla_parse_nested_deprecated(tb, NL80211_MESH_SETUP_ATTR_MAX, info->attrs[NL80211_ATTR_MESH_SETUP], nl80211_mesh_setup_params_policy, info->extack))
c80d545d
JC
7363 return -EINVAL;
7364
d299a1f2
JC
7365 if (tb[NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC])
7366 setup->sync_method =
7367 (nla_get_u8(tb[NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC])) ?
7368 IEEE80211_SYNC_METHOD_VENDOR :
7369 IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET;
7370
c80d545d
JC
7371 if (tb[NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL])
7372 setup->path_sel_proto =
7373 (nla_get_u8(tb[NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL])) ?
7374 IEEE80211_PATH_PROTOCOL_VENDOR :
7375 IEEE80211_PATH_PROTOCOL_HWMP;
7376
7377 if (tb[NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC])
7378 setup->path_metric =
7379 (nla_get_u8(tb[NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC])) ?
7380 IEEE80211_PATH_METRIC_VENDOR :
7381 IEEE80211_PATH_METRIC_AIRTIME;
7382
581a8b0f 7383 if (tb[NL80211_MESH_SETUP_IE]) {
c80d545d 7384 struct nlattr *ieattr =
581a8b0f 7385 tb[NL80211_MESH_SETUP_IE];
581a8b0f
JC
7386 setup->ie = nla_data(ieattr);
7387 setup->ie_len = nla_len(ieattr);
c80d545d 7388 }
bb2798d4
TP
7389 if (tb[NL80211_MESH_SETUP_USERSPACE_MPM] &&
7390 !(rdev->wiphy.features & NL80211_FEATURE_USERSPACE_MPM))
7391 return -EINVAL;
7392 setup->user_mpm = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_MPM]);
b130e5ce
JC
7393 setup->is_authenticated = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AUTH]);
7394 setup->is_secure = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AMPE]);
bb2798d4
TP
7395 if (setup->is_secure)
7396 setup->user_mpm = true;
c80d545d 7397
6e16d90b
CT
7398 if (tb[NL80211_MESH_SETUP_AUTH_PROTOCOL]) {
7399 if (!setup->user_mpm)
7400 return -EINVAL;
7401 setup->auth_id =
7402 nla_get_u8(tb[NL80211_MESH_SETUP_AUTH_PROTOCOL]);
7403 }
7404
c80d545d
JC
7405 return 0;
7406}
7407
24bdd9f4 7408static int nl80211_update_mesh_config(struct sk_buff *skb,
29cbe68c 7409 struct genl_info *info)
bd90fdcc
JB
7410{
7411 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7412 struct net_device *dev = info->user_ptr[1];
29cbe68c 7413 struct wireless_dev *wdev = dev->ieee80211_ptr;
bd90fdcc
JB
7414 struct mesh_config cfg;
7415 u32 mask;
7416 int err;
7417
29cbe68c
JB
7418 if (wdev->iftype != NL80211_IFTYPE_MESH_POINT)
7419 return -EOPNOTSUPP;
7420
24bdd9f4 7421 if (!rdev->ops->update_mesh_config)
bd90fdcc
JB
7422 return -EOPNOTSUPP;
7423
24bdd9f4 7424 err = nl80211_parse_mesh_config(info, &cfg, &mask);
bd90fdcc
JB
7425 if (err)
7426 return err;
7427
29cbe68c
JB
7428 wdev_lock(wdev);
7429 if (!wdev->mesh_id_len)
7430 err = -ENOLINK;
7431
7432 if (!err)
e35e4d28 7433 err = rdev_update_mesh_config(rdev, dev, mask, &cfg);
29cbe68c
JB
7434
7435 wdev_unlock(wdev);
7436
7437 return err;
93da9cc1 7438}
7439
ad30ca2c
AN
7440static int nl80211_put_regdom(const struct ieee80211_regdomain *regdom,
7441 struct sk_buff *msg)
f130347c 7442{
f130347c
LR
7443 struct nlattr *nl_reg_rules;
7444 unsigned int i;
f130347c 7445
458f4f9e
JB
7446 if (nla_put_string(msg, NL80211_ATTR_REG_ALPHA2, regdom->alpha2) ||
7447 (regdom->dfs_region &&
7448 nla_put_u8(msg, NL80211_ATTR_DFS_REGION, regdom->dfs_region)))
ad30ca2c 7449 goto nla_put_failure;
458f4f9e 7450
ae0be8de 7451 nl_reg_rules = nla_nest_start_noflag(msg, NL80211_ATTR_REG_RULES);
f130347c 7452 if (!nl_reg_rules)
ad30ca2c 7453 goto nla_put_failure;
f130347c 7454
458f4f9e 7455 for (i = 0; i < regdom->n_reg_rules; i++) {
f130347c
LR
7456 struct nlattr *nl_reg_rule;
7457 const struct ieee80211_reg_rule *reg_rule;
7458 const struct ieee80211_freq_range *freq_range;
7459 const struct ieee80211_power_rule *power_rule;
97524820 7460 unsigned int max_bandwidth_khz;
f130347c 7461
458f4f9e 7462 reg_rule = &regdom->reg_rules[i];
f130347c
LR
7463 freq_range = &reg_rule->freq_range;
7464 power_rule = &reg_rule->power_rule;
7465
ae0be8de 7466 nl_reg_rule = nla_nest_start_noflag(msg, i);
f130347c 7467 if (!nl_reg_rule)
ad30ca2c 7468 goto nla_put_failure;
f130347c 7469
97524820
JD
7470 max_bandwidth_khz = freq_range->max_bandwidth_khz;
7471 if (!max_bandwidth_khz)
7472 max_bandwidth_khz = reg_get_max_bandwidth(regdom,
7473 reg_rule);
7474
9360ffd1
DM
7475 if (nla_put_u32(msg, NL80211_ATTR_REG_RULE_FLAGS,
7476 reg_rule->flags) ||
7477 nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_START,
7478 freq_range->start_freq_khz) ||
7479 nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_END,
7480 freq_range->end_freq_khz) ||
7481 nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_MAX_BW,
97524820 7482 max_bandwidth_khz) ||
9360ffd1
DM
7483 nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN,
7484 power_rule->max_antenna_gain) ||
7485 nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_EIRP,
089027e5
JD
7486 power_rule->max_eirp) ||
7487 nla_put_u32(msg, NL80211_ATTR_DFS_CAC_TIME,
7488 reg_rule->dfs_cac_ms))
ad30ca2c 7489 goto nla_put_failure;
f130347c
LR
7490
7491 nla_nest_end(msg, nl_reg_rule);
7492 }
7493
7494 nla_nest_end(msg, nl_reg_rules);
ad30ca2c
AN
7495 return 0;
7496
7497nla_put_failure:
7498 return -EMSGSIZE;
7499}
7500
7501static int nl80211_get_reg_do(struct sk_buff *skb, struct genl_info *info)
7502{
7503 const struct ieee80211_regdomain *regdom = NULL;
7504 struct cfg80211_registered_device *rdev;
7505 struct wiphy *wiphy = NULL;
7506 struct sk_buff *msg;
7507 void *hdr;
7508
7509 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
7510 if (!msg)
7511 return -ENOBUFS;
7512
7513 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
7514 NL80211_CMD_GET_REG);
7515 if (!hdr)
7516 goto put_failure;
7517
7518 if (info->attrs[NL80211_ATTR_WIPHY]) {
1bdd716c
AN
7519 bool self_managed;
7520
ad30ca2c
AN
7521 rdev = cfg80211_get_dev_from_info(genl_info_net(info), info);
7522 if (IS_ERR(rdev)) {
7523 nlmsg_free(msg);
7524 return PTR_ERR(rdev);
7525 }
7526
7527 wiphy = &rdev->wiphy;
1bdd716c
AN
7528 self_managed = wiphy->regulatory_flags &
7529 REGULATORY_WIPHY_SELF_MANAGED;
ad30ca2c
AN
7530 regdom = get_wiphy_regdom(wiphy);
7531
1bdd716c
AN
7532 /* a self-managed-reg device must have a private regdom */
7533 if (WARN_ON(!regdom && self_managed)) {
7534 nlmsg_free(msg);
7535 return -EINVAL;
7536 }
7537
ad30ca2c
AN
7538 if (regdom &&
7539 nla_put_u32(msg, NL80211_ATTR_WIPHY, get_wiphy_idx(wiphy)))
7540 goto nla_put_failure;
7541 }
7542
7543 if (!wiphy && reg_last_request_cell_base() &&
7544 nla_put_u32(msg, NL80211_ATTR_USER_REG_HINT_TYPE,
7545 NL80211_USER_REG_HINT_CELL_BASE))
7546 goto nla_put_failure;
7547
7548 rcu_read_lock();
7549
7550 if (!regdom)
7551 regdom = rcu_dereference(cfg80211_regdomain);
7552
7553 if (nl80211_put_regdom(regdom, msg))
7554 goto nla_put_failure_rcu;
7555
7556 rcu_read_unlock();
f130347c
LR
7557
7558 genlmsg_end(msg, hdr);
5fe231e8 7559 return genlmsg_reply(msg, info);
f130347c 7560
458f4f9e
JB
7561nla_put_failure_rcu:
7562 rcu_read_unlock();
f130347c 7563nla_put_failure:
efe1cf0c 7564put_failure:
d080e275 7565 nlmsg_free(msg);
5fe231e8 7566 return -EMSGSIZE;
f130347c
LR
7567}
7568
ad30ca2c
AN
7569static int nl80211_send_regdom(struct sk_buff *msg, struct netlink_callback *cb,
7570 u32 seq, int flags, struct wiphy *wiphy,
7571 const struct ieee80211_regdomain *regdom)
7572{
7573 void *hdr = nl80211hdr_put(msg, NETLINK_CB(cb->skb).portid, seq, flags,
7574 NL80211_CMD_GET_REG);
7575
7576 if (!hdr)
7577 return -1;
7578
0a833c29 7579 genl_dump_check_consistent(cb, hdr);
ad30ca2c
AN
7580
7581 if (nl80211_put_regdom(regdom, msg))
7582 goto nla_put_failure;
7583
7584 if (!wiphy && reg_last_request_cell_base() &&
7585 nla_put_u32(msg, NL80211_ATTR_USER_REG_HINT_TYPE,
7586 NL80211_USER_REG_HINT_CELL_BASE))
7587 goto nla_put_failure;
7588
7589 if (wiphy &&
7590 nla_put_u32(msg, NL80211_ATTR_WIPHY, get_wiphy_idx(wiphy)))
7591 goto nla_put_failure;
7592
1bdd716c
AN
7593 if (wiphy && wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED &&
7594 nla_put_flag(msg, NL80211_ATTR_WIPHY_SELF_MANAGED_REG))
7595 goto nla_put_failure;
7596
053c095a
JB
7597 genlmsg_end(msg, hdr);
7598 return 0;
ad30ca2c
AN
7599
7600nla_put_failure:
7601 genlmsg_cancel(msg, hdr);
7602 return -EMSGSIZE;
7603}
7604
7605static int nl80211_get_reg_dump(struct sk_buff *skb,
7606 struct netlink_callback *cb)
7607{
7608 const struct ieee80211_regdomain *regdom = NULL;
7609 struct cfg80211_registered_device *rdev;
7610 int err, reg_idx, start = cb->args[2];
7611
7612 rtnl_lock();
7613
7614 if (cfg80211_regdomain && start == 0) {
7615 err = nl80211_send_regdom(skb, cb, cb->nlh->nlmsg_seq,
7616 NLM_F_MULTI, NULL,
7617 rtnl_dereference(cfg80211_regdomain));
7618 if (err < 0)
7619 goto out_err;
7620 }
7621
7622 /* the global regdom is idx 0 */
7623 reg_idx = 1;
7624 list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
7625 regdom = get_wiphy_regdom(&rdev->wiphy);
7626 if (!regdom)
7627 continue;
7628
7629 if (++reg_idx <= start)
7630 continue;
7631
7632 err = nl80211_send_regdom(skb, cb, cb->nlh->nlmsg_seq,
7633 NLM_F_MULTI, &rdev->wiphy, regdom);
7634 if (err < 0) {
7635 reg_idx--;
7636 break;
7637 }
7638 }
7639
7640 cb->args[2] = reg_idx;
7641 err = skb->len;
7642out_err:
7643 rtnl_unlock();
7644 return err;
7645}
7646
b6863036
JB
7647#ifdef CONFIG_CFG80211_CRDA_SUPPORT
7648static const struct nla_policy reg_rule_policy[NL80211_REG_RULE_ATTR_MAX + 1] = {
7649 [NL80211_ATTR_REG_RULE_FLAGS] = { .type = NLA_U32 },
7650 [NL80211_ATTR_FREQ_RANGE_START] = { .type = NLA_U32 },
7651 [NL80211_ATTR_FREQ_RANGE_END] = { .type = NLA_U32 },
7652 [NL80211_ATTR_FREQ_RANGE_MAX_BW] = { .type = NLA_U32 },
7653 [NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN] = { .type = NLA_U32 },
7654 [NL80211_ATTR_POWER_RULE_MAX_EIRP] = { .type = NLA_U32 },
7655 [NL80211_ATTR_DFS_CAC_TIME] = { .type = NLA_U32 },
7656};
7657
7658static int parse_reg_rule(struct nlattr *tb[],
7659 struct ieee80211_reg_rule *reg_rule)
7660{
7661 struct ieee80211_freq_range *freq_range = &reg_rule->freq_range;
7662 struct ieee80211_power_rule *power_rule = &reg_rule->power_rule;
7663
7664 if (!tb[NL80211_ATTR_REG_RULE_FLAGS])
7665 return -EINVAL;
7666 if (!tb[NL80211_ATTR_FREQ_RANGE_START])
7667 return -EINVAL;
7668 if (!tb[NL80211_ATTR_FREQ_RANGE_END])
7669 return -EINVAL;
7670 if (!tb[NL80211_ATTR_FREQ_RANGE_MAX_BW])
7671 return -EINVAL;
7672 if (!tb[NL80211_ATTR_POWER_RULE_MAX_EIRP])
7673 return -EINVAL;
7674
7675 reg_rule->flags = nla_get_u32(tb[NL80211_ATTR_REG_RULE_FLAGS]);
7676
7677 freq_range->start_freq_khz =
7678 nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]);
7679 freq_range->end_freq_khz =
7680 nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]);
7681 freq_range->max_bandwidth_khz =
7682 nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]);
7683
7684 power_rule->max_eirp =
7685 nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_EIRP]);
7686
7687 if (tb[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN])
7688 power_rule->max_antenna_gain =
7689 nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN]);
7690
7691 if (tb[NL80211_ATTR_DFS_CAC_TIME])
7692 reg_rule->dfs_cac_ms =
7693 nla_get_u32(tb[NL80211_ATTR_DFS_CAC_TIME]);
7694
7695 return 0;
7696}
7697
b2e1b302
LR
7698static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
7699{
7700 struct nlattr *tb[NL80211_REG_RULE_ATTR_MAX + 1];
7701 struct nlattr *nl_reg_rule;
ea372c54
JB
7702 char *alpha2;
7703 int rem_reg_rules, r;
391d132c 7704 u32 num_rules = 0, rule_idx = 0;
4c7d3982 7705 enum nl80211_dfs_regions dfs_region = NL80211_DFS_UNSET;
ea372c54 7706 struct ieee80211_regdomain *rd;
b2e1b302
LR
7707
7708 if (!info->attrs[NL80211_ATTR_REG_ALPHA2])
7709 return -EINVAL;
7710
7711 if (!info->attrs[NL80211_ATTR_REG_RULES])
7712 return -EINVAL;
7713
7714 alpha2 = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]);
7715
8b60b078
LR
7716 if (info->attrs[NL80211_ATTR_DFS_REGION])
7717 dfs_region = nla_get_u8(info->attrs[NL80211_ATTR_DFS_REGION]);
7718
b2e1b302 7719 nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES],
1a919318 7720 rem_reg_rules) {
b2e1b302
LR
7721 num_rules++;
7722 if (num_rules > NL80211_MAX_SUPP_REG_RULES)
4776c6e7 7723 return -EINVAL;
b2e1b302
LR
7724 }
7725
e438768f
LR
7726 if (!reg_is_valid_request(alpha2))
7727 return -EINVAL;
7728
391d132c 7729 rd = kzalloc(struct_size(rd, reg_rules, num_rules), GFP_KERNEL);
6913b49a
JB
7730 if (!rd)
7731 return -ENOMEM;
b2e1b302
LR
7732
7733 rd->n_reg_rules = num_rules;
7734 rd->alpha2[0] = alpha2[0];
7735 rd->alpha2[1] = alpha2[1];
7736
8b60b078
LR
7737 /*
7738 * Disable DFS master mode if the DFS region was
7739 * not supported or known on this kernel.
7740 */
7741 if (reg_supported_dfs_region(dfs_region))
7742 rd->dfs_region = dfs_region;
7743
b2e1b302 7744 nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES],
1a919318 7745 rem_reg_rules) {
8cb08174
JB
7746 r = nla_parse_nested_deprecated(tb, NL80211_REG_RULE_ATTR_MAX,
7747 nl_reg_rule, reg_rule_policy,
7748 info->extack);
ae811e21
JB
7749 if (r)
7750 goto bad_reg;
b2e1b302
LR
7751 r = parse_reg_rule(tb, &rd->reg_rules[rule_idx]);
7752 if (r)
7753 goto bad_reg;
7754
7755 rule_idx++;
7756
d0e18f83
LR
7757 if (rule_idx > NL80211_MAX_SUPP_REG_RULES) {
7758 r = -EINVAL;
b2e1b302 7759 goto bad_reg;
d0e18f83 7760 }
b2e1b302
LR
7761 }
7762
06627990
JB
7763 /* set_regdom takes ownership of rd */
7764 return set_regdom(rd, REGD_SOURCE_CRDA);
d2372b31 7765 bad_reg:
b2e1b302 7766 kfree(rd);
d0e18f83 7767 return r;
b2e1b302 7768}
b6863036 7769#endif /* CONFIG_CFG80211_CRDA_SUPPORT */
b2e1b302 7770
83f5e2cf
JB
7771static int validate_scan_freqs(struct nlattr *freqs)
7772{
7773 struct nlattr *attr1, *attr2;
7774 int n_channels = 0, tmp1, tmp2;
7775
d7f13f74
SD
7776 nla_for_each_nested(attr1, freqs, tmp1)
7777 if (nla_len(attr1) != sizeof(u32))
7778 return 0;
7779
83f5e2cf
JB
7780 nla_for_each_nested(attr1, freqs, tmp1) {
7781 n_channels++;
7782 /*
7783 * Some hardware has a limited channel list for
7784 * scanning, and it is pretty much nonsensical
7785 * to scan for a channel twice, so disallow that
7786 * and don't require drivers to check that the
7787 * channel list they get isn't longer than what
7788 * they can scan, as long as they can scan all
7789 * the channels they registered at once.
7790 */
7791 nla_for_each_nested(attr2, freqs, tmp2)
7792 if (attr1 != attr2 &&
7793 nla_get_u32(attr1) == nla_get_u32(attr2))
7794 return 0;
7795 }
7796
7797 return n_channels;
7798}
7799
57fbcce3 7800static bool is_band_valid(struct wiphy *wiphy, enum nl80211_band b)
38de03d2 7801{
57fbcce3 7802 return b < NUM_NL80211_BANDS && wiphy->bands[b];
38de03d2
AS
7803}
7804
7805static int parse_bss_select(struct nlattr *nla, struct wiphy *wiphy,
7806 struct cfg80211_bss_selection *bss_select)
7807{
7808 struct nlattr *attr[NL80211_BSS_SELECT_ATTR_MAX + 1];
7809 struct nlattr *nest;
7810 int err;
7811 bool found = false;
7812 int i;
7813
7814 /* only process one nested attribute */
7815 nest = nla_data(nla);
7816 if (!nla_ok(nest, nla_len(nest)))
7817 return -EINVAL;
7818
8cb08174
JB
7819 err = nla_parse_nested_deprecated(attr, NL80211_BSS_SELECT_ATTR_MAX,
7820 nest, nl80211_bss_select_policy,
7821 NULL);
38de03d2
AS
7822 if (err)
7823 return err;
7824
7825 /* only one attribute may be given */
7826 for (i = 0; i <= NL80211_BSS_SELECT_ATTR_MAX; i++) {
7827 if (attr[i]) {
7828 if (found)
7829 return -EINVAL;
7830 found = true;
7831 }
7832 }
7833
7834 bss_select->behaviour = __NL80211_BSS_SELECT_ATTR_INVALID;
7835
7836 if (attr[NL80211_BSS_SELECT_ATTR_RSSI])
7837 bss_select->behaviour = NL80211_BSS_SELECT_ATTR_RSSI;
7838
7839 if (attr[NL80211_BSS_SELECT_ATTR_BAND_PREF]) {
7840 bss_select->behaviour = NL80211_BSS_SELECT_ATTR_BAND_PREF;
7841 bss_select->param.band_pref =
7842 nla_get_u32(attr[NL80211_BSS_SELECT_ATTR_BAND_PREF]);
7843 if (!is_band_valid(wiphy, bss_select->param.band_pref))
7844 return -EINVAL;
7845 }
7846
7847 if (attr[NL80211_BSS_SELECT_ATTR_RSSI_ADJUST]) {
7848 struct nl80211_bss_select_rssi_adjust *adj_param;
7849
7850 adj_param = nla_data(attr[NL80211_BSS_SELECT_ATTR_RSSI_ADJUST]);
7851 bss_select->behaviour = NL80211_BSS_SELECT_ATTR_RSSI_ADJUST;
7852 bss_select->param.adjust.band = adj_param->band;
7853 bss_select->param.adjust.delta = adj_param->delta;
7854 if (!is_band_valid(wiphy, bss_select->param.adjust.band))
7855 return -EINVAL;
7856 }
7857
7858 /* user-space did not provide behaviour attribute */
7859 if (bss_select->behaviour == __NL80211_BSS_SELECT_ATTR_INVALID)
7860 return -EINVAL;
7861
7862 if (!(wiphy->bss_select_support & BIT(bss_select->behaviour)))
7863 return -EINVAL;
7864
7865 return 0;
7866}
7867
9bb7e0f2
JB
7868int nl80211_parse_random_mac(struct nlattr **attrs,
7869 u8 *mac_addr, u8 *mac_addr_mask)
ad2b26ab
JB
7870{
7871 int i;
7872
7873 if (!attrs[NL80211_ATTR_MAC] && !attrs[NL80211_ATTR_MAC_MASK]) {
d2beae10
JP
7874 eth_zero_addr(mac_addr);
7875 eth_zero_addr(mac_addr_mask);
ad2b26ab
JB
7876 mac_addr[0] = 0x2;
7877 mac_addr_mask[0] = 0x3;
7878
7879 return 0;
7880 }
7881
7882 /* need both or none */
7883 if (!attrs[NL80211_ATTR_MAC] || !attrs[NL80211_ATTR_MAC_MASK])
7884 return -EINVAL;
7885
7886 memcpy(mac_addr, nla_data(attrs[NL80211_ATTR_MAC]), ETH_ALEN);
7887 memcpy(mac_addr_mask, nla_data(attrs[NL80211_ATTR_MAC_MASK]), ETH_ALEN);
7888
7889 /* don't allow or configure an mcast address */
7890 if (!is_multicast_ether_addr(mac_addr_mask) ||
7891 is_multicast_ether_addr(mac_addr))
7892 return -EINVAL;
7893
7894 /*
7895 * allow users to pass a MAC address that has bits set outside
7896 * of the mask, but don't bother drivers with having to deal
7897 * with such bits
7898 */
7899 for (i = 0; i < ETH_ALEN; i++)
7900 mac_addr[i] &= mac_addr_mask[i];
7901
7902 return 0;
7903}
7904
34373d12
VT
7905static bool cfg80211_off_channel_oper_allowed(struct wireless_dev *wdev)
7906{
7907 ASSERT_WDEV_LOCK(wdev);
7908
7909 if (!cfg80211_beaconing_iface_active(wdev))
7910 return true;
7911
7912 if (!(wdev->chandef.chan->flags & IEEE80211_CHAN_RADAR))
7913 return true;
7914
7915 return regulatory_pre_cac_allowed(wdev->wiphy);
7916}
7917
db0a4ad8
JB
7918static bool nl80211_check_scan_feat(struct wiphy *wiphy, u32 flags, u32 flag,
7919 enum nl80211_ext_feature_index feat)
7920{
7921 if (!(flags & flag))
7922 return true;
7923 if (wiphy_ext_feature_isset(wiphy, feat))
7924 return true;
7925 return false;
7926}
7927
2d23d073
RZ
7928static int
7929nl80211_check_scan_flags(struct wiphy *wiphy, struct wireless_dev *wdev,
7930 void *request, struct nlattr **attrs,
7931 bool is_sched_scan)
7932{
7933 u8 *mac_addr, *mac_addr_mask;
7934 u32 *flags;
7935 enum nl80211_feature_flags randomness_flag;
7936
7937 if (!attrs[NL80211_ATTR_SCAN_FLAGS])
7938 return 0;
7939
7940 if (is_sched_scan) {
7941 struct cfg80211_sched_scan_request *req = request;
7942
7943 randomness_flag = wdev ?
7944 NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR :
7945 NL80211_FEATURE_ND_RANDOM_MAC_ADDR;
7946 flags = &req->flags;
7947 mac_addr = req->mac_addr;
7948 mac_addr_mask = req->mac_addr_mask;
7949 } else {
7950 struct cfg80211_scan_request *req = request;
7951
7952 randomness_flag = NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
7953 flags = &req->flags;
7954 mac_addr = req->mac_addr;
7955 mac_addr_mask = req->mac_addr_mask;
7956 }
7957
7958 *flags = nla_get_u32(attrs[NL80211_ATTR_SCAN_FLAGS]);
7959
5037a009
SD
7960 if (((*flags & NL80211_SCAN_FLAG_LOW_PRIORITY) &&
7961 !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) ||
db0a4ad8
JB
7962 !nl80211_check_scan_feat(wiphy, *flags,
7963 NL80211_SCAN_FLAG_LOW_SPAN,
7964 NL80211_EXT_FEATURE_LOW_SPAN_SCAN) ||
7965 !nl80211_check_scan_feat(wiphy, *flags,
7966 NL80211_SCAN_FLAG_LOW_POWER,
7967 NL80211_EXT_FEATURE_LOW_POWER_SCAN) ||
7968 !nl80211_check_scan_feat(wiphy, *flags,
7969 NL80211_SCAN_FLAG_HIGH_ACCURACY,
7970 NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN) ||
7971 !nl80211_check_scan_feat(wiphy, *flags,
7972 NL80211_SCAN_FLAG_FILS_MAX_CHANNEL_TIME,
7973 NL80211_EXT_FEATURE_FILS_MAX_CHANNEL_TIME) ||
7974 !nl80211_check_scan_feat(wiphy, *flags,
7975 NL80211_SCAN_FLAG_ACCEPT_BCAST_PROBE_RESP,
7976 NL80211_EXT_FEATURE_ACCEPT_BCAST_PROBE_RESP) ||
7977 !nl80211_check_scan_feat(wiphy, *flags,
7978 NL80211_SCAN_FLAG_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION,
7979 NL80211_EXT_FEATURE_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION) ||
7980 !nl80211_check_scan_feat(wiphy, *flags,
7981 NL80211_SCAN_FLAG_OCE_PROBE_REQ_HIGH_TX_RATE,
2e076f19
JB
7982 NL80211_EXT_FEATURE_OCE_PROBE_REQ_HIGH_TX_RATE) ||
7983 !nl80211_check_scan_feat(wiphy, *flags,
7984 NL80211_SCAN_FLAG_RANDOM_SN,
7985 NL80211_EXT_FEATURE_SCAN_RANDOM_SN) ||
7986 !nl80211_check_scan_feat(wiphy, *flags,
7987 NL80211_SCAN_FLAG_MIN_PREQ_CONTENT,
7988 NL80211_EXT_FEATURE_SCAN_MIN_PREQ_CONTENT))
2d23d073
RZ
7989 return -EOPNOTSUPP;
7990
7991 if (*flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
7992 int err;
7993
7994 if (!(wiphy->features & randomness_flag) ||
7995 (wdev && wdev->current_bss))
7996 return -EOPNOTSUPP;
7997
7998 err = nl80211_parse_random_mac(attrs, mac_addr, mac_addr_mask);
7999 if (err)
8000 return err;
8001 }
8002
2d23d073
RZ
8003 return 0;
8004}
8005
2a519311
JB
8006static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
8007{
4c476991 8008 struct cfg80211_registered_device *rdev = info->user_ptr[0];
fd014284 8009 struct wireless_dev *wdev = info->user_ptr[1];
2a519311 8010 struct cfg80211_scan_request *request;
2032f3b2
TP
8011 struct nlattr *scan_freqs = NULL;
8012 bool scan_freqs_khz = false;
2a519311
JB
8013 struct nlattr *attr;
8014 struct wiphy *wiphy;
83f5e2cf 8015 int err, tmp, n_ssids = 0, n_channels, i;
70692ad2 8016 size_t ie_len;
2a519311 8017
79c97e97 8018 wiphy = &rdev->wiphy;
2a519311 8019
cb3b7d87
AB
8020 if (wdev->iftype == NL80211_IFTYPE_NAN)
8021 return -EOPNOTSUPP;
8022
4c476991
JB
8023 if (!rdev->ops->scan)
8024 return -EOPNOTSUPP;
2a519311 8025
83286856
CJ
8026 if (rdev->scan_req || rdev->scan_msg)
8027 return -EBUSY;
2a519311 8028
2032f3b2
TP
8029 if (info->attrs[NL80211_ATTR_SCAN_FREQ_KHZ]) {
8030 if (!wiphy_ext_feature_isset(wiphy,
8031 NL80211_EXT_FEATURE_SCAN_FREQ_KHZ))
8032 return -EOPNOTSUPP;
8033 scan_freqs = info->attrs[NL80211_ATTR_SCAN_FREQ_KHZ];
8034 scan_freqs_khz = true;
8035 } else if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES])
8036 scan_freqs = info->attrs[NL80211_ATTR_SCAN_FREQUENCIES];
8037
8038 if (scan_freqs) {
8039 n_channels = validate_scan_freqs(scan_freqs);
83286856
CJ
8040 if (!n_channels)
8041 return -EINVAL;
2a519311 8042 } else {
bdfbec2d 8043 n_channels = ieee80211_get_num_supported_channels(wiphy);
2a519311
JB
8044 }
8045
8046 if (info->attrs[NL80211_ATTR_SCAN_SSIDS])
8047 nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp)
8048 n_ssids++;
8049
83286856
CJ
8050 if (n_ssids > wiphy->max_scan_ssids)
8051 return -EINVAL;
2a519311 8052
70692ad2
JM
8053 if (info->attrs[NL80211_ATTR_IE])
8054 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
8055 else
8056 ie_len = 0;
8057
83286856
CJ
8058 if (ie_len > wiphy->max_scan_ie_len)
8059 return -EINVAL;
18a83659 8060
2a519311 8061 request = kzalloc(sizeof(*request)
a2cd43c5
LC
8062 + sizeof(*request->ssids) * n_ssids
8063 + sizeof(*request->channels) * n_channels
70692ad2 8064 + ie_len, GFP_KERNEL);
83286856
CJ
8065 if (!request)
8066 return -ENOMEM;
2a519311 8067
2a519311 8068 if (n_ssids)
5ba63533 8069 request->ssids = (void *)&request->channels[n_channels];
2a519311 8070 request->n_ssids = n_ssids;
70692ad2 8071 if (ie_len) {
13874e4b 8072 if (n_ssids)
70692ad2
JM
8073 request->ie = (void *)(request->ssids + n_ssids);
8074 else
8075 request->ie = (void *)(request->channels + n_channels);
8076 }
2a519311 8077
584991dc 8078 i = 0;
2032f3b2 8079 if (scan_freqs) {
2a519311 8080 /* user specified, bail out if channel not found */
2032f3b2 8081 nla_for_each_nested(attr, scan_freqs, tmp) {
584991dc 8082 struct ieee80211_channel *chan;
2032f3b2 8083 int freq = nla_get_u32(attr);
584991dc 8084
2032f3b2
TP
8085 if (!scan_freqs_khz)
8086 freq = MHZ_TO_KHZ(freq);
584991dc 8087
2032f3b2 8088 chan = ieee80211_get_channel_khz(wiphy, freq);
584991dc 8089 if (!chan) {
2a519311
JB
8090 err = -EINVAL;
8091 goto out_free;
8092 }
584991dc
JB
8093
8094 /* ignore disabled channels */
8095 if (chan->flags & IEEE80211_CHAN_DISABLED)
8096 continue;
8097
8098 request->channels[i] = chan;
2a519311
JB
8099 i++;
8100 }
8101 } else {
57fbcce3 8102 enum nl80211_band band;
34850ab2 8103
2a519311 8104 /* all channels */
57fbcce3 8105 for (band = 0; band < NUM_NL80211_BANDS; band++) {
2a519311 8106 int j;
7a087e74 8107
2a519311
JB
8108 if (!wiphy->bands[band])
8109 continue;
8110 for (j = 0; j < wiphy->bands[band]->n_channels; j++) {
584991dc
JB
8111 struct ieee80211_channel *chan;
8112
8113 chan = &wiphy->bands[band]->channels[j];
8114
8115 if (chan->flags & IEEE80211_CHAN_DISABLED)
8116 continue;
8117
8118 request->channels[i] = chan;
2a519311
JB
8119 i++;
8120 }
8121 }
8122 }
8123
584991dc
JB
8124 if (!i) {
8125 err = -EINVAL;
8126 goto out_free;
8127 }
8128
8129 request->n_channels = i;
8130
34373d12
VT
8131 wdev_lock(wdev);
8132 if (!cfg80211_off_channel_oper_allowed(wdev)) {
8133 struct ieee80211_channel *chan;
8134
8135 if (request->n_channels != 1) {
8136 wdev_unlock(wdev);
8137 err = -EBUSY;
8138 goto out_free;
8139 }
8140
8141 chan = request->channels[0];
8142 if (chan->center_freq != wdev->chandef.chan->center_freq) {
8143 wdev_unlock(wdev);
8144 err = -EBUSY;
8145 goto out_free;
8146 }
8147 }
8148 wdev_unlock(wdev);
8149
2a519311 8150 i = 0;
13874e4b 8151 if (n_ssids) {
2a519311 8152 nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) {
57a27e1d 8153 if (nla_len(attr) > IEEE80211_MAX_SSID_LEN) {
2a519311
JB
8154 err = -EINVAL;
8155 goto out_free;
8156 }
57a27e1d 8157 request->ssids[i].ssid_len = nla_len(attr);
2a519311 8158 memcpy(request->ssids[i].ssid, nla_data(attr), nla_len(attr));
2a519311
JB
8159 i++;
8160 }
8161 }
8162
70692ad2
JM
8163 if (info->attrs[NL80211_ATTR_IE]) {
8164 request->ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
de95a54b
JB
8165 memcpy((void *)request->ie,
8166 nla_data(info->attrs[NL80211_ATTR_IE]),
70692ad2
JM
8167 request->ie_len);
8168 }
8169
57fbcce3 8170 for (i = 0; i < NUM_NL80211_BANDS; i++)
a401d2bb
JB
8171 if (wiphy->bands[i])
8172 request->rates[i] =
8173 (1 << wiphy->bands[i]->n_bitrates) - 1;
34850ab2
JB
8174
8175 if (info->attrs[NL80211_ATTR_SCAN_SUPP_RATES]) {
8176 nla_for_each_nested(attr,
8177 info->attrs[NL80211_ATTR_SCAN_SUPP_RATES],
8178 tmp) {
57fbcce3 8179 enum nl80211_band band = nla_type(attr);
34850ab2 8180
57fbcce3 8181 if (band < 0 || band >= NUM_NL80211_BANDS) {
34850ab2
JB
8182 err = -EINVAL;
8183 goto out_free;
8184 }
1b09cd82
FF
8185
8186 if (!wiphy->bands[band])
8187 continue;
8188
34850ab2
JB
8189 err = ieee80211_get_ratemask(wiphy->bands[band],
8190 nla_data(attr),
8191 nla_len(attr),
8192 &request->rates[band]);
8193 if (err)
8194 goto out_free;
8195 }
8196 }
8197
1d76250b
AS
8198 if (info->attrs[NL80211_ATTR_MEASUREMENT_DURATION]) {
8199 if (!wiphy_ext_feature_isset(wiphy,
8200 NL80211_EXT_FEATURE_SET_SCAN_DWELL)) {
8201 err = -EOPNOTSUPP;
8202 goto out_free;
8203 }
8204
8205 request->duration =
8206 nla_get_u16(info->attrs[NL80211_ATTR_MEASUREMENT_DURATION]);
8207 request->duration_mandatory =
8208 nla_get_flag(info->attrs[NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY]);
8209 }
8210
2d23d073
RZ
8211 err = nl80211_check_scan_flags(wiphy, wdev, request, info->attrs,
8212 false);
8213 if (err)
8214 goto out_free;
ed473771 8215
e9f935e3
RM
8216 request->no_cck =
8217 nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]);
8218
2fa436b3
VK
8219 /* Initial implementation used NL80211_ATTR_MAC to set the specific
8220 * BSSID to scan for. This was problematic because that same attribute
8221 * was already used for another purpose (local random MAC address). The
8222 * NL80211_ATTR_BSSID attribute was added to fix this. For backwards
8223 * compatibility with older userspace components, also use the
8224 * NL80211_ATTR_MAC value here if it can be determined to be used for
8225 * the specific BSSID use case instead of the random MAC address
8226 * (NL80211_ATTR_SCAN_FLAGS is used to enable random MAC address use).
8227 */
8228 if (info->attrs[NL80211_ATTR_BSSID])
8229 memcpy(request->bssid,
8230 nla_data(info->attrs[NL80211_ATTR_BSSID]), ETH_ALEN);
8231 else if (!(request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) &&
8232 info->attrs[NL80211_ATTR_MAC])
818965d3
JM
8233 memcpy(request->bssid, nla_data(info->attrs[NL80211_ATTR_MAC]),
8234 ETH_ALEN);
8235 else
8236 eth_broadcast_addr(request->bssid);
8237
fd014284 8238 request->wdev = wdev;
79c97e97 8239 request->wiphy = &rdev->wiphy;
15d6030b 8240 request->scan_start = jiffies;
2a519311 8241
79c97e97 8242 rdev->scan_req = request;
c8cb5b85 8243 err = cfg80211_scan(rdev);
2a519311 8244
504776be
CJ
8245 if (err)
8246 goto out_free;
8247
8248 nl80211_send_scan_start(rdev, wdev);
8249 if (wdev->netdev)
8250 dev_hold(wdev->netdev);
8251
8252 return 0;
8253
2a519311 8254 out_free:
504776be
CJ
8255 rdev->scan_req = NULL;
8256 kfree(request);
3b85875a 8257
2a519311
JB
8258 return err;
8259}
8260
91d3ab46
VK
8261static int nl80211_abort_scan(struct sk_buff *skb, struct genl_info *info)
8262{
8263 struct cfg80211_registered_device *rdev = info->user_ptr[0];
8264 struct wireless_dev *wdev = info->user_ptr[1];
8265
8266 if (!rdev->ops->abort_scan)
8267 return -EOPNOTSUPP;
8268
8269 if (rdev->scan_msg)
8270 return 0;
8271
8272 if (!rdev->scan_req)
8273 return -ENOENT;
8274
8275 rdev_abort_scan(rdev, wdev);
8276 return 0;
8277}
8278
3b06d277
AS
8279static int
8280nl80211_parse_sched_scan_plans(struct wiphy *wiphy, int n_plans,
8281 struct cfg80211_sched_scan_request *request,
8282 struct nlattr **attrs)
8283{
8284 int tmp, err, i = 0;
8285 struct nlattr *attr;
8286
8287 if (!attrs[NL80211_ATTR_SCHED_SCAN_PLANS]) {
8288 u32 interval;
8289
8290 /*
8291 * If scan plans are not specified,
5a88de53 8292 * %NL80211_ATTR_SCHED_SCAN_INTERVAL will be specified. In this
3b06d277
AS
8293 * case one scan plan will be set with the specified scan
8294 * interval and infinite number of iterations.
8295 */
3b06d277
AS
8296 interval = nla_get_u32(attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL]);
8297 if (!interval)
8298 return -EINVAL;
8299
8300 request->scan_plans[0].interval =
8301 DIV_ROUND_UP(interval, MSEC_PER_SEC);
8302 if (!request->scan_plans[0].interval)
8303 return -EINVAL;
8304
8305 if (request->scan_plans[0].interval >
8306 wiphy->max_sched_scan_plan_interval)
8307 request->scan_plans[0].interval =
8308 wiphy->max_sched_scan_plan_interval;
8309
8310 return 0;
8311 }
8312
8313 nla_for_each_nested(attr, attrs[NL80211_ATTR_SCHED_SCAN_PLANS], tmp) {
8314 struct nlattr *plan[NL80211_SCHED_SCAN_PLAN_MAX + 1];
8315
8316 if (WARN_ON(i >= n_plans))
8317 return -EINVAL;
8318
8cb08174
JB
8319 err = nla_parse_nested_deprecated(plan,
8320 NL80211_SCHED_SCAN_PLAN_MAX,
8321 attr, nl80211_plan_policy,
8322 NULL);
3b06d277
AS
8323 if (err)
8324 return err;
8325
8326 if (!plan[NL80211_SCHED_SCAN_PLAN_INTERVAL])
8327 return -EINVAL;
8328
8329 request->scan_plans[i].interval =
8330 nla_get_u32(plan[NL80211_SCHED_SCAN_PLAN_INTERVAL]);
8331 if (!request->scan_plans[i].interval ||
8332 request->scan_plans[i].interval >
8333 wiphy->max_sched_scan_plan_interval)
8334 return -EINVAL;
8335
8336 if (plan[NL80211_SCHED_SCAN_PLAN_ITERATIONS]) {
8337 request->scan_plans[i].iterations =
8338 nla_get_u32(plan[NL80211_SCHED_SCAN_PLAN_ITERATIONS]);
8339 if (!request->scan_plans[i].iterations ||
8340 (request->scan_plans[i].iterations >
8341 wiphy->max_sched_scan_plan_iterations))
8342 return -EINVAL;
8343 } else if (i < n_plans - 1) {
8344 /*
8345 * All scan plans but the last one must specify
8346 * a finite number of iterations
8347 */
8348 return -EINVAL;
8349 }
8350
8351 i++;
8352 }
8353
8354 /*
8355 * The last scan plan must not specify the number of
8356 * iterations, it is supposed to run infinitely
8357 */
8358 if (request->scan_plans[n_plans - 1].iterations)
8359 return -EINVAL;
8360
8361 return 0;
8362}
8363
1e1b11b6 8364static int
8365nl80211_parse_sched_scan_per_band_rssi(struct wiphy *wiphy,
8366 struct cfg80211_match_set *match_sets,
8367 struct nlattr *tb_band_rssi,
8368 s32 rssi_thold)
8369{
8370 struct nlattr *attr;
8371 int i, tmp, ret = 0;
8372
8373 if (!wiphy_ext_feature_isset(wiphy,
8374 NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD)) {
8375 if (tb_band_rssi)
8376 ret = -EOPNOTSUPP;
8377 else
8378 for (i = 0; i < NUM_NL80211_BANDS; i++)
8379 match_sets->per_band_rssi_thold[i] =
8380 NL80211_SCAN_RSSI_THOLD_OFF;
8381 return ret;
8382 }
8383
8384 for (i = 0; i < NUM_NL80211_BANDS; i++)
8385 match_sets->per_band_rssi_thold[i] = rssi_thold;
8386
8387 nla_for_each_nested(attr, tb_band_rssi, tmp) {
8388 enum nl80211_band band = nla_type(attr);
8389
8390 if (band < 0 || band >= NUM_NL80211_BANDS)
8391 return -EINVAL;
8392
8393 match_sets->per_band_rssi_thold[band] = nla_get_s32(attr);
8394 }
8395
8396 return 0;
8397}
8398
256da02d 8399static struct cfg80211_sched_scan_request *
ad2b26ab 8400nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev,
aad1e812 8401 struct nlattr **attrs, int max_match_sets)
807f8a8c
LC
8402{
8403 struct cfg80211_sched_scan_request *request;
807f8a8c 8404 struct nlattr *attr;
3b06d277 8405 int err, tmp, n_ssids = 0, n_match_sets = 0, n_channels, i, n_plans = 0;
57fbcce3 8406 enum nl80211_band band;
807f8a8c 8407 size_t ie_len;
a1f1c21c 8408 struct nlattr *tb[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1];
ea73cbce 8409 s32 default_match_rssi = NL80211_SCAN_RSSI_THOLD_OFF;
807f8a8c 8410
256da02d 8411 if (attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
807f8a8c 8412 n_channels = validate_scan_freqs(
256da02d 8413 attrs[NL80211_ATTR_SCAN_FREQUENCIES]);
807f8a8c 8414 if (!n_channels)
256da02d 8415 return ERR_PTR(-EINVAL);
807f8a8c 8416 } else {
bdfbec2d 8417 n_channels = ieee80211_get_num_supported_channels(wiphy);
807f8a8c
LC
8418 }
8419
256da02d
LC
8420 if (attrs[NL80211_ATTR_SCAN_SSIDS])
8421 nla_for_each_nested(attr, attrs[NL80211_ATTR_SCAN_SSIDS],
807f8a8c
LC
8422 tmp)
8423 n_ssids++;
8424
93b6aa69 8425 if (n_ssids > wiphy->max_sched_scan_ssids)
256da02d 8426 return ERR_PTR(-EINVAL);
807f8a8c 8427
ea73cbce
JB
8428 /*
8429 * First, count the number of 'real' matchsets. Due to an issue with
8430 * the old implementation, matchsets containing only the RSSI attribute
8431 * (NL80211_SCHED_SCAN_MATCH_ATTR_RSSI) are considered as the 'default'
8432 * RSSI for all matchsets, rather than their own matchset for reporting
8433 * all APs with a strong RSSI. This is needed to be compatible with
8434 * older userspace that treated a matchset with only the RSSI as the
8435 * global RSSI for all other matchsets - if there are other matchsets.
8436 */
256da02d 8437 if (attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) {
a1f1c21c 8438 nla_for_each_nested(attr,
256da02d 8439 attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
ea73cbce
JB
8440 tmp) {
8441 struct nlattr *rssi;
8442
8cb08174
JB
8443 err = nla_parse_nested_deprecated(tb,
8444 NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
8445 attr,
8446 nl80211_match_policy,
8447 NULL);
ea73cbce 8448 if (err)
256da02d 8449 return ERR_PTR(err);
3007e352
AVS
8450
8451 /* SSID and BSSID are mutually exclusive */
8452 if (tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID] &&
8453 tb[NL80211_SCHED_SCAN_MATCH_ATTR_BSSID])
8454 return ERR_PTR(-EINVAL);
8455
ea73cbce 8456 /* add other standalone attributes here */
3007e352
AVS
8457 if (tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID] ||
8458 tb[NL80211_SCHED_SCAN_MATCH_ATTR_BSSID]) {
ea73cbce
JB
8459 n_match_sets++;
8460 continue;
8461 }
8462 rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI];
8463 if (rssi)
8464 default_match_rssi = nla_get_s32(rssi);
8465 }
8466 }
8467
8468 /* However, if there's no other matchset, add the RSSI one */
8469 if (!n_match_sets && default_match_rssi != NL80211_SCAN_RSSI_THOLD_OFF)
8470 n_match_sets = 1;
a1f1c21c 8471
aad1e812 8472 if (n_match_sets > max_match_sets)
256da02d 8473 return ERR_PTR(-EINVAL);
a1f1c21c 8474
256da02d
LC
8475 if (attrs[NL80211_ATTR_IE])
8476 ie_len = nla_len(attrs[NL80211_ATTR_IE]);
807f8a8c
LC
8477 else
8478 ie_len = 0;
8479
5a865bad 8480 if (ie_len > wiphy->max_sched_scan_ie_len)
256da02d 8481 return ERR_PTR(-EINVAL);
c10841ca 8482
3b06d277
AS
8483 if (attrs[NL80211_ATTR_SCHED_SCAN_PLANS]) {
8484 /*
8485 * NL80211_ATTR_SCHED_SCAN_INTERVAL must not be specified since
8486 * each scan plan already specifies its own interval
8487 */
8488 if (attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL])
8489 return ERR_PTR(-EINVAL);
8490
8491 nla_for_each_nested(attr,
8492 attrs[NL80211_ATTR_SCHED_SCAN_PLANS], tmp)
8493 n_plans++;
8494 } else {
8495 /*
8496 * The scan interval attribute is kept for backward
8497 * compatibility. If no scan plans are specified and sched scan
8498 * interval is specified, one scan plan will be set with this
8499 * scan interval and infinite number of iterations.
8500 */
8501 if (!attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL])
8502 return ERR_PTR(-EINVAL);
8503
8504 n_plans = 1;
8505 }
8506
8507 if (!n_plans || n_plans > wiphy->max_sched_scan_plans)
8508 return ERR_PTR(-EINVAL);
8509
bf95ecdb 8510 if (!wiphy_ext_feature_isset(
8511 wiphy, NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI) &&
8512 (attrs[NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI] ||
8513 attrs[NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST]))
8514 return ERR_PTR(-EINVAL);
8515
807f8a8c 8516 request = kzalloc(sizeof(*request)
a2cd43c5 8517 + sizeof(*request->ssids) * n_ssids
a1f1c21c 8518 + sizeof(*request->match_sets) * n_match_sets
3b06d277 8519 + sizeof(*request->scan_plans) * n_plans
a2cd43c5 8520 + sizeof(*request->channels) * n_channels
807f8a8c 8521 + ie_len, GFP_KERNEL);
256da02d
LC
8522 if (!request)
8523 return ERR_PTR(-ENOMEM);
807f8a8c
LC
8524
8525 if (n_ssids)
8526 request->ssids = (void *)&request->channels[n_channels];
8527 request->n_ssids = n_ssids;
8528 if (ie_len) {
13874e4b 8529 if (n_ssids)
807f8a8c
LC
8530 request->ie = (void *)(request->ssids + n_ssids);
8531 else
8532 request->ie = (void *)(request->channels + n_channels);
8533 }
8534
a1f1c21c
LC
8535 if (n_match_sets) {
8536 if (request->ie)
8537 request->match_sets = (void *)(request->ie + ie_len);
13874e4b 8538 else if (n_ssids)
a1f1c21c
LC
8539 request->match_sets =
8540 (void *)(request->ssids + n_ssids);
8541 else
8542 request->match_sets =
8543 (void *)(request->channels + n_channels);
8544 }
8545 request->n_match_sets = n_match_sets;
8546
3b06d277
AS
8547 if (n_match_sets)
8548 request->scan_plans = (void *)(request->match_sets +
8549 n_match_sets);
8550 else if (request->ie)
8551 request->scan_plans = (void *)(request->ie + ie_len);
8552 else if (n_ssids)
8553 request->scan_plans = (void *)(request->ssids + n_ssids);
8554 else
8555 request->scan_plans = (void *)(request->channels + n_channels);
8556
8557 request->n_scan_plans = n_plans;
8558
807f8a8c 8559 i = 0;
256da02d 8560 if (attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
807f8a8c
LC
8561 /* user specified, bail out if channel not found */
8562 nla_for_each_nested(attr,
256da02d 8563 attrs[NL80211_ATTR_SCAN_FREQUENCIES],
807f8a8c
LC
8564 tmp) {
8565 struct ieee80211_channel *chan;
8566
8567 chan = ieee80211_get_channel(wiphy, nla_get_u32(attr));
8568
8569 if (!chan) {
8570 err = -EINVAL;
8571 goto out_free;
8572 }
8573
8574 /* ignore disabled channels */
8575 if (chan->flags & IEEE80211_CHAN_DISABLED)
8576 continue;
8577
8578 request->channels[i] = chan;
8579 i++;
8580 }
8581 } else {
8582 /* all channels */
57fbcce3 8583 for (band = 0; band < NUM_NL80211_BANDS; band++) {
807f8a8c 8584 int j;
7a087e74 8585
807f8a8c
LC
8586 if (!wiphy->bands[band])
8587 continue;
8588 for (j = 0; j < wiphy->bands[band]->n_channels; j++) {
8589 struct ieee80211_channel *chan;
8590
8591 chan = &wiphy->bands[band]->channels[j];
8592
8593 if (chan->flags & IEEE80211_CHAN_DISABLED)
8594 continue;
8595
8596 request->channels[i] = chan;
8597 i++;
8598 }
8599 }
8600 }
8601
8602 if (!i) {
8603 err = -EINVAL;
8604 goto out_free;
8605 }
8606
8607 request->n_channels = i;
8608
8609 i = 0;
13874e4b 8610 if (n_ssids) {
256da02d 8611 nla_for_each_nested(attr, attrs[NL80211_ATTR_SCAN_SSIDS],
807f8a8c 8612 tmp) {
57a27e1d 8613 if (nla_len(attr) > IEEE80211_MAX_SSID_LEN) {
807f8a8c
LC
8614 err = -EINVAL;
8615 goto out_free;
8616 }
57a27e1d 8617 request->ssids[i].ssid_len = nla_len(attr);
807f8a8c
LC
8618 memcpy(request->ssids[i].ssid, nla_data(attr),
8619 nla_len(attr));
807f8a8c
LC
8620 i++;
8621 }
8622 }
8623
a1f1c21c 8624 i = 0;
256da02d 8625 if (attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) {
a1f1c21c 8626 nla_for_each_nested(attr,
256da02d 8627 attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
a1f1c21c 8628 tmp) {
3007e352 8629 struct nlattr *ssid, *bssid, *rssi;
a1f1c21c 8630
8cb08174
JB
8631 err = nla_parse_nested_deprecated(tb,
8632 NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
8633 attr,
8634 nl80211_match_policy,
8635 NULL);
ae811e21
JB
8636 if (err)
8637 goto out_free;
4a4ab0d7 8638 ssid = tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID];
3007e352 8639 bssid = tb[NL80211_SCHED_SCAN_MATCH_ATTR_BSSID];
d39f3b4f
JB
8640
8641 if (!ssid && !bssid) {
8642 i++;
8643 continue;
8644 }
8645
8646 if (WARN_ON(i >= n_match_sets)) {
8647 /* this indicates a programming error,
8648 * the loop above should have verified
8649 * things properly
8650 */
8651 err = -EINVAL;
8652 goto out_free;
8653 }
8654
8655 if (ssid) {
d39f3b4f
JB
8656 memcpy(request->match_sets[i].ssid.ssid,
8657 nla_data(ssid), nla_len(ssid));
8658 request->match_sets[i].ssid.ssid_len =
8659 nla_len(ssid);
8660 }
cb9abd48 8661 if (bssid)
d39f3b4f
JB
8662 memcpy(request->match_sets[i].bssid,
8663 nla_data(bssid), ETH_ALEN);
3007e352 8664
d39f3b4f
JB
8665 /* special attribute - old implementation w/a */
8666 request->match_sets[i].rssi_thold = default_match_rssi;
8667 rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI];
8668 if (rssi)
ea73cbce 8669 request->match_sets[i].rssi_thold =
d39f3b4f 8670 nla_get_s32(rssi);
1e1b11b6 8671
8672 /* Parse per band RSSI attribute */
8673 err = nl80211_parse_sched_scan_per_band_rssi(wiphy,
8674 &request->match_sets[i],
8675 tb[NL80211_SCHED_SCAN_MATCH_PER_BAND_RSSI],
8676 request->match_sets[i].rssi_thold);
8677 if (err)
8678 goto out_free;
8679
a1f1c21c
LC
8680 i++;
8681 }
ea73cbce
JB
8682
8683 /* there was no other matchset, so the RSSI one is alone */
f89f46cf 8684 if (i == 0 && n_match_sets)
ea73cbce
JB
8685 request->match_sets[0].rssi_thold = default_match_rssi;
8686
8687 request->min_rssi_thold = INT_MAX;
8688 for (i = 0; i < n_match_sets; i++)
8689 request->min_rssi_thold =
8690 min(request->match_sets[i].rssi_thold,
8691 request->min_rssi_thold);
8692 } else {
8693 request->min_rssi_thold = NL80211_SCAN_RSSI_THOLD_OFF;
a1f1c21c
LC
8694 }
8695
9900e484
JB
8696 if (ie_len) {
8697 request->ie_len = ie_len;
807f8a8c 8698 memcpy((void *)request->ie,
256da02d 8699 nla_data(attrs[NL80211_ATTR_IE]),
807f8a8c
LC
8700 request->ie_len);
8701 }
8702
2d23d073
RZ
8703 err = nl80211_check_scan_flags(wiphy, wdev, request, attrs, true);
8704 if (err)
8705 goto out_free;
ed473771 8706
9c748934
LC
8707 if (attrs[NL80211_ATTR_SCHED_SCAN_DELAY])
8708 request->delay =
8709 nla_get_u32(attrs[NL80211_ATTR_SCHED_SCAN_DELAY]);
8710
bf95ecdb 8711 if (attrs[NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI]) {
8712 request->relative_rssi = nla_get_s8(
8713 attrs[NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI]);
8714 request->relative_rssi_set = true;
8715 }
8716
8717 if (request->relative_rssi_set &&
8718 attrs[NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST]) {
8719 struct nl80211_bss_select_rssi_adjust *rssi_adjust;
8720
8721 rssi_adjust = nla_data(
8722 attrs[NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST]);
8723 request->rssi_adjust.band = rssi_adjust->band;
8724 request->rssi_adjust.delta = rssi_adjust->delta;
8725 if (!is_band_valid(wiphy, request->rssi_adjust.band)) {
8726 err = -EINVAL;
8727 goto out_free;
8728 }
8729 }
8730
3b06d277
AS
8731 err = nl80211_parse_sched_scan_plans(wiphy, n_plans, request, attrs);
8732 if (err)
8733 goto out_free;
8734
15d6030b 8735 request->scan_start = jiffies;
807f8a8c 8736
256da02d 8737 return request;
807f8a8c
LC
8738
8739out_free:
8740 kfree(request);
256da02d
LC
8741 return ERR_PTR(err);
8742}
8743
8744static int nl80211_start_sched_scan(struct sk_buff *skb,
8745 struct genl_info *info)
8746{
8747 struct cfg80211_registered_device *rdev = info->user_ptr[0];
8748 struct net_device *dev = info->user_ptr[1];
ad2b26ab 8749 struct wireless_dev *wdev = dev->ieee80211_ptr;
31a60ed1 8750 struct cfg80211_sched_scan_request *sched_scan_req;
ca986ad9 8751 bool want_multi;
256da02d
LC
8752 int err;
8753
ca986ad9 8754 if (!rdev->wiphy.max_sched_scan_reqs || !rdev->ops->sched_scan_start)
256da02d
LC
8755 return -EOPNOTSUPP;
8756
ca986ad9
AVS
8757 want_multi = info->attrs[NL80211_ATTR_SCHED_SCAN_MULTI];
8758 err = cfg80211_sched_scan_req_possible(rdev, want_multi);
8759 if (err)
8760 return err;
256da02d 8761
31a60ed1 8762 sched_scan_req = nl80211_parse_sched_scan(&rdev->wiphy, wdev,
aad1e812
AVS
8763 info->attrs,
8764 rdev->wiphy.max_match_sets);
31a60ed1
JR
8765
8766 err = PTR_ERR_OR_ZERO(sched_scan_req);
256da02d
LC
8767 if (err)
8768 goto out_err;
8769
ca986ad9
AVS
8770 /* leave request id zero for legacy request
8771 * or if driver does not support multi-scheduled scan
8772 */
2fd351a8
DK
8773 if (want_multi && rdev->wiphy.max_sched_scan_reqs > 1)
8774 sched_scan_req->reqid = cfg80211_assign_cookie(rdev);
ca986ad9 8775
31a60ed1 8776 err = rdev_sched_scan_start(rdev, dev, sched_scan_req);
256da02d
LC
8777 if (err)
8778 goto out_free;
8779
31a60ed1
JR
8780 sched_scan_req->dev = dev;
8781 sched_scan_req->wiphy = &rdev->wiphy;
8782
93a1e86c
JR
8783 if (info->attrs[NL80211_ATTR_SOCKET_OWNER])
8784 sched_scan_req->owner_nlportid = info->snd_portid;
8785
ca986ad9 8786 cfg80211_add_sched_scan_req(rdev, sched_scan_req);
256da02d 8787
96b08fd6 8788 nl80211_send_sched_scan(sched_scan_req, NL80211_CMD_START_SCHED_SCAN);
256da02d
LC
8789 return 0;
8790
8791out_free:
31a60ed1 8792 kfree(sched_scan_req);
256da02d 8793out_err:
807f8a8c
LC
8794 return err;
8795}
8796
8797static int nl80211_stop_sched_scan(struct sk_buff *skb,
8798 struct genl_info *info)
8799{
ca986ad9 8800 struct cfg80211_sched_scan_request *req;
807f8a8c 8801 struct cfg80211_registered_device *rdev = info->user_ptr[0];
ca986ad9 8802 u64 cookie;
807f8a8c 8803
ca986ad9 8804 if (!rdev->wiphy.max_sched_scan_reqs || !rdev->ops->sched_scan_stop)
807f8a8c
LC
8805 return -EOPNOTSUPP;
8806
ca986ad9
AVS
8807 if (info->attrs[NL80211_ATTR_COOKIE]) {
8808 cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);
8809 return __cfg80211_stop_sched_scan(rdev, cookie, false);
8810 }
8811
8812 req = list_first_or_null_rcu(&rdev->sched_scan_req_list,
8813 struct cfg80211_sched_scan_request,
8814 list);
8815 if (!req || req->reqid ||
8816 (req->owner_nlportid &&
8817 req->owner_nlportid != info->snd_portid))
8818 return -ENOENT;
8819
8820 return cfg80211_stop_sched_scan_req(rdev, req, false);
807f8a8c
LC
8821}
8822
04f39047
SW
8823static int nl80211_start_radar_detection(struct sk_buff *skb,
8824 struct genl_info *info)
8825{
8826 struct cfg80211_registered_device *rdev = info->user_ptr[0];
8827 struct net_device *dev = info->user_ptr[1];
8828 struct wireless_dev *wdev = dev->ieee80211_ptr;
13cf6dec 8829 struct wiphy *wiphy = wdev->wiphy;
04f39047 8830 struct cfg80211_chan_def chandef;
55f7435c 8831 enum nl80211_dfs_regions dfs_region;
31559f35 8832 unsigned int cac_time_ms;
04f39047
SW
8833 int err;
8834
13cf6dec 8835 dfs_region = reg_get_dfs_region(wiphy);
55f7435c
LR
8836 if (dfs_region == NL80211_DFS_UNSET)
8837 return -EINVAL;
8838
04f39047
SW
8839 err = nl80211_parse_chandef(rdev, info, &chandef);
8840 if (err)
8841 return err;
8842
ff311bc1
SW
8843 if (netif_carrier_ok(dev))
8844 return -EBUSY;
8845
04f39047
SW
8846 if (wdev->cac_started)
8847 return -EBUSY;
8848
13cf6dec 8849 err = cfg80211_chandef_dfs_required(wiphy, &chandef, wdev->iftype);
04f39047
SW
8850 if (err < 0)
8851 return err;
8852
8853 if (err == 0)
8854 return -EINVAL;
8855
13cf6dec 8856 if (!cfg80211_chandef_dfs_usable(wiphy, &chandef))
04f39047
SW
8857 return -EINVAL;
8858
13cf6dec
DL
8859 /* CAC start is offloaded to HW and can't be started manually */
8860 if (wiphy_ext_feature_isset(wiphy, NL80211_EXT_FEATURE_DFS_OFFLOAD))
8861 return -EOPNOTSUPP;
8862
04f39047
SW
8863 if (!rdev->ops->start_radar_detection)
8864 return -EOPNOTSUPP;
8865
31559f35
JD
8866 cac_time_ms = cfg80211_chandef_dfs_cac_time(&rdev->wiphy, &chandef);
8867 if (WARN_ON(!cac_time_ms))
8868 cac_time_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
8869
a1056b1b 8870 err = rdev_start_radar_detection(rdev, dev, &chandef, cac_time_ms);
04f39047 8871 if (!err) {
9e0e2961 8872 wdev->chandef = chandef;
04f39047
SW
8873 wdev->cac_started = true;
8874 wdev->cac_start_time = jiffies;
31559f35 8875 wdev->cac_time_ms = cac_time_ms;
04f39047 8876 }
04f39047
SW
8877 return err;
8878}
8879
30c63115
S
8880static int nl80211_notify_radar_detection(struct sk_buff *skb,
8881 struct genl_info *info)
8882{
8883 struct cfg80211_registered_device *rdev = info->user_ptr[0];
8884 struct net_device *dev = info->user_ptr[1];
8885 struct wireless_dev *wdev = dev->ieee80211_ptr;
8886 struct wiphy *wiphy = wdev->wiphy;
8887 struct cfg80211_chan_def chandef;
8888 enum nl80211_dfs_regions dfs_region;
8889 int err;
8890
8891 dfs_region = reg_get_dfs_region(wiphy);
8892 if (dfs_region == NL80211_DFS_UNSET) {
8893 GENL_SET_ERR_MSG(info,
8894 "DFS Region is not set. Unexpected Radar indication");
8895 return -EINVAL;
8896 }
8897
8898 err = nl80211_parse_chandef(rdev, info, &chandef);
8899 if (err) {
8900 GENL_SET_ERR_MSG(info, "Unable to extract chandef info");
8901 return err;
8902 }
8903
8904 err = cfg80211_chandef_dfs_required(wiphy, &chandef, wdev->iftype);
8905 if (err < 0) {
8906 GENL_SET_ERR_MSG(info, "chandef is invalid");
8907 return err;
8908 }
8909
8910 if (err == 0) {
8911 GENL_SET_ERR_MSG(info,
8912 "Unexpected Radar indication for chandef/iftype");
8913 return -EINVAL;
8914 }
8915
8916 /* Do not process this notification if radar is already detected
8917 * by kernel on this channel, and return success.
8918 */
8919 if (chandef.chan->dfs_state == NL80211_DFS_UNAVAILABLE)
8920 return 0;
8921
8922 cfg80211_set_dfs_state(wiphy, &chandef, NL80211_DFS_UNAVAILABLE);
8923
8924 cfg80211_sched_dfs_chan_update(rdev);
8925
a680fe46 8926 rdev->radar_chandef = chandef;
30c63115
S
8927
8928 /* Propagate this notification to other radios as well */
8929 queue_work(cfg80211_wq, &rdev->propagate_radar_detect_wk);
8930
8931 return 0;
8932}
8933
16ef1fe2
SW
8934static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
8935{
8936 struct cfg80211_registered_device *rdev = info->user_ptr[0];
8937 struct net_device *dev = info->user_ptr[1];
8938 struct wireless_dev *wdev = dev->ieee80211_ptr;
8939 struct cfg80211_csa_settings params;
8940 /* csa_attrs is defined static to avoid waste of stack size - this
8941 * function is called under RTNL lock, so this should not be a problem.
8942 */
8943 static struct nlattr *csa_attrs[NL80211_ATTR_MAX+1];
16ef1fe2 8944 int err;
ee4bc9e7 8945 bool need_new_beacon = false;
8d9de16f 8946 bool need_handle_dfs_flag = true;
9a774c78 8947 int len, i;
252e07ca 8948 u32 cs_count;
16ef1fe2
SW
8949
8950 if (!rdev->ops->channel_switch ||
8951 !(rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH))
8952 return -EOPNOTSUPP;
8953
ee4bc9e7
SW
8954 switch (dev->ieee80211_ptr->iftype) {
8955 case NL80211_IFTYPE_AP:
8956 case NL80211_IFTYPE_P2P_GO:
8957 need_new_beacon = true;
8d9de16f
BB
8958 /* For all modes except AP the handle_dfs flag needs to be
8959 * supplied to tell the kernel that userspace will handle radar
8960 * events when they happen. Otherwise a switch to a channel
8961 * requiring DFS will be rejected.
8962 */
8963 need_handle_dfs_flag = false;
ee4bc9e7
SW
8964
8965 /* useless if AP is not running */
8966 if (!wdev->beacon_interval)
1ff79dfa 8967 return -ENOTCONN;
ee4bc9e7
SW
8968 break;
8969 case NL80211_IFTYPE_ADHOC:
1ff79dfa
JB
8970 if (!wdev->ssid_len)
8971 return -ENOTCONN;
8972 break;
c6da674a 8973 case NL80211_IFTYPE_MESH_POINT:
1ff79dfa
JB
8974 if (!wdev->mesh_id_len)
8975 return -ENOTCONN;
ee4bc9e7
SW
8976 break;
8977 default:
16ef1fe2 8978 return -EOPNOTSUPP;
ee4bc9e7 8979 }
16ef1fe2
SW
8980
8981 memset(&params, 0, sizeof(params));
c177db2d 8982 params.beacon_csa.ftm_responder = -1;
16ef1fe2
SW
8983
8984 if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] ||
8985 !info->attrs[NL80211_ATTR_CH_SWITCH_COUNT])
8986 return -EINVAL;
8987
8988 /* only important for AP, IBSS and mesh create IEs internally */
d0a361a5 8989 if (need_new_beacon && !info->attrs[NL80211_ATTR_CSA_IES])
16ef1fe2
SW
8990 return -EINVAL;
8991
252e07ca
LC
8992 /* Even though the attribute is u32, the specification says
8993 * u8, so let's make sure we don't overflow.
8994 */
8995 cs_count = nla_get_u32(info->attrs[NL80211_ATTR_CH_SWITCH_COUNT]);
8996 if (cs_count > 255)
8997 return -EINVAL;
8998
8999 params.count = cs_count;
16ef1fe2 9000
ee4bc9e7
SW
9001 if (!need_new_beacon)
9002 goto skip_beacons;
9003
81e54d08 9004 err = nl80211_parse_beacon(rdev, info->attrs, &params.beacon_after);
16ef1fe2
SW
9005 if (err)
9006 return err;
9007
8cb08174
JB
9008 err = nla_parse_nested_deprecated(csa_attrs, NL80211_ATTR_MAX,
9009 info->attrs[NL80211_ATTR_CSA_IES],
9010 nl80211_policy, info->extack);
16ef1fe2
SW
9011 if (err)
9012 return err;
9013
81e54d08 9014 err = nl80211_parse_beacon(rdev, csa_attrs, &params.beacon_csa);
16ef1fe2
SW
9015 if (err)
9016 return err;
9017
00c207ed 9018 if (!csa_attrs[NL80211_ATTR_CNTDWN_OFFS_BEACON])
16ef1fe2
SW
9019 return -EINVAL;
9020
00c207ed 9021 len = nla_len(csa_attrs[NL80211_ATTR_CNTDWN_OFFS_BEACON]);
9a774c78 9022 if (!len || (len % sizeof(u16)))
16ef1fe2
SW
9023 return -EINVAL;
9024
9a774c78
AO
9025 params.n_counter_offsets_beacon = len / sizeof(u16);
9026 if (rdev->wiphy.max_num_csa_counters &&
9027 (params.n_counter_offsets_beacon >
9028 rdev->wiphy.max_num_csa_counters))
16ef1fe2
SW
9029 return -EINVAL;
9030
9a774c78 9031 params.counter_offsets_beacon =
00c207ed 9032 nla_data(csa_attrs[NL80211_ATTR_CNTDWN_OFFS_BEACON]);
9a774c78
AO
9033
9034 /* sanity checks - counters should fit and be the same */
9035 for (i = 0; i < params.n_counter_offsets_beacon; i++) {
9036 u16 offset = params.counter_offsets_beacon[i];
9037
9038 if (offset >= params.beacon_csa.tail_len)
9039 return -EINVAL;
9040
9041 if (params.beacon_csa.tail[offset] != params.count)
9042 return -EINVAL;
9043 }
9044
00c207ed
JC
9045 if (csa_attrs[NL80211_ATTR_CNTDWN_OFFS_PRESP]) {
9046 len = nla_len(csa_attrs[NL80211_ATTR_CNTDWN_OFFS_PRESP]);
9a774c78 9047 if (!len || (len % sizeof(u16)))
16ef1fe2
SW
9048 return -EINVAL;
9049
9a774c78
AO
9050 params.n_counter_offsets_presp = len / sizeof(u16);
9051 if (rdev->wiphy.max_num_csa_counters &&
ad5987b4 9052 (params.n_counter_offsets_presp >
9a774c78 9053 rdev->wiphy.max_num_csa_counters))
16ef1fe2 9054 return -EINVAL;
9a774c78
AO
9055
9056 params.counter_offsets_presp =
00c207ed 9057 nla_data(csa_attrs[NL80211_ATTR_CNTDWN_OFFS_PRESP]);
9a774c78
AO
9058
9059 /* sanity checks - counters should fit and be the same */
9060 for (i = 0; i < params.n_counter_offsets_presp; i++) {
9061 u16 offset = params.counter_offsets_presp[i];
9062
9063 if (offset >= params.beacon_csa.probe_resp_len)
9064 return -EINVAL;
9065
9066 if (params.beacon_csa.probe_resp[offset] !=
9067 params.count)
9068 return -EINVAL;
9069 }
16ef1fe2
SW
9070 }
9071
ee4bc9e7 9072skip_beacons:
16ef1fe2
SW
9073 err = nl80211_parse_chandef(rdev, info, &params.chandef);
9074 if (err)
9075 return err;
9076
923b352f
AN
9077 if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &params.chandef,
9078 wdev->iftype))
16ef1fe2
SW
9079 return -EINVAL;
9080
2beb6dab
LC
9081 err = cfg80211_chandef_dfs_required(wdev->wiphy,
9082 &params.chandef,
9083 wdev->iftype);
9084 if (err < 0)
9085 return err;
9086
8d9de16f 9087 if (err > 0) {
2beb6dab 9088 params.radar_required = true;
8d9de16f
BB
9089 if (need_handle_dfs_flag &&
9090 !nla_get_flag(info->attrs[NL80211_ATTR_HANDLE_DFS])) {
9091 return -EINVAL;
9092 }
9093 }
16ef1fe2 9094
16ef1fe2
SW
9095 if (info->attrs[NL80211_ATTR_CH_SWITCH_BLOCK_TX])
9096 params.block_tx = true;
9097
c56589ed
SW
9098 wdev_lock(wdev);
9099 err = rdev_channel_switch(rdev, dev, &params);
9100 wdev_unlock(wdev);
9101
9102 return err;
16ef1fe2
SW
9103}
9104
9720bb3a
JB
9105static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
9106 u32 seq, int flags,
2a519311 9107 struct cfg80211_registered_device *rdev,
48ab905d
JB
9108 struct wireless_dev *wdev,
9109 struct cfg80211_internal_bss *intbss)
2a519311 9110{
48ab905d 9111 struct cfg80211_bss *res = &intbss->pub;
9caf0364 9112 const struct cfg80211_bss_ies *ies;
2a519311
JB
9113 void *hdr;
9114 struct nlattr *bss;
48ab905d
JB
9115
9116 ASSERT_WDEV_LOCK(wdev);
2a519311 9117
15e47304 9118 hdr = nl80211hdr_put(msg, NETLINK_CB(cb->skb).portid, seq, flags,
2a519311
JB
9119 NL80211_CMD_NEW_SCAN_RESULTS);
9120 if (!hdr)
9121 return -1;
9122
0a833c29 9123 genl_dump_check_consistent(cb, hdr);
9720bb3a 9124
97990a06
JB
9125 if (nla_put_u32(msg, NL80211_ATTR_GENERATION, rdev->bss_generation))
9126 goto nla_put_failure;
9127 if (wdev->netdev &&
9360ffd1
DM
9128 nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex))
9129 goto nla_put_failure;
2dad624e
ND
9130 if (nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
9131 NL80211_ATTR_PAD))
97990a06 9132 goto nla_put_failure;
2a519311 9133
ae0be8de 9134 bss = nla_nest_start_noflag(msg, NL80211_ATTR_BSS);
2a519311
JB
9135 if (!bss)
9136 goto nla_put_failure;
9360ffd1 9137 if ((!is_zero_ether_addr(res->bssid) &&
9caf0364 9138 nla_put(msg, NL80211_BSS_BSSID, ETH_ALEN, res->bssid)))
9360ffd1 9139 goto nla_put_failure;
9caf0364
JB
9140
9141 rcu_read_lock();
0e227084
JB
9142 /* indicate whether we have probe response data or not */
9143 if (rcu_access_pointer(res->proberesp_ies) &&
9144 nla_put_flag(msg, NL80211_BSS_PRESP_DATA))
9145 goto fail_unlock_rcu;
9146
9147 /* this pointer prefers to be pointed to probe response data
9148 * but is always valid
9149 */
9caf0364 9150 ies = rcu_dereference(res->ies);
8cef2c9d 9151 if (ies) {
2dad624e
ND
9152 if (nla_put_u64_64bit(msg, NL80211_BSS_TSF, ies->tsf,
9153 NL80211_BSS_PAD))
8cef2c9d 9154 goto fail_unlock_rcu;
8cef2c9d
JB
9155 if (ies->len && nla_put(msg, NL80211_BSS_INFORMATION_ELEMENTS,
9156 ies->len, ies->data))
9157 goto fail_unlock_rcu;
9caf0364 9158 }
0e227084
JB
9159
9160 /* and this pointer is always (unless driver didn't know) beacon data */
9caf0364 9161 ies = rcu_dereference(res->beacon_ies);
0e227084 9162 if (ies && ies->from_beacon) {
2dad624e
ND
9163 if (nla_put_u64_64bit(msg, NL80211_BSS_BEACON_TSF, ies->tsf,
9164 NL80211_BSS_PAD))
8cef2c9d
JB
9165 goto fail_unlock_rcu;
9166 if (ies->len && nla_put(msg, NL80211_BSS_BEACON_IES,
9167 ies->len, ies->data))
9168 goto fail_unlock_rcu;
9caf0364
JB
9169 }
9170 rcu_read_unlock();
9171
9360ffd1
DM
9172 if (res->beacon_interval &&
9173 nla_put_u16(msg, NL80211_BSS_BEACON_INTERVAL, res->beacon_interval))
9174 goto nla_put_failure;
9175 if (nla_put_u16(msg, NL80211_BSS_CAPABILITY, res->capability) ||
9176 nla_put_u32(msg, NL80211_BSS_FREQUENCY, res->channel->center_freq) ||
942ba88b
TP
9177 nla_put_u32(msg, NL80211_BSS_FREQUENCY_OFFSET,
9178 res->channel->freq_offset) ||
dcd6eac1 9179 nla_put_u32(msg, NL80211_BSS_CHAN_WIDTH, res->scan_width) ||
9360ffd1
DM
9180 nla_put_u32(msg, NL80211_BSS_SEEN_MS_AGO,
9181 jiffies_to_msecs(jiffies - intbss->ts)))
9182 goto nla_put_failure;
2a519311 9183
1d76250b
AS
9184 if (intbss->parent_tsf &&
9185 (nla_put_u64_64bit(msg, NL80211_BSS_PARENT_TSF,
9186 intbss->parent_tsf, NL80211_BSS_PAD) ||
9187 nla_put(msg, NL80211_BSS_PARENT_BSSID, ETH_ALEN,
9188 intbss->parent_bssid)))
9189 goto nla_put_failure;
9190
6e19bc4b 9191 if (intbss->ts_boottime &&
2dad624e
ND
9192 nla_put_u64_64bit(msg, NL80211_BSS_LAST_SEEN_BOOTTIME,
9193 intbss->ts_boottime, NL80211_BSS_PAD))
6e19bc4b
DS
9194 goto nla_put_failure;
9195
983dafaa
SD
9196 if (!nl80211_put_signal(msg, intbss->pub.chains,
9197 intbss->pub.chain_signal,
9198 NL80211_BSS_CHAIN_SIGNAL))
9199 goto nla_put_failure;
9200
77965c97 9201 switch (rdev->wiphy.signal_type) {
2a519311 9202 case CFG80211_SIGNAL_TYPE_MBM:
9360ffd1
DM
9203 if (nla_put_u32(msg, NL80211_BSS_SIGNAL_MBM, res->signal))
9204 goto nla_put_failure;
2a519311
JB
9205 break;
9206 case CFG80211_SIGNAL_TYPE_UNSPEC:
9360ffd1
DM
9207 if (nla_put_u8(msg, NL80211_BSS_SIGNAL_UNSPEC, res->signal))
9208 goto nla_put_failure;
2a519311
JB
9209 break;
9210 default:
9211 break;
9212 }
9213
48ab905d 9214 switch (wdev->iftype) {
074ac8df 9215 case NL80211_IFTYPE_P2P_CLIENT:
48ab905d 9216 case NL80211_IFTYPE_STATION:
9360ffd1
DM
9217 if (intbss == wdev->current_bss &&
9218 nla_put_u32(msg, NL80211_BSS_STATUS,
9219 NL80211_BSS_STATUS_ASSOCIATED))
9220 goto nla_put_failure;
48ab905d
JB
9221 break;
9222 case NL80211_IFTYPE_ADHOC:
9360ffd1
DM
9223 if (intbss == wdev->current_bss &&
9224 nla_put_u32(msg, NL80211_BSS_STATUS,
9225 NL80211_BSS_STATUS_IBSS_JOINED))
9226 goto nla_put_failure;
48ab905d
JB
9227 break;
9228 default:
9229 break;
9230 }
9231
2a519311
JB
9232 nla_nest_end(msg, bss);
9233
053c095a
JB
9234 genlmsg_end(msg, hdr);
9235 return 0;
2a519311 9236
8cef2c9d
JB
9237 fail_unlock_rcu:
9238 rcu_read_unlock();
2a519311
JB
9239 nla_put_failure:
9240 genlmsg_cancel(msg, hdr);
9241 return -EMSGSIZE;
9242}
9243
97990a06 9244static int nl80211_dump_scan(struct sk_buff *skb, struct netlink_callback *cb)
2a519311 9245{
48ab905d 9246 struct cfg80211_registered_device *rdev;
2a519311 9247 struct cfg80211_internal_bss *scan;
48ab905d 9248 struct wireless_dev *wdev;
97990a06 9249 int start = cb->args[2], idx = 0;
2a519311
JB
9250 int err;
9251
ea90e0dc 9252 rtnl_lock();
5297c65c 9253 err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev);
ea90e0dc
JB
9254 if (err) {
9255 rtnl_unlock();
67748893 9256 return err;
ea90e0dc 9257 }
2a519311 9258
48ab905d
JB
9259 wdev_lock(wdev);
9260 spin_lock_bh(&rdev->bss_lock);
d1e23c94
DK
9261
9262 /*
9263 * dump_scan will be called multiple times to break up the scan results
9264 * into multiple messages. It is unlikely that any more bss-es will be
9265 * expired after the first call, so only call only call this on the
9266 * first dump_scan invocation.
9267 */
9268 if (start == 0)
9269 cfg80211_bss_expire(rdev);
48ab905d 9270
9720bb3a
JB
9271 cb->seq = rdev->bss_generation;
9272
48ab905d 9273 list_for_each_entry(scan, &rdev->bss_list, list) {
2a519311
JB
9274 if (++idx <= start)
9275 continue;
9720bb3a 9276 if (nl80211_send_bss(skb, cb,
2a519311 9277 cb->nlh->nlmsg_seq, NLM_F_MULTI,
48ab905d 9278 rdev, wdev, scan) < 0) {
2a519311 9279 idx--;
67748893 9280 break;
2a519311
JB
9281 }
9282 }
9283
48ab905d
JB
9284 spin_unlock_bh(&rdev->bss_lock);
9285 wdev_unlock(wdev);
2a519311 9286
97990a06 9287 cb->args[2] = idx;
ea90e0dc 9288 rtnl_unlock();
2a519311 9289
67748893 9290 return skb->len;
2a519311
JB
9291}
9292
15e47304 9293static int nl80211_send_survey(struct sk_buff *msg, u32 portid, u32 seq,
11f78ac3
JB
9294 int flags, struct net_device *dev,
9295 bool allow_radio_stats,
9296 struct survey_info *survey)
61fa713c
HS
9297{
9298 void *hdr;
9299 struct nlattr *infoattr;
9300
11f78ac3
JB
9301 /* skip radio stats if userspace didn't request them */
9302 if (!survey->channel && !allow_radio_stats)
9303 return 0;
9304
15e47304 9305 hdr = nl80211hdr_put(msg, portid, seq, flags,
61fa713c
HS
9306 NL80211_CMD_NEW_SURVEY_RESULTS);
9307 if (!hdr)
9308 return -ENOMEM;
9309
9360ffd1
DM
9310 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
9311 goto nla_put_failure;
61fa713c 9312
ae0be8de 9313 infoattr = nla_nest_start_noflag(msg, NL80211_ATTR_SURVEY_INFO);
61fa713c
HS
9314 if (!infoattr)
9315 goto nla_put_failure;
9316
11f78ac3
JB
9317 if (survey->channel &&
9318 nla_put_u32(msg, NL80211_SURVEY_INFO_FREQUENCY,
9360ffd1
DM
9319 survey->channel->center_freq))
9320 goto nla_put_failure;
9321
9322 if ((survey->filled & SURVEY_INFO_NOISE_DBM) &&
9323 nla_put_u8(msg, NL80211_SURVEY_INFO_NOISE, survey->noise))
9324 goto nla_put_failure;
9325 if ((survey->filled & SURVEY_INFO_IN_USE) &&
9326 nla_put_flag(msg, NL80211_SURVEY_INFO_IN_USE))
9327 goto nla_put_failure;
4ed20beb 9328 if ((survey->filled & SURVEY_INFO_TIME) &&
2dad624e
ND
9329 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME,
9330 survey->time, NL80211_SURVEY_INFO_PAD))
9360ffd1 9331 goto nla_put_failure;
4ed20beb 9332 if ((survey->filled & SURVEY_INFO_TIME_BUSY) &&
2dad624e
ND
9333 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_BUSY,
9334 survey->time_busy, NL80211_SURVEY_INFO_PAD))
9360ffd1 9335 goto nla_put_failure;
4ed20beb 9336 if ((survey->filled & SURVEY_INFO_TIME_EXT_BUSY) &&
2dad624e
ND
9337 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_EXT_BUSY,
9338 survey->time_ext_busy, NL80211_SURVEY_INFO_PAD))
9360ffd1 9339 goto nla_put_failure;
4ed20beb 9340 if ((survey->filled & SURVEY_INFO_TIME_RX) &&
2dad624e
ND
9341 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_RX,
9342 survey->time_rx, NL80211_SURVEY_INFO_PAD))
9360ffd1 9343 goto nla_put_failure;
4ed20beb 9344 if ((survey->filled & SURVEY_INFO_TIME_TX) &&
2dad624e
ND
9345 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_TX,
9346 survey->time_tx, NL80211_SURVEY_INFO_PAD))
9360ffd1 9347 goto nla_put_failure;
052536ab 9348 if ((survey->filled & SURVEY_INFO_TIME_SCAN) &&
2dad624e
ND
9349 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_SCAN,
9350 survey->time_scan, NL80211_SURVEY_INFO_PAD))
052536ab 9351 goto nla_put_failure;
c8cd6e7f
FF
9352 if ((survey->filled & SURVEY_INFO_TIME_BSS_RX) &&
9353 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_BSS_RX,
9354 survey->time_bss_rx, NL80211_SURVEY_INFO_PAD))
9355 goto nla_put_failure;
61fa713c
HS
9356
9357 nla_nest_end(msg, infoattr);
9358
053c095a
JB
9359 genlmsg_end(msg, hdr);
9360 return 0;
61fa713c
HS
9361
9362 nla_put_failure:
9363 genlmsg_cancel(msg, hdr);
9364 return -EMSGSIZE;
9365}
9366
11f78ac3 9367static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb)
61fa713c 9368{
50508d94 9369 struct nlattr **attrbuf;
61fa713c 9370 struct survey_info survey;
1b8ec87a 9371 struct cfg80211_registered_device *rdev;
97990a06
JB
9372 struct wireless_dev *wdev;
9373 int survey_idx = cb->args[2];
61fa713c 9374 int res;
11f78ac3 9375 bool radio_stats;
61fa713c 9376
50508d94
JB
9377 attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf), GFP_KERNEL);
9378 if (!attrbuf)
9379 return -ENOMEM;
9380
ea90e0dc 9381 rtnl_lock();
5297c65c 9382 res = nl80211_prepare_wdev_dump(cb, &rdev, &wdev);
67748893 9383 if (res)
ea90e0dc 9384 goto out_err;
61fa713c 9385
11f78ac3 9386 /* prepare_wdev_dump parsed the attributes */
c90c39da 9387 radio_stats = attrbuf[NL80211_ATTR_SURVEY_RADIO_STATS];
11f78ac3 9388
97990a06
JB
9389 if (!wdev->netdev) {
9390 res = -EINVAL;
9391 goto out_err;
9392 }
9393
1b8ec87a 9394 if (!rdev->ops->dump_survey) {
61fa713c
HS
9395 res = -EOPNOTSUPP;
9396 goto out_err;
9397 }
9398
9399 while (1) {
1b8ec87a 9400 res = rdev_dump_survey(rdev, wdev->netdev, survey_idx, &survey);
61fa713c
HS
9401 if (res == -ENOENT)
9402 break;
9403 if (res)
9404 goto out_err;
9405
11f78ac3
JB
9406 /* don't send disabled channels, but do send non-channel data */
9407 if (survey.channel &&
9408 survey.channel->flags & IEEE80211_CHAN_DISABLED) {
180cdc79
LR
9409 survey_idx++;
9410 continue;
9411 }
9412
61fa713c 9413 if (nl80211_send_survey(skb,
15e47304 9414 NETLINK_CB(cb->skb).portid,
61fa713c 9415 cb->nlh->nlmsg_seq, NLM_F_MULTI,
11f78ac3 9416 wdev->netdev, radio_stats, &survey) < 0)
61fa713c
HS
9417 goto out;
9418 survey_idx++;
9419 }
9420
9421 out:
97990a06 9422 cb->args[2] = survey_idx;
61fa713c
HS
9423 res = skb->len;
9424 out_err:
50508d94 9425 kfree(attrbuf);
ea90e0dc 9426 rtnl_unlock();
61fa713c
HS
9427 return res;
9428}
9429
b23aa676
SO
9430static bool nl80211_valid_wpa_versions(u32 wpa_versions)
9431{
9432 return !(wpa_versions & ~(NL80211_WPA_VERSION_1 |
cc3e14c2
CHH
9433 NL80211_WPA_VERSION_2 |
9434 NL80211_WPA_VERSION_3));
b23aa676
SO
9435}
9436
636a5d36
JM
9437static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
9438{
4c476991
JB
9439 struct cfg80211_registered_device *rdev = info->user_ptr[0];
9440 struct net_device *dev = info->user_ptr[1];
19957bb3 9441 struct ieee80211_channel *chan;
11b6b5a4
JM
9442 const u8 *bssid, *ssid, *ie = NULL, *auth_data = NULL;
9443 int err, ssid_len, ie_len = 0, auth_data_len = 0;
19957bb3 9444 enum nl80211_auth_type auth_type;
fffd0934 9445 struct key_parse key;
d5cdfacb 9446 bool local_state_change;
942ba88b 9447 u32 freq;
636a5d36 9448
f4a11bb0
JB
9449 if (!info->attrs[NL80211_ATTR_MAC])
9450 return -EINVAL;
9451
1778092e
JM
9452 if (!info->attrs[NL80211_ATTR_AUTH_TYPE])
9453 return -EINVAL;
9454
19957bb3
JB
9455 if (!info->attrs[NL80211_ATTR_SSID])
9456 return -EINVAL;
9457
9458 if (!info->attrs[NL80211_ATTR_WIPHY_FREQ])
9459 return -EINVAL;
9460
fffd0934
JB
9461 err = nl80211_parse_key(info, &key);
9462 if (err)
9463 return err;
9464
9465 if (key.idx >= 0) {
e31b8213
JB
9466 if (key.type != -1 && key.type != NL80211_KEYTYPE_GROUP)
9467 return -EINVAL;
fffd0934
JB
9468 if (!key.p.key || !key.p.key_len)
9469 return -EINVAL;
9470 if ((key.p.cipher != WLAN_CIPHER_SUITE_WEP40 ||
9471 key.p.key_len != WLAN_KEY_LEN_WEP40) &&
9472 (key.p.cipher != WLAN_CIPHER_SUITE_WEP104 ||
9473 key.p.key_len != WLAN_KEY_LEN_WEP104))
9474 return -EINVAL;
b6b5555b 9475 if (key.idx > 3)
fffd0934
JB
9476 return -EINVAL;
9477 } else {
9478 key.p.key_len = 0;
9479 key.p.key = NULL;
9480 }
9481
afea0b7a
JB
9482 if (key.idx >= 0) {
9483 int i;
9484 bool ok = false;
7a087e74 9485
afea0b7a
JB
9486 for (i = 0; i < rdev->wiphy.n_cipher_suites; i++) {
9487 if (key.p.cipher == rdev->wiphy.cipher_suites[i]) {
9488 ok = true;
9489 break;
9490 }
9491 }
4c476991
JB
9492 if (!ok)
9493 return -EINVAL;
afea0b7a
JB
9494 }
9495
4c476991
JB
9496 if (!rdev->ops->auth)
9497 return -EOPNOTSUPP;
636a5d36 9498
074ac8df 9499 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
9500 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
9501 return -EOPNOTSUPP;
eec60b03 9502
19957bb3 9503 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
942ba88b
TP
9504 freq = MHZ_TO_KHZ(nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
9505 if (info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET])
9506 freq +=
9507 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET]);
9508
9509 chan = nl80211_get_valid_chan(&rdev->wiphy, freq);
664834de 9510 if (!chan)
4c476991 9511 return -EINVAL;
636a5d36 9512
19957bb3
JB
9513 ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
9514 ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
636a5d36
JM
9515
9516 if (info->attrs[NL80211_ATTR_IE]) {
19957bb3
JB
9517 ie = nla_data(info->attrs[NL80211_ATTR_IE]);
9518 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
636a5d36
JM
9519 }
9520
19957bb3 9521 auth_type = nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
e39e5b5e 9522 if (!nl80211_valid_auth_type(rdev, auth_type, NL80211_CMD_AUTHENTICATE))
4c476991 9523 return -EINVAL;
636a5d36 9524
63181060
JM
9525 if ((auth_type == NL80211_AUTHTYPE_SAE ||
9526 auth_type == NL80211_AUTHTYPE_FILS_SK ||
9527 auth_type == NL80211_AUTHTYPE_FILS_SK_PFS ||
9528 auth_type == NL80211_AUTHTYPE_FILS_PK) &&
11b6b5a4 9529 !info->attrs[NL80211_ATTR_AUTH_DATA])
e39e5b5e
JM
9530 return -EINVAL;
9531
11b6b5a4 9532 if (info->attrs[NL80211_ATTR_AUTH_DATA]) {
63181060
JM
9533 if (auth_type != NL80211_AUTHTYPE_SAE &&
9534 auth_type != NL80211_AUTHTYPE_FILS_SK &&
9535 auth_type != NL80211_AUTHTYPE_FILS_SK_PFS &&
9536 auth_type != NL80211_AUTHTYPE_FILS_PK)
e39e5b5e 9537 return -EINVAL;
11b6b5a4
JM
9538 auth_data = nla_data(info->attrs[NL80211_ATTR_AUTH_DATA]);
9539 auth_data_len = nla_len(info->attrs[NL80211_ATTR_AUTH_DATA]);
e39e5b5e
JM
9540 }
9541
d5cdfacb
JM
9542 local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
9543
95de817b
JB
9544 /*
9545 * Since we no longer track auth state, ignore
9546 * requests to only change local state.
9547 */
9548 if (local_state_change)
9549 return 0;
9550
91bf9b26
JB
9551 wdev_lock(dev->ieee80211_ptr);
9552 err = cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
9553 ssid, ssid_len, ie, ie_len,
9554 key.p.key, key.p.key_len, key.idx,
11b6b5a4 9555 auth_data, auth_data_len);
91bf9b26
JB
9556 wdev_unlock(dev->ieee80211_ptr);
9557 return err;
636a5d36
JM
9558}
9559
64bf3d4b
DK
9560static int validate_pae_over_nl80211(struct cfg80211_registered_device *rdev,
9561 struct genl_info *info)
9562{
9563 if (!info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
9564 GENL_SET_ERR_MSG(info, "SOCKET_OWNER not set");
9565 return -EINVAL;
9566 }
9567
9568 if (!rdev->ops->tx_control_port ||
9569 !wiphy_ext_feature_isset(&rdev->wiphy,
9570 NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211))
9571 return -EOPNOTSUPP;
9572
9573 return 0;
9574}
9575
c0692b8f
JB
9576static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev,
9577 struct genl_info *info,
3dc27d25
JB
9578 struct cfg80211_crypto_settings *settings,
9579 int cipher_limit)
b23aa676 9580{
c0b2bbd8
JB
9581 memset(settings, 0, sizeof(*settings));
9582
b23aa676
SO
9583 settings->control_port = info->attrs[NL80211_ATTR_CONTROL_PORT];
9584
c0692b8f
JB
9585 if (info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]) {
9586 u16 proto;
7a087e74 9587
c0692b8f
JB
9588 proto = nla_get_u16(
9589 info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]);
9590 settings->control_port_ethertype = cpu_to_be16(proto);
9591 if (!(rdev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) &&
9592 proto != ETH_P_PAE)
9593 return -EINVAL;
9594 if (info->attrs[NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT])
9595 settings->control_port_no_encrypt = true;
9596 } else
9597 settings->control_port_ethertype = cpu_to_be16(ETH_P_PAE);
9598
64bf3d4b
DK
9599 if (info->attrs[NL80211_ATTR_CONTROL_PORT_OVER_NL80211]) {
9600 int r = validate_pae_over_nl80211(rdev, info);
9601
9602 if (r < 0)
9603 return r;
9604
9605 settings->control_port_over_nl80211 = true;
7f3f96ce
MT
9606
9607 if (info->attrs[NL80211_ATTR_CONTROL_PORT_NO_PREAUTH])
9608 settings->control_port_no_preauth = true;
64bf3d4b
DK
9609 }
9610
b23aa676
SO
9611 if (info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE]) {
9612 void *data;
9613 int len, i;
9614
9615 data = nla_data(info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE]);
9616 len = nla_len(info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE]);
9617 settings->n_ciphers_pairwise = len / sizeof(u32);
9618
9619 if (len % sizeof(u32))
9620 return -EINVAL;
9621
3dc27d25 9622 if (settings->n_ciphers_pairwise > cipher_limit)
b23aa676
SO
9623 return -EINVAL;
9624
9625 memcpy(settings->ciphers_pairwise, data, len);
9626
9627 for (i = 0; i < settings->n_ciphers_pairwise; i++)
38ba3c57
JM
9628 if (!cfg80211_supported_cipher_suite(
9629 &rdev->wiphy,
b23aa676
SO
9630 settings->ciphers_pairwise[i]))
9631 return -EINVAL;
9632 }
9633
9634 if (info->attrs[NL80211_ATTR_CIPHER_SUITE_GROUP]) {
9635 settings->cipher_group =
9636 nla_get_u32(info->attrs[NL80211_ATTR_CIPHER_SUITE_GROUP]);
38ba3c57
JM
9637 if (!cfg80211_supported_cipher_suite(&rdev->wiphy,
9638 settings->cipher_group))
b23aa676
SO
9639 return -EINVAL;
9640 }
9641
9642 if (info->attrs[NL80211_ATTR_WPA_VERSIONS]) {
9643 settings->wpa_versions =
9644 nla_get_u32(info->attrs[NL80211_ATTR_WPA_VERSIONS]);
9645 if (!nl80211_valid_wpa_versions(settings->wpa_versions))
9646 return -EINVAL;
9647 }
9648
9649 if (info->attrs[NL80211_ATTR_AKM_SUITES]) {
9650 void *data;
6d30240e 9651 int len;
b23aa676
SO
9652
9653 data = nla_data(info->attrs[NL80211_ATTR_AKM_SUITES]);
9654 len = nla_len(info->attrs[NL80211_ATTR_AKM_SUITES]);
9655 settings->n_akm_suites = len / sizeof(u32);
9656
9657 if (len % sizeof(u32))
9658 return -EINVAL;
9659
1b9ca027
JM
9660 if (settings->n_akm_suites > NL80211_MAX_NR_AKM_SUITES)
9661 return -EINVAL;
9662
b23aa676 9663 memcpy(settings->akm_suites, data, len);
b23aa676
SO
9664 }
9665
91b5ab62
EP
9666 if (info->attrs[NL80211_ATTR_PMK]) {
9667 if (nla_len(info->attrs[NL80211_ATTR_PMK]) != WLAN_PMK_LEN)
9668 return -EINVAL;
9669 if (!wiphy_ext_feature_isset(&rdev->wiphy,
f9662274
CHH
9670 NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK) &&
9671 !wiphy_ext_feature_isset(&rdev->wiphy,
9672 NL80211_EXT_FEATURE_4WAY_HANDSHAKE_AP_PSK))
91b5ab62
EP
9673 return -EINVAL;
9674 settings->psk = nla_data(info->attrs[NL80211_ATTR_PMK]);
9675 }
9676
26f7044e
CHH
9677 if (info->attrs[NL80211_ATTR_SAE_PASSWORD]) {
9678 if (!wiphy_ext_feature_isset(&rdev->wiphy,
2831a631
CHH
9679 NL80211_EXT_FEATURE_SAE_OFFLOAD) &&
9680 !wiphy_ext_feature_isset(&rdev->wiphy,
9681 NL80211_EXT_FEATURE_SAE_OFFLOAD_AP))
26f7044e
CHH
9682 return -EINVAL;
9683 settings->sae_pwd =
9684 nla_data(info->attrs[NL80211_ATTR_SAE_PASSWORD]);
9685 settings->sae_pwd_len =
9686 nla_len(info->attrs[NL80211_ATTR_SAE_PASSWORD]);
9687 }
9688
b23aa676
SO
9689 return 0;
9690}
9691
636a5d36
JM
9692static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
9693{
4c476991
JB
9694 struct cfg80211_registered_device *rdev = info->user_ptr[0];
9695 struct net_device *dev = info->user_ptr[1];
f444de05 9696 struct ieee80211_channel *chan;
f62fab73
JB
9697 struct cfg80211_assoc_request req = {};
9698 const u8 *bssid, *ssid;
9699 int err, ssid_len = 0;
942ba88b 9700 u32 freq;
636a5d36 9701
bad29297
AZ
9702 if (dev->ieee80211_ptr->conn_owner_nlportid &&
9703 dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)
9704 return -EPERM;
9705
f4a11bb0 9706 if (!info->attrs[NL80211_ATTR_MAC] ||
19957bb3
JB
9707 !info->attrs[NL80211_ATTR_SSID] ||
9708 !info->attrs[NL80211_ATTR_WIPHY_FREQ])
f4a11bb0
JB
9709 return -EINVAL;
9710
4c476991
JB
9711 if (!rdev->ops->assoc)
9712 return -EOPNOTSUPP;
636a5d36 9713
074ac8df 9714 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
9715 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
9716 return -EOPNOTSUPP;
eec60b03 9717
19957bb3 9718 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
636a5d36 9719
942ba88b
TP
9720 freq = MHZ_TO_KHZ(nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
9721 if (info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET])
9722 freq +=
9723 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET]);
9724 chan = nl80211_get_valid_chan(&rdev->wiphy, freq);
664834de 9725 if (!chan)
4c476991 9726 return -EINVAL;
636a5d36 9727
19957bb3
JB
9728 ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
9729 ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
636a5d36
JM
9730
9731 if (info->attrs[NL80211_ATTR_IE]) {
f62fab73
JB
9732 req.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
9733 req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
636a5d36
JM
9734 }
9735
dc6382ce 9736 if (info->attrs[NL80211_ATTR_USE_MFP]) {
4f5dadce 9737 enum nl80211_mfp mfp =
dc6382ce 9738 nla_get_u32(info->attrs[NL80211_ATTR_USE_MFP]);
4f5dadce 9739 if (mfp == NL80211_MFP_REQUIRED)
f62fab73 9740 req.use_mfp = true;
4c476991
JB
9741 else if (mfp != NL80211_MFP_NO)
9742 return -EINVAL;
dc6382ce
JM
9743 }
9744
3e5d7649 9745 if (info->attrs[NL80211_ATTR_PREV_BSSID])
f62fab73 9746 req.prev_bssid = nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]);
3e5d7649 9747
7e7c8926 9748 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HT]))
f62fab73 9749 req.flags |= ASSOC_REQ_DISABLE_HT;
7e7c8926
BG
9750
9751 if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
f62fab73
JB
9752 memcpy(&req.ht_capa_mask,
9753 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]),
9754 sizeof(req.ht_capa_mask));
7e7c8926
BG
9755
9756 if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
f62fab73 9757 if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
7e7c8926 9758 return -EINVAL;
f62fab73
JB
9759 memcpy(&req.ht_capa,
9760 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]),
9761 sizeof(req.ht_capa));
7e7c8926
BG
9762 }
9763
ee2aca34 9764 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_VHT]))
f62fab73 9765 req.flags |= ASSOC_REQ_DISABLE_VHT;
ee2aca34
JB
9766
9767 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK])
f62fab73
JB
9768 memcpy(&req.vht_capa_mask,
9769 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]),
9770 sizeof(req.vht_capa_mask));
ee2aca34
JB
9771
9772 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY]) {
f62fab73 9773 if (!info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK])
ee2aca34 9774 return -EINVAL;
f62fab73
JB
9775 memcpy(&req.vht_capa,
9776 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]),
9777 sizeof(req.vht_capa));
ee2aca34
JB
9778 }
9779
bab5ab7d 9780 if (nla_get_flag(info->attrs[NL80211_ATTR_USE_RRM])) {
0c9ca11b
BL
9781 if (!((rdev->wiphy.features &
9782 NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES) &&
9783 (rdev->wiphy.features & NL80211_FEATURE_QUIET)) &&
9784 !wiphy_ext_feature_isset(&rdev->wiphy,
9785 NL80211_EXT_FEATURE_RRM))
bab5ab7d
AK
9786 return -EINVAL;
9787 req.flags |= ASSOC_REQ_USE_RRM;
9788 }
9789
348bd456
JM
9790 if (info->attrs[NL80211_ATTR_FILS_KEK]) {
9791 req.fils_kek = nla_data(info->attrs[NL80211_ATTR_FILS_KEK]);
9792 req.fils_kek_len = nla_len(info->attrs[NL80211_ATTR_FILS_KEK]);
9793 if (!info->attrs[NL80211_ATTR_FILS_NONCES])
9794 return -EINVAL;
9795 req.fils_nonces =
9796 nla_data(info->attrs[NL80211_ATTR_FILS_NONCES]);
9797 }
9798
d2b7588a
TP
9799 if (info->attrs[NL80211_ATTR_S1G_CAPABILITY_MASK]) {
9800 if (!info->attrs[NL80211_ATTR_S1G_CAPABILITY])
9801 return -EINVAL;
9802 memcpy(&req.s1g_capa_mask,
9803 nla_data(info->attrs[NL80211_ATTR_S1G_CAPABILITY_MASK]),
9804 sizeof(req.s1g_capa_mask));
9805 }
9806
9807 if (info->attrs[NL80211_ATTR_S1G_CAPABILITY]) {
9808 if (!info->attrs[NL80211_ATTR_S1G_CAPABILITY_MASK])
9809 return -EINVAL;
9810 memcpy(&req.s1g_capa,
9811 nla_data(info->attrs[NL80211_ATTR_S1G_CAPABILITY]),
9812 sizeof(req.s1g_capa));
9813 }
9814
f62fab73 9815 err = nl80211_crypto_settings(rdev, info, &req.crypto, 1);
91bf9b26
JB
9816 if (!err) {
9817 wdev_lock(dev->ieee80211_ptr);
bd2522b1 9818
f62fab73
JB
9819 err = cfg80211_mlme_assoc(rdev, dev, chan, bssid,
9820 ssid, ssid_len, &req);
bd2522b1
AZ
9821
9822 if (!err && info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
9823 dev->ieee80211_ptr->conn_owner_nlportid =
9824 info->snd_portid;
9825 memcpy(dev->ieee80211_ptr->disconnect_bssid,
9826 bssid, ETH_ALEN);
9827 }
9828
91bf9b26
JB
9829 wdev_unlock(dev->ieee80211_ptr);
9830 }
636a5d36 9831
636a5d36
JM
9832 return err;
9833}
9834
9835static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info)
9836{
4c476991
JB
9837 struct cfg80211_registered_device *rdev = info->user_ptr[0];
9838 struct net_device *dev = info->user_ptr[1];
19957bb3 9839 const u8 *ie = NULL, *bssid;
91bf9b26 9840 int ie_len = 0, err;
19957bb3 9841 u16 reason_code;
d5cdfacb 9842 bool local_state_change;
636a5d36 9843
bad29297
AZ
9844 if (dev->ieee80211_ptr->conn_owner_nlportid &&
9845 dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)
9846 return -EPERM;
9847
f4a11bb0
JB
9848 if (!info->attrs[NL80211_ATTR_MAC])
9849 return -EINVAL;
9850
9851 if (!info->attrs[NL80211_ATTR_REASON_CODE])
9852 return -EINVAL;
9853
4c476991
JB
9854 if (!rdev->ops->deauth)
9855 return -EOPNOTSUPP;
636a5d36 9856
074ac8df 9857 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
9858 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
9859 return -EOPNOTSUPP;
eec60b03 9860
19957bb3 9861 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
636a5d36 9862
19957bb3
JB
9863 reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
9864 if (reason_code == 0) {
f4a11bb0 9865 /* Reason Code 0 is reserved */
4c476991 9866 return -EINVAL;
255e737e 9867 }
636a5d36
JM
9868
9869 if (info->attrs[NL80211_ATTR_IE]) {
19957bb3
JB
9870 ie = nla_data(info->attrs[NL80211_ATTR_IE]);
9871 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
636a5d36
JM
9872 }
9873
d5cdfacb
JM
9874 local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
9875
91bf9b26
JB
9876 wdev_lock(dev->ieee80211_ptr);
9877 err = cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code,
9878 local_state_change);
9879 wdev_unlock(dev->ieee80211_ptr);
9880 return err;
636a5d36
JM
9881}
9882
9883static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info)
9884{
4c476991
JB
9885 struct cfg80211_registered_device *rdev = info->user_ptr[0];
9886 struct net_device *dev = info->user_ptr[1];
19957bb3 9887 const u8 *ie = NULL, *bssid;
91bf9b26 9888 int ie_len = 0, err;
19957bb3 9889 u16 reason_code;
d5cdfacb 9890 bool local_state_change;
636a5d36 9891
bad29297
AZ
9892 if (dev->ieee80211_ptr->conn_owner_nlportid &&
9893 dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)
9894 return -EPERM;
9895
f4a11bb0
JB
9896 if (!info->attrs[NL80211_ATTR_MAC])
9897 return -EINVAL;
9898
9899 if (!info->attrs[NL80211_ATTR_REASON_CODE])
9900 return -EINVAL;
9901
4c476991
JB
9902 if (!rdev->ops->disassoc)
9903 return -EOPNOTSUPP;
636a5d36 9904
074ac8df 9905 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
9906 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
9907 return -EOPNOTSUPP;
eec60b03 9908
19957bb3 9909 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
636a5d36 9910
19957bb3
JB
9911 reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
9912 if (reason_code == 0) {
f4a11bb0 9913 /* Reason Code 0 is reserved */
4c476991 9914 return -EINVAL;
255e737e 9915 }
636a5d36
JM
9916
9917 if (info->attrs[NL80211_ATTR_IE]) {
19957bb3
JB
9918 ie = nla_data(info->attrs[NL80211_ATTR_IE]);
9919 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
636a5d36
JM
9920 }
9921
d5cdfacb
JM
9922 local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
9923
91bf9b26
JB
9924 wdev_lock(dev->ieee80211_ptr);
9925 err = cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code,
9926 local_state_change);
9927 wdev_unlock(dev->ieee80211_ptr);
9928 return err;
636a5d36
JM
9929}
9930
dd5b4cc7
FF
9931static bool
9932nl80211_parse_mcast_rate(struct cfg80211_registered_device *rdev,
57fbcce3 9933 int mcast_rate[NUM_NL80211_BANDS],
dd5b4cc7
FF
9934 int rateval)
9935{
9936 struct wiphy *wiphy = &rdev->wiphy;
9937 bool found = false;
9938 int band, i;
9939
57fbcce3 9940 for (band = 0; band < NUM_NL80211_BANDS; band++) {
dd5b4cc7
FF
9941 struct ieee80211_supported_band *sband;
9942
9943 sband = wiphy->bands[band];
9944 if (!sband)
9945 continue;
9946
9947 for (i = 0; i < sband->n_bitrates; i++) {
9948 if (sband->bitrates[i].bitrate == rateval) {
9949 mcast_rate[band] = i + 1;
9950 found = true;
9951 break;
9952 }
9953 }
9954 }
9955
9956 return found;
9957}
9958
04a773ad
JB
9959static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
9960{
4c476991
JB
9961 struct cfg80211_registered_device *rdev = info->user_ptr[0];
9962 struct net_device *dev = info->user_ptr[1];
04a773ad
JB
9963 struct cfg80211_ibss_params ibss;
9964 struct wiphy *wiphy;
fffd0934 9965 struct cfg80211_cached_keys *connkeys = NULL;
04a773ad
JB
9966 int err;
9967
8e30bc55
JB
9968 memset(&ibss, 0, sizeof(ibss));
9969
683b6d3b 9970 if (!info->attrs[NL80211_ATTR_SSID] ||
04a773ad
JB
9971 !nla_len(info->attrs[NL80211_ATTR_SSID]))
9972 return -EINVAL;
9973
8e30bc55
JB
9974 ibss.beacon_interval = 100;
9975
12d20fc9 9976 if (info->attrs[NL80211_ATTR_BEACON_INTERVAL])
8e30bc55
JB
9977 ibss.beacon_interval =
9978 nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
12d20fc9 9979
0c317a02
PK
9980 err = cfg80211_validate_beacon_int(rdev, NL80211_IFTYPE_ADHOC,
9981 ibss.beacon_interval);
12d20fc9
PK
9982 if (err)
9983 return err;
8e30bc55 9984
4c476991
JB
9985 if (!rdev->ops->join_ibss)
9986 return -EOPNOTSUPP;
04a773ad 9987
4c476991
JB
9988 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC)
9989 return -EOPNOTSUPP;
04a773ad 9990
79c97e97 9991 wiphy = &rdev->wiphy;
04a773ad 9992
39193498 9993 if (info->attrs[NL80211_ATTR_MAC]) {
04a773ad 9994 ibss.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
39193498
JB
9995
9996 if (!is_valid_ether_addr(ibss.bssid))
9997 return -EINVAL;
9998 }
04a773ad
JB
9999 ibss.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
10000 ibss.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
10001
10002 if (info->attrs[NL80211_ATTR_IE]) {
10003 ibss.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
10004 ibss.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
10005 }
10006
683b6d3b
JB
10007 err = nl80211_parse_chandef(rdev, info, &ibss.chandef);
10008 if (err)
10009 return err;
04a773ad 10010
174e0cd2
IP
10011 if (!cfg80211_reg_can_beacon(&rdev->wiphy, &ibss.chandef,
10012 NL80211_IFTYPE_ADHOC))
54858ee5
AS
10013 return -EINVAL;
10014
2f301ab2 10015 switch (ibss.chandef.width) {
bf372645
SW
10016 case NL80211_CHAN_WIDTH_5:
10017 case NL80211_CHAN_WIDTH_10:
2f301ab2
SW
10018 case NL80211_CHAN_WIDTH_20_NOHT:
10019 break;
10020 case NL80211_CHAN_WIDTH_20:
10021 case NL80211_CHAN_WIDTH_40:
ffc11991
JD
10022 if (!(rdev->wiphy.features & NL80211_FEATURE_HT_IBSS))
10023 return -EINVAL;
10024 break;
10025 case NL80211_CHAN_WIDTH_80:
10026 case NL80211_CHAN_WIDTH_80P80:
10027 case NL80211_CHAN_WIDTH_160:
10028 if (!(rdev->wiphy.features & NL80211_FEATURE_HT_IBSS))
10029 return -EINVAL;
10030 if (!wiphy_ext_feature_isset(&rdev->wiphy,
10031 NL80211_EXT_FEATURE_VHT_IBSS))
10032 return -EINVAL;
10033 break;
2f301ab2 10034 default:
c04d6150 10035 return -EINVAL;
2f301ab2 10036 }
db9c64cf 10037
04a773ad 10038 ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED];
fffd0934
JB
10039 ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY];
10040
fbd2c8dc
TP
10041 if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) {
10042 u8 *rates =
10043 nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
10044 int n_rates =
10045 nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
10046 struct ieee80211_supported_band *sband =
683b6d3b 10047 wiphy->bands[ibss.chandef.chan->band];
fbd2c8dc 10048
34850ab2
JB
10049 err = ieee80211_get_ratemask(sband, rates, n_rates,
10050 &ibss.basic_rates);
10051 if (err)
10052 return err;
fbd2c8dc 10053 }
dd5b4cc7 10054
803768f5
SW
10055 if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
10056 memcpy(&ibss.ht_capa_mask,
10057 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]),
10058 sizeof(ibss.ht_capa_mask));
10059
10060 if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
10061 if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
10062 return -EINVAL;
10063 memcpy(&ibss.ht_capa,
10064 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]),
10065 sizeof(ibss.ht_capa));
10066 }
10067
dd5b4cc7
FF
10068 if (info->attrs[NL80211_ATTR_MCAST_RATE] &&
10069 !nl80211_parse_mcast_rate(rdev, ibss.mcast_rate,
10070 nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE])))
10071 return -EINVAL;
fbd2c8dc 10072
4c476991 10073 if (ibss.privacy && info->attrs[NL80211_ATTR_KEYS]) {
de7044ee
SM
10074 bool no_ht = false;
10075
768075eb 10076 connkeys = nl80211_parse_connkeys(rdev, info, &no_ht);
4c476991
JB
10077 if (IS_ERR(connkeys))
10078 return PTR_ERR(connkeys);
de7044ee 10079
3d9d1d66
JB
10080 if ((ibss.chandef.width != NL80211_CHAN_WIDTH_20_NOHT) &&
10081 no_ht) {
453431a5 10082 kfree_sensitive(connkeys);
de7044ee
SM
10083 return -EINVAL;
10084 }
4c476991 10085 }
04a773ad 10086
267335d6
AQ
10087 ibss.control_port =
10088 nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT]);
10089
c3bfe1f6
DK
10090 if (info->attrs[NL80211_ATTR_CONTROL_PORT_OVER_NL80211]) {
10091 int r = validate_pae_over_nl80211(rdev, info);
10092
d350a0f4 10093 if (r < 0) {
453431a5 10094 kfree_sensitive(connkeys);
c3bfe1f6 10095 return r;
d350a0f4 10096 }
c3bfe1f6
DK
10097
10098 ibss.control_port_over_nl80211 = true;
10099 }
10100
5336fa88
SW
10101 ibss.userspace_handles_dfs =
10102 nla_get_flag(info->attrs[NL80211_ATTR_HANDLE_DFS]);
10103
f8d16d3e
DK
10104 wdev_lock(dev->ieee80211_ptr);
10105 err = __cfg80211_join_ibss(rdev, dev, &ibss, connkeys);
fffd0934 10106 if (err)
453431a5 10107 kfree_sensitive(connkeys);
f8d16d3e
DK
10108 else if (info->attrs[NL80211_ATTR_SOCKET_OWNER])
10109 dev->ieee80211_ptr->conn_owner_nlportid = info->snd_portid;
10110 wdev_unlock(dev->ieee80211_ptr);
10111
04a773ad
JB
10112 return err;
10113}
10114
10115static int nl80211_leave_ibss(struct sk_buff *skb, struct genl_info *info)
10116{
4c476991
JB
10117 struct cfg80211_registered_device *rdev = info->user_ptr[0];
10118 struct net_device *dev = info->user_ptr[1];
04a773ad 10119
4c476991
JB
10120 if (!rdev->ops->leave_ibss)
10121 return -EOPNOTSUPP;
04a773ad 10122
4c476991
JB
10123 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC)
10124 return -EOPNOTSUPP;
04a773ad 10125
4c476991 10126 return cfg80211_leave_ibss(rdev, dev, false);
04a773ad
JB
10127}
10128
f4e583c8
AQ
10129static int nl80211_set_mcast_rate(struct sk_buff *skb, struct genl_info *info)
10130{
10131 struct cfg80211_registered_device *rdev = info->user_ptr[0];
10132 struct net_device *dev = info->user_ptr[1];
57fbcce3 10133 int mcast_rate[NUM_NL80211_BANDS];
f4e583c8
AQ
10134 u32 nla_rate;
10135 int err;
10136
10137 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC &&
876dc930
BVB
10138 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT &&
10139 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_OCB)
f4e583c8
AQ
10140 return -EOPNOTSUPP;
10141
10142 if (!rdev->ops->set_mcast_rate)
10143 return -EOPNOTSUPP;
10144
10145 memset(mcast_rate, 0, sizeof(mcast_rate));
10146
10147 if (!info->attrs[NL80211_ATTR_MCAST_RATE])
10148 return -EINVAL;
10149
10150 nla_rate = nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE]);
10151 if (!nl80211_parse_mcast_rate(rdev, mcast_rate, nla_rate))
10152 return -EINVAL;
10153
a1056b1b 10154 err = rdev_set_mcast_rate(rdev, dev, mcast_rate);
f4e583c8
AQ
10155
10156 return err;
10157}
10158
ad7e718c
JB
10159static struct sk_buff *
10160__cfg80211_alloc_vendor_skb(struct cfg80211_registered_device *rdev,
6c09e791
AK
10161 struct wireless_dev *wdev, int approxlen,
10162 u32 portid, u32 seq, enum nl80211_commands cmd,
567ffc35
JB
10163 enum nl80211_attrs attr,
10164 const struct nl80211_vendor_cmd_info *info,
10165 gfp_t gfp)
ad7e718c
JB
10166{
10167 struct sk_buff *skb;
10168 void *hdr;
10169 struct nlattr *data;
10170
10171 skb = nlmsg_new(approxlen + 100, gfp);
10172 if (!skb)
10173 return NULL;
10174
10175 hdr = nl80211hdr_put(skb, portid, seq, 0, cmd);
10176 if (!hdr) {
10177 kfree_skb(skb);
10178 return NULL;
10179 }
10180
10181 if (nla_put_u32(skb, NL80211_ATTR_WIPHY, rdev->wiphy_idx))
10182 goto nla_put_failure;
567ffc35
JB
10183
10184 if (info) {
10185 if (nla_put_u32(skb, NL80211_ATTR_VENDOR_ID,
10186 info->vendor_id))
10187 goto nla_put_failure;
10188 if (nla_put_u32(skb, NL80211_ATTR_VENDOR_SUBCMD,
10189 info->subcmd))
10190 goto nla_put_failure;
10191 }
10192
6c09e791 10193 if (wdev) {
2dad624e
ND
10194 if (nla_put_u64_64bit(skb, NL80211_ATTR_WDEV,
10195 wdev_id(wdev), NL80211_ATTR_PAD))
6c09e791
AK
10196 goto nla_put_failure;
10197 if (wdev->netdev &&
10198 nla_put_u32(skb, NL80211_ATTR_IFINDEX,
10199 wdev->netdev->ifindex))
10200 goto nla_put_failure;
10201 }
10202
ae0be8de 10203 data = nla_nest_start_noflag(skb, attr);
76e1fb4b
JB
10204 if (!data)
10205 goto nla_put_failure;
ad7e718c
JB
10206
10207 ((void **)skb->cb)[0] = rdev;
10208 ((void **)skb->cb)[1] = hdr;
10209 ((void **)skb->cb)[2] = data;
10210
10211 return skb;
10212
10213 nla_put_failure:
10214 kfree_skb(skb);
10215 return NULL;
10216}
f4e583c8 10217
e03ad6ea 10218struct sk_buff *__cfg80211_alloc_event_skb(struct wiphy *wiphy,
6c09e791 10219 struct wireless_dev *wdev,
e03ad6ea
JB
10220 enum nl80211_commands cmd,
10221 enum nl80211_attrs attr,
55c1fdf0 10222 unsigned int portid,
e03ad6ea
JB
10223 int vendor_event_idx,
10224 int approxlen, gfp_t gfp)
10225{
f26cbf40 10226 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
e03ad6ea
JB
10227 const struct nl80211_vendor_cmd_info *info;
10228
10229 switch (cmd) {
10230 case NL80211_CMD_TESTMODE:
10231 if (WARN_ON(vendor_event_idx != -1))
10232 return NULL;
10233 info = NULL;
10234 break;
10235 case NL80211_CMD_VENDOR:
10236 if (WARN_ON(vendor_event_idx < 0 ||
10237 vendor_event_idx >= wiphy->n_vendor_events))
10238 return NULL;
10239 info = &wiphy->vendor_events[vendor_event_idx];
10240 break;
10241 default:
10242 WARN_ON(1);
10243 return NULL;
10244 }
10245
55c1fdf0 10246 return __cfg80211_alloc_vendor_skb(rdev, wdev, approxlen, portid, 0,
e03ad6ea
JB
10247 cmd, attr, info, gfp);
10248}
10249EXPORT_SYMBOL(__cfg80211_alloc_event_skb);
10250
10251void __cfg80211_send_event_skb(struct sk_buff *skb, gfp_t gfp)
10252{
10253 struct cfg80211_registered_device *rdev = ((void **)skb->cb)[0];
10254 void *hdr = ((void **)skb->cb)[1];
55c1fdf0 10255 struct nlmsghdr *nlhdr = nlmsg_hdr(skb);
e03ad6ea
JB
10256 struct nlattr *data = ((void **)skb->cb)[2];
10257 enum nl80211_multicast_groups mcgrp = NL80211_MCGRP_TESTMODE;
10258
bd8c78e7
JB
10259 /* clear CB data for netlink core to own from now on */
10260 memset(skb->cb, 0, sizeof(skb->cb));
10261
e03ad6ea
JB
10262 nla_nest_end(skb, data);
10263 genlmsg_end(skb, hdr);
10264
55c1fdf0
JB
10265 if (nlhdr->nlmsg_pid) {
10266 genlmsg_unicast(wiphy_net(&rdev->wiphy), skb,
10267 nlhdr->nlmsg_pid);
10268 } else {
10269 if (data->nla_type == NL80211_ATTR_VENDOR_DATA)
10270 mcgrp = NL80211_MCGRP_VENDOR;
e03ad6ea 10271
55c1fdf0
JB
10272 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
10273 skb, 0, mcgrp, gfp);
10274 }
e03ad6ea
JB
10275}
10276EXPORT_SYMBOL(__cfg80211_send_event_skb);
10277
aff89a9b 10278#ifdef CONFIG_NL80211_TESTMODE
aff89a9b
JB
10279static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info)
10280{
4c476991 10281 struct cfg80211_registered_device *rdev = info->user_ptr[0];
fc73f11f
DS
10282 struct wireless_dev *wdev =
10283 __cfg80211_wdev_from_attrs(genl_info_net(info), info->attrs);
aff89a9b
JB
10284 int err;
10285
fc73f11f
DS
10286 if (!rdev->ops->testmode_cmd)
10287 return -EOPNOTSUPP;
10288
10289 if (IS_ERR(wdev)) {
10290 err = PTR_ERR(wdev);
10291 if (err != -EINVAL)
10292 return err;
10293 wdev = NULL;
10294 } else if (wdev->wiphy != &rdev->wiphy) {
10295 return -EINVAL;
10296 }
10297
aff89a9b
JB
10298 if (!info->attrs[NL80211_ATTR_TESTDATA])
10299 return -EINVAL;
10300
ad7e718c 10301 rdev->cur_cmd_info = info;
fc73f11f 10302 err = rdev_testmode_cmd(rdev, wdev,
aff89a9b
JB
10303 nla_data(info->attrs[NL80211_ATTR_TESTDATA]),
10304 nla_len(info->attrs[NL80211_ATTR_TESTDATA]));
ad7e718c 10305 rdev->cur_cmd_info = NULL;
aff89a9b 10306
aff89a9b
JB
10307 return err;
10308}
10309
71063f0e
WYG
10310static int nl80211_testmode_dump(struct sk_buff *skb,
10311 struct netlink_callback *cb)
10312{
00918d33 10313 struct cfg80211_registered_device *rdev;
50508d94 10314 struct nlattr **attrbuf = NULL;
71063f0e
WYG
10315 int err;
10316 long phy_idx;
10317 void *data = NULL;
10318 int data_len = 0;
10319
5fe231e8
JB
10320 rtnl_lock();
10321
71063f0e
WYG
10322 if (cb->args[0]) {
10323 /*
10324 * 0 is a valid index, but not valid for args[0],
10325 * so we need to offset by 1.
10326 */
10327 phy_idx = cb->args[0] - 1;
a4956dca
LC
10328
10329 rdev = cfg80211_rdev_by_wiphy_idx(phy_idx);
10330 if (!rdev) {
10331 err = -ENOENT;
10332 goto out_err;
10333 }
71063f0e 10334 } else {
50508d94
JB
10335 attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf),
10336 GFP_KERNEL);
10337 if (!attrbuf) {
10338 err = -ENOMEM;
10339 goto out_err;
10340 }
c90c39da 10341
8cb08174
JB
10342 err = nlmsg_parse_deprecated(cb->nlh,
10343 GENL_HDRLEN + nl80211_fam.hdrsize,
10344 attrbuf, nl80211_fam.maxattr,
10345 nl80211_policy, NULL);
71063f0e 10346 if (err)
5fe231e8 10347 goto out_err;
00918d33 10348
c90c39da 10349 rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk), attrbuf);
2bd7e35d 10350 if (IS_ERR(rdev)) {
5fe231e8
JB
10351 err = PTR_ERR(rdev);
10352 goto out_err;
00918d33 10353 }
2bd7e35d 10354 phy_idx = rdev->wiphy_idx;
2bd7e35d 10355
c90c39da
JB
10356 if (attrbuf[NL80211_ATTR_TESTDATA])
10357 cb->args[1] = (long)attrbuf[NL80211_ATTR_TESTDATA];
71063f0e
WYG
10358 }
10359
10360 if (cb->args[1]) {
10361 data = nla_data((void *)cb->args[1]);
10362 data_len = nla_len((void *)cb->args[1]);
10363 }
10364
00918d33 10365 if (!rdev->ops->testmode_dump) {
71063f0e
WYG
10366 err = -EOPNOTSUPP;
10367 goto out_err;
10368 }
10369
10370 while (1) {
15e47304 10371 void *hdr = nl80211hdr_put(skb, NETLINK_CB(cb->skb).portid,
71063f0e
WYG
10372 cb->nlh->nlmsg_seq, NLM_F_MULTI,
10373 NL80211_CMD_TESTMODE);
10374 struct nlattr *tmdata;
10375
cb35fba3
DC
10376 if (!hdr)
10377 break;
10378
9360ffd1 10379 if (nla_put_u32(skb, NL80211_ATTR_WIPHY, phy_idx)) {
71063f0e
WYG
10380 genlmsg_cancel(skb, hdr);
10381 break;
10382 }
10383
ae0be8de 10384 tmdata = nla_nest_start_noflag(skb, NL80211_ATTR_TESTDATA);
71063f0e
WYG
10385 if (!tmdata) {
10386 genlmsg_cancel(skb, hdr);
10387 break;
10388 }
e35e4d28 10389 err = rdev_testmode_dump(rdev, skb, cb, data, data_len);
71063f0e
WYG
10390 nla_nest_end(skb, tmdata);
10391
10392 if (err == -ENOBUFS || err == -ENOENT) {
10393 genlmsg_cancel(skb, hdr);
10394 break;
10395 } else if (err) {
10396 genlmsg_cancel(skb, hdr);
10397 goto out_err;
10398 }
10399
10400 genlmsg_end(skb, hdr);
10401 }
10402
10403 err = skb->len;
10404 /* see above */
10405 cb->args[0] = phy_idx + 1;
10406 out_err:
50508d94 10407 kfree(attrbuf);
5fe231e8 10408 rtnl_unlock();
71063f0e
WYG
10409 return err;
10410}
aff89a9b
JB
10411#endif
10412
b23aa676
SO
10413static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
10414{
4c476991
JB
10415 struct cfg80211_registered_device *rdev = info->user_ptr[0];
10416 struct net_device *dev = info->user_ptr[1];
b23aa676
SO
10417 struct cfg80211_connect_params connect;
10418 struct wiphy *wiphy;
fffd0934 10419 struct cfg80211_cached_keys *connkeys = NULL;
942ba88b 10420 u32 freq = 0;
b23aa676
SO
10421 int err;
10422
10423 memset(&connect, 0, sizeof(connect));
10424
b23aa676
SO
10425 if (!info->attrs[NL80211_ATTR_SSID] ||
10426 !nla_len(info->attrs[NL80211_ATTR_SSID]))
10427 return -EINVAL;
10428
10429 if (info->attrs[NL80211_ATTR_AUTH_TYPE]) {
10430 connect.auth_type =
10431 nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
e39e5b5e
JM
10432 if (!nl80211_valid_auth_type(rdev, connect.auth_type,
10433 NL80211_CMD_CONNECT))
b23aa676
SO
10434 return -EINVAL;
10435 } else
10436 connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
10437
10438 connect.privacy = info->attrs[NL80211_ATTR_PRIVACY];
10439
3a00df57
AS
10440 if (info->attrs[NL80211_ATTR_WANT_1X_4WAY_HS] &&
10441 !wiphy_ext_feature_isset(&rdev->wiphy,
10442 NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X))
10443 return -EINVAL;
10444 connect.want_1x = info->attrs[NL80211_ATTR_WANT_1X_4WAY_HS];
10445
c0692b8f 10446 err = nl80211_crypto_settings(rdev, info, &connect.crypto,
3dc27d25 10447 NL80211_MAX_NR_CIPHER_SUITES);
b23aa676
SO
10448 if (err)
10449 return err;
b23aa676 10450
074ac8df 10451 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
10452 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
10453 return -EOPNOTSUPP;
b23aa676 10454
79c97e97 10455 wiphy = &rdev->wiphy;
b23aa676 10456
4486ea98
BS
10457 connect.bg_scan_period = -1;
10458 if (info->attrs[NL80211_ATTR_BG_SCAN_PERIOD] &&
10459 (wiphy->flags & WIPHY_FLAG_SUPPORTS_FW_ROAM)) {
10460 connect.bg_scan_period =
10461 nla_get_u16(info->attrs[NL80211_ATTR_BG_SCAN_PERIOD]);
10462 }
10463
b23aa676
SO
10464 if (info->attrs[NL80211_ATTR_MAC])
10465 connect.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
1df4a510
JM
10466 else if (info->attrs[NL80211_ATTR_MAC_HINT])
10467 connect.bssid_hint =
10468 nla_data(info->attrs[NL80211_ATTR_MAC_HINT]);
b23aa676
SO
10469 connect.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
10470 connect.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
10471
10472 if (info->attrs[NL80211_ATTR_IE]) {
10473 connect.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
10474 connect.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
10475 }
10476
cee00a95
JM
10477 if (info->attrs[NL80211_ATTR_USE_MFP]) {
10478 connect.mfp = nla_get_u32(info->attrs[NL80211_ATTR_USE_MFP]);
65026002
EG
10479 if (connect.mfp == NL80211_MFP_OPTIONAL &&
10480 !wiphy_ext_feature_isset(&rdev->wiphy,
10481 NL80211_EXT_FEATURE_MFP_OPTIONAL))
10482 return -EOPNOTSUPP;
cee00a95
JM
10483 } else {
10484 connect.mfp = NL80211_MFP_NO;
10485 }
10486
ba6fbacf
JM
10487 if (info->attrs[NL80211_ATTR_PREV_BSSID])
10488 connect.prev_bssid =
10489 nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]);
10490
942ba88b
TP
10491 if (info->attrs[NL80211_ATTR_WIPHY_FREQ])
10492 freq = MHZ_TO_KHZ(nla_get_u32(
10493 info->attrs[NL80211_ATTR_WIPHY_FREQ]));
10494 if (info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET])
10495 freq +=
10496 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET]);
10497
10498 if (freq) {
10499 connect.channel = nl80211_get_valid_chan(wiphy, freq);
664834de 10500 if (!connect.channel)
1df4a510
JM
10501 return -EINVAL;
10502 } else if (info->attrs[NL80211_ATTR_WIPHY_FREQ_HINT]) {
942ba88b
TP
10503 freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ_HINT]);
10504 freq = MHZ_TO_KHZ(freq);
10505 connect.channel_hint = nl80211_get_valid_chan(wiphy, freq);
664834de 10506 if (!connect.channel_hint)
4c476991 10507 return -EINVAL;
b23aa676
SO
10508 }
10509
2a38075c
AAL
10510 if (info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]) {
10511 connect.edmg.channels =
10512 nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]);
10513
10514 if (info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG])
10515 connect.edmg.bw_config =
10516 nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG]);
10517 }
10518
fffd0934 10519 if (connect.privacy && info->attrs[NL80211_ATTR_KEYS]) {
768075eb 10520 connkeys = nl80211_parse_connkeys(rdev, info, NULL);
4c476991
JB
10521 if (IS_ERR(connkeys))
10522 return PTR_ERR(connkeys);
fffd0934
JB
10523 }
10524
7e7c8926
BG
10525 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HT]))
10526 connect.flags |= ASSOC_REQ_DISABLE_HT;
10527
10528 if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
10529 memcpy(&connect.ht_capa_mask,
10530 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]),
10531 sizeof(connect.ht_capa_mask));
10532
10533 if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
b4e4f47e 10534 if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]) {
453431a5 10535 kfree_sensitive(connkeys);
7e7c8926 10536 return -EINVAL;
b4e4f47e 10537 }
7e7c8926
BG
10538 memcpy(&connect.ht_capa,
10539 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]),
10540 sizeof(connect.ht_capa));
10541 }
10542
ee2aca34
JB
10543 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_VHT]))
10544 connect.flags |= ASSOC_REQ_DISABLE_VHT;
10545
10546 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK])
10547 memcpy(&connect.vht_capa_mask,
10548 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]),
10549 sizeof(connect.vht_capa_mask));
10550
10551 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY]) {
10552 if (!info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]) {
453431a5 10553 kfree_sensitive(connkeys);
ee2aca34
JB
10554 return -EINVAL;
10555 }
10556 memcpy(&connect.vht_capa,
10557 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]),
10558 sizeof(connect.vht_capa));
10559 }
10560
bab5ab7d 10561 if (nla_get_flag(info->attrs[NL80211_ATTR_USE_RRM])) {
0c9ca11b
BL
10562 if (!((rdev->wiphy.features &
10563 NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES) &&
10564 (rdev->wiphy.features & NL80211_FEATURE_QUIET)) &&
10565 !wiphy_ext_feature_isset(&rdev->wiphy,
10566 NL80211_EXT_FEATURE_RRM)) {
453431a5 10567 kfree_sensitive(connkeys);
bab5ab7d 10568 return -EINVAL;
707554b4 10569 }
bab5ab7d
AK
10570 connect.flags |= ASSOC_REQ_USE_RRM;
10571 }
10572
34d50519 10573 connect.pbss = nla_get_flag(info->attrs[NL80211_ATTR_PBSS]);
57fbcce3 10574 if (connect.pbss && !rdev->wiphy.bands[NL80211_BAND_60GHZ]) {
453431a5 10575 kfree_sensitive(connkeys);
34d50519
LD
10576 return -EOPNOTSUPP;
10577 }
10578
38de03d2
AS
10579 if (info->attrs[NL80211_ATTR_BSS_SELECT]) {
10580 /* bss selection makes no sense if bssid is set */
10581 if (connect.bssid) {
453431a5 10582 kfree_sensitive(connkeys);
38de03d2
AS
10583 return -EINVAL;
10584 }
10585
10586 err = parse_bss_select(info->attrs[NL80211_ATTR_BSS_SELECT],
10587 wiphy, &connect.bss_select);
10588 if (err) {
453431a5 10589 kfree_sensitive(connkeys);
38de03d2
AS
10590 return err;
10591 }
10592 }
10593
a3caf744
VK
10594 if (wiphy_ext_feature_isset(&rdev->wiphy,
10595 NL80211_EXT_FEATURE_FILS_SK_OFFLOAD) &&
10596 info->attrs[NL80211_ATTR_FILS_ERP_USERNAME] &&
10597 info->attrs[NL80211_ATTR_FILS_ERP_REALM] &&
10598 info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] &&
10599 info->attrs[NL80211_ATTR_FILS_ERP_RRK]) {
10600 connect.fils_erp_username =
10601 nla_data(info->attrs[NL80211_ATTR_FILS_ERP_USERNAME]);
10602 connect.fils_erp_username_len =
10603 nla_len(info->attrs[NL80211_ATTR_FILS_ERP_USERNAME]);
10604 connect.fils_erp_realm =
10605 nla_data(info->attrs[NL80211_ATTR_FILS_ERP_REALM]);
10606 connect.fils_erp_realm_len =
10607 nla_len(info->attrs[NL80211_ATTR_FILS_ERP_REALM]);
10608 connect.fils_erp_next_seq_num =
10609 nla_get_u16(
10610 info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM]);
10611 connect.fils_erp_rrk =
10612 nla_data(info->attrs[NL80211_ATTR_FILS_ERP_RRK]);
10613 connect.fils_erp_rrk_len =
10614 nla_len(info->attrs[NL80211_ATTR_FILS_ERP_RRK]);
10615 } else if (info->attrs[NL80211_ATTR_FILS_ERP_USERNAME] ||
10616 info->attrs[NL80211_ATTR_FILS_ERP_REALM] ||
10617 info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] ||
10618 info->attrs[NL80211_ATTR_FILS_ERP_RRK]) {
453431a5 10619 kfree_sensitive(connkeys);
a3caf744
VK
10620 return -EINVAL;
10621 }
10622
40cbfa90
SD
10623 if (nla_get_flag(info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])) {
10624 if (!info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
453431a5 10625 kfree_sensitive(connkeys);
40cbfa90
SD
10626 GENL_SET_ERR_MSG(info,
10627 "external auth requires connection ownership");
10628 return -EINVAL;
10629 }
10630 connect.flags |= CONNECT_REQ_EXTERNAL_AUTH_SUPPORT;
10631 }
10632
83739b03 10633 wdev_lock(dev->ieee80211_ptr);
bd2522b1 10634
4ce2bd9c
JM
10635 err = cfg80211_connect(rdev, dev, &connect, connkeys,
10636 connect.prev_bssid);
fffd0934 10637 if (err)
453431a5 10638 kfree_sensitive(connkeys);
bd2522b1
AZ
10639
10640 if (!err && info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
10641 dev->ieee80211_ptr->conn_owner_nlportid = info->snd_portid;
10642 if (connect.bssid)
10643 memcpy(dev->ieee80211_ptr->disconnect_bssid,
10644 connect.bssid, ETH_ALEN);
10645 else
3b1648f1 10646 eth_zero_addr(dev->ieee80211_ptr->disconnect_bssid);
bd2522b1
AZ
10647 }
10648
10649 wdev_unlock(dev->ieee80211_ptr);
10650
b23aa676
SO
10651 return err;
10652}
10653
088e8df8 10654static int nl80211_update_connect_params(struct sk_buff *skb,
10655 struct genl_info *info)
10656{
10657 struct cfg80211_connect_params connect = {};
10658 struct cfg80211_registered_device *rdev = info->user_ptr[0];
10659 struct net_device *dev = info->user_ptr[1];
10660 struct wireless_dev *wdev = dev->ieee80211_ptr;
7f9a3e15
VK
10661 bool fils_sk_offload;
10662 u32 auth_type;
088e8df8 10663 u32 changed = 0;
10664 int ret;
10665
10666 if (!rdev->ops->update_connect_params)
10667 return -EOPNOTSUPP;
10668
10669 if (info->attrs[NL80211_ATTR_IE]) {
088e8df8 10670 connect.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
10671 connect.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
10672 changed |= UPDATE_ASSOC_IES;
10673 }
10674
7f9a3e15
VK
10675 fils_sk_offload = wiphy_ext_feature_isset(&rdev->wiphy,
10676 NL80211_EXT_FEATURE_FILS_SK_OFFLOAD);
10677
10678 /*
10679 * when driver supports fils-sk offload all attributes must be
10680 * provided. So the else covers "fils-sk-not-all" and
10681 * "no-fils-sk-any".
10682 */
10683 if (fils_sk_offload &&
10684 info->attrs[NL80211_ATTR_FILS_ERP_USERNAME] &&
10685 info->attrs[NL80211_ATTR_FILS_ERP_REALM] &&
10686 info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] &&
10687 info->attrs[NL80211_ATTR_FILS_ERP_RRK]) {
10688 connect.fils_erp_username =
10689 nla_data(info->attrs[NL80211_ATTR_FILS_ERP_USERNAME]);
10690 connect.fils_erp_username_len =
10691 nla_len(info->attrs[NL80211_ATTR_FILS_ERP_USERNAME]);
10692 connect.fils_erp_realm =
10693 nla_data(info->attrs[NL80211_ATTR_FILS_ERP_REALM]);
10694 connect.fils_erp_realm_len =
10695 nla_len(info->attrs[NL80211_ATTR_FILS_ERP_REALM]);
10696 connect.fils_erp_next_seq_num =
10697 nla_get_u16(
10698 info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM]);
10699 connect.fils_erp_rrk =
10700 nla_data(info->attrs[NL80211_ATTR_FILS_ERP_RRK]);
10701 connect.fils_erp_rrk_len =
10702 nla_len(info->attrs[NL80211_ATTR_FILS_ERP_RRK]);
10703 changed |= UPDATE_FILS_ERP_INFO;
10704 } else if (info->attrs[NL80211_ATTR_FILS_ERP_USERNAME] ||
10705 info->attrs[NL80211_ATTR_FILS_ERP_REALM] ||
10706 info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] ||
10707 info->attrs[NL80211_ATTR_FILS_ERP_RRK]) {
10708 return -EINVAL;
10709 }
10710
10711 if (info->attrs[NL80211_ATTR_AUTH_TYPE]) {
10712 auth_type = nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
10713 if (!nl80211_valid_auth_type(rdev, auth_type,
10714 NL80211_CMD_CONNECT))
10715 return -EINVAL;
10716
10717 if (auth_type == NL80211_AUTHTYPE_FILS_SK &&
10718 fils_sk_offload && !(changed & UPDATE_FILS_ERP_INFO))
10719 return -EINVAL;
10720
10721 connect.auth_type = auth_type;
10722 changed |= UPDATE_AUTH_TYPE;
10723 }
10724
088e8df8 10725 wdev_lock(dev->ieee80211_ptr);
10726 if (!wdev->current_bss)
10727 ret = -ENOLINK;
10728 else
10729 ret = rdev_update_connect_params(rdev, dev, &connect, changed);
10730 wdev_unlock(dev->ieee80211_ptr);
10731
10732 return ret;
10733}
10734
b23aa676
SO
10735static int nl80211_disconnect(struct sk_buff *skb, struct genl_info *info)
10736{
4c476991
JB
10737 struct cfg80211_registered_device *rdev = info->user_ptr[0];
10738 struct net_device *dev = info->user_ptr[1];
b23aa676 10739 u16 reason;
83739b03 10740 int ret;
b23aa676 10741
bad29297
AZ
10742 if (dev->ieee80211_ptr->conn_owner_nlportid &&
10743 dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)
10744 return -EPERM;
10745
b23aa676
SO
10746 if (!info->attrs[NL80211_ATTR_REASON_CODE])
10747 reason = WLAN_REASON_DEAUTH_LEAVING;
10748 else
10749 reason = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
10750
10751 if (reason == 0)
10752 return -EINVAL;
10753
074ac8df 10754 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
10755 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
10756 return -EOPNOTSUPP;
b23aa676 10757
83739b03
JB
10758 wdev_lock(dev->ieee80211_ptr);
10759 ret = cfg80211_disconnect(rdev, dev, reason, true);
10760 wdev_unlock(dev->ieee80211_ptr);
10761 return ret;
b23aa676
SO
10762}
10763
463d0183
JB
10764static int nl80211_wiphy_netns(struct sk_buff *skb, struct genl_info *info)
10765{
4c476991 10766 struct cfg80211_registered_device *rdev = info->user_ptr[0];
463d0183
JB
10767 struct net *net;
10768 int err;
463d0183 10769
4b681c82
VK
10770 if (info->attrs[NL80211_ATTR_PID]) {
10771 u32 pid = nla_get_u32(info->attrs[NL80211_ATTR_PID]);
10772
10773 net = get_net_ns_by_pid(pid);
10774 } else if (info->attrs[NL80211_ATTR_NETNS_FD]) {
10775 u32 fd = nla_get_u32(info->attrs[NL80211_ATTR_NETNS_FD]);
463d0183 10776
4b681c82
VK
10777 net = get_net_ns_by_fd(fd);
10778 } else {
10779 return -EINVAL;
10780 }
463d0183 10781
4c476991
JB
10782 if (IS_ERR(net))
10783 return PTR_ERR(net);
463d0183
JB
10784
10785 err = 0;
10786
10787 /* check if anything to do */
4c476991
JB
10788 if (!net_eq(wiphy_net(&rdev->wiphy), net))
10789 err = cfg80211_switch_netns(rdev, net);
463d0183 10790
463d0183 10791 put_net(net);
463d0183
JB
10792 return err;
10793}
10794
67fbb16b
SO
10795static int nl80211_setdel_pmksa(struct sk_buff *skb, struct genl_info *info)
10796{
4c476991 10797 struct cfg80211_registered_device *rdev = info->user_ptr[0];
67fbb16b
SO
10798 int (*rdev_ops)(struct wiphy *wiphy, struct net_device *dev,
10799 struct cfg80211_pmksa *pmksa) = NULL;
4c476991 10800 struct net_device *dev = info->user_ptr[1];
67fbb16b
SO
10801 struct cfg80211_pmksa pmksa;
10802
10803 memset(&pmksa, 0, sizeof(struct cfg80211_pmksa));
10804
67fbb16b
SO
10805 if (!info->attrs[NL80211_ATTR_PMKID])
10806 return -EINVAL;
10807
67fbb16b 10808 pmksa.pmkid = nla_data(info->attrs[NL80211_ATTR_PMKID]);
a3caf744
VK
10809
10810 if (info->attrs[NL80211_ATTR_MAC]) {
10811 pmksa.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
10812 } else if (info->attrs[NL80211_ATTR_SSID] &&
10813 info->attrs[NL80211_ATTR_FILS_CACHE_ID] &&
10814 (info->genlhdr->cmd == NL80211_CMD_DEL_PMKSA ||
10815 info->attrs[NL80211_ATTR_PMK])) {
10816 pmksa.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
10817 pmksa.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
10818 pmksa.cache_id =
10819 nla_data(info->attrs[NL80211_ATTR_FILS_CACHE_ID]);
10820 } else {
10821 return -EINVAL;
10822 }
10823 if (info->attrs[NL80211_ATTR_PMK]) {
10824 pmksa.pmk = nla_data(info->attrs[NL80211_ATTR_PMK]);
10825 pmksa.pmk_len = nla_len(info->attrs[NL80211_ATTR_PMK]);
10826 }
67fbb16b 10827
7fc82af8
VJ
10828 if (info->attrs[NL80211_ATTR_PMK_LIFETIME])
10829 pmksa.pmk_lifetime =
10830 nla_get_u32(info->attrs[NL80211_ATTR_PMK_LIFETIME]);
10831
10832 if (info->attrs[NL80211_ATTR_PMK_REAUTH_THRESHOLD])
10833 pmksa.pmk_reauth_threshold =
10834 nla_get_u8(
10835 info->attrs[NL80211_ATTR_PMK_REAUTH_THRESHOLD]);
10836
074ac8df 10837 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
6c900360
LD
10838 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT &&
10839 !(dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP &&
10840 wiphy_ext_feature_isset(&rdev->wiphy,
10841 NL80211_EXT_FEATURE_AP_PMKSA_CACHING)))
4c476991 10842 return -EOPNOTSUPP;
67fbb16b
SO
10843
10844 switch (info->genlhdr->cmd) {
10845 case NL80211_CMD_SET_PMKSA:
10846 rdev_ops = rdev->ops->set_pmksa;
10847 break;
10848 case NL80211_CMD_DEL_PMKSA:
10849 rdev_ops = rdev->ops->del_pmksa;
10850 break;
10851 default:
10852 WARN_ON(1);
10853 break;
10854 }
10855
4c476991
JB
10856 if (!rdev_ops)
10857 return -EOPNOTSUPP;
67fbb16b 10858
4c476991 10859 return rdev_ops(&rdev->wiphy, dev, &pmksa);
67fbb16b
SO
10860}
10861
10862static int nl80211_flush_pmksa(struct sk_buff *skb, struct genl_info *info)
10863{
4c476991
JB
10864 struct cfg80211_registered_device *rdev = info->user_ptr[0];
10865 struct net_device *dev = info->user_ptr[1];
67fbb16b 10866
074ac8df 10867 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
10868 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
10869 return -EOPNOTSUPP;
67fbb16b 10870
4c476991
JB
10871 if (!rdev->ops->flush_pmksa)
10872 return -EOPNOTSUPP;
67fbb16b 10873
e35e4d28 10874 return rdev_flush_pmksa(rdev, dev);
67fbb16b
SO
10875}
10876
109086ce
AN
10877static int nl80211_tdls_mgmt(struct sk_buff *skb, struct genl_info *info)
10878{
10879 struct cfg80211_registered_device *rdev = info->user_ptr[0];
10880 struct net_device *dev = info->user_ptr[1];
10881 u8 action_code, dialog_token;
df942e7b 10882 u32 peer_capability = 0;
109086ce
AN
10883 u16 status_code;
10884 u8 *peer;
31fa97c5 10885 bool initiator;
109086ce
AN
10886
10887 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) ||
10888 !rdev->ops->tdls_mgmt)
10889 return -EOPNOTSUPP;
10890
10891 if (!info->attrs[NL80211_ATTR_TDLS_ACTION] ||
10892 !info->attrs[NL80211_ATTR_STATUS_CODE] ||
10893 !info->attrs[NL80211_ATTR_TDLS_DIALOG_TOKEN] ||
10894 !info->attrs[NL80211_ATTR_IE] ||
10895 !info->attrs[NL80211_ATTR_MAC])
10896 return -EINVAL;
10897
10898 peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
10899 action_code = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_ACTION]);
10900 status_code = nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]);
10901 dialog_token = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_DIALOG_TOKEN]);
31fa97c5 10902 initiator = nla_get_flag(info->attrs[NL80211_ATTR_TDLS_INITIATOR]);
df942e7b
SDU
10903 if (info->attrs[NL80211_ATTR_TDLS_PEER_CAPABILITY])
10904 peer_capability =
10905 nla_get_u32(info->attrs[NL80211_ATTR_TDLS_PEER_CAPABILITY]);
109086ce 10906
e35e4d28 10907 return rdev_tdls_mgmt(rdev, dev, peer, action_code,
df942e7b 10908 dialog_token, status_code, peer_capability,
31fa97c5 10909 initiator,
e35e4d28
HG
10910 nla_data(info->attrs[NL80211_ATTR_IE]),
10911 nla_len(info->attrs[NL80211_ATTR_IE]));
109086ce
AN
10912}
10913
10914static int nl80211_tdls_oper(struct sk_buff *skb, struct genl_info *info)
10915{
10916 struct cfg80211_registered_device *rdev = info->user_ptr[0];
10917 struct net_device *dev = info->user_ptr[1];
10918 enum nl80211_tdls_operation operation;
10919 u8 *peer;
10920
10921 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) ||
10922 !rdev->ops->tdls_oper)
10923 return -EOPNOTSUPP;
10924
10925 if (!info->attrs[NL80211_ATTR_TDLS_OPERATION] ||
10926 !info->attrs[NL80211_ATTR_MAC])
10927 return -EINVAL;
10928
10929 operation = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_OPERATION]);
10930 peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
10931
e35e4d28 10932 return rdev_tdls_oper(rdev, dev, peer, operation);
109086ce
AN
10933}
10934
9588bbd5
JM
10935static int nl80211_remain_on_channel(struct sk_buff *skb,
10936 struct genl_info *info)
10937{
4c476991 10938 struct cfg80211_registered_device *rdev = info->user_ptr[0];
71bbc994 10939 struct wireless_dev *wdev = info->user_ptr[1];
683b6d3b 10940 struct cfg80211_chan_def chandef;
34373d12 10941 const struct cfg80211_chan_def *compat_chandef;
9588bbd5
JM
10942 struct sk_buff *msg;
10943 void *hdr;
10944 u64 cookie;
683b6d3b 10945 u32 duration;
9588bbd5
JM
10946 int err;
10947
10948 if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] ||
10949 !info->attrs[NL80211_ATTR_DURATION])
10950 return -EINVAL;
10951
10952 duration = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]);
10953
ebf348fc
JB
10954 if (!rdev->ops->remain_on_channel ||
10955 !(rdev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL))
10956 return -EOPNOTSUPP;
10957
9588bbd5 10958 /*
ebf348fc
JB
10959 * We should be on that channel for at least a minimum amount of
10960 * time (10ms) but no longer than the driver supports.
9588bbd5 10961 */
ebf348fc 10962 if (duration < NL80211_MIN_REMAIN_ON_CHANNEL_TIME ||
a293911d 10963 duration > rdev->wiphy.max_remain_on_channel_duration)
9588bbd5
JM
10964 return -EINVAL;
10965
683b6d3b
JB
10966 err = nl80211_parse_chandef(rdev, info, &chandef);
10967 if (err)
10968 return err;
9588bbd5 10969
34373d12
VT
10970 wdev_lock(wdev);
10971 if (!cfg80211_off_channel_oper_allowed(wdev) &&
10972 !cfg80211_chandef_identical(&wdev->chandef, &chandef)) {
10973 compat_chandef = cfg80211_chandef_compatible(&wdev->chandef,
10974 &chandef);
10975 if (compat_chandef != &chandef) {
10976 wdev_unlock(wdev);
10977 return -EBUSY;
10978 }
10979 }
10980 wdev_unlock(wdev);
10981
9588bbd5 10982 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4c476991
JB
10983 if (!msg)
10984 return -ENOMEM;
9588bbd5 10985
15e47304 10986 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
9588bbd5 10987 NL80211_CMD_REMAIN_ON_CHANNEL);
cb35fba3
DC
10988 if (!hdr) {
10989 err = -ENOBUFS;
9588bbd5
JM
10990 goto free_msg;
10991 }
10992
683b6d3b
JB
10993 err = rdev_remain_on_channel(rdev, wdev, chandef.chan,
10994 duration, &cookie);
9588bbd5
JM
10995
10996 if (err)
10997 goto free_msg;
10998
2dad624e
ND
10999 if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
11000 NL80211_ATTR_PAD))
9360ffd1 11001 goto nla_put_failure;
9588bbd5
JM
11002
11003 genlmsg_end(msg, hdr);
4c476991
JB
11004
11005 return genlmsg_reply(msg, info);
9588bbd5
JM
11006
11007 nla_put_failure:
11008 err = -ENOBUFS;
11009 free_msg:
11010 nlmsg_free(msg);
9588bbd5
JM
11011 return err;
11012}
11013
11014static int nl80211_cancel_remain_on_channel(struct sk_buff *skb,
11015 struct genl_info *info)
11016{
4c476991 11017 struct cfg80211_registered_device *rdev = info->user_ptr[0];
71bbc994 11018 struct wireless_dev *wdev = info->user_ptr[1];
9588bbd5 11019 u64 cookie;
9588bbd5
JM
11020
11021 if (!info->attrs[NL80211_ATTR_COOKIE])
11022 return -EINVAL;
11023
4c476991
JB
11024 if (!rdev->ops->cancel_remain_on_channel)
11025 return -EOPNOTSUPP;
9588bbd5 11026
9588bbd5
JM
11027 cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);
11028
e35e4d28 11029 return rdev_cancel_remain_on_channel(rdev, wdev, cookie);
9588bbd5
JM
11030}
11031
13ae75b1
JM
11032static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
11033 struct genl_info *info)
11034{
13ae75b1 11035 struct cfg80211_bitrate_mask mask;
a7c7fbff 11036 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4c476991 11037 struct net_device *dev = info->user_ptr[1];
a7c7fbff 11038 int err;
13ae75b1 11039
4c476991
JB
11040 if (!rdev->ops->set_bitrate_mask)
11041 return -EOPNOTSUPP;
13ae75b1 11042
9a5f6488 11043 err = nl80211_parse_tx_bitrate_mask(info, info->attrs,
eb89a6a6
MH
11044 NL80211_ATTR_TX_RATES, &mask,
11045 dev);
a7c7fbff
PK
11046 if (err)
11047 return err;
13ae75b1 11048
e35e4d28 11049 return rdev_set_bitrate_mask(rdev, dev, NULL, &mask);
13ae75b1
JM
11050}
11051
2e161f78 11052static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info)
026331c4 11053{
4c476991 11054 struct cfg80211_registered_device *rdev = info->user_ptr[0];
71bbc994 11055 struct wireless_dev *wdev = info->user_ptr[1];
2e161f78 11056 u16 frame_type = IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION;
026331c4
JM
11057
11058 if (!info->attrs[NL80211_ATTR_FRAME_MATCH])
11059 return -EINVAL;
11060
2e161f78
JB
11061 if (info->attrs[NL80211_ATTR_FRAME_TYPE])
11062 frame_type = nla_get_u16(info->attrs[NL80211_ATTR_FRAME_TYPE]);
026331c4 11063
71bbc994
JB
11064 switch (wdev->iftype) {
11065 case NL80211_IFTYPE_STATION:
11066 case NL80211_IFTYPE_ADHOC:
11067 case NL80211_IFTYPE_P2P_CLIENT:
11068 case NL80211_IFTYPE_AP:
11069 case NL80211_IFTYPE_AP_VLAN:
11070 case NL80211_IFTYPE_MESH_POINT:
11071 case NL80211_IFTYPE_P2P_GO:
98104fde 11072 case NL80211_IFTYPE_P2P_DEVICE:
71bbc994 11073 break;
cb3b7d87 11074 case NL80211_IFTYPE_NAN:
71bbc994 11075 default:
4c476991 11076 return -EOPNOTSUPP;
71bbc994 11077 }
026331c4
JM
11078
11079 /* not much point in registering if we can't reply */
4c476991
JB
11080 if (!rdev->ops->mgmt_tx)
11081 return -EOPNOTSUPP;
026331c4 11082
9dba48a6
JB
11083 if (info->attrs[NL80211_ATTR_RECEIVE_MULTICAST] &&
11084 !wiphy_ext_feature_isset(&rdev->wiphy,
11085 NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS)) {
11086 GENL_SET_ERR_MSG(info,
11087 "multicast RX registrations are not supported");
11088 return -EOPNOTSUPP;
11089 }
11090
15e47304 11091 return cfg80211_mlme_register_mgmt(wdev, info->snd_portid, frame_type,
ff74c51e
IP
11092 nla_data(info->attrs[NL80211_ATTR_FRAME_MATCH]),
11093 nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH]),
9dba48a6 11094 info->attrs[NL80211_ATTR_RECEIVE_MULTICAST],
ff74c51e 11095 info->extack);
026331c4
JM
11096}
11097
2e161f78 11098static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
026331c4 11099{
4c476991 11100 struct cfg80211_registered_device *rdev = info->user_ptr[0];
71bbc994 11101 struct wireless_dev *wdev = info->user_ptr[1];
683b6d3b 11102 struct cfg80211_chan_def chandef;
026331c4 11103 int err;
d64d373f 11104 void *hdr = NULL;
026331c4 11105 u64 cookie;
e247bd90 11106 struct sk_buff *msg = NULL;
b176e629
AO
11107 struct cfg80211_mgmt_tx_params params = {
11108 .dont_wait_for_ack =
11109 info->attrs[NL80211_ATTR_DONT_WAIT_FOR_ACK],
11110 };
026331c4 11111
683b6d3b 11112 if (!info->attrs[NL80211_ATTR_FRAME])
026331c4
JM
11113 return -EINVAL;
11114
4c476991
JB
11115 if (!rdev->ops->mgmt_tx)
11116 return -EOPNOTSUPP;
026331c4 11117
71bbc994 11118 switch (wdev->iftype) {
ea141b75
AQ
11119 case NL80211_IFTYPE_P2P_DEVICE:
11120 if (!info->attrs[NL80211_ATTR_WIPHY_FREQ])
11121 return -EINVAL;
71bbc994
JB
11122 case NL80211_IFTYPE_STATION:
11123 case NL80211_IFTYPE_ADHOC:
11124 case NL80211_IFTYPE_P2P_CLIENT:
11125 case NL80211_IFTYPE_AP:
11126 case NL80211_IFTYPE_AP_VLAN:
11127 case NL80211_IFTYPE_MESH_POINT:
11128 case NL80211_IFTYPE_P2P_GO:
11129 break;
cb3b7d87 11130 case NL80211_IFTYPE_NAN:
71bbc994 11131 default:
4c476991 11132 return -EOPNOTSUPP;
71bbc994 11133 }
026331c4 11134
f7ca38df 11135 if (info->attrs[NL80211_ATTR_DURATION]) {
7c4ef712 11136 if (!(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX))
f7ca38df 11137 return -EINVAL;
b176e629 11138 params.wait = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]);
ebf348fc
JB
11139
11140 /*
11141 * We should wait on the channel for at least a minimum amount
11142 * of time (10ms) but no longer than the driver supports.
11143 */
b176e629
AO
11144 if (params.wait < NL80211_MIN_REMAIN_ON_CHANNEL_TIME ||
11145 params.wait > rdev->wiphy.max_remain_on_channel_duration)
ebf348fc 11146 return -EINVAL;
f7ca38df
JB
11147 }
11148
b176e629 11149 params.offchan = info->attrs[NL80211_ATTR_OFFCHANNEL_TX_OK];
f7ca38df 11150
b176e629 11151 if (params.offchan && !(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX))
7c4ef712
JB
11152 return -EINVAL;
11153
b176e629 11154 params.no_cck = nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]);
e9f935e3 11155
ea141b75
AQ
11156 /* get the channel if any has been specified, otherwise pass NULL to
11157 * the driver. The latter will use the current one
11158 */
11159 chandef.chan = NULL;
11160 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
11161 err = nl80211_parse_chandef(rdev, info, &chandef);
11162 if (err)
11163 return err;
11164 }
11165
b176e629 11166 if (!chandef.chan && params.offchan)
ea141b75 11167 return -EINVAL;
026331c4 11168
34373d12
VT
11169 wdev_lock(wdev);
11170 if (params.offchan && !cfg80211_off_channel_oper_allowed(wdev)) {
11171 wdev_unlock(wdev);
11172 return -EBUSY;
11173 }
11174 wdev_unlock(wdev);
11175
34d22ce2
AO
11176 params.buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
11177 params.len = nla_len(info->attrs[NL80211_ATTR_FRAME]);
11178
11179 if (info->attrs[NL80211_ATTR_CSA_C_OFFSETS_TX]) {
11180 int len = nla_len(info->attrs[NL80211_ATTR_CSA_C_OFFSETS_TX]);
11181 int i;
11182
11183 if (len % sizeof(u16))
11184 return -EINVAL;
11185
11186 params.n_csa_offsets = len / sizeof(u16);
11187 params.csa_offsets =
11188 nla_data(info->attrs[NL80211_ATTR_CSA_C_OFFSETS_TX]);
11189
11190 /* check that all the offsets fit the frame */
11191 for (i = 0; i < params.n_csa_offsets; i++) {
11192 if (params.csa_offsets[i] >= params.len)
11193 return -EINVAL;
11194 }
11195 }
11196
b176e629 11197 if (!params.dont_wait_for_ack) {
e247bd90
JB
11198 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
11199 if (!msg)
11200 return -ENOMEM;
026331c4 11201
15e47304 11202 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
e247bd90 11203 NL80211_CMD_FRAME);
cb35fba3
DC
11204 if (!hdr) {
11205 err = -ENOBUFS;
e247bd90
JB
11206 goto free_msg;
11207 }
026331c4 11208 }
e247bd90 11209
b176e629
AO
11210 params.chan = chandef.chan;
11211 err = cfg80211_mlme_mgmt_tx(rdev, wdev, &params, &cookie);
026331c4
JM
11212 if (err)
11213 goto free_msg;
11214
e247bd90 11215 if (msg) {
2dad624e
ND
11216 if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
11217 NL80211_ATTR_PAD))
9360ffd1 11218 goto nla_put_failure;
026331c4 11219
e247bd90
JB
11220 genlmsg_end(msg, hdr);
11221 return genlmsg_reply(msg, info);
11222 }
11223
11224 return 0;
026331c4
JM
11225
11226 nla_put_failure:
11227 err = -ENOBUFS;
11228 free_msg:
11229 nlmsg_free(msg);
026331c4
JM
11230 return err;
11231}
11232
f7ca38df
JB
11233static int nl80211_tx_mgmt_cancel_wait(struct sk_buff *skb, struct genl_info *info)
11234{
11235 struct cfg80211_registered_device *rdev = info->user_ptr[0];
71bbc994 11236 struct wireless_dev *wdev = info->user_ptr[1];
f7ca38df
JB
11237 u64 cookie;
11238
11239 if (!info->attrs[NL80211_ATTR_COOKIE])
11240 return -EINVAL;
11241
11242 if (!rdev->ops->mgmt_tx_cancel_wait)
11243 return -EOPNOTSUPP;
11244
71bbc994
JB
11245 switch (wdev->iftype) {
11246 case NL80211_IFTYPE_STATION:
11247 case NL80211_IFTYPE_ADHOC:
11248 case NL80211_IFTYPE_P2P_CLIENT:
11249 case NL80211_IFTYPE_AP:
11250 case NL80211_IFTYPE_AP_VLAN:
11251 case NL80211_IFTYPE_P2P_GO:
98104fde 11252 case NL80211_IFTYPE_P2P_DEVICE:
71bbc994 11253 break;
cb3b7d87 11254 case NL80211_IFTYPE_NAN:
71bbc994 11255 default:
f7ca38df 11256 return -EOPNOTSUPP;
71bbc994 11257 }
f7ca38df
JB
11258
11259 cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);
11260
e35e4d28 11261 return rdev_mgmt_tx_cancel_wait(rdev, wdev, cookie);
f7ca38df
JB
11262}
11263
ffb9eb3d
KV
11264static int nl80211_set_power_save(struct sk_buff *skb, struct genl_info *info)
11265{
4c476991 11266 struct cfg80211_registered_device *rdev = info->user_ptr[0];
ffb9eb3d 11267 struct wireless_dev *wdev;
4c476991 11268 struct net_device *dev = info->user_ptr[1];
ffb9eb3d
KV
11269 u8 ps_state;
11270 bool state;
11271 int err;
11272
4c476991
JB
11273 if (!info->attrs[NL80211_ATTR_PS_STATE])
11274 return -EINVAL;
ffb9eb3d
KV
11275
11276 ps_state = nla_get_u32(info->attrs[NL80211_ATTR_PS_STATE]);
11277
ffb9eb3d
KV
11278 wdev = dev->ieee80211_ptr;
11279
4c476991
JB
11280 if (!rdev->ops->set_power_mgmt)
11281 return -EOPNOTSUPP;
ffb9eb3d
KV
11282
11283 state = (ps_state == NL80211_PS_ENABLED) ? true : false;
11284
11285 if (state == wdev->ps)
4c476991 11286 return 0;
ffb9eb3d 11287
e35e4d28 11288 err = rdev_set_power_mgmt(rdev, dev, state, wdev->ps_timeout);
4c476991
JB
11289 if (!err)
11290 wdev->ps = state;
ffb9eb3d
KV
11291 return err;
11292}
11293
11294static int nl80211_get_power_save(struct sk_buff *skb, struct genl_info *info)
11295{
4c476991 11296 struct cfg80211_registered_device *rdev = info->user_ptr[0];
ffb9eb3d
KV
11297 enum nl80211_ps_state ps_state;
11298 struct wireless_dev *wdev;
4c476991 11299 struct net_device *dev = info->user_ptr[1];
ffb9eb3d
KV
11300 struct sk_buff *msg;
11301 void *hdr;
11302 int err;
11303
ffb9eb3d
KV
11304 wdev = dev->ieee80211_ptr;
11305
4c476991
JB
11306 if (!rdev->ops->set_power_mgmt)
11307 return -EOPNOTSUPP;
ffb9eb3d
KV
11308
11309 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4c476991
JB
11310 if (!msg)
11311 return -ENOMEM;
ffb9eb3d 11312
15e47304 11313 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
ffb9eb3d
KV
11314 NL80211_CMD_GET_POWER_SAVE);
11315 if (!hdr) {
4c476991 11316 err = -ENOBUFS;
ffb9eb3d
KV
11317 goto free_msg;
11318 }
11319
11320 if (wdev->ps)
11321 ps_state = NL80211_PS_ENABLED;
11322 else
11323 ps_state = NL80211_PS_DISABLED;
11324
9360ffd1
DM
11325 if (nla_put_u32(msg, NL80211_ATTR_PS_STATE, ps_state))
11326 goto nla_put_failure;
ffb9eb3d
KV
11327
11328 genlmsg_end(msg, hdr);
4c476991 11329 return genlmsg_reply(msg, info);
ffb9eb3d 11330
4c476991 11331 nla_put_failure:
ffb9eb3d 11332 err = -ENOBUFS;
4c476991 11333 free_msg:
ffb9eb3d 11334 nlmsg_free(msg);
ffb9eb3d
KV
11335 return err;
11336}
11337
94e860f1
JB
11338static const struct nla_policy
11339nl80211_attr_cqm_policy[NL80211_ATTR_CQM_MAX + 1] = {
4a4b8169 11340 [NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_BINARY },
d6dc1a38
JO
11341 [NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U32 },
11342 [NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 },
84f10708
TP
11343 [NL80211_ATTR_CQM_TXE_RATE] = { .type = NLA_U32 },
11344 [NL80211_ATTR_CQM_TXE_PKTS] = { .type = NLA_U32 },
11345 [NL80211_ATTR_CQM_TXE_INTVL] = { .type = NLA_U32 },
bee427b8 11346 [NL80211_ATTR_CQM_RSSI_LEVEL] = { .type = NLA_S32 },
d6dc1a38
JO
11347};
11348
84f10708 11349static int nl80211_set_cqm_txe(struct genl_info *info,
d9d8b019 11350 u32 rate, u32 pkts, u32 intvl)
84f10708
TP
11351{
11352 struct cfg80211_registered_device *rdev = info->user_ptr[0];
84f10708 11353 struct net_device *dev = info->user_ptr[1];
1da5fcc8 11354 struct wireless_dev *wdev = dev->ieee80211_ptr;
84f10708 11355
d9d8b019 11356 if (rate > 100 || intvl > NL80211_CQM_TXE_MAX_INTVL)
84f10708
TP
11357 return -EINVAL;
11358
84f10708
TP
11359 if (!rdev->ops->set_cqm_txe_config)
11360 return -EOPNOTSUPP;
11361
11362 if (wdev->iftype != NL80211_IFTYPE_STATION &&
11363 wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
11364 return -EOPNOTSUPP;
11365
e35e4d28 11366 return rdev_set_cqm_txe_config(rdev, dev, rate, pkts, intvl);
84f10708
TP
11367}
11368
4a4b8169
AZ
11369static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev,
11370 struct net_device *dev)
11371{
11372 struct wireless_dev *wdev = dev->ieee80211_ptr;
11373 s32 last, low, high;
11374 u32 hyst;
1222a160 11375 int i, n, low_index;
4a4b8169
AZ
11376 int err;
11377
11378 /* RSSI reporting disabled? */
11379 if (!wdev->cqm_config)
11380 return rdev_set_cqm_rssi_range_config(rdev, dev, 0, 0);
11381
11382 /*
11383 * Obtain current RSSI value if possible, if not and no RSSI threshold
11384 * event has been received yet, we should receive an event after a
11385 * connection is established and enough beacons received to calculate
11386 * the average.
11387 */
11388 if (!wdev->cqm_config->last_rssi_event_value && wdev->current_bss &&
11389 rdev->ops->get_station) {
73887fd9 11390 struct station_info sinfo = {};
4a4b8169
AZ
11391 u8 *mac_addr;
11392
11393 mac_addr = wdev->current_bss->pub.bssid;
11394
73887fd9
JB
11395 err = rdev_get_station(rdev, dev, mac_addr, &sinfo);
11396 if (err)
4a4b8169
AZ
11397 return err;
11398
df16737d 11399 cfg80211_sinfo_release_content(&sinfo);
397c657a 11400 if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_BEACON_SIGNAL_AVG))
4a4b8169 11401 wdev->cqm_config->last_rssi_event_value =
73887fd9 11402 (s8) sinfo.rx_beacon_signal_avg;
4a4b8169
AZ
11403 }
11404
11405 last = wdev->cqm_config->last_rssi_event_value;
11406 hyst = wdev->cqm_config->rssi_hyst;
11407 n = wdev->cqm_config->n_rssi_thresholds;
11408
4b2c5a14
MH
11409 for (i = 0; i < n; i++) {
11410 i = array_index_nospec(i, n);
4a4b8169
AZ
11411 if (last < wdev->cqm_config->rssi_thresholds[i])
11412 break;
4b2c5a14 11413 }
4a4b8169 11414
1222a160
MH
11415 low_index = i - 1;
11416 if (low_index >= 0) {
11417 low_index = array_index_nospec(low_index, n);
11418 low = wdev->cqm_config->rssi_thresholds[low_index] - hyst;
11419 } else {
11420 low = S32_MIN;
11421 }
11422 if (i < n) {
11423 i = array_index_nospec(i, n);
11424 high = wdev->cqm_config->rssi_thresholds[i] + hyst - 1;
11425 } else {
11426 high = S32_MAX;
11427 }
4a4b8169
AZ
11428
11429 return rdev_set_cqm_rssi_range_config(rdev, dev, low, high);
11430}
11431
d6dc1a38 11432static int nl80211_set_cqm_rssi(struct genl_info *info,
4a4b8169
AZ
11433 const s32 *thresholds, int n_thresholds,
11434 u32 hysteresis)
d6dc1a38 11435{
4c476991 11436 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4c476991 11437 struct net_device *dev = info->user_ptr[1];
1da5fcc8 11438 struct wireless_dev *wdev = dev->ieee80211_ptr;
4a4b8169
AZ
11439 int i, err;
11440 s32 prev = S32_MIN;
d6dc1a38 11441
4a4b8169
AZ
11442 /* Check all values negative and sorted */
11443 for (i = 0; i < n_thresholds; i++) {
11444 if (thresholds[i] > 0 || thresholds[i] <= prev)
11445 return -EINVAL;
d6dc1a38 11446
4a4b8169
AZ
11447 prev = thresholds[i];
11448 }
d6dc1a38 11449
074ac8df 11450 if (wdev->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
11451 wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
11452 return -EOPNOTSUPP;
d6dc1a38 11453
4a4b8169
AZ
11454 wdev_lock(wdev);
11455 cfg80211_cqm_config_free(wdev);
11456 wdev_unlock(wdev);
11457
11458 if (n_thresholds <= 1 && rdev->ops->set_cqm_rssi_config) {
11459 if (n_thresholds == 0 || thresholds[0] == 0) /* Disabling */
11460 return rdev_set_cqm_rssi_config(rdev, dev, 0, 0);
11461
11462 return rdev_set_cqm_rssi_config(rdev, dev,
11463 thresholds[0], hysteresis);
11464 }
11465
11466 if (!wiphy_ext_feature_isset(&rdev->wiphy,
11467 NL80211_EXT_FEATURE_CQM_RSSI_LIST))
11468 return -EOPNOTSUPP;
11469
11470 if (n_thresholds == 1 && thresholds[0] == 0) /* Disabling */
11471 n_thresholds = 0;
11472
11473 wdev_lock(wdev);
11474 if (n_thresholds) {
11475 struct cfg80211_cqm_config *cqm_config;
11476
11477 cqm_config = kzalloc(sizeof(struct cfg80211_cqm_config) +
11478 n_thresholds * sizeof(s32), GFP_KERNEL);
11479 if (!cqm_config) {
11480 err = -ENOMEM;
11481 goto unlock;
11482 }
11483
11484 cqm_config->rssi_hyst = hysteresis;
11485 cqm_config->n_rssi_thresholds = n_thresholds;
11486 memcpy(cqm_config->rssi_thresholds, thresholds,
11487 n_thresholds * sizeof(s32));
11488
11489 wdev->cqm_config = cqm_config;
11490 }
11491
11492 err = cfg80211_cqm_rssi_update(rdev, dev);
11493
11494unlock:
11495 wdev_unlock(wdev);
11496
11497 return err;
d6dc1a38
JO
11498}
11499
11500static int nl80211_set_cqm(struct sk_buff *skb, struct genl_info *info)
11501{
11502 struct nlattr *attrs[NL80211_ATTR_CQM_MAX + 1];
11503 struct nlattr *cqm;
11504 int err;
11505
11506 cqm = info->attrs[NL80211_ATTR_CQM];
1da5fcc8
JB
11507 if (!cqm)
11508 return -EINVAL;
d6dc1a38 11509
8cb08174
JB
11510 err = nla_parse_nested_deprecated(attrs, NL80211_ATTR_CQM_MAX, cqm,
11511 nl80211_attr_cqm_policy,
11512 info->extack);
d6dc1a38 11513 if (err)
1da5fcc8 11514 return err;
d6dc1a38
JO
11515
11516 if (attrs[NL80211_ATTR_CQM_RSSI_THOLD] &&
11517 attrs[NL80211_ATTR_CQM_RSSI_HYST]) {
4a4b8169
AZ
11518 const s32 *thresholds =
11519 nla_data(attrs[NL80211_ATTR_CQM_RSSI_THOLD]);
11520 int len = nla_len(attrs[NL80211_ATTR_CQM_RSSI_THOLD]);
1da5fcc8 11521 u32 hysteresis = nla_get_u32(attrs[NL80211_ATTR_CQM_RSSI_HYST]);
d6dc1a38 11522
4a4b8169
AZ
11523 if (len % 4)
11524 return -EINVAL;
11525
11526 return nl80211_set_cqm_rssi(info, thresholds, len / 4,
11527 hysteresis);
1da5fcc8
JB
11528 }
11529
11530 if (attrs[NL80211_ATTR_CQM_TXE_RATE] &&
11531 attrs[NL80211_ATTR_CQM_TXE_PKTS] &&
11532 attrs[NL80211_ATTR_CQM_TXE_INTVL]) {
11533 u32 rate = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_RATE]);
11534 u32 pkts = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_PKTS]);
11535 u32 intvl = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_INTVL]);
11536
11537 return nl80211_set_cqm_txe(info, rate, pkts, intvl);
11538 }
11539
11540 return -EINVAL;
d6dc1a38
JO
11541}
11542
6e0bd6c3
RL
11543static int nl80211_join_ocb(struct sk_buff *skb, struct genl_info *info)
11544{
11545 struct cfg80211_registered_device *rdev = info->user_ptr[0];
11546 struct net_device *dev = info->user_ptr[1];
11547 struct ocb_setup setup = {};
11548 int err;
11549
11550 err = nl80211_parse_chandef(rdev, info, &setup.chandef);
11551 if (err)
11552 return err;
11553
11554 return cfg80211_join_ocb(rdev, dev, &setup);
11555}
11556
11557static int nl80211_leave_ocb(struct sk_buff *skb, struct genl_info *info)
11558{
11559 struct cfg80211_registered_device *rdev = info->user_ptr[0];
11560 struct net_device *dev = info->user_ptr[1];
11561
11562 return cfg80211_leave_ocb(rdev, dev);
11563}
11564
29cbe68c
JB
11565static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info)
11566{
11567 struct cfg80211_registered_device *rdev = info->user_ptr[0];
11568 struct net_device *dev = info->user_ptr[1];
11569 struct mesh_config cfg;
c80d545d 11570 struct mesh_setup setup;
29cbe68c
JB
11571 int err;
11572
11573 /* start with default */
11574 memcpy(&cfg, &default_mesh_config, sizeof(cfg));
c80d545d 11575 memcpy(&setup, &default_mesh_setup, sizeof(setup));
29cbe68c 11576
24bdd9f4 11577 if (info->attrs[NL80211_ATTR_MESH_CONFIG]) {
29cbe68c 11578 /* and parse parameters if given */
24bdd9f4 11579 err = nl80211_parse_mesh_config(info, &cfg, NULL);
29cbe68c
JB
11580 if (err)
11581 return err;
11582 }
11583
11584 if (!info->attrs[NL80211_ATTR_MESH_ID] ||
11585 !nla_len(info->attrs[NL80211_ATTR_MESH_ID]))
11586 return -EINVAL;
11587
c80d545d
JC
11588 setup.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]);
11589 setup.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
11590
4bb62344
CYY
11591 if (info->attrs[NL80211_ATTR_MCAST_RATE] &&
11592 !nl80211_parse_mcast_rate(rdev, setup.mcast_rate,
11593 nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE])))
11594 return -EINVAL;
11595
9bdbf04d
MP
11596 if (info->attrs[NL80211_ATTR_BEACON_INTERVAL]) {
11597 setup.beacon_interval =
11598 nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
12d20fc9 11599
0c317a02
PK
11600 err = cfg80211_validate_beacon_int(rdev,
11601 NL80211_IFTYPE_MESH_POINT,
11602 setup.beacon_interval);
12d20fc9
PK
11603 if (err)
11604 return err;
9bdbf04d
MP
11605 }
11606
11607 if (info->attrs[NL80211_ATTR_DTIM_PERIOD]) {
11608 setup.dtim_period =
11609 nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);
11610 if (setup.dtim_period < 1 || setup.dtim_period > 100)
11611 return -EINVAL;
11612 }
11613
c80d545d
JC
11614 if (info->attrs[NL80211_ATTR_MESH_SETUP]) {
11615 /* parse additional setup parameters if given */
11616 err = nl80211_parse_mesh_setup(info, &setup);
11617 if (err)
11618 return err;
11619 }
11620
d37bb18a
TP
11621 if (setup.user_mpm)
11622 cfg.auto_open_plinks = false;
11623
cc1d2806 11624 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
683b6d3b
JB
11625 err = nl80211_parse_chandef(rdev, info, &setup.chandef);
11626 if (err)
11627 return err;
cc1d2806 11628 } else {
188c1b3c 11629 /* __cfg80211_join_mesh() will sort it out */
683b6d3b 11630 setup.chandef.chan = NULL;
cc1d2806
JB
11631 }
11632
ffb3cf30
AN
11633 if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) {
11634 u8 *rates = nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
11635 int n_rates =
11636 nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
11637 struct ieee80211_supported_band *sband;
11638
11639 if (!setup.chandef.chan)
11640 return -EINVAL;
11641
11642 sband = rdev->wiphy.bands[setup.chandef.chan->band];
11643
11644 err = ieee80211_get_ratemask(sband, rates, n_rates,
11645 &setup.basic_rates);
11646 if (err)
11647 return err;
11648 }
11649
8564e382 11650 if (info->attrs[NL80211_ATTR_TX_RATES]) {
9a5f6488
TC
11651 err = nl80211_parse_tx_bitrate_mask(info, info->attrs,
11652 NL80211_ATTR_TX_RATES,
eb89a6a6
MH
11653 &setup.beacon_rate,
11654 dev);
8564e382
JB
11655 if (err)
11656 return err;
11657
265698d7
JB
11658 if (!setup.chandef.chan)
11659 return -EINVAL;
11660
8564e382
JB
11661 err = validate_beacon_tx_rate(rdev, setup.chandef.chan->band,
11662 &setup.beacon_rate);
11663 if (err)
11664 return err;
11665 }
11666
d37d49c2
BB
11667 setup.userspace_handles_dfs =
11668 nla_get_flag(info->attrs[NL80211_ATTR_HANDLE_DFS]);
11669
1224f583
DK
11670 if (info->attrs[NL80211_ATTR_CONTROL_PORT_OVER_NL80211]) {
11671 int r = validate_pae_over_nl80211(rdev, info);
11672
11673 if (r < 0)
11674 return r;
11675
11676 setup.control_port_over_nl80211 = true;
11677 }
11678
188c1b3c
DK
11679 wdev_lock(dev->ieee80211_ptr);
11680 err = __cfg80211_join_mesh(rdev, dev, &setup, &cfg);
11681 if (!err && info->attrs[NL80211_ATTR_SOCKET_OWNER])
11682 dev->ieee80211_ptr->conn_owner_nlportid = info->snd_portid;
11683 wdev_unlock(dev->ieee80211_ptr);
11684
11685 return err;
29cbe68c
JB
11686}
11687
11688static int nl80211_leave_mesh(struct sk_buff *skb, struct genl_info *info)
11689{
11690 struct cfg80211_registered_device *rdev = info->user_ptr[0];
11691 struct net_device *dev = info->user_ptr[1];
11692
11693 return cfg80211_leave_mesh(rdev, dev);
11694}
11695
dfb89c56 11696#ifdef CONFIG_PM
bb92d199
AK
11697static int nl80211_send_wowlan_patterns(struct sk_buff *msg,
11698 struct cfg80211_registered_device *rdev)
11699{
6abb9cb9 11700 struct cfg80211_wowlan *wowlan = rdev->wiphy.wowlan_config;
bb92d199
AK
11701 struct nlattr *nl_pats, *nl_pat;
11702 int i, pat_len;
11703
6abb9cb9 11704 if (!wowlan->n_patterns)
bb92d199
AK
11705 return 0;
11706
ae0be8de 11707 nl_pats = nla_nest_start_noflag(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN);
bb92d199
AK
11708 if (!nl_pats)
11709 return -ENOBUFS;
11710
6abb9cb9 11711 for (i = 0; i < wowlan->n_patterns; i++) {
ae0be8de 11712 nl_pat = nla_nest_start_noflag(msg, i + 1);
bb92d199
AK
11713 if (!nl_pat)
11714 return -ENOBUFS;
6abb9cb9 11715 pat_len = wowlan->patterns[i].pattern_len;
50ac6607 11716 if (nla_put(msg, NL80211_PKTPAT_MASK, DIV_ROUND_UP(pat_len, 8),
6abb9cb9 11717 wowlan->patterns[i].mask) ||
50ac6607
AK
11718 nla_put(msg, NL80211_PKTPAT_PATTERN, pat_len,
11719 wowlan->patterns[i].pattern) ||
11720 nla_put_u32(msg, NL80211_PKTPAT_OFFSET,
6abb9cb9 11721 wowlan->patterns[i].pkt_offset))
bb92d199
AK
11722 return -ENOBUFS;
11723 nla_nest_end(msg, nl_pat);
11724 }
11725 nla_nest_end(msg, nl_pats);
11726
11727 return 0;
11728}
11729
2a0e047e
JB
11730static int nl80211_send_wowlan_tcp(struct sk_buff *msg,
11731 struct cfg80211_wowlan_tcp *tcp)
11732{
11733 struct nlattr *nl_tcp;
11734
11735 if (!tcp)
11736 return 0;
11737
ae0be8de
MK
11738 nl_tcp = nla_nest_start_noflag(msg,
11739 NL80211_WOWLAN_TRIG_TCP_CONNECTION);
2a0e047e
JB
11740 if (!nl_tcp)
11741 return -ENOBUFS;
11742
930345ea
JB
11743 if (nla_put_in_addr(msg, NL80211_WOWLAN_TCP_SRC_IPV4, tcp->src) ||
11744 nla_put_in_addr(msg, NL80211_WOWLAN_TCP_DST_IPV4, tcp->dst) ||
2a0e047e
JB
11745 nla_put(msg, NL80211_WOWLAN_TCP_DST_MAC, ETH_ALEN, tcp->dst_mac) ||
11746 nla_put_u16(msg, NL80211_WOWLAN_TCP_SRC_PORT, tcp->src_port) ||
11747 nla_put_u16(msg, NL80211_WOWLAN_TCP_DST_PORT, tcp->dst_port) ||
11748 nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD,
11749 tcp->payload_len, tcp->payload) ||
11750 nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_INTERVAL,
11751 tcp->data_interval) ||
11752 nla_put(msg, NL80211_WOWLAN_TCP_WAKE_PAYLOAD,
11753 tcp->wake_len, tcp->wake_data) ||
11754 nla_put(msg, NL80211_WOWLAN_TCP_WAKE_MASK,
11755 DIV_ROUND_UP(tcp->wake_len, 8), tcp->wake_mask))
11756 return -ENOBUFS;
11757
11758 if (tcp->payload_seq.len &&
11759 nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ,
11760 sizeof(tcp->payload_seq), &tcp->payload_seq))
11761 return -ENOBUFS;
11762
11763 if (tcp->payload_tok.len &&
11764 nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN,
11765 sizeof(tcp->payload_tok) + tcp->tokens_size,
11766 &tcp->payload_tok))
11767 return -ENOBUFS;
11768
e248ad30
JB
11769 nla_nest_end(msg, nl_tcp);
11770
2a0e047e
JB
11771 return 0;
11772}
11773
75453ccb
LC
11774static int nl80211_send_wowlan_nd(struct sk_buff *msg,
11775 struct cfg80211_sched_scan_request *req)
11776{
3b06d277 11777 struct nlattr *nd, *freqs, *matches, *match, *scan_plans, *scan_plan;
75453ccb
LC
11778 int i;
11779
11780 if (!req)
11781 return 0;
11782
ae0be8de 11783 nd = nla_nest_start_noflag(msg, NL80211_WOWLAN_TRIG_NET_DETECT);
75453ccb
LC
11784 if (!nd)
11785 return -ENOBUFS;
11786
3b06d277
AS
11787 if (req->n_scan_plans == 1 &&
11788 nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_INTERVAL,
11789 req->scan_plans[0].interval * 1000))
75453ccb
LC
11790 return -ENOBUFS;
11791
21fea567
LC
11792 if (nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_DELAY, req->delay))
11793 return -ENOBUFS;
11794
bf95ecdb 11795 if (req->relative_rssi_set) {
11796 struct nl80211_bss_select_rssi_adjust rssi_adjust;
11797
11798 if (nla_put_s8(msg, NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI,
11799 req->relative_rssi))
11800 return -ENOBUFS;
11801
11802 rssi_adjust.band = req->rssi_adjust.band;
11803 rssi_adjust.delta = req->rssi_adjust.delta;
11804 if (nla_put(msg, NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST,
11805 sizeof(rssi_adjust), &rssi_adjust))
11806 return -ENOBUFS;
11807 }
11808
ae0be8de 11809 freqs = nla_nest_start_noflag(msg, NL80211_ATTR_SCAN_FREQUENCIES);
75453ccb
LC
11810 if (!freqs)
11811 return -ENOBUFS;
11812
53b18980
JB
11813 for (i = 0; i < req->n_channels; i++) {
11814 if (nla_put_u32(msg, i, req->channels[i]->center_freq))
11815 return -ENOBUFS;
11816 }
75453ccb
LC
11817
11818 nla_nest_end(msg, freqs);
11819
11820 if (req->n_match_sets) {
ae0be8de
MK
11821 matches = nla_nest_start_noflag(msg,
11822 NL80211_ATTR_SCHED_SCAN_MATCH);
76e1fb4b
JB
11823 if (!matches)
11824 return -ENOBUFS;
11825
75453ccb 11826 for (i = 0; i < req->n_match_sets; i++) {
ae0be8de 11827 match = nla_nest_start_noflag(msg, i);
76e1fb4b
JB
11828 if (!match)
11829 return -ENOBUFS;
11830
53b18980
JB
11831 if (nla_put(msg, NL80211_SCHED_SCAN_MATCH_ATTR_SSID,
11832 req->match_sets[i].ssid.ssid_len,
11833 req->match_sets[i].ssid.ssid))
11834 return -ENOBUFS;
75453ccb
LC
11835 nla_nest_end(msg, match);
11836 }
11837 nla_nest_end(msg, matches);
11838 }
11839
ae0be8de 11840 scan_plans = nla_nest_start_noflag(msg, NL80211_ATTR_SCHED_SCAN_PLANS);
3b06d277
AS
11841 if (!scan_plans)
11842 return -ENOBUFS;
11843
11844 for (i = 0; i < req->n_scan_plans; i++) {
ae0be8de 11845 scan_plan = nla_nest_start_noflag(msg, i + 1);
76e1fb4b
JB
11846 if (!scan_plan)
11847 return -ENOBUFS;
11848
67626964 11849 if (nla_put_u32(msg, NL80211_SCHED_SCAN_PLAN_INTERVAL,
3b06d277
AS
11850 req->scan_plans[i].interval) ||
11851 (req->scan_plans[i].iterations &&
11852 nla_put_u32(msg, NL80211_SCHED_SCAN_PLAN_ITERATIONS,
11853 req->scan_plans[i].iterations)))
11854 return -ENOBUFS;
11855 nla_nest_end(msg, scan_plan);
11856 }
11857 nla_nest_end(msg, scan_plans);
11858
75453ccb
LC
11859 nla_nest_end(msg, nd);
11860
11861 return 0;
11862}
11863
ff1b6e69
JB
11864static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info)
11865{
11866 struct cfg80211_registered_device *rdev = info->user_ptr[0];
11867 struct sk_buff *msg;
11868 void *hdr;
2a0e047e 11869 u32 size = NLMSG_DEFAULT_SIZE;
ff1b6e69 11870
964dc9e2 11871 if (!rdev->wiphy.wowlan)
ff1b6e69
JB
11872 return -EOPNOTSUPP;
11873
6abb9cb9 11874 if (rdev->wiphy.wowlan_config && rdev->wiphy.wowlan_config->tcp) {
2a0e047e 11875 /* adjust size to have room for all the data */
6abb9cb9
JB
11876 size += rdev->wiphy.wowlan_config->tcp->tokens_size +
11877 rdev->wiphy.wowlan_config->tcp->payload_len +
11878 rdev->wiphy.wowlan_config->tcp->wake_len +
11879 rdev->wiphy.wowlan_config->tcp->wake_len / 8;
2a0e047e
JB
11880 }
11881
11882 msg = nlmsg_new(size, GFP_KERNEL);
ff1b6e69
JB
11883 if (!msg)
11884 return -ENOMEM;
11885
15e47304 11886 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
ff1b6e69
JB
11887 NL80211_CMD_GET_WOWLAN);
11888 if (!hdr)
11889 goto nla_put_failure;
11890
6abb9cb9 11891 if (rdev->wiphy.wowlan_config) {
ff1b6e69
JB
11892 struct nlattr *nl_wowlan;
11893
ae0be8de
MK
11894 nl_wowlan = nla_nest_start_noflag(msg,
11895 NL80211_ATTR_WOWLAN_TRIGGERS);
ff1b6e69
JB
11896 if (!nl_wowlan)
11897 goto nla_put_failure;
11898
6abb9cb9 11899 if ((rdev->wiphy.wowlan_config->any &&
9360ffd1 11900 nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) ||
6abb9cb9 11901 (rdev->wiphy.wowlan_config->disconnect &&
9360ffd1 11902 nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) ||
6abb9cb9 11903 (rdev->wiphy.wowlan_config->magic_pkt &&
9360ffd1 11904 nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) ||
6abb9cb9 11905 (rdev->wiphy.wowlan_config->gtk_rekey_failure &&
9360ffd1 11906 nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) ||
6abb9cb9 11907 (rdev->wiphy.wowlan_config->eap_identity_req &&
9360ffd1 11908 nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) ||
6abb9cb9 11909 (rdev->wiphy.wowlan_config->four_way_handshake &&
9360ffd1 11910 nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) ||
6abb9cb9 11911 (rdev->wiphy.wowlan_config->rfkill_release &&
9360ffd1
DM
11912 nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE)))
11913 goto nla_put_failure;
2a0e047e 11914
bb92d199
AK
11915 if (nl80211_send_wowlan_patterns(msg, rdev))
11916 goto nla_put_failure;
2a0e047e 11917
6abb9cb9
JB
11918 if (nl80211_send_wowlan_tcp(msg,
11919 rdev->wiphy.wowlan_config->tcp))
2a0e047e 11920 goto nla_put_failure;
75453ccb
LC
11921
11922 if (nl80211_send_wowlan_nd(
11923 msg,
11924 rdev->wiphy.wowlan_config->nd_config))
11925 goto nla_put_failure;
2a0e047e 11926
ff1b6e69
JB
11927 nla_nest_end(msg, nl_wowlan);
11928 }
11929
11930 genlmsg_end(msg, hdr);
11931 return genlmsg_reply(msg, info);
11932
11933nla_put_failure:
11934 nlmsg_free(msg);
11935 return -ENOBUFS;
11936}
11937
2a0e047e
JB
11938static int nl80211_parse_wowlan_tcp(struct cfg80211_registered_device *rdev,
11939 struct nlattr *attr,
11940 struct cfg80211_wowlan *trig)
11941{
11942 struct nlattr *tb[NUM_NL80211_WOWLAN_TCP];
11943 struct cfg80211_wowlan_tcp *cfg;
11944 struct nl80211_wowlan_tcp_data_token *tok = NULL;
11945 struct nl80211_wowlan_tcp_data_seq *seq = NULL;
11946 u32 size;
11947 u32 data_size, wake_size, tokens_size = 0, wake_mask_size;
11948 int err, port;
11949
964dc9e2 11950 if (!rdev->wiphy.wowlan->tcp)
2a0e047e
JB
11951 return -EINVAL;
11952
8cb08174
JB
11953 err = nla_parse_nested_deprecated(tb, MAX_NL80211_WOWLAN_TCP, attr,
11954 nl80211_wowlan_tcp_policy, NULL);
2a0e047e
JB
11955 if (err)
11956 return err;
11957
11958 if (!tb[NL80211_WOWLAN_TCP_SRC_IPV4] ||
11959 !tb[NL80211_WOWLAN_TCP_DST_IPV4] ||
11960 !tb[NL80211_WOWLAN_TCP_DST_MAC] ||
11961 !tb[NL80211_WOWLAN_TCP_DST_PORT] ||
11962 !tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD] ||
11963 !tb[NL80211_WOWLAN_TCP_DATA_INTERVAL] ||
11964 !tb[NL80211_WOWLAN_TCP_WAKE_PAYLOAD] ||
11965 !tb[NL80211_WOWLAN_TCP_WAKE_MASK])
11966 return -EINVAL;
11967
11968 data_size = nla_len(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD]);
964dc9e2 11969 if (data_size > rdev->wiphy.wowlan->tcp->data_payload_max)
2a0e047e
JB
11970 return -EINVAL;
11971
11972 if (nla_get_u32(tb[NL80211_WOWLAN_TCP_DATA_INTERVAL]) >
964dc9e2 11973 rdev->wiphy.wowlan->tcp->data_interval_max ||
723d568a 11974 nla_get_u32(tb[NL80211_WOWLAN_TCP_DATA_INTERVAL]) == 0)
2a0e047e
JB
11975 return -EINVAL;
11976
11977 wake_size = nla_len(tb[NL80211_WOWLAN_TCP_WAKE_PAYLOAD]);
964dc9e2 11978 if (wake_size > rdev->wiphy.wowlan->tcp->wake_payload_max)
2a0e047e
JB
11979 return -EINVAL;
11980
11981 wake_mask_size = nla_len(tb[NL80211_WOWLAN_TCP_WAKE_MASK]);
11982 if (wake_mask_size != DIV_ROUND_UP(wake_size, 8))
11983 return -EINVAL;
11984
11985 if (tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN]) {
11986 u32 tokln = nla_len(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN]);
11987
11988 tok = nla_data(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN]);
11989 tokens_size = tokln - sizeof(*tok);
11990
11991 if (!tok->len || tokens_size % tok->len)
11992 return -EINVAL;
964dc9e2 11993 if (!rdev->wiphy.wowlan->tcp->tok)
2a0e047e 11994 return -EINVAL;
964dc9e2 11995 if (tok->len > rdev->wiphy.wowlan->tcp->tok->max_len)
2a0e047e 11996 return -EINVAL;
964dc9e2 11997 if (tok->len < rdev->wiphy.wowlan->tcp->tok->min_len)
2a0e047e 11998 return -EINVAL;
964dc9e2 11999 if (tokens_size > rdev->wiphy.wowlan->tcp->tok->bufsize)
2a0e047e
JB
12000 return -EINVAL;
12001 if (tok->offset + tok->len > data_size)
12002 return -EINVAL;
12003 }
12004
12005 if (tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ]) {
12006 seq = nla_data(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ]);
964dc9e2 12007 if (!rdev->wiphy.wowlan->tcp->seq)
2a0e047e
JB
12008 return -EINVAL;
12009 if (seq->len == 0 || seq->len > 4)
12010 return -EINVAL;
12011 if (seq->len + seq->offset > data_size)
12012 return -EINVAL;
12013 }
12014
12015 size = sizeof(*cfg);
12016 size += data_size;
12017 size += wake_size + wake_mask_size;
12018 size += tokens_size;
12019
12020 cfg = kzalloc(size, GFP_KERNEL);
12021 if (!cfg)
12022 return -ENOMEM;
67b61f6c
JB
12023 cfg->src = nla_get_in_addr(tb[NL80211_WOWLAN_TCP_SRC_IPV4]);
12024 cfg->dst = nla_get_in_addr(tb[NL80211_WOWLAN_TCP_DST_IPV4]);
2a0e047e
JB
12025 memcpy(cfg->dst_mac, nla_data(tb[NL80211_WOWLAN_TCP_DST_MAC]),
12026 ETH_ALEN);
12027 if (tb[NL80211_WOWLAN_TCP_SRC_PORT])
12028 port = nla_get_u16(tb[NL80211_WOWLAN_TCP_SRC_PORT]);
12029 else
12030 port = 0;
12031#ifdef CONFIG_INET
12032 /* allocate a socket and port for it and use it */
12033 err = __sock_create(wiphy_net(&rdev->wiphy), PF_INET, SOCK_STREAM,
12034 IPPROTO_TCP, &cfg->sock, 1);
12035 if (err) {
12036 kfree(cfg);
12037 return err;
12038 }
12039 if (inet_csk_get_port(cfg->sock->sk, port)) {
12040 sock_release(cfg->sock);
12041 kfree(cfg);
12042 return -EADDRINUSE;
12043 }
12044 cfg->src_port = inet_sk(cfg->sock->sk)->inet_num;
12045#else
12046 if (!port) {
12047 kfree(cfg);
12048 return -EINVAL;
12049 }
12050 cfg->src_port = port;
12051#endif
12052
12053 cfg->dst_port = nla_get_u16(tb[NL80211_WOWLAN_TCP_DST_PORT]);
12054 cfg->payload_len = data_size;
12055 cfg->payload = (u8 *)cfg + sizeof(*cfg) + tokens_size;
12056 memcpy((void *)cfg->payload,
12057 nla_data(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD]),
12058 data_size);
12059 if (seq)
12060 cfg->payload_seq = *seq;
12061 cfg->data_interval = nla_get_u32(tb[NL80211_WOWLAN_TCP_DATA_INTERVAL]);
12062 cfg->wake_len = wake_size;
12063 cfg->wake_data = (u8 *)cfg + sizeof(*cfg) + tokens_size + data_size;
12064 memcpy((void *)cfg->wake_data,
12065 nla_data(tb[NL80211_WOWLAN_TCP_WAKE_PAYLOAD]),
12066 wake_size);
12067 cfg->wake_mask = (u8 *)cfg + sizeof(*cfg) + tokens_size +
12068 data_size + wake_size;
12069 memcpy((void *)cfg->wake_mask,
12070 nla_data(tb[NL80211_WOWLAN_TCP_WAKE_MASK]),
12071 wake_mask_size);
12072 if (tok) {
12073 cfg->tokens_size = tokens_size;
12074 memcpy(&cfg->payload_tok, tok, sizeof(*tok) + tokens_size);
12075 }
12076
12077 trig->tcp = cfg;
12078
12079 return 0;
12080}
12081
8cd4d456
LC
12082static int nl80211_parse_wowlan_nd(struct cfg80211_registered_device *rdev,
12083 const struct wiphy_wowlan_support *wowlan,
12084 struct nlattr *attr,
12085 struct cfg80211_wowlan *trig)
12086{
12087 struct nlattr **tb;
12088 int err;
12089
6396bb22 12090 tb = kcalloc(NUM_NL80211_ATTR, sizeof(*tb), GFP_KERNEL);
8cd4d456
LC
12091 if (!tb)
12092 return -ENOMEM;
12093
12094 if (!(wowlan->flags & WIPHY_WOWLAN_NET_DETECT)) {
12095 err = -EOPNOTSUPP;
12096 goto out;
12097 }
12098
8cb08174
JB
12099 err = nla_parse_nested_deprecated(tb, NL80211_ATTR_MAX, attr,
12100 nl80211_policy, NULL);
8cd4d456
LC
12101 if (err)
12102 goto out;
12103
aad1e812
AVS
12104 trig->nd_config = nl80211_parse_sched_scan(&rdev->wiphy, NULL, tb,
12105 wowlan->max_nd_match_sets);
8cd4d456
LC
12106 err = PTR_ERR_OR_ZERO(trig->nd_config);
12107 if (err)
12108 trig->nd_config = NULL;
12109
12110out:
12111 kfree(tb);
12112 return err;
12113}
12114
ff1b6e69
JB
12115static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
12116{
12117 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12118 struct nlattr *tb[NUM_NL80211_WOWLAN_TRIG];
ff1b6e69 12119 struct cfg80211_wowlan new_triggers = {};
ae33bd81 12120 struct cfg80211_wowlan *ntrig;
964dc9e2 12121 const struct wiphy_wowlan_support *wowlan = rdev->wiphy.wowlan;
ff1b6e69 12122 int err, i;
6abb9cb9 12123 bool prev_enabled = rdev->wiphy.wowlan_config;
98fc4386 12124 bool regular = false;
ff1b6e69 12125
964dc9e2 12126 if (!wowlan)
ff1b6e69
JB
12127 return -EOPNOTSUPP;
12128
ae33bd81
JB
12129 if (!info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS]) {
12130 cfg80211_rdev_free_wowlan(rdev);
6abb9cb9 12131 rdev->wiphy.wowlan_config = NULL;
ae33bd81
JB
12132 goto set_wakeup;
12133 }
ff1b6e69 12134
8cb08174
JB
12135 err = nla_parse_nested_deprecated(tb, MAX_NL80211_WOWLAN_TRIG,
12136 info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS],
12137 nl80211_wowlan_policy, info->extack);
ff1b6e69
JB
12138 if (err)
12139 return err;
12140
12141 if (tb[NL80211_WOWLAN_TRIG_ANY]) {
12142 if (!(wowlan->flags & WIPHY_WOWLAN_ANY))
12143 return -EINVAL;
12144 new_triggers.any = true;
12145 }
12146
12147 if (tb[NL80211_WOWLAN_TRIG_DISCONNECT]) {
12148 if (!(wowlan->flags & WIPHY_WOWLAN_DISCONNECT))
12149 return -EINVAL;
12150 new_triggers.disconnect = true;
98fc4386 12151 regular = true;
ff1b6e69
JB
12152 }
12153
12154 if (tb[NL80211_WOWLAN_TRIG_MAGIC_PKT]) {
12155 if (!(wowlan->flags & WIPHY_WOWLAN_MAGIC_PKT))
12156 return -EINVAL;
12157 new_triggers.magic_pkt = true;
98fc4386 12158 regular = true;
ff1b6e69
JB
12159 }
12160
77dbbb13
JB
12161 if (tb[NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED])
12162 return -EINVAL;
12163
12164 if (tb[NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE]) {
12165 if (!(wowlan->flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE))
12166 return -EINVAL;
12167 new_triggers.gtk_rekey_failure = true;
98fc4386 12168 regular = true;
77dbbb13
JB
12169 }
12170
12171 if (tb[NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST]) {
12172 if (!(wowlan->flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ))
12173 return -EINVAL;
12174 new_triggers.eap_identity_req = true;
98fc4386 12175 regular = true;
77dbbb13
JB
12176 }
12177
12178 if (tb[NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE]) {
12179 if (!(wowlan->flags & WIPHY_WOWLAN_4WAY_HANDSHAKE))
12180 return -EINVAL;
12181 new_triggers.four_way_handshake = true;
98fc4386 12182 regular = true;
77dbbb13
JB
12183 }
12184
12185 if (tb[NL80211_WOWLAN_TRIG_RFKILL_RELEASE]) {
12186 if (!(wowlan->flags & WIPHY_WOWLAN_RFKILL_RELEASE))
12187 return -EINVAL;
12188 new_triggers.rfkill_release = true;
98fc4386 12189 regular = true;
77dbbb13
JB
12190 }
12191
ff1b6e69
JB
12192 if (tb[NL80211_WOWLAN_TRIG_PKT_PATTERN]) {
12193 struct nlattr *pat;
12194 int n_patterns = 0;
bb92d199 12195 int rem, pat_len, mask_len, pkt_offset;
50ac6607 12196 struct nlattr *pat_tb[NUM_NL80211_PKTPAT];
ff1b6e69 12197
98fc4386
JB
12198 regular = true;
12199
ff1b6e69
JB
12200 nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN],
12201 rem)
12202 n_patterns++;
12203 if (n_patterns > wowlan->n_patterns)
12204 return -EINVAL;
12205
12206 new_triggers.patterns = kcalloc(n_patterns,
12207 sizeof(new_triggers.patterns[0]),
12208 GFP_KERNEL);
12209 if (!new_triggers.patterns)
12210 return -ENOMEM;
12211
12212 new_triggers.n_patterns = n_patterns;
12213 i = 0;
12214
12215 nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN],
12216 rem) {
922bd80f
JB
12217 u8 *mask_pat;
12218
8cb08174
JB
12219 err = nla_parse_nested_deprecated(pat_tb,
12220 MAX_NL80211_PKTPAT,
12221 pat,
12222 nl80211_packet_pattern_policy,
12223 info->extack);
95bca62f
JB
12224 if (err)
12225 goto error;
12226
ff1b6e69 12227 err = -EINVAL;
50ac6607
AK
12228 if (!pat_tb[NL80211_PKTPAT_MASK] ||
12229 !pat_tb[NL80211_PKTPAT_PATTERN])
ff1b6e69 12230 goto error;
50ac6607 12231 pat_len = nla_len(pat_tb[NL80211_PKTPAT_PATTERN]);
ff1b6e69 12232 mask_len = DIV_ROUND_UP(pat_len, 8);
50ac6607 12233 if (nla_len(pat_tb[NL80211_PKTPAT_MASK]) != mask_len)
ff1b6e69
JB
12234 goto error;
12235 if (pat_len > wowlan->pattern_max_len ||
12236 pat_len < wowlan->pattern_min_len)
12237 goto error;
12238
50ac6607 12239 if (!pat_tb[NL80211_PKTPAT_OFFSET])
bb92d199
AK
12240 pkt_offset = 0;
12241 else
12242 pkt_offset = nla_get_u32(
50ac6607 12243 pat_tb[NL80211_PKTPAT_OFFSET]);
bb92d199
AK
12244 if (pkt_offset > wowlan->max_pkt_offset)
12245 goto error;
12246 new_triggers.patterns[i].pkt_offset = pkt_offset;
12247
922bd80f
JB
12248 mask_pat = kmalloc(mask_len + pat_len, GFP_KERNEL);
12249 if (!mask_pat) {
ff1b6e69
JB
12250 err = -ENOMEM;
12251 goto error;
12252 }
922bd80f
JB
12253 new_triggers.patterns[i].mask = mask_pat;
12254 memcpy(mask_pat, nla_data(pat_tb[NL80211_PKTPAT_MASK]),
ff1b6e69 12255 mask_len);
922bd80f
JB
12256 mask_pat += mask_len;
12257 new_triggers.patterns[i].pattern = mask_pat;
ff1b6e69 12258 new_triggers.patterns[i].pattern_len = pat_len;
922bd80f 12259 memcpy(mask_pat,
50ac6607 12260 nla_data(pat_tb[NL80211_PKTPAT_PATTERN]),
ff1b6e69
JB
12261 pat_len);
12262 i++;
12263 }
12264 }
12265
2a0e047e 12266 if (tb[NL80211_WOWLAN_TRIG_TCP_CONNECTION]) {
98fc4386 12267 regular = true;
2a0e047e
JB
12268 err = nl80211_parse_wowlan_tcp(
12269 rdev, tb[NL80211_WOWLAN_TRIG_TCP_CONNECTION],
12270 &new_triggers);
12271 if (err)
12272 goto error;
12273 }
12274
8cd4d456 12275 if (tb[NL80211_WOWLAN_TRIG_NET_DETECT]) {
98fc4386 12276 regular = true;
8cd4d456
LC
12277 err = nl80211_parse_wowlan_nd(
12278 rdev, wowlan, tb[NL80211_WOWLAN_TRIG_NET_DETECT],
12279 &new_triggers);
12280 if (err)
12281 goto error;
12282 }
12283
98fc4386
JB
12284 /* The 'any' trigger means the device continues operating more or less
12285 * as in its normal operation mode and wakes up the host on most of the
12286 * normal interrupts (like packet RX, ...)
12287 * It therefore makes little sense to combine with the more constrained
12288 * wakeup trigger modes.
12289 */
12290 if (new_triggers.any && regular) {
12291 err = -EINVAL;
12292 goto error;
12293 }
12294
ae33bd81
JB
12295 ntrig = kmemdup(&new_triggers, sizeof(new_triggers), GFP_KERNEL);
12296 if (!ntrig) {
12297 err = -ENOMEM;
12298 goto error;
ff1b6e69 12299 }
ae33bd81 12300 cfg80211_rdev_free_wowlan(rdev);
6abb9cb9 12301 rdev->wiphy.wowlan_config = ntrig;
ff1b6e69 12302
ae33bd81 12303 set_wakeup:
6abb9cb9
JB
12304 if (rdev->ops->set_wakeup &&
12305 prev_enabled != !!rdev->wiphy.wowlan_config)
12306 rdev_set_wakeup(rdev, rdev->wiphy.wowlan_config);
6d52563f 12307
ff1b6e69
JB
12308 return 0;
12309 error:
12310 for (i = 0; i < new_triggers.n_patterns; i++)
12311 kfree(new_triggers.patterns[i].mask);
12312 kfree(new_triggers.patterns);
2a0e047e
JB
12313 if (new_triggers.tcp && new_triggers.tcp->sock)
12314 sock_release(new_triggers.tcp->sock);
12315 kfree(new_triggers.tcp);
e5dbe070 12316 kfree(new_triggers.nd_config);
ff1b6e69
JB
12317 return err;
12318}
dfb89c56 12319#endif
ff1b6e69 12320
be29b99a
AK
12321static int nl80211_send_coalesce_rules(struct sk_buff *msg,
12322 struct cfg80211_registered_device *rdev)
12323{
12324 struct nlattr *nl_pats, *nl_pat, *nl_rule, *nl_rules;
12325 int i, j, pat_len;
12326 struct cfg80211_coalesce_rules *rule;
12327
12328 if (!rdev->coalesce->n_rules)
12329 return 0;
12330
ae0be8de 12331 nl_rules = nla_nest_start_noflag(msg, NL80211_ATTR_COALESCE_RULE);
be29b99a
AK
12332 if (!nl_rules)
12333 return -ENOBUFS;
12334
12335 for (i = 0; i < rdev->coalesce->n_rules; i++) {
ae0be8de 12336 nl_rule = nla_nest_start_noflag(msg, i + 1);
be29b99a
AK
12337 if (!nl_rule)
12338 return -ENOBUFS;
12339
12340 rule = &rdev->coalesce->rules[i];
12341 if (nla_put_u32(msg, NL80211_ATTR_COALESCE_RULE_DELAY,
12342 rule->delay))
12343 return -ENOBUFS;
12344
12345 if (nla_put_u32(msg, NL80211_ATTR_COALESCE_RULE_CONDITION,
12346 rule->condition))
12347 return -ENOBUFS;
12348
ae0be8de
MK
12349 nl_pats = nla_nest_start_noflag(msg,
12350 NL80211_ATTR_COALESCE_RULE_PKT_PATTERN);
be29b99a
AK
12351 if (!nl_pats)
12352 return -ENOBUFS;
12353
12354 for (j = 0; j < rule->n_patterns; j++) {
ae0be8de 12355 nl_pat = nla_nest_start_noflag(msg, j + 1);
be29b99a
AK
12356 if (!nl_pat)
12357 return -ENOBUFS;
12358 pat_len = rule->patterns[j].pattern_len;
12359 if (nla_put(msg, NL80211_PKTPAT_MASK,
12360 DIV_ROUND_UP(pat_len, 8),
12361 rule->patterns[j].mask) ||
12362 nla_put(msg, NL80211_PKTPAT_PATTERN, pat_len,
12363 rule->patterns[j].pattern) ||
12364 nla_put_u32(msg, NL80211_PKTPAT_OFFSET,
12365 rule->patterns[j].pkt_offset))
12366 return -ENOBUFS;
12367 nla_nest_end(msg, nl_pat);
12368 }
12369 nla_nest_end(msg, nl_pats);
12370 nla_nest_end(msg, nl_rule);
12371 }
12372 nla_nest_end(msg, nl_rules);
12373
12374 return 0;
12375}
12376
12377static int nl80211_get_coalesce(struct sk_buff *skb, struct genl_info *info)
12378{
12379 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12380 struct sk_buff *msg;
12381 void *hdr;
12382
12383 if (!rdev->wiphy.coalesce)
12384 return -EOPNOTSUPP;
12385
12386 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
12387 if (!msg)
12388 return -ENOMEM;
12389
12390 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
12391 NL80211_CMD_GET_COALESCE);
12392 if (!hdr)
12393 goto nla_put_failure;
12394
12395 if (rdev->coalesce && nl80211_send_coalesce_rules(msg, rdev))
12396 goto nla_put_failure;
12397
12398 genlmsg_end(msg, hdr);
12399 return genlmsg_reply(msg, info);
12400
12401nla_put_failure:
12402 nlmsg_free(msg);
12403 return -ENOBUFS;
12404}
12405
12406void cfg80211_rdev_free_coalesce(struct cfg80211_registered_device *rdev)
12407{
12408 struct cfg80211_coalesce *coalesce = rdev->coalesce;
12409 int i, j;
12410 struct cfg80211_coalesce_rules *rule;
12411
12412 if (!coalesce)
12413 return;
12414
12415 for (i = 0; i < coalesce->n_rules; i++) {
12416 rule = &coalesce->rules[i];
12417 for (j = 0; j < rule->n_patterns; j++)
12418 kfree(rule->patterns[j].mask);
12419 kfree(rule->patterns);
12420 }
12421 kfree(coalesce->rules);
12422 kfree(coalesce);
12423 rdev->coalesce = NULL;
12424}
12425
12426static int nl80211_parse_coalesce_rule(struct cfg80211_registered_device *rdev,
12427 struct nlattr *rule,
12428 struct cfg80211_coalesce_rules *new_rule)
12429{
12430 int err, i;
12431 const struct wiphy_coalesce_support *coalesce = rdev->wiphy.coalesce;
12432 struct nlattr *tb[NUM_NL80211_ATTR_COALESCE_RULE], *pat;
12433 int rem, pat_len, mask_len, pkt_offset, n_patterns = 0;
12434 struct nlattr *pat_tb[NUM_NL80211_PKTPAT];
12435
8cb08174
JB
12436 err = nla_parse_nested_deprecated(tb, NL80211_ATTR_COALESCE_RULE_MAX,
12437 rule, nl80211_coalesce_policy, NULL);
be29b99a
AK
12438 if (err)
12439 return err;
12440
12441 if (tb[NL80211_ATTR_COALESCE_RULE_DELAY])
12442 new_rule->delay =
12443 nla_get_u32(tb[NL80211_ATTR_COALESCE_RULE_DELAY]);
12444 if (new_rule->delay > coalesce->max_delay)
12445 return -EINVAL;
12446
12447 if (tb[NL80211_ATTR_COALESCE_RULE_CONDITION])
12448 new_rule->condition =
12449 nla_get_u32(tb[NL80211_ATTR_COALESCE_RULE_CONDITION]);
be29b99a
AK
12450
12451 if (!tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN])
12452 return -EINVAL;
12453
12454 nla_for_each_nested(pat, tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN],
12455 rem)
12456 n_patterns++;
12457 if (n_patterns > coalesce->n_patterns)
12458 return -EINVAL;
12459
12460 new_rule->patterns = kcalloc(n_patterns, sizeof(new_rule->patterns[0]),
12461 GFP_KERNEL);
12462 if (!new_rule->patterns)
12463 return -ENOMEM;
12464
12465 new_rule->n_patterns = n_patterns;
12466 i = 0;
12467
12468 nla_for_each_nested(pat, tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN],
12469 rem) {
922bd80f
JB
12470 u8 *mask_pat;
12471
8cb08174
JB
12472 err = nla_parse_nested_deprecated(pat_tb, MAX_NL80211_PKTPAT,
12473 pat,
12474 nl80211_packet_pattern_policy,
12475 NULL);
95bca62f
JB
12476 if (err)
12477 return err;
12478
be29b99a
AK
12479 if (!pat_tb[NL80211_PKTPAT_MASK] ||
12480 !pat_tb[NL80211_PKTPAT_PATTERN])
12481 return -EINVAL;
12482 pat_len = nla_len(pat_tb[NL80211_PKTPAT_PATTERN]);
12483 mask_len = DIV_ROUND_UP(pat_len, 8);
12484 if (nla_len(pat_tb[NL80211_PKTPAT_MASK]) != mask_len)
12485 return -EINVAL;
12486 if (pat_len > coalesce->pattern_max_len ||
12487 pat_len < coalesce->pattern_min_len)
12488 return -EINVAL;
12489
12490 if (!pat_tb[NL80211_PKTPAT_OFFSET])
12491 pkt_offset = 0;
12492 else
12493 pkt_offset = nla_get_u32(pat_tb[NL80211_PKTPAT_OFFSET]);
12494 if (pkt_offset > coalesce->max_pkt_offset)
12495 return -EINVAL;
12496 new_rule->patterns[i].pkt_offset = pkt_offset;
12497
922bd80f
JB
12498 mask_pat = kmalloc(mask_len + pat_len, GFP_KERNEL);
12499 if (!mask_pat)
be29b99a 12500 return -ENOMEM;
922bd80f
JB
12501
12502 new_rule->patterns[i].mask = mask_pat;
12503 memcpy(mask_pat, nla_data(pat_tb[NL80211_PKTPAT_MASK]),
12504 mask_len);
12505
12506 mask_pat += mask_len;
12507 new_rule->patterns[i].pattern = mask_pat;
be29b99a 12508 new_rule->patterns[i].pattern_len = pat_len;
922bd80f
JB
12509 memcpy(mask_pat, nla_data(pat_tb[NL80211_PKTPAT_PATTERN]),
12510 pat_len);
be29b99a
AK
12511 i++;
12512 }
12513
12514 return 0;
12515}
12516
12517static int nl80211_set_coalesce(struct sk_buff *skb, struct genl_info *info)
12518{
12519 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12520 const struct wiphy_coalesce_support *coalesce = rdev->wiphy.coalesce;
12521 struct cfg80211_coalesce new_coalesce = {};
12522 struct cfg80211_coalesce *n_coalesce;
12523 int err, rem_rule, n_rules = 0, i, j;
12524 struct nlattr *rule;
12525 struct cfg80211_coalesce_rules *tmp_rule;
12526
12527 if (!rdev->wiphy.coalesce || !rdev->ops->set_coalesce)
12528 return -EOPNOTSUPP;
12529
12530 if (!info->attrs[NL80211_ATTR_COALESCE_RULE]) {
12531 cfg80211_rdev_free_coalesce(rdev);
a1056b1b 12532 rdev_set_coalesce(rdev, NULL);
be29b99a
AK
12533 return 0;
12534 }
12535
12536 nla_for_each_nested(rule, info->attrs[NL80211_ATTR_COALESCE_RULE],
12537 rem_rule)
12538 n_rules++;
12539 if (n_rules > coalesce->n_rules)
12540 return -EINVAL;
12541
12542 new_coalesce.rules = kcalloc(n_rules, sizeof(new_coalesce.rules[0]),
12543 GFP_KERNEL);
12544 if (!new_coalesce.rules)
12545 return -ENOMEM;
12546
12547 new_coalesce.n_rules = n_rules;
12548 i = 0;
12549
12550 nla_for_each_nested(rule, info->attrs[NL80211_ATTR_COALESCE_RULE],
12551 rem_rule) {
12552 err = nl80211_parse_coalesce_rule(rdev, rule,
12553 &new_coalesce.rules[i]);
12554 if (err)
12555 goto error;
12556
12557 i++;
12558 }
12559
a1056b1b 12560 err = rdev_set_coalesce(rdev, &new_coalesce);
be29b99a
AK
12561 if (err)
12562 goto error;
12563
12564 n_coalesce = kmemdup(&new_coalesce, sizeof(new_coalesce), GFP_KERNEL);
12565 if (!n_coalesce) {
12566 err = -ENOMEM;
12567 goto error;
12568 }
12569 cfg80211_rdev_free_coalesce(rdev);
12570 rdev->coalesce = n_coalesce;
12571
12572 return 0;
12573error:
12574 for (i = 0; i < new_coalesce.n_rules; i++) {
12575 tmp_rule = &new_coalesce.rules[i];
12576 for (j = 0; j < tmp_rule->n_patterns; j++)
12577 kfree(tmp_rule->patterns[j].mask);
12578 kfree(tmp_rule->patterns);
12579 }
12580 kfree(new_coalesce.rules);
12581
12582 return err;
12583}
12584
e5497d76
JB
12585static int nl80211_set_rekey_data(struct sk_buff *skb, struct genl_info *info)
12586{
12587 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12588 struct net_device *dev = info->user_ptr[1];
12589 struct wireless_dev *wdev = dev->ieee80211_ptr;
12590 struct nlattr *tb[NUM_NL80211_REKEY_DATA];
12591 struct cfg80211_gtk_rekey_data rekey_data;
12592 int err;
12593
12594 if (!info->attrs[NL80211_ATTR_REKEY_DATA])
12595 return -EINVAL;
12596
8cb08174
JB
12597 err = nla_parse_nested_deprecated(tb, MAX_NL80211_REKEY_DATA,
12598 info->attrs[NL80211_ATTR_REKEY_DATA],
12599 nl80211_rekey_policy, info->extack);
e5497d76
JB
12600 if (err)
12601 return err;
12602
e785fa0a
VD
12603 if (!tb[NL80211_REKEY_DATA_REPLAY_CTR] || !tb[NL80211_REKEY_DATA_KEK] ||
12604 !tb[NL80211_REKEY_DATA_KCK])
12605 return -EINVAL;
093a48d2
NE
12606 if (nla_len(tb[NL80211_REKEY_DATA_KEK]) != NL80211_KEK_LEN &&
12607 !(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_EXT_KEK_KCK &&
12608 nla_len(tb[NL80211_REKEY_DATA_KEK]) == NL80211_KEK_EXT_LEN))
e5497d76 12609 return -ERANGE;
093a48d2
NE
12610 if (nla_len(tb[NL80211_REKEY_DATA_KCK]) != NL80211_KCK_LEN &&
12611 !(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_EXT_KEK_KCK &&
12612 nla_len(tb[NL80211_REKEY_DATA_KEK]) == NL80211_KCK_EXT_LEN))
e5497d76
JB
12613 return -ERANGE;
12614
78f686ca
JB
12615 rekey_data.kek = nla_data(tb[NL80211_REKEY_DATA_KEK]);
12616 rekey_data.kck = nla_data(tb[NL80211_REKEY_DATA_KCK]);
12617 rekey_data.replay_ctr = nla_data(tb[NL80211_REKEY_DATA_REPLAY_CTR]);
093a48d2
NE
12618 rekey_data.kek_len = nla_len(tb[NL80211_REKEY_DATA_KEK]);
12619 rekey_data.kck_len = nla_len(tb[NL80211_REKEY_DATA_KCK]);
12620 if (tb[NL80211_REKEY_DATA_AKM])
12621 rekey_data.akm = nla_get_u32(tb[NL80211_REKEY_DATA_AKM]);
e5497d76
JB
12622
12623 wdev_lock(wdev);
12624 if (!wdev->current_bss) {
12625 err = -ENOTCONN;
12626 goto out;
12627 }
12628
12629 if (!rdev->ops->set_rekey_data) {
12630 err = -EOPNOTSUPP;
12631 goto out;
12632 }
12633
e35e4d28 12634 err = rdev_set_rekey_data(rdev, dev, &rekey_data);
e5497d76
JB
12635 out:
12636 wdev_unlock(wdev);
12637 return err;
12638}
12639
28946da7
JB
12640static int nl80211_register_unexpected_frame(struct sk_buff *skb,
12641 struct genl_info *info)
12642{
12643 struct net_device *dev = info->user_ptr[1];
12644 struct wireless_dev *wdev = dev->ieee80211_ptr;
12645
12646 if (wdev->iftype != NL80211_IFTYPE_AP &&
12647 wdev->iftype != NL80211_IFTYPE_P2P_GO)
12648 return -EINVAL;
12649
15e47304 12650 if (wdev->ap_unexpected_nlportid)
28946da7
JB
12651 return -EBUSY;
12652
15e47304 12653 wdev->ap_unexpected_nlportid = info->snd_portid;
28946da7
JB
12654 return 0;
12655}
12656
7f6cf311
JB
12657static int nl80211_probe_client(struct sk_buff *skb,
12658 struct genl_info *info)
12659{
12660 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12661 struct net_device *dev = info->user_ptr[1];
12662 struct wireless_dev *wdev = dev->ieee80211_ptr;
12663 struct sk_buff *msg;
12664 void *hdr;
12665 const u8 *addr;
12666 u64 cookie;
12667 int err;
12668
12669 if (wdev->iftype != NL80211_IFTYPE_AP &&
12670 wdev->iftype != NL80211_IFTYPE_P2P_GO)
12671 return -EOPNOTSUPP;
12672
12673 if (!info->attrs[NL80211_ATTR_MAC])
12674 return -EINVAL;
12675
12676 if (!rdev->ops->probe_client)
12677 return -EOPNOTSUPP;
12678
12679 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
12680 if (!msg)
12681 return -ENOMEM;
12682
15e47304 12683 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
7f6cf311 12684 NL80211_CMD_PROBE_CLIENT);
cb35fba3
DC
12685 if (!hdr) {
12686 err = -ENOBUFS;
7f6cf311
JB
12687 goto free_msg;
12688 }
12689
12690 addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
12691
e35e4d28 12692 err = rdev_probe_client(rdev, dev, addr, &cookie);
7f6cf311
JB
12693 if (err)
12694 goto free_msg;
12695
2dad624e
ND
12696 if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
12697 NL80211_ATTR_PAD))
9360ffd1 12698 goto nla_put_failure;
7f6cf311
JB
12699
12700 genlmsg_end(msg, hdr);
12701
12702 return genlmsg_reply(msg, info);
12703
12704 nla_put_failure:
12705 err = -ENOBUFS;
12706 free_msg:
12707 nlmsg_free(msg);
12708 return err;
12709}
12710
5e760230
JB
12711static int nl80211_register_beacons(struct sk_buff *skb, struct genl_info *info)
12712{
12713 struct cfg80211_registered_device *rdev = info->user_ptr[0];
37c73b5f
BG
12714 struct cfg80211_beacon_registration *reg, *nreg;
12715 int rv;
5e760230
JB
12716
12717 if (!(rdev->wiphy.flags & WIPHY_FLAG_REPORTS_OBSS))
12718 return -EOPNOTSUPP;
12719
37c73b5f
BG
12720 nreg = kzalloc(sizeof(*nreg), GFP_KERNEL);
12721 if (!nreg)
12722 return -ENOMEM;
12723
12724 /* First, check if already registered. */
12725 spin_lock_bh(&rdev->beacon_registrations_lock);
12726 list_for_each_entry(reg, &rdev->beacon_registrations, list) {
12727 if (reg->nlportid == info->snd_portid) {
12728 rv = -EALREADY;
12729 goto out_err;
12730 }
12731 }
12732 /* Add it to the list */
12733 nreg->nlportid = info->snd_portid;
12734 list_add(&nreg->list, &rdev->beacon_registrations);
5e760230 12735
37c73b5f 12736 spin_unlock_bh(&rdev->beacon_registrations_lock);
5e760230
JB
12737
12738 return 0;
37c73b5f
BG
12739out_err:
12740 spin_unlock_bh(&rdev->beacon_registrations_lock);
12741 kfree(nreg);
12742 return rv;
5e760230
JB
12743}
12744
98104fde
JB
12745static int nl80211_start_p2p_device(struct sk_buff *skb, struct genl_info *info)
12746{
12747 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12748 struct wireless_dev *wdev = info->user_ptr[1];
12749 int err;
12750
12751 if (!rdev->ops->start_p2p_device)
12752 return -EOPNOTSUPP;
12753
12754 if (wdev->iftype != NL80211_IFTYPE_P2P_DEVICE)
12755 return -EOPNOTSUPP;
12756
73c7da3d 12757 if (wdev_running(wdev))
98104fde
JB
12758 return 0;
12759
b6a55015
LC
12760 if (rfkill_blocked(rdev->rfkill))
12761 return -ERFKILL;
98104fde 12762
eeb126e9 12763 err = rdev_start_p2p_device(rdev, wdev);
98104fde
JB
12764 if (err)
12765 return err;
12766
73c7da3d 12767 wdev->is_running = true;
98104fde 12768 rdev->opencount++;
98104fde
JB
12769
12770 return 0;
12771}
12772
12773static int nl80211_stop_p2p_device(struct sk_buff *skb, struct genl_info *info)
12774{
12775 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12776 struct wireless_dev *wdev = info->user_ptr[1];
12777
12778 if (wdev->iftype != NL80211_IFTYPE_P2P_DEVICE)
12779 return -EOPNOTSUPP;
12780
12781 if (!rdev->ops->stop_p2p_device)
12782 return -EOPNOTSUPP;
12783
f9f47529 12784 cfg80211_stop_p2p_device(rdev, wdev);
98104fde
JB
12785
12786 return 0;
12787}
12788
cb3b7d87
AB
12789static int nl80211_start_nan(struct sk_buff *skb, struct genl_info *info)
12790{
12791 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12792 struct wireless_dev *wdev = info->user_ptr[1];
12793 struct cfg80211_nan_conf conf = {};
12794 int err;
12795
12796 if (wdev->iftype != NL80211_IFTYPE_NAN)
12797 return -EOPNOTSUPP;
12798
eeb04a96 12799 if (wdev_running(wdev))
cb3b7d87
AB
12800 return -EEXIST;
12801
12802 if (rfkill_blocked(rdev->rfkill))
12803 return -ERFKILL;
12804
12805 if (!info->attrs[NL80211_ATTR_NAN_MASTER_PREF])
12806 return -EINVAL;
12807
cb3b7d87
AB
12808 conf.master_pref =
12809 nla_get_u8(info->attrs[NL80211_ATTR_NAN_MASTER_PREF]);
cb3b7d87 12810
8585989d
LC
12811 if (info->attrs[NL80211_ATTR_BANDS]) {
12812 u32 bands = nla_get_u32(info->attrs[NL80211_ATTR_BANDS]);
12813
12814 if (bands & ~(u32)wdev->wiphy->nan_supported_bands)
12815 return -EOPNOTSUPP;
12816
12817 if (bands && !(bands & BIT(NL80211_BAND_2GHZ)))
12818 return -EINVAL;
12819
12820 conf.bands = bands;
12821 }
cb3b7d87
AB
12822
12823 err = rdev_start_nan(rdev, wdev, &conf);
12824 if (err)
12825 return err;
12826
73c7da3d 12827 wdev->is_running = true;
cb3b7d87
AB
12828 rdev->opencount++;
12829
12830 return 0;
12831}
12832
12833static int nl80211_stop_nan(struct sk_buff *skb, struct genl_info *info)
12834{
12835 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12836 struct wireless_dev *wdev = info->user_ptr[1];
12837
12838 if (wdev->iftype != NL80211_IFTYPE_NAN)
12839 return -EOPNOTSUPP;
12840
12841 cfg80211_stop_nan(rdev, wdev);
12842
12843 return 0;
12844}
12845
a442b761
AB
12846static int validate_nan_filter(struct nlattr *filter_attr)
12847{
12848 struct nlattr *attr;
12849 int len = 0, n_entries = 0, rem;
12850
12851 nla_for_each_nested(attr, filter_attr, rem) {
12852 len += nla_len(attr);
12853 n_entries++;
12854 }
12855
12856 if (len >= U8_MAX)
12857 return -EINVAL;
12858
12859 return n_entries;
12860}
12861
12862static int handle_nan_filter(struct nlattr *attr_filter,
12863 struct cfg80211_nan_func *func,
12864 bool tx)
12865{
12866 struct nlattr *attr;
12867 int n_entries, rem, i;
12868 struct cfg80211_nan_func_filter *filter;
12869
12870 n_entries = validate_nan_filter(attr_filter);
12871 if (n_entries < 0)
12872 return n_entries;
12873
12874 BUILD_BUG_ON(sizeof(*func->rx_filters) != sizeof(*func->tx_filters));
12875
12876 filter = kcalloc(n_entries, sizeof(*func->rx_filters), GFP_KERNEL);
12877 if (!filter)
12878 return -ENOMEM;
12879
12880 i = 0;
12881 nla_for_each_nested(attr, attr_filter, rem) {
b15ca182 12882 filter[i].filter = nla_memdup(attr, GFP_KERNEL);
a442b761
AB
12883 filter[i].len = nla_len(attr);
12884 i++;
12885 }
12886 if (tx) {
12887 func->num_tx_filters = n_entries;
12888 func->tx_filters = filter;
12889 } else {
12890 func->num_rx_filters = n_entries;
12891 func->rx_filters = filter;
12892 }
12893
12894 return 0;
12895}
12896
12897static int nl80211_nan_add_func(struct sk_buff *skb,
12898 struct genl_info *info)
12899{
12900 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12901 struct wireless_dev *wdev = info->user_ptr[1];
12902 struct nlattr *tb[NUM_NL80211_NAN_FUNC_ATTR], *func_attr;
12903 struct cfg80211_nan_func *func;
12904 struct sk_buff *msg = NULL;
12905 void *hdr = NULL;
12906 int err = 0;
12907
12908 if (wdev->iftype != NL80211_IFTYPE_NAN)
12909 return -EOPNOTSUPP;
12910
73c7da3d 12911 if (!wdev_running(wdev))
a442b761
AB
12912 return -ENOTCONN;
12913
12914 if (!info->attrs[NL80211_ATTR_NAN_FUNC])
12915 return -EINVAL;
12916
8cb08174
JB
12917 err = nla_parse_nested_deprecated(tb, NL80211_NAN_FUNC_ATTR_MAX,
12918 info->attrs[NL80211_ATTR_NAN_FUNC],
12919 nl80211_nan_func_policy,
12920 info->extack);
a442b761
AB
12921 if (err)
12922 return err;
12923
12924 func = kzalloc(sizeof(*func), GFP_KERNEL);
12925 if (!func)
12926 return -ENOMEM;
12927
b60ad348 12928 func->cookie = cfg80211_assign_cookie(rdev);
a442b761 12929
cb9abd48 12930 if (!tb[NL80211_NAN_FUNC_TYPE]) {
a442b761
AB
12931 err = -EINVAL;
12932 goto out;
12933 }
12934
12935
12936 func->type = nla_get_u8(tb[NL80211_NAN_FUNC_TYPE]);
12937
12938 if (!tb[NL80211_NAN_FUNC_SERVICE_ID]) {
12939 err = -EINVAL;
12940 goto out;
12941 }
12942
12943 memcpy(func->service_id, nla_data(tb[NL80211_NAN_FUNC_SERVICE_ID]),
12944 sizeof(func->service_id));
12945
12946 func->close_range =
12947 nla_get_flag(tb[NL80211_NAN_FUNC_CLOSE_RANGE]);
12948
12949 if (tb[NL80211_NAN_FUNC_SERVICE_INFO]) {
12950 func->serv_spec_info_len =
12951 nla_len(tb[NL80211_NAN_FUNC_SERVICE_INFO]);
12952 func->serv_spec_info =
12953 kmemdup(nla_data(tb[NL80211_NAN_FUNC_SERVICE_INFO]),
12954 func->serv_spec_info_len,
12955 GFP_KERNEL);
12956 if (!func->serv_spec_info) {
12957 err = -ENOMEM;
12958 goto out;
12959 }
12960 }
12961
12962 if (tb[NL80211_NAN_FUNC_TTL])
12963 func->ttl = nla_get_u32(tb[NL80211_NAN_FUNC_TTL]);
12964
12965 switch (func->type) {
12966 case NL80211_NAN_FUNC_PUBLISH:
12967 if (!tb[NL80211_NAN_FUNC_PUBLISH_TYPE]) {
12968 err = -EINVAL;
12969 goto out;
12970 }
12971
12972 func->publish_type =
12973 nla_get_u8(tb[NL80211_NAN_FUNC_PUBLISH_TYPE]);
12974 func->publish_bcast =
12975 nla_get_flag(tb[NL80211_NAN_FUNC_PUBLISH_BCAST]);
12976
12977 if ((!(func->publish_type & NL80211_NAN_SOLICITED_PUBLISH)) &&
12978 func->publish_bcast) {
12979 err = -EINVAL;
12980 goto out;
12981 }
12982 break;
12983 case NL80211_NAN_FUNC_SUBSCRIBE:
12984 func->subscribe_active =
12985 nla_get_flag(tb[NL80211_NAN_FUNC_SUBSCRIBE_ACTIVE]);
12986 break;
12987 case NL80211_NAN_FUNC_FOLLOW_UP:
12988 if (!tb[NL80211_NAN_FUNC_FOLLOW_UP_ID] ||
3ea15452
HC
12989 !tb[NL80211_NAN_FUNC_FOLLOW_UP_REQ_ID] ||
12990 !tb[NL80211_NAN_FUNC_FOLLOW_UP_DEST]) {
a442b761
AB
12991 err = -EINVAL;
12992 goto out;
12993 }
12994
12995 func->followup_id =
12996 nla_get_u8(tb[NL80211_NAN_FUNC_FOLLOW_UP_ID]);
12997 func->followup_reqid =
12998 nla_get_u8(tb[NL80211_NAN_FUNC_FOLLOW_UP_REQ_ID]);
12999 memcpy(func->followup_dest.addr,
13000 nla_data(tb[NL80211_NAN_FUNC_FOLLOW_UP_DEST]),
13001 sizeof(func->followup_dest.addr));
13002 if (func->ttl) {
13003 err = -EINVAL;
13004 goto out;
13005 }
13006 break;
13007 default:
13008 err = -EINVAL;
13009 goto out;
13010 }
13011
13012 if (tb[NL80211_NAN_FUNC_SRF]) {
13013 struct nlattr *srf_tb[NUM_NL80211_NAN_SRF_ATTR];
13014
8cb08174
JB
13015 err = nla_parse_nested_deprecated(srf_tb,
13016 NL80211_NAN_SRF_ATTR_MAX,
13017 tb[NL80211_NAN_FUNC_SRF],
13018 nl80211_nan_srf_policy,
13019 info->extack);
a442b761
AB
13020 if (err)
13021 goto out;
13022
13023 func->srf_include =
13024 nla_get_flag(srf_tb[NL80211_NAN_SRF_INCLUDE]);
13025
13026 if (srf_tb[NL80211_NAN_SRF_BF]) {
13027 if (srf_tb[NL80211_NAN_SRF_MAC_ADDRS] ||
13028 !srf_tb[NL80211_NAN_SRF_BF_IDX]) {
13029 err = -EINVAL;
13030 goto out;
13031 }
13032
13033 func->srf_bf_len =
13034 nla_len(srf_tb[NL80211_NAN_SRF_BF]);
13035 func->srf_bf =
13036 kmemdup(nla_data(srf_tb[NL80211_NAN_SRF_BF]),
13037 func->srf_bf_len, GFP_KERNEL);
13038 if (!func->srf_bf) {
13039 err = -ENOMEM;
13040 goto out;
13041 }
13042
13043 func->srf_bf_idx =
13044 nla_get_u8(srf_tb[NL80211_NAN_SRF_BF_IDX]);
13045 } else {
13046 struct nlattr *attr, *mac_attr =
13047 srf_tb[NL80211_NAN_SRF_MAC_ADDRS];
13048 int n_entries, rem, i = 0;
13049
13050 if (!mac_attr) {
13051 err = -EINVAL;
13052 goto out;
13053 }
13054
13055 n_entries = validate_acl_mac_addrs(mac_attr);
13056 if (n_entries <= 0) {
13057 err = -EINVAL;
13058 goto out;
13059 }
13060
13061 func->srf_num_macs = n_entries;
13062 func->srf_macs =
6396bb22 13063 kcalloc(n_entries, sizeof(*func->srf_macs),
a442b761
AB
13064 GFP_KERNEL);
13065 if (!func->srf_macs) {
13066 err = -ENOMEM;
13067 goto out;
13068 }
13069
13070 nla_for_each_nested(attr, mac_attr, rem)
13071 memcpy(func->srf_macs[i++].addr, nla_data(attr),
13072 sizeof(*func->srf_macs));
13073 }
13074 }
13075
13076 if (tb[NL80211_NAN_FUNC_TX_MATCH_FILTER]) {
13077 err = handle_nan_filter(tb[NL80211_NAN_FUNC_TX_MATCH_FILTER],
13078 func, true);
13079 if (err)
13080 goto out;
13081 }
13082
13083 if (tb[NL80211_NAN_FUNC_RX_MATCH_FILTER]) {
13084 err = handle_nan_filter(tb[NL80211_NAN_FUNC_RX_MATCH_FILTER],
13085 func, false);
13086 if (err)
13087 goto out;
13088 }
13089
13090 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
13091 if (!msg) {
13092 err = -ENOMEM;
13093 goto out;
13094 }
13095
13096 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
13097 NL80211_CMD_ADD_NAN_FUNCTION);
13098 /* This can't really happen - we just allocated 4KB */
13099 if (WARN_ON(!hdr)) {
13100 err = -ENOMEM;
13101 goto out;
13102 }
13103
13104 err = rdev_add_nan_func(rdev, wdev, func);
13105out:
13106 if (err < 0) {
13107 cfg80211_free_nan_func(func);
13108 nlmsg_free(msg);
13109 return err;
13110 }
13111
13112 /* propagate the instance id and cookie to userspace */
13113 if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, func->cookie,
13114 NL80211_ATTR_PAD))
13115 goto nla_put_failure;
13116
ae0be8de 13117 func_attr = nla_nest_start_noflag(msg, NL80211_ATTR_NAN_FUNC);
a442b761
AB
13118 if (!func_attr)
13119 goto nla_put_failure;
13120
13121 if (nla_put_u8(msg, NL80211_NAN_FUNC_INSTANCE_ID,
13122 func->instance_id))
13123 goto nla_put_failure;
13124
13125 nla_nest_end(msg, func_attr);
13126
13127 genlmsg_end(msg, hdr);
13128 return genlmsg_reply(msg, info);
13129
13130nla_put_failure:
13131 nlmsg_free(msg);
13132 return -ENOBUFS;
13133}
13134
13135static int nl80211_nan_del_func(struct sk_buff *skb,
13136 struct genl_info *info)
13137{
13138 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13139 struct wireless_dev *wdev = info->user_ptr[1];
13140 u64 cookie;
13141
13142 if (wdev->iftype != NL80211_IFTYPE_NAN)
13143 return -EOPNOTSUPP;
13144
73c7da3d 13145 if (!wdev_running(wdev))
a442b761
AB
13146 return -ENOTCONN;
13147
13148 if (!info->attrs[NL80211_ATTR_COOKIE])
13149 return -EINVAL;
13150
a442b761
AB
13151 cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);
13152
13153 rdev_del_nan_func(rdev, wdev, cookie);
13154
13155 return 0;
13156}
13157
a5a9dcf2
AB
13158static int nl80211_nan_change_config(struct sk_buff *skb,
13159 struct genl_info *info)
13160{
13161 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13162 struct wireless_dev *wdev = info->user_ptr[1];
13163 struct cfg80211_nan_conf conf = {};
13164 u32 changed = 0;
13165
13166 if (wdev->iftype != NL80211_IFTYPE_NAN)
13167 return -EOPNOTSUPP;
13168
73c7da3d 13169 if (!wdev_running(wdev))
a5a9dcf2
AB
13170 return -ENOTCONN;
13171
13172 if (info->attrs[NL80211_ATTR_NAN_MASTER_PREF]) {
13173 conf.master_pref =
13174 nla_get_u8(info->attrs[NL80211_ATTR_NAN_MASTER_PREF]);
13175 if (conf.master_pref <= 1 || conf.master_pref == 255)
13176 return -EINVAL;
13177
13178 changed |= CFG80211_NAN_CONF_CHANGED_PREF;
13179 }
13180
8585989d
LC
13181 if (info->attrs[NL80211_ATTR_BANDS]) {
13182 u32 bands = nla_get_u32(info->attrs[NL80211_ATTR_BANDS]);
13183
13184 if (bands & ~(u32)wdev->wiphy->nan_supported_bands)
13185 return -EOPNOTSUPP;
13186
13187 if (bands && !(bands & BIT(NL80211_BAND_2GHZ)))
13188 return -EINVAL;
13189
13190 conf.bands = bands;
13191 changed |= CFG80211_NAN_CONF_CHANGED_BANDS;
a5a9dcf2
AB
13192 }
13193
13194 if (!changed)
13195 return -EINVAL;
13196
13197 return rdev_nan_change_conf(rdev, wdev, &conf, changed);
13198}
13199
50bcd31d
AB
13200void cfg80211_nan_match(struct wireless_dev *wdev,
13201 struct cfg80211_nan_match_params *match, gfp_t gfp)
13202{
13203 struct wiphy *wiphy = wdev->wiphy;
13204 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
13205 struct nlattr *match_attr, *local_func_attr, *peer_func_attr;
13206 struct sk_buff *msg;
13207 void *hdr;
13208
13209 if (WARN_ON(!match->inst_id || !match->peer_inst_id || !match->addr))
13210 return;
13211
13212 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
13213 if (!msg)
13214 return;
13215
13216 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NAN_MATCH);
13217 if (!hdr) {
13218 nlmsg_free(msg);
13219 return;
13220 }
13221
13222 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
13223 (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
13224 wdev->netdev->ifindex)) ||
13225 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
13226 NL80211_ATTR_PAD))
13227 goto nla_put_failure;
13228
13229 if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, match->cookie,
13230 NL80211_ATTR_PAD) ||
13231 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, match->addr))
13232 goto nla_put_failure;
13233
ae0be8de 13234 match_attr = nla_nest_start_noflag(msg, NL80211_ATTR_NAN_MATCH);
50bcd31d
AB
13235 if (!match_attr)
13236 goto nla_put_failure;
13237
ae0be8de
MK
13238 local_func_attr = nla_nest_start_noflag(msg,
13239 NL80211_NAN_MATCH_FUNC_LOCAL);
50bcd31d
AB
13240 if (!local_func_attr)
13241 goto nla_put_failure;
13242
13243 if (nla_put_u8(msg, NL80211_NAN_FUNC_INSTANCE_ID, match->inst_id))
13244 goto nla_put_failure;
13245
13246 nla_nest_end(msg, local_func_attr);
13247
ae0be8de
MK
13248 peer_func_attr = nla_nest_start_noflag(msg,
13249 NL80211_NAN_MATCH_FUNC_PEER);
50bcd31d
AB
13250 if (!peer_func_attr)
13251 goto nla_put_failure;
13252
13253 if (nla_put_u8(msg, NL80211_NAN_FUNC_TYPE, match->type) ||
13254 nla_put_u8(msg, NL80211_NAN_FUNC_INSTANCE_ID, match->peer_inst_id))
13255 goto nla_put_failure;
13256
13257 if (match->info && match->info_len &&
13258 nla_put(msg, NL80211_NAN_FUNC_SERVICE_INFO, match->info_len,
13259 match->info))
13260 goto nla_put_failure;
13261
13262 nla_nest_end(msg, peer_func_attr);
13263 nla_nest_end(msg, match_attr);
13264 genlmsg_end(msg, hdr);
13265
13266 if (!wdev->owner_nlportid)
13267 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
13268 msg, 0, NL80211_MCGRP_NAN, gfp);
13269 else
13270 genlmsg_unicast(wiphy_net(&rdev->wiphy), msg,
13271 wdev->owner_nlportid);
13272
13273 return;
13274
13275nla_put_failure:
13276 nlmsg_free(msg);
13277}
13278EXPORT_SYMBOL(cfg80211_nan_match);
13279
368e5a7b
AB
13280void cfg80211_nan_func_terminated(struct wireless_dev *wdev,
13281 u8 inst_id,
13282 enum nl80211_nan_func_term_reason reason,
13283 u64 cookie, gfp_t gfp)
13284{
13285 struct wiphy *wiphy = wdev->wiphy;
13286 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
13287 struct sk_buff *msg;
13288 struct nlattr *func_attr;
13289 void *hdr;
13290
13291 if (WARN_ON(!inst_id))
13292 return;
13293
13294 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
13295 if (!msg)
13296 return;
13297
13298 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_DEL_NAN_FUNCTION);
13299 if (!hdr) {
13300 nlmsg_free(msg);
13301 return;
13302 }
13303
13304 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
13305 (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
13306 wdev->netdev->ifindex)) ||
13307 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
13308 NL80211_ATTR_PAD))
13309 goto nla_put_failure;
13310
13311 if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
13312 NL80211_ATTR_PAD))
13313 goto nla_put_failure;
13314
ae0be8de 13315 func_attr = nla_nest_start_noflag(msg, NL80211_ATTR_NAN_FUNC);
368e5a7b
AB
13316 if (!func_attr)
13317 goto nla_put_failure;
13318
13319 if (nla_put_u8(msg, NL80211_NAN_FUNC_INSTANCE_ID, inst_id) ||
13320 nla_put_u8(msg, NL80211_NAN_FUNC_TERM_REASON, reason))
13321 goto nla_put_failure;
13322
13323 nla_nest_end(msg, func_attr);
13324 genlmsg_end(msg, hdr);
13325
13326 if (!wdev->owner_nlportid)
13327 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
13328 msg, 0, NL80211_MCGRP_NAN, gfp);
13329 else
13330 genlmsg_unicast(wiphy_net(&rdev->wiphy), msg,
13331 wdev->owner_nlportid);
13332
13333 return;
13334
13335nla_put_failure:
13336 nlmsg_free(msg);
13337}
13338EXPORT_SYMBOL(cfg80211_nan_func_terminated);
13339
3713b4e3
JB
13340static int nl80211_get_protocol_features(struct sk_buff *skb,
13341 struct genl_info *info)
13342{
13343 void *hdr;
13344 struct sk_buff *msg;
13345
13346 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
13347 if (!msg)
13348 return -ENOMEM;
13349
13350 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
13351 NL80211_CMD_GET_PROTOCOL_FEATURES);
13352 if (!hdr)
13353 goto nla_put_failure;
13354
13355 if (nla_put_u32(msg, NL80211_ATTR_PROTOCOL_FEATURES,
13356 NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP))
13357 goto nla_put_failure;
13358
13359 genlmsg_end(msg, hdr);
13360 return genlmsg_reply(msg, info);
13361
13362 nla_put_failure:
13363 kfree_skb(msg);
13364 return -ENOBUFS;
13365}
13366
355199e0
JM
13367static int nl80211_update_ft_ies(struct sk_buff *skb, struct genl_info *info)
13368{
13369 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13370 struct cfg80211_update_ft_ies_params ft_params;
13371 struct net_device *dev = info->user_ptr[1];
13372
13373 if (!rdev->ops->update_ft_ies)
13374 return -EOPNOTSUPP;
13375
13376 if (!info->attrs[NL80211_ATTR_MDID] ||
3d7af878 13377 !info->attrs[NL80211_ATTR_IE])
355199e0
JM
13378 return -EINVAL;
13379
13380 memset(&ft_params, 0, sizeof(ft_params));
13381 ft_params.md = nla_get_u16(info->attrs[NL80211_ATTR_MDID]);
13382 ft_params.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
13383 ft_params.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
13384
13385 return rdev_update_ft_ies(rdev, dev, &ft_params);
13386}
13387
5de17984
AS
13388static int nl80211_crit_protocol_start(struct sk_buff *skb,
13389 struct genl_info *info)
13390{
13391 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13392 struct wireless_dev *wdev = info->user_ptr[1];
13393 enum nl80211_crit_proto_id proto = NL80211_CRIT_PROTO_UNSPEC;
13394 u16 duration;
13395 int ret;
13396
13397 if (!rdev->ops->crit_proto_start)
13398 return -EOPNOTSUPP;
13399
13400 if (WARN_ON(!rdev->ops->crit_proto_stop))
13401 return -EINVAL;
13402
13403 if (rdev->crit_proto_nlportid)
13404 return -EBUSY;
13405
13406 /* determine protocol if provided */
13407 if (info->attrs[NL80211_ATTR_CRIT_PROT_ID])
13408 proto = nla_get_u16(info->attrs[NL80211_ATTR_CRIT_PROT_ID]);
13409
13410 if (proto >= NUM_NL80211_CRIT_PROTO)
13411 return -EINVAL;
13412
13413 /* timeout must be provided */
13414 if (!info->attrs[NL80211_ATTR_MAX_CRIT_PROT_DURATION])
13415 return -EINVAL;
13416
13417 duration =
13418 nla_get_u16(info->attrs[NL80211_ATTR_MAX_CRIT_PROT_DURATION]);
13419
5de17984
AS
13420 ret = rdev_crit_proto_start(rdev, wdev, proto, duration);
13421 if (!ret)
13422 rdev->crit_proto_nlportid = info->snd_portid;
13423
13424 return ret;
13425}
13426
13427static int nl80211_crit_protocol_stop(struct sk_buff *skb,
13428 struct genl_info *info)
13429{
13430 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13431 struct wireless_dev *wdev = info->user_ptr[1];
13432
13433 if (!rdev->ops->crit_proto_stop)
13434 return -EOPNOTSUPP;
13435
13436 if (rdev->crit_proto_nlportid) {
13437 rdev->crit_proto_nlportid = 0;
13438 rdev_crit_proto_stop(rdev, wdev);
13439 }
13440 return 0;
13441}
13442
901bb989
JB
13443static int nl80211_vendor_check_policy(const struct wiphy_vendor_command *vcmd,
13444 struct nlattr *attr,
13445 struct netlink_ext_ack *extack)
13446{
13447 if (vcmd->policy == VENDOR_CMD_RAW_DATA) {
13448 if (attr->nla_type & NLA_F_NESTED) {
13449 NL_SET_ERR_MSG_ATTR(extack, attr,
13450 "unexpected nested data");
13451 return -EINVAL;
13452 }
13453
13454 return 0;
13455 }
13456
13457 if (!(attr->nla_type & NLA_F_NESTED)) {
13458 NL_SET_ERR_MSG_ATTR(extack, attr, "expected nested data");
13459 return -EINVAL;
13460 }
13461
32d5109a 13462 return nla_validate_nested(attr, vcmd->maxattr, vcmd->policy, extack);
901bb989
JB
13463}
13464
ad7e718c
JB
13465static int nl80211_vendor_cmd(struct sk_buff *skb, struct genl_info *info)
13466{
13467 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13468 struct wireless_dev *wdev =
13469 __cfg80211_wdev_from_attrs(genl_info_net(info), info->attrs);
13470 int i, err;
13471 u32 vid, subcmd;
13472
13473 if (!rdev->wiphy.vendor_commands)
13474 return -EOPNOTSUPP;
13475
13476 if (IS_ERR(wdev)) {
13477 err = PTR_ERR(wdev);
13478 if (err != -EINVAL)
13479 return err;
13480 wdev = NULL;
13481 } else if (wdev->wiphy != &rdev->wiphy) {
13482 return -EINVAL;
13483 }
13484
13485 if (!info->attrs[NL80211_ATTR_VENDOR_ID] ||
13486 !info->attrs[NL80211_ATTR_VENDOR_SUBCMD])
13487 return -EINVAL;
13488
13489 vid = nla_get_u32(info->attrs[NL80211_ATTR_VENDOR_ID]);
13490 subcmd = nla_get_u32(info->attrs[NL80211_ATTR_VENDOR_SUBCMD]);
13491 for (i = 0; i < rdev->wiphy.n_vendor_commands; i++) {
13492 const struct wiphy_vendor_command *vcmd;
13493 void *data = NULL;
13494 int len = 0;
13495
13496 vcmd = &rdev->wiphy.vendor_commands[i];
13497
13498 if (vcmd->info.vendor_id != vid || vcmd->info.subcmd != subcmd)
13499 continue;
13500
13501 if (vcmd->flags & (WIPHY_VENDOR_CMD_NEED_WDEV |
13502 WIPHY_VENDOR_CMD_NEED_NETDEV)) {
13503 if (!wdev)
13504 return -EINVAL;
13505 if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_NETDEV &&
13506 !wdev->netdev)
13507 return -EINVAL;
13508
13509 if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_RUNNING) {
73c7da3d 13510 if (!wdev_running(wdev))
ad7e718c
JB
13511 return -ENETDOWN;
13512 }
13513 } else {
13514 wdev = NULL;
13515 }
13516
4052d3d2
JS
13517 if (!vcmd->doit)
13518 return -EOPNOTSUPP;
13519
ad7e718c
JB
13520 if (info->attrs[NL80211_ATTR_VENDOR_DATA]) {
13521 data = nla_data(info->attrs[NL80211_ATTR_VENDOR_DATA]);
13522 len = nla_len(info->attrs[NL80211_ATTR_VENDOR_DATA]);
901bb989
JB
13523
13524 err = nl80211_vendor_check_policy(vcmd,
13525 info->attrs[NL80211_ATTR_VENDOR_DATA],
13526 info->extack);
13527 if (err)
13528 return err;
ad7e718c
JB
13529 }
13530
13531 rdev->cur_cmd_info = info;
901bb989 13532 err = vcmd->doit(&rdev->wiphy, wdev, data, len);
ad7e718c
JB
13533 rdev->cur_cmd_info = NULL;
13534 return err;
13535 }
13536
13537 return -EOPNOTSUPP;
13538}
13539
7bdbe400
JB
13540static int nl80211_prepare_vendor_dump(struct sk_buff *skb,
13541 struct netlink_callback *cb,
13542 struct cfg80211_registered_device **rdev,
13543 struct wireless_dev **wdev)
13544{
50508d94 13545 struct nlattr **attrbuf;
7bdbe400
JB
13546 u32 vid, subcmd;
13547 unsigned int i;
13548 int vcmd_idx = -1;
13549 int err;
13550 void *data = NULL;
13551 unsigned int data_len = 0;
13552
7bdbe400
JB
13553 if (cb->args[0]) {
13554 /* subtract the 1 again here */
13555 struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0] - 1);
13556 struct wireless_dev *tmp;
13557
ea90e0dc
JB
13558 if (!wiphy)
13559 return -ENODEV;
7bdbe400
JB
13560 *rdev = wiphy_to_rdev(wiphy);
13561 *wdev = NULL;
13562
13563 if (cb->args[1]) {
53873f13 13564 list_for_each_entry(tmp, &wiphy->wdev_list, list) {
7bdbe400
JB
13565 if (tmp->identifier == cb->args[1] - 1) {
13566 *wdev = tmp;
13567 break;
13568 }
13569 }
13570 }
13571
13572 /* keep rtnl locked in successful case */
13573 return 0;
13574 }
13575
50508d94
JB
13576 attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf), GFP_KERNEL);
13577 if (!attrbuf)
13578 return -ENOMEM;
13579
8cb08174
JB
13580 err = nlmsg_parse_deprecated(cb->nlh,
13581 GENL_HDRLEN + nl80211_fam.hdrsize,
13582 attrbuf, nl80211_fam.maxattr,
13583 nl80211_policy, NULL);
7bdbe400 13584 if (err)
50508d94 13585 goto out;
7bdbe400 13586
c90c39da 13587 if (!attrbuf[NL80211_ATTR_VENDOR_ID] ||
50508d94
JB
13588 !attrbuf[NL80211_ATTR_VENDOR_SUBCMD]) {
13589 err = -EINVAL;
13590 goto out;
13591 }
7bdbe400 13592
c90c39da 13593 *wdev = __cfg80211_wdev_from_attrs(sock_net(skb->sk), attrbuf);
7bdbe400
JB
13594 if (IS_ERR(*wdev))
13595 *wdev = NULL;
13596
c90c39da 13597 *rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk), attrbuf);
50508d94
JB
13598 if (IS_ERR(*rdev)) {
13599 err = PTR_ERR(*rdev);
13600 goto out;
13601 }
7bdbe400 13602
c90c39da
JB
13603 vid = nla_get_u32(attrbuf[NL80211_ATTR_VENDOR_ID]);
13604 subcmd = nla_get_u32(attrbuf[NL80211_ATTR_VENDOR_SUBCMD]);
7bdbe400
JB
13605
13606 for (i = 0; i < (*rdev)->wiphy.n_vendor_commands; i++) {
13607 const struct wiphy_vendor_command *vcmd;
13608
13609 vcmd = &(*rdev)->wiphy.vendor_commands[i];
13610
13611 if (vcmd->info.vendor_id != vid || vcmd->info.subcmd != subcmd)
13612 continue;
13613
50508d94
JB
13614 if (!vcmd->dumpit) {
13615 err = -EOPNOTSUPP;
13616 goto out;
13617 }
7bdbe400
JB
13618
13619 vcmd_idx = i;
13620 break;
13621 }
13622
50508d94
JB
13623 if (vcmd_idx < 0) {
13624 err = -EOPNOTSUPP;
13625 goto out;
13626 }
7bdbe400 13627
c90c39da
JB
13628 if (attrbuf[NL80211_ATTR_VENDOR_DATA]) {
13629 data = nla_data(attrbuf[NL80211_ATTR_VENDOR_DATA]);
13630 data_len = nla_len(attrbuf[NL80211_ATTR_VENDOR_DATA]);
901bb989
JB
13631
13632 err = nl80211_vendor_check_policy(
13633 &(*rdev)->wiphy.vendor_commands[vcmd_idx],
13634 attrbuf[NL80211_ATTR_VENDOR_DATA],
13635 cb->extack);
13636 if (err)
50508d94 13637 goto out;
7bdbe400
JB
13638 }
13639
13640 /* 0 is the first index - add 1 to parse only once */
13641 cb->args[0] = (*rdev)->wiphy_idx + 1;
13642 /* add 1 to know if it was NULL */
13643 cb->args[1] = *wdev ? (*wdev)->identifier + 1 : 0;
13644 cb->args[2] = vcmd_idx;
13645 cb->args[3] = (unsigned long)data;
13646 cb->args[4] = data_len;
13647
13648 /* keep rtnl locked in successful case */
50508d94
JB
13649 err = 0;
13650out:
13651 kfree(attrbuf);
13652 return err;
7bdbe400
JB
13653}
13654
13655static int nl80211_vendor_cmd_dump(struct sk_buff *skb,
13656 struct netlink_callback *cb)
13657{
13658 struct cfg80211_registered_device *rdev;
13659 struct wireless_dev *wdev;
13660 unsigned int vcmd_idx;
13661 const struct wiphy_vendor_command *vcmd;
13662 void *data;
13663 int data_len;
13664 int err;
13665 struct nlattr *vendor_data;
13666
ea90e0dc 13667 rtnl_lock();
7bdbe400
JB
13668 err = nl80211_prepare_vendor_dump(skb, cb, &rdev, &wdev);
13669 if (err)
ea90e0dc 13670 goto out;
7bdbe400
JB
13671
13672 vcmd_idx = cb->args[2];
13673 data = (void *)cb->args[3];
13674 data_len = cb->args[4];
13675 vcmd = &rdev->wiphy.vendor_commands[vcmd_idx];
13676
13677 if (vcmd->flags & (WIPHY_VENDOR_CMD_NEED_WDEV |
13678 WIPHY_VENDOR_CMD_NEED_NETDEV)) {
ea90e0dc
JB
13679 if (!wdev) {
13680 err = -EINVAL;
13681 goto out;
13682 }
7bdbe400 13683 if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_NETDEV &&
ea90e0dc
JB
13684 !wdev->netdev) {
13685 err = -EINVAL;
13686 goto out;
13687 }
7bdbe400
JB
13688
13689 if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_RUNNING) {
ea90e0dc
JB
13690 if (!wdev_running(wdev)) {
13691 err = -ENETDOWN;
13692 goto out;
13693 }
7bdbe400
JB
13694 }
13695 }
13696
13697 while (1) {
13698 void *hdr = nl80211hdr_put(skb, NETLINK_CB(cb->skb).portid,
13699 cb->nlh->nlmsg_seq, NLM_F_MULTI,
13700 NL80211_CMD_VENDOR);
13701 if (!hdr)
13702 break;
13703
13704 if (nla_put_u32(skb, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
2dad624e
ND
13705 (wdev && nla_put_u64_64bit(skb, NL80211_ATTR_WDEV,
13706 wdev_id(wdev),
13707 NL80211_ATTR_PAD))) {
7bdbe400
JB
13708 genlmsg_cancel(skb, hdr);
13709 break;
13710 }
13711
ae0be8de
MK
13712 vendor_data = nla_nest_start_noflag(skb,
13713 NL80211_ATTR_VENDOR_DATA);
7bdbe400
JB
13714 if (!vendor_data) {
13715 genlmsg_cancel(skb, hdr);
13716 break;
13717 }
13718
13719 err = vcmd->dumpit(&rdev->wiphy, wdev, skb, data, data_len,
13720 (unsigned long *)&cb->args[5]);
13721 nla_nest_end(skb, vendor_data);
13722
13723 if (err == -ENOBUFS || err == -ENOENT) {
13724 genlmsg_cancel(skb, hdr);
13725 break;
9c167b2d 13726 } else if (err <= 0) {
7bdbe400
JB
13727 genlmsg_cancel(skb, hdr);
13728 goto out;
13729 }
13730
13731 genlmsg_end(skb, hdr);
13732 }
13733
13734 err = skb->len;
13735 out:
13736 rtnl_unlock();
13737 return err;
13738}
13739
ad7e718c
JB
13740struct sk_buff *__cfg80211_alloc_reply_skb(struct wiphy *wiphy,
13741 enum nl80211_commands cmd,
13742 enum nl80211_attrs attr,
13743 int approxlen)
13744{
f26cbf40 13745 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
ad7e718c
JB
13746
13747 if (WARN_ON(!rdev->cur_cmd_info))
13748 return NULL;
13749
6c09e791 13750 return __cfg80211_alloc_vendor_skb(rdev, NULL, approxlen,
ad7e718c
JB
13751 rdev->cur_cmd_info->snd_portid,
13752 rdev->cur_cmd_info->snd_seq,
567ffc35 13753 cmd, attr, NULL, GFP_KERNEL);
ad7e718c
JB
13754}
13755EXPORT_SYMBOL(__cfg80211_alloc_reply_skb);
13756
13757int cfg80211_vendor_cmd_reply(struct sk_buff *skb)
13758{
13759 struct cfg80211_registered_device *rdev = ((void **)skb->cb)[0];
13760 void *hdr = ((void **)skb->cb)[1];
13761 struct nlattr *data = ((void **)skb->cb)[2];
13762
bd8c78e7
JB
13763 /* clear CB data for netlink core to own from now on */
13764 memset(skb->cb, 0, sizeof(skb->cb));
13765
ad7e718c
JB
13766 if (WARN_ON(!rdev->cur_cmd_info)) {
13767 kfree_skb(skb);
13768 return -EINVAL;
13769 }
13770
13771 nla_nest_end(skb, data);
13772 genlmsg_end(skb, hdr);
13773 return genlmsg_reply(skb, rdev->cur_cmd_info);
13774}
13775EXPORT_SYMBOL_GPL(cfg80211_vendor_cmd_reply);
13776
55c1fdf0
JB
13777unsigned int cfg80211_vendor_cmd_get_sender(struct wiphy *wiphy)
13778{
13779 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
13780
13781 if (WARN_ON(!rdev->cur_cmd_info))
13782 return 0;
13783
13784 return rdev->cur_cmd_info->snd_portid;
13785}
13786EXPORT_SYMBOL_GPL(cfg80211_vendor_cmd_get_sender);
13787
fa9ffc74
KP
13788static int nl80211_set_qos_map(struct sk_buff *skb,
13789 struct genl_info *info)
13790{
13791 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13792 struct cfg80211_qos_map *qos_map = NULL;
13793 struct net_device *dev = info->user_ptr[1];
13794 u8 *pos, len, num_des, des_len, des;
13795 int ret;
13796
13797 if (!rdev->ops->set_qos_map)
13798 return -EOPNOTSUPP;
13799
13800 if (info->attrs[NL80211_ATTR_QOS_MAP]) {
13801 pos = nla_data(info->attrs[NL80211_ATTR_QOS_MAP]);
13802 len = nla_len(info->attrs[NL80211_ATTR_QOS_MAP]);
13803
c8b82802 13804 if (len % 2)
fa9ffc74
KP
13805 return -EINVAL;
13806
13807 qos_map = kzalloc(sizeof(struct cfg80211_qos_map), GFP_KERNEL);
13808 if (!qos_map)
13809 return -ENOMEM;
13810
13811 num_des = (len - IEEE80211_QOS_MAP_LEN_MIN) >> 1;
13812 if (num_des) {
13813 des_len = num_des *
13814 sizeof(struct cfg80211_dscp_exception);
13815 memcpy(qos_map->dscp_exception, pos, des_len);
13816 qos_map->num_des = num_des;
13817 for (des = 0; des < num_des; des++) {
13818 if (qos_map->dscp_exception[des].up > 7) {
13819 kfree(qos_map);
13820 return -EINVAL;
13821 }
13822 }
13823 pos += des_len;
13824 }
13825 memcpy(qos_map->up, pos, IEEE80211_QOS_MAP_LEN_MIN);
13826 }
13827
13828 wdev_lock(dev->ieee80211_ptr);
13829 ret = nl80211_key_allowed(dev->ieee80211_ptr);
13830 if (!ret)
13831 ret = rdev_set_qos_map(rdev, dev, qos_map);
13832 wdev_unlock(dev->ieee80211_ptr);
13833
13834 kfree(qos_map);
13835 return ret;
13836}
13837
960d01ac
JB
13838static int nl80211_add_tx_ts(struct sk_buff *skb, struct genl_info *info)
13839{
13840 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13841 struct net_device *dev = info->user_ptr[1];
13842 struct wireless_dev *wdev = dev->ieee80211_ptr;
13843 const u8 *peer;
13844 u8 tsid, up;
13845 u16 admitted_time = 0;
13846 int err;
13847
723e73ac 13848 if (!(rdev->wiphy.features & NL80211_FEATURE_SUPPORTS_WMM_ADMISSION))
960d01ac
JB
13849 return -EOPNOTSUPP;
13850
13851 if (!info->attrs[NL80211_ATTR_TSID] || !info->attrs[NL80211_ATTR_MAC] ||
13852 !info->attrs[NL80211_ATTR_USER_PRIO])
13853 return -EINVAL;
13854
13855 tsid = nla_get_u8(info->attrs[NL80211_ATTR_TSID]);
960d01ac 13856 up = nla_get_u8(info->attrs[NL80211_ATTR_USER_PRIO]);
960d01ac
JB
13857
13858 /* WMM uses TIDs 0-7 even for TSPEC */
723e73ac 13859 if (tsid >= IEEE80211_FIRST_TSPEC_TSID) {
960d01ac 13860 /* TODO: handle 802.11 TSPEC/admission control
723e73ac
JB
13861 * need more attributes for that (e.g. BA session requirement);
13862 * change the WMM adminssion test above to allow both then
960d01ac
JB
13863 */
13864 return -EINVAL;
13865 }
13866
13867 peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
13868
13869 if (info->attrs[NL80211_ATTR_ADMITTED_TIME]) {
13870 admitted_time =
13871 nla_get_u16(info->attrs[NL80211_ATTR_ADMITTED_TIME]);
13872 if (!admitted_time)
13873 return -EINVAL;
13874 }
13875
13876 wdev_lock(wdev);
13877 switch (wdev->iftype) {
13878 case NL80211_IFTYPE_STATION:
13879 case NL80211_IFTYPE_P2P_CLIENT:
13880 if (wdev->current_bss)
13881 break;
13882 err = -ENOTCONN;
13883 goto out;
13884 default:
13885 err = -EOPNOTSUPP;
13886 goto out;
13887 }
13888
13889 err = rdev_add_tx_ts(rdev, dev, tsid, peer, up, admitted_time);
13890
13891 out:
13892 wdev_unlock(wdev);
13893 return err;
13894}
13895
13896static int nl80211_del_tx_ts(struct sk_buff *skb, struct genl_info *info)
13897{
13898 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13899 struct net_device *dev = info->user_ptr[1];
13900 struct wireless_dev *wdev = dev->ieee80211_ptr;
13901 const u8 *peer;
13902 u8 tsid;
13903 int err;
13904
13905 if (!info->attrs[NL80211_ATTR_TSID] || !info->attrs[NL80211_ATTR_MAC])
13906 return -EINVAL;
13907
13908 tsid = nla_get_u8(info->attrs[NL80211_ATTR_TSID]);
13909 peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
13910
13911 wdev_lock(wdev);
13912 err = rdev_del_tx_ts(rdev, dev, tsid, peer);
13913 wdev_unlock(wdev);
13914
13915 return err;
13916}
13917
1057d35e
AN
13918static int nl80211_tdls_channel_switch(struct sk_buff *skb,
13919 struct genl_info *info)
13920{
13921 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13922 struct net_device *dev = info->user_ptr[1];
13923 struct wireless_dev *wdev = dev->ieee80211_ptr;
13924 struct cfg80211_chan_def chandef = {};
13925 const u8 *addr;
13926 u8 oper_class;
13927 int err;
13928
13929 if (!rdev->ops->tdls_channel_switch ||
13930 !(rdev->wiphy.features & NL80211_FEATURE_TDLS_CHANNEL_SWITCH))
13931 return -EOPNOTSUPP;
13932
13933 switch (dev->ieee80211_ptr->iftype) {
13934 case NL80211_IFTYPE_STATION:
13935 case NL80211_IFTYPE_P2P_CLIENT:
13936 break;
13937 default:
13938 return -EOPNOTSUPP;
13939 }
13940
13941 if (!info->attrs[NL80211_ATTR_MAC] ||
13942 !info->attrs[NL80211_ATTR_OPER_CLASS])
13943 return -EINVAL;
13944
13945 err = nl80211_parse_chandef(rdev, info, &chandef);
13946 if (err)
13947 return err;
13948
13949 /*
13950 * Don't allow wide channels on the 2.4Ghz band, as per IEEE802.11-2012
13951 * section 10.22.6.2.1. Disallow 5/10Mhz channels as well for now, the
13952 * specification is not defined for them.
13953 */
57fbcce3 13954 if (chandef.chan->band == NL80211_BAND_2GHZ &&
1057d35e
AN
13955 chandef.width != NL80211_CHAN_WIDTH_20_NOHT &&
13956 chandef.width != NL80211_CHAN_WIDTH_20)
13957 return -EINVAL;
13958
13959 /* we will be active on the TDLS link */
923b352f
AN
13960 if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &chandef,
13961 wdev->iftype))
1057d35e
AN
13962 return -EINVAL;
13963
13964 /* don't allow switching to DFS channels */
13965 if (cfg80211_chandef_dfs_required(wdev->wiphy, &chandef, wdev->iftype))
13966 return -EINVAL;
13967
13968 addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
13969 oper_class = nla_get_u8(info->attrs[NL80211_ATTR_OPER_CLASS]);
13970
13971 wdev_lock(wdev);
13972 err = rdev_tdls_channel_switch(rdev, dev, addr, oper_class, &chandef);
13973 wdev_unlock(wdev);
13974
13975 return err;
13976}
13977
13978static int nl80211_tdls_cancel_channel_switch(struct sk_buff *skb,
13979 struct genl_info *info)
13980{
13981 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13982 struct net_device *dev = info->user_ptr[1];
13983 struct wireless_dev *wdev = dev->ieee80211_ptr;
13984 const u8 *addr;
13985
13986 if (!rdev->ops->tdls_channel_switch ||
13987 !rdev->ops->tdls_cancel_channel_switch ||
13988 !(rdev->wiphy.features & NL80211_FEATURE_TDLS_CHANNEL_SWITCH))
13989 return -EOPNOTSUPP;
13990
13991 switch (dev->ieee80211_ptr->iftype) {
13992 case NL80211_IFTYPE_STATION:
13993 case NL80211_IFTYPE_P2P_CLIENT:
13994 break;
13995 default:
13996 return -EOPNOTSUPP;
13997 }
13998
13999 if (!info->attrs[NL80211_ATTR_MAC])
14000 return -EINVAL;
14001
14002 addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
14003
14004 wdev_lock(wdev);
14005 rdev_tdls_cancel_channel_switch(rdev, dev, addr);
14006 wdev_unlock(wdev);
14007
14008 return 0;
14009}
14010
ce0ce13a
MB
14011static int nl80211_set_multicast_to_unicast(struct sk_buff *skb,
14012 struct genl_info *info)
14013{
14014 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14015 struct net_device *dev = info->user_ptr[1];
14016 struct wireless_dev *wdev = dev->ieee80211_ptr;
14017 const struct nlattr *nla;
14018 bool enabled;
14019
ce0ce13a
MB
14020 if (!rdev->ops->set_multicast_to_unicast)
14021 return -EOPNOTSUPP;
14022
14023 if (wdev->iftype != NL80211_IFTYPE_AP &&
14024 wdev->iftype != NL80211_IFTYPE_P2P_GO)
14025 return -EOPNOTSUPP;
14026
14027 nla = info->attrs[NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED];
14028 enabled = nla_get_flag(nla);
14029
14030 return rdev_set_multicast_to_unicast(rdev, dev, enabled);
14031}
14032
3a00df57
AS
14033static int nl80211_set_pmk(struct sk_buff *skb, struct genl_info *info)
14034{
14035 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14036 struct net_device *dev = info->user_ptr[1];
14037 struct wireless_dev *wdev = dev->ieee80211_ptr;
14038 struct cfg80211_pmk_conf pmk_conf = {};
14039 int ret;
14040
14041 if (wdev->iftype != NL80211_IFTYPE_STATION &&
14042 wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
14043 return -EOPNOTSUPP;
14044
14045 if (!wiphy_ext_feature_isset(&rdev->wiphy,
14046 NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X))
14047 return -EOPNOTSUPP;
14048
14049 if (!info->attrs[NL80211_ATTR_MAC] || !info->attrs[NL80211_ATTR_PMK])
14050 return -EINVAL;
14051
14052 wdev_lock(wdev);
14053 if (!wdev->current_bss) {
14054 ret = -ENOTCONN;
14055 goto out;
14056 }
14057
14058 pmk_conf.aa = nla_data(info->attrs[NL80211_ATTR_MAC]);
14059 if (memcmp(pmk_conf.aa, wdev->current_bss->pub.bssid, ETH_ALEN)) {
14060 ret = -EINVAL;
14061 goto out;
14062 }
14063
14064 pmk_conf.pmk = nla_data(info->attrs[NL80211_ATTR_PMK]);
14065 pmk_conf.pmk_len = nla_len(info->attrs[NL80211_ATTR_PMK]);
14066 if (pmk_conf.pmk_len != WLAN_PMK_LEN &&
14067 pmk_conf.pmk_len != WLAN_PMK_LEN_SUITE_B_192) {
14068 ret = -EINVAL;
14069 goto out;
14070 }
14071
cb9abd48 14072 if (info->attrs[NL80211_ATTR_PMKR0_NAME])
3a00df57
AS
14073 pmk_conf.pmk_r0_name =
14074 nla_data(info->attrs[NL80211_ATTR_PMKR0_NAME]);
3a00df57
AS
14075
14076 ret = rdev_set_pmk(rdev, dev, &pmk_conf);
14077out:
14078 wdev_unlock(wdev);
14079 return ret;
14080}
14081
14082static int nl80211_del_pmk(struct sk_buff *skb, struct genl_info *info)
14083{
14084 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14085 struct net_device *dev = info->user_ptr[1];
14086 struct wireless_dev *wdev = dev->ieee80211_ptr;
14087 const u8 *aa;
14088 int ret;
14089
14090 if (wdev->iftype != NL80211_IFTYPE_STATION &&
14091 wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
14092 return -EOPNOTSUPP;
14093
14094 if (!wiphy_ext_feature_isset(&rdev->wiphy,
14095 NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X))
14096 return -EOPNOTSUPP;
14097
14098 if (!info->attrs[NL80211_ATTR_MAC])
14099 return -EINVAL;
14100
14101 wdev_lock(wdev);
14102 aa = nla_data(info->attrs[NL80211_ATTR_MAC]);
14103 ret = rdev_del_pmk(rdev, dev, aa);
14104 wdev_unlock(wdev);
14105
14106 return ret;
14107}
14108
40cbfa90
SD
14109static int nl80211_external_auth(struct sk_buff *skb, struct genl_info *info)
14110{
14111 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14112 struct net_device *dev = info->user_ptr[1];
14113 struct cfg80211_external_auth_params params;
14114
db8d93a7 14115 if (!rdev->ops->external_auth)
40cbfa90
SD
14116 return -EOPNOTSUPP;
14117
fe494370
SD
14118 if (!info->attrs[NL80211_ATTR_SSID] &&
14119 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
14120 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
40cbfa90
SD
14121 return -EINVAL;
14122
14123 if (!info->attrs[NL80211_ATTR_BSSID])
14124 return -EINVAL;
14125
14126 if (!info->attrs[NL80211_ATTR_STATUS_CODE])
14127 return -EINVAL;
14128
14129 memset(&params, 0, sizeof(params));
14130
fe494370
SD
14131 if (info->attrs[NL80211_ATTR_SSID]) {
14132 params.ssid.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
cb9abd48 14133 if (params.ssid.ssid_len == 0)
fe494370
SD
14134 return -EINVAL;
14135 memcpy(params.ssid.ssid,
14136 nla_data(info->attrs[NL80211_ATTR_SSID]),
14137 params.ssid.ssid_len);
14138 }
40cbfa90
SD
14139
14140 memcpy(params.bssid, nla_data(info->attrs[NL80211_ATTR_BSSID]),
14141 ETH_ALEN);
14142
14143 params.status = nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]);
14144
fe494370
SD
14145 if (info->attrs[NL80211_ATTR_PMKID])
14146 params.pmkid = nla_data(info->attrs[NL80211_ATTR_PMKID]);
14147
40cbfa90
SD
14148 return rdev_external_auth(rdev, dev, &params);
14149}
14150
2576a9ac
DK
14151static int nl80211_tx_control_port(struct sk_buff *skb, struct genl_info *info)
14152{
dca9ca2d 14153 bool dont_wait_for_ack = info->attrs[NL80211_ATTR_DONT_WAIT_FOR_ACK];
2576a9ac
DK
14154 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14155 struct net_device *dev = info->user_ptr[1];
14156 struct wireless_dev *wdev = dev->ieee80211_ptr;
14157 const u8 *buf;
14158 size_t len;
14159 u8 *dest;
14160 u16 proto;
14161 bool noencrypt;
dca9ca2d 14162 u64 cookie = 0;
2576a9ac
DK
14163 int err;
14164
14165 if (!wiphy_ext_feature_isset(&rdev->wiphy,
14166 NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211))
14167 return -EOPNOTSUPP;
14168
14169 if (!rdev->ops->tx_control_port)
14170 return -EOPNOTSUPP;
14171
14172 if (!info->attrs[NL80211_ATTR_FRAME] ||
14173 !info->attrs[NL80211_ATTR_MAC] ||
14174 !info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]) {
14175 GENL_SET_ERR_MSG(info, "Frame, MAC or ethertype missing");
14176 return -EINVAL;
14177 }
14178
14179 wdev_lock(wdev);
14180
14181 switch (wdev->iftype) {
14182 case NL80211_IFTYPE_AP:
14183 case NL80211_IFTYPE_P2P_GO:
14184 case NL80211_IFTYPE_MESH_POINT:
14185 break;
14186 case NL80211_IFTYPE_ADHOC:
14187 case NL80211_IFTYPE_STATION:
14188 case NL80211_IFTYPE_P2P_CLIENT:
14189 if (wdev->current_bss)
14190 break;
14191 err = -ENOTCONN;
14192 goto out;
14193 default:
14194 err = -EOPNOTSUPP;
14195 goto out;
14196 }
14197
14198 wdev_unlock(wdev);
14199
14200 buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
14201 len = nla_len(info->attrs[NL80211_ATTR_FRAME]);
14202 dest = nla_data(info->attrs[NL80211_ATTR_MAC]);
14203 proto = nla_get_u16(info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]);
14204 noencrypt =
14205 nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT]);
14206
dca9ca2d
MT
14207 err = rdev_tx_control_port(rdev, dev, buf, len,
14208 dest, cpu_to_be16(proto), noencrypt,
14209 dont_wait_for_ack ? NULL : &cookie);
14210 if (!err && !dont_wait_for_ack)
14211 nl_set_extack_cookie_u64(info->extack, cookie);
14212 return err;
2576a9ac
DK
14213 out:
14214 wdev_unlock(wdev);
14215 return err;
14216}
14217
81e54d08
PKC
14218static int nl80211_get_ftm_responder_stats(struct sk_buff *skb,
14219 struct genl_info *info)
14220{
14221 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14222 struct net_device *dev = info->user_ptr[1];
14223 struct wireless_dev *wdev = dev->ieee80211_ptr;
14224 struct cfg80211_ftm_responder_stats ftm_stats = {};
14225 struct sk_buff *msg;
14226 void *hdr;
14227 struct nlattr *ftm_stats_attr;
14228 int err;
14229
14230 if (wdev->iftype != NL80211_IFTYPE_AP || !wdev->beacon_interval)
14231 return -EOPNOTSUPP;
14232
14233 err = rdev_get_ftm_responder_stats(rdev, dev, &ftm_stats);
14234 if (err)
14235 return err;
14236
14237 if (!ftm_stats.filled)
14238 return -ENODATA;
14239
14240 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
14241 if (!msg)
14242 return -ENOMEM;
14243
14244 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
14245 NL80211_CMD_GET_FTM_RESPONDER_STATS);
14246 if (!hdr)
1399c59f 14247 goto nla_put_failure;
81e54d08
PKC
14248
14249 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
14250 goto nla_put_failure;
14251
ae0be8de
MK
14252 ftm_stats_attr = nla_nest_start_noflag(msg,
14253 NL80211_ATTR_FTM_RESPONDER_STATS);
81e54d08
PKC
14254 if (!ftm_stats_attr)
14255 goto nla_put_failure;
14256
14257#define SET_FTM(field, name, type) \
14258 do { if ((ftm_stats.filled & BIT(NL80211_FTM_STATS_ ## name)) && \
14259 nla_put_ ## type(msg, NL80211_FTM_STATS_ ## name, \
14260 ftm_stats.field)) \
14261 goto nla_put_failure; } while (0)
14262#define SET_FTM_U64(field, name) \
14263 do { if ((ftm_stats.filled & BIT(NL80211_FTM_STATS_ ## name)) && \
14264 nla_put_u64_64bit(msg, NL80211_FTM_STATS_ ## name, \
14265 ftm_stats.field, NL80211_FTM_STATS_PAD)) \
14266 goto nla_put_failure; } while (0)
14267
14268 SET_FTM(success_num, SUCCESS_NUM, u32);
14269 SET_FTM(partial_num, PARTIAL_NUM, u32);
14270 SET_FTM(failed_num, FAILED_NUM, u32);
14271 SET_FTM(asap_num, ASAP_NUM, u32);
14272 SET_FTM(non_asap_num, NON_ASAP_NUM, u32);
14273 SET_FTM_U64(total_duration_ms, TOTAL_DURATION_MSEC);
14274 SET_FTM(unknown_triggers_num, UNKNOWN_TRIGGERS_NUM, u32);
14275 SET_FTM(reschedule_requests_num, RESCHEDULE_REQUESTS_NUM, u32);
14276 SET_FTM(out_of_window_triggers_num, OUT_OF_WINDOW_TRIGGERS_NUM, u32);
14277#undef SET_FTM
14278
14279 nla_nest_end(msg, ftm_stats_attr);
14280
14281 genlmsg_end(msg, hdr);
14282 return genlmsg_reply(msg, info);
14283
14284nla_put_failure:
14285 nlmsg_free(msg);
14286 return -ENOBUFS;
14287}
14288
cb74e977
SD
14289static int nl80211_update_owe_info(struct sk_buff *skb, struct genl_info *info)
14290{
14291 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14292 struct cfg80211_update_owe_info owe_info;
14293 struct net_device *dev = info->user_ptr[1];
14294
14295 if (!rdev->ops->update_owe_info)
14296 return -EOPNOTSUPP;
14297
14298 if (!info->attrs[NL80211_ATTR_STATUS_CODE] ||
14299 !info->attrs[NL80211_ATTR_MAC])
14300 return -EINVAL;
14301
14302 memset(&owe_info, 0, sizeof(owe_info));
14303 owe_info.status = nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]);
14304 nla_memcpy(owe_info.peer, info->attrs[NL80211_ATTR_MAC], ETH_ALEN);
14305
14306 if (info->attrs[NL80211_ATTR_IE]) {
14307 owe_info.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
14308 owe_info.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
14309 }
14310
14311 return rdev_update_owe_info(rdev, dev, &owe_info);
14312}
14313
5ab92e7f
RM
14314static int nl80211_probe_mesh_link(struct sk_buff *skb, struct genl_info *info)
14315{
14316 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14317 struct net_device *dev = info->user_ptr[1];
14318 struct wireless_dev *wdev = dev->ieee80211_ptr;
14319 struct station_info sinfo = {};
14320 const u8 *buf;
14321 size_t len;
14322 u8 *dest;
14323 int err;
14324
14325 if (!rdev->ops->probe_mesh_link || !rdev->ops->get_station)
14326 return -EOPNOTSUPP;
14327
14328 if (!info->attrs[NL80211_ATTR_MAC] ||
14329 !info->attrs[NL80211_ATTR_FRAME]) {
14330 GENL_SET_ERR_MSG(info, "Frame or MAC missing");
14331 return -EINVAL;
14332 }
14333
14334 if (wdev->iftype != NL80211_IFTYPE_MESH_POINT)
14335 return -EOPNOTSUPP;
14336
14337 dest = nla_data(info->attrs[NL80211_ATTR_MAC]);
14338 buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
14339 len = nla_len(info->attrs[NL80211_ATTR_FRAME]);
14340
14341 if (len < sizeof(struct ethhdr))
14342 return -EINVAL;
14343
14344 if (!ether_addr_equal(buf, dest) || is_multicast_ether_addr(buf) ||
14345 !ether_addr_equal(buf + ETH_ALEN, dev->dev_addr))
14346 return -EINVAL;
14347
14348 err = rdev_get_station(rdev, dev, dest, &sinfo);
14349 if (err)
14350 return err;
14351
2a279b34
FF
14352 cfg80211_sinfo_release_content(&sinfo);
14353
5ab92e7f
RM
14354 return rdev_probe_mesh_link(rdev, dev, dest, buf, len);
14355}
14356
77f576de
T
14357static int parse_tid_conf(struct cfg80211_registered_device *rdev,
14358 struct nlattr *attrs[], struct net_device *dev,
3710a8a6 14359 struct cfg80211_tid_cfg *tid_conf,
77f576de
T
14360 struct genl_info *info, const u8 *peer)
14361{
14362 struct netlink_ext_ack *extack = info->extack;
3710a8a6 14363 u64 mask;
77f576de
T
14364 int err;
14365
14366 if (!attrs[NL80211_TID_CONFIG_ATTR_TIDS])
14367 return -EINVAL;
14368
14369 tid_conf->config_override =
14370 nla_get_flag(attrs[NL80211_TID_CONFIG_ATTR_OVERRIDE]);
3710a8a6 14371 tid_conf->tids = nla_get_u16(attrs[NL80211_TID_CONFIG_ATTR_TIDS]);
77f576de
T
14372
14373 if (tid_conf->config_override) {
14374 if (rdev->ops->reset_tid_config) {
14375 err = rdev_reset_tid_config(rdev, dev, peer,
3710a8a6 14376 tid_conf->tids);
c0336955 14377 if (err)
77f576de
T
14378 return err;
14379 } else {
14380 return -EINVAL;
14381 }
14382 }
14383
14384 if (attrs[NL80211_TID_CONFIG_ATTR_NOACK]) {
3710a8a6 14385 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_NOACK);
77f576de
T
14386 tid_conf->noack =
14387 nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_NOACK]);
14388 }
14389
6a21d16c
T
14390 if (attrs[NL80211_TID_CONFIG_ATTR_RETRY_SHORT]) {
14391 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_RETRY_SHORT);
14392 tid_conf->retry_short =
14393 nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_RETRY_SHORT]);
14394
14395 if (tid_conf->retry_short > rdev->wiphy.max_data_retry_count)
14396 return -EINVAL;
14397 }
14398
14399 if (attrs[NL80211_TID_CONFIG_ATTR_RETRY_LONG]) {
14400 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_RETRY_LONG);
14401 tid_conf->retry_long =
14402 nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_RETRY_LONG]);
14403
14404 if (tid_conf->retry_long > rdev->wiphy.max_data_retry_count)
14405 return -EINVAL;
14406 }
14407
ade274b2
T
14408 if (attrs[NL80211_TID_CONFIG_ATTR_AMPDU_CTRL]) {
14409 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_AMPDU_CTRL);
14410 tid_conf->ampdu =
14411 nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_AMPDU_CTRL]);
14412 }
14413
04f7d142
T
14414 if (attrs[NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL]) {
14415 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL);
14416 tid_conf->rtscts =
14417 nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL]);
14418 }
14419
33462e68
SM
14420 if (attrs[NL80211_TID_CONFIG_ATTR_AMSDU_CTRL]) {
14421 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_AMSDU_CTRL);
14422 tid_conf->amsdu =
14423 nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_AMSDU_CTRL]);
14424 }
14425
9a5f6488
TC
14426 if (attrs[NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE]) {
14427 u32 idx = NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE, attr;
14428
14429 tid_conf->txrate_type = nla_get_u8(attrs[idx]);
14430
14431 if (tid_conf->txrate_type != NL80211_TX_RATE_AUTOMATIC) {
14432 attr = NL80211_TID_CONFIG_ATTR_TX_RATE;
14433 err = nl80211_parse_tx_bitrate_mask(info, attrs, attr,
eb89a6a6 14434 &tid_conf->txrate_mask, dev);
9a5f6488
TC
14435 if (err)
14436 return err;
14437
14438 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_TX_RATE);
14439 }
14440 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE);
14441 }
14442
3710a8a6
JB
14443 if (peer)
14444 mask = rdev->wiphy.tid_config_support.peer;
14445 else
14446 mask = rdev->wiphy.tid_config_support.vif;
14447
14448 if (tid_conf->mask & ~mask) {
14449 NL_SET_ERR_MSG(extack, "unsupported TID configuration");
14450 return -ENOTSUPP;
14451 }
14452
77f576de
T
14453 return 0;
14454}
14455
14456static int nl80211_set_tid_config(struct sk_buff *skb,
14457 struct genl_info *info)
14458{
14459 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14460 struct nlattr *attrs[NL80211_TID_CONFIG_ATTR_MAX + 1];
14461 struct net_device *dev = info->user_ptr[1];
3710a8a6 14462 struct cfg80211_tid_config *tid_config;
77f576de
T
14463 struct nlattr *tid;
14464 int conf_idx = 0, rem_conf;
14465 int ret = -EINVAL;
14466 u32 num_conf = 0;
14467
14468 if (!info->attrs[NL80211_ATTR_TID_CONFIG])
14469 return -EINVAL;
14470
14471 if (!rdev->ops->set_tid_config)
14472 return -EOPNOTSUPP;
14473
14474 nla_for_each_nested(tid, info->attrs[NL80211_ATTR_TID_CONFIG],
14475 rem_conf)
14476 num_conf++;
14477
14478 tid_config = kzalloc(struct_size(tid_config, tid_conf, num_conf),
14479 GFP_KERNEL);
14480 if (!tid_config)
14481 return -ENOMEM;
14482
14483 tid_config->n_tid_conf = num_conf;
14484
14485 if (info->attrs[NL80211_ATTR_MAC])
14486 tid_config->peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
14487
14488 nla_for_each_nested(tid, info->attrs[NL80211_ATTR_TID_CONFIG],
14489 rem_conf) {
14490 ret = nla_parse_nested(attrs, NL80211_TID_CONFIG_ATTR_MAX,
14491 tid, NULL, NULL);
14492
14493 if (ret)
14494 goto bad_tid_conf;
14495
14496 ret = parse_tid_conf(rdev, attrs, dev,
14497 &tid_config->tid_conf[conf_idx],
14498 info, tid_config->peer);
14499 if (ret)
14500 goto bad_tid_conf;
14501
14502 conf_idx++;
14503 }
14504
14505 ret = rdev_set_tid_config(rdev, dev, tid_config);
14506
14507bad_tid_conf:
14508 kfree(tid_config);
14509 return ret;
14510}
14511
4c476991
JB
14512#define NL80211_FLAG_NEED_WIPHY 0x01
14513#define NL80211_FLAG_NEED_NETDEV 0x02
14514#define NL80211_FLAG_NEED_RTNL 0x04
41265714
JB
14515#define NL80211_FLAG_CHECK_NETDEV_UP 0x08
14516#define NL80211_FLAG_NEED_NETDEV_UP (NL80211_FLAG_NEED_NETDEV |\
14517 NL80211_FLAG_CHECK_NETDEV_UP)
1bf614ef 14518#define NL80211_FLAG_NEED_WDEV 0x10
98104fde 14519/* If a netdev is associated, it must be UP, P2P must be started */
1bf614ef
JB
14520#define NL80211_FLAG_NEED_WDEV_UP (NL80211_FLAG_NEED_WDEV |\
14521 NL80211_FLAG_CHECK_NETDEV_UP)
5393b917 14522#define NL80211_FLAG_CLEAR_SKB 0x20
4c476991 14523
f84f771d 14524static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
4c476991
JB
14525 struct genl_info *info)
14526{
14527 struct cfg80211_registered_device *rdev;
89a54e48 14528 struct wireless_dev *wdev;
4c476991 14529 struct net_device *dev;
4c476991
JB
14530 bool rtnl = ops->internal_flags & NL80211_FLAG_NEED_RTNL;
14531
14532 if (rtnl)
14533 rtnl_lock();
14534
14535 if (ops->internal_flags & NL80211_FLAG_NEED_WIPHY) {
4f7eff10 14536 rdev = cfg80211_get_dev_from_info(genl_info_net(info), info);
4c476991
JB
14537 if (IS_ERR(rdev)) {
14538 if (rtnl)
14539 rtnl_unlock();
14540 return PTR_ERR(rdev);
14541 }
14542 info->user_ptr[0] = rdev;
1bf614ef
JB
14543 } else if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV ||
14544 ops->internal_flags & NL80211_FLAG_NEED_WDEV) {
5fe231e8
JB
14545 ASSERT_RTNL();
14546
89a54e48
JB
14547 wdev = __cfg80211_wdev_from_attrs(genl_info_net(info),
14548 info->attrs);
14549 if (IS_ERR(wdev)) {
4c476991
JB
14550 if (rtnl)
14551 rtnl_unlock();
89a54e48 14552 return PTR_ERR(wdev);
4c476991 14553 }
89a54e48 14554
89a54e48 14555 dev = wdev->netdev;
f26cbf40 14556 rdev = wiphy_to_rdev(wdev->wiphy);
89a54e48 14557
1bf614ef
JB
14558 if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV) {
14559 if (!dev) {
1bf614ef
JB
14560 if (rtnl)
14561 rtnl_unlock();
14562 return -EINVAL;
14563 }
14564
14565 info->user_ptr[1] = dev;
14566 } else {
14567 info->user_ptr[1] = wdev;
41265714 14568 }
1bf614ef 14569
73c7da3d
AVS
14570 if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP &&
14571 !wdev_running(wdev)) {
14572 if (rtnl)
14573 rtnl_unlock();
14574 return -ENETDOWN;
14575 }
1bf614ef 14576
73c7da3d 14577 if (dev)
1bf614ef 14578 dev_hold(dev);
89a54e48 14579
4c476991 14580 info->user_ptr[0] = rdev;
4c476991
JB
14581 }
14582
14583 return 0;
14584}
14585
f84f771d 14586static void nl80211_post_doit(const struct genl_ops *ops, struct sk_buff *skb,
4c476991
JB
14587 struct genl_info *info)
14588{
1bf614ef
JB
14589 if (info->user_ptr[1]) {
14590 if (ops->internal_flags & NL80211_FLAG_NEED_WDEV) {
14591 struct wireless_dev *wdev = info->user_ptr[1];
14592
14593 if (wdev->netdev)
14594 dev_put(wdev->netdev);
14595 } else {
14596 dev_put(info->user_ptr[1]);
14597 }
14598 }
5393b917 14599
4c476991
JB
14600 if (ops->internal_flags & NL80211_FLAG_NEED_RTNL)
14601 rtnl_unlock();
5393b917
JB
14602
14603 /* If needed, clear the netlink message payload from the SKB
14604 * as it might contain key data that shouldn't stick around on
14605 * the heap after the SKB is freed. The netlink message header
14606 * is still needed for further processing, so leave it intact.
14607 */
14608 if (ops->internal_flags & NL80211_FLAG_CLEAR_SKB) {
14609 struct nlmsghdr *nlh = nlmsg_hdr(skb);
14610
14611 memset(nlmsg_data(nlh), 0, nlmsg_len(nlh));
14612 }
4c476991
JB
14613}
14614
4534de83 14615static const struct genl_ops nl80211_ops[] = {
55682965
JB
14616 {
14617 .cmd = NL80211_CMD_GET_WIPHY,
ef6243ac 14618 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
55682965
JB
14619 .doit = nl80211_get_wiphy,
14620 .dumpit = nl80211_dump_wiphy,
86e8cf98 14621 .done = nl80211_dump_wiphy_done,
55682965 14622 /* can be retrieved by unprivileged users */
5fe231e8
JB
14623 .internal_flags = NL80211_FLAG_NEED_WIPHY |
14624 NL80211_FLAG_NEED_RTNL,
55682965
JB
14625 },
14626 {
14627 .cmd = NL80211_CMD_SET_WIPHY,
ef6243ac 14628 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
55682965 14629 .doit = nl80211_set_wiphy,
5617c6cd 14630 .flags = GENL_UNS_ADMIN_PERM,
4c476991 14631 .internal_flags = NL80211_FLAG_NEED_RTNL,
55682965
JB
14632 },
14633 {
14634 .cmd = NL80211_CMD_GET_INTERFACE,
ef6243ac 14635 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
55682965
JB
14636 .doit = nl80211_get_interface,
14637 .dumpit = nl80211_dump_interface,
55682965 14638 /* can be retrieved by unprivileged users */
5fe231e8
JB
14639 .internal_flags = NL80211_FLAG_NEED_WDEV |
14640 NL80211_FLAG_NEED_RTNL,
55682965
JB
14641 },
14642 {
14643 .cmd = NL80211_CMD_SET_INTERFACE,
ef6243ac 14644 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
55682965 14645 .doit = nl80211_set_interface,
5617c6cd 14646 .flags = GENL_UNS_ADMIN_PERM,
4c476991
JB
14647 .internal_flags = NL80211_FLAG_NEED_NETDEV |
14648 NL80211_FLAG_NEED_RTNL,
55682965
JB
14649 },
14650 {
14651 .cmd = NL80211_CMD_NEW_INTERFACE,
ef6243ac 14652 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
55682965 14653 .doit = nl80211_new_interface,
5617c6cd 14654 .flags = GENL_UNS_ADMIN_PERM,
4c476991
JB
14655 .internal_flags = NL80211_FLAG_NEED_WIPHY |
14656 NL80211_FLAG_NEED_RTNL,
55682965
JB
14657 },
14658 {
14659 .cmd = NL80211_CMD_DEL_INTERFACE,
ef6243ac 14660 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
55682965 14661 .doit = nl80211_del_interface,
5617c6cd 14662 .flags = GENL_UNS_ADMIN_PERM,
84efbb84 14663 .internal_flags = NL80211_FLAG_NEED_WDEV |
4c476991 14664 NL80211_FLAG_NEED_RTNL,
41ade00f
JB
14665 },
14666 {
14667 .cmd = NL80211_CMD_GET_KEY,
ef6243ac 14668 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
41ade00f 14669 .doit = nl80211_get_key,
5617c6cd 14670 .flags = GENL_UNS_ADMIN_PERM,
2b5f8b0b 14671 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4c476991 14672 NL80211_FLAG_NEED_RTNL,
41ade00f
JB
14673 },
14674 {
14675 .cmd = NL80211_CMD_SET_KEY,
ef6243ac 14676 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
41ade00f 14677 .doit = nl80211_set_key,
5617c6cd 14678 .flags = GENL_UNS_ADMIN_PERM,
41265714 14679 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
5393b917
JB
14680 NL80211_FLAG_NEED_RTNL |
14681 NL80211_FLAG_CLEAR_SKB,
41ade00f
JB
14682 },
14683 {
14684 .cmd = NL80211_CMD_NEW_KEY,
ef6243ac 14685 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
41ade00f 14686 .doit = nl80211_new_key,
5617c6cd 14687 .flags = GENL_UNS_ADMIN_PERM,
41265714 14688 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
5393b917
JB
14689 NL80211_FLAG_NEED_RTNL |
14690 NL80211_FLAG_CLEAR_SKB,
41ade00f
JB
14691 },
14692 {
14693 .cmd = NL80211_CMD_DEL_KEY,
ef6243ac 14694 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
41ade00f 14695 .doit = nl80211_del_key,
5617c6cd 14696 .flags = GENL_UNS_ADMIN_PERM,
41265714 14697 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4c476991 14698 NL80211_FLAG_NEED_RTNL,
55682965 14699 },
ed1b6cc7
JB
14700 {
14701 .cmd = NL80211_CMD_SET_BEACON,
ef6243ac 14702 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5617c6cd 14703 .flags = GENL_UNS_ADMIN_PERM,
8860020e 14704 .doit = nl80211_set_beacon,
2b5f8b0b 14705 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4c476991 14706 NL80211_FLAG_NEED_RTNL,
ed1b6cc7
JB
14707 },
14708 {
8860020e 14709 .cmd = NL80211_CMD_START_AP,
ef6243ac 14710 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5617c6cd 14711 .flags = GENL_UNS_ADMIN_PERM,
8860020e 14712 .doit = nl80211_start_ap,
2b5f8b0b 14713 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4c476991 14714 NL80211_FLAG_NEED_RTNL,
ed1b6cc7
JB
14715 },
14716 {
8860020e 14717 .cmd = NL80211_CMD_STOP_AP,
ef6243ac 14718 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5617c6cd 14719 .flags = GENL_UNS_ADMIN_PERM,
8860020e 14720 .doit = nl80211_stop_ap,
2b5f8b0b 14721 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4c476991 14722 NL80211_FLAG_NEED_RTNL,
ed1b6cc7 14723 },
5727ef1b
JB
14724 {
14725 .cmd = NL80211_CMD_GET_STATION,
ef6243ac 14726 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5727ef1b 14727 .doit = nl80211_get_station,
2ec600d6 14728 .dumpit = nl80211_dump_station,
4c476991
JB
14729 .internal_flags = NL80211_FLAG_NEED_NETDEV |
14730 NL80211_FLAG_NEED_RTNL,
5727ef1b
JB
14731 },
14732 {
14733 .cmd = NL80211_CMD_SET_STATION,
ef6243ac 14734 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5727ef1b 14735 .doit = nl80211_set_station,
5617c6cd 14736 .flags = GENL_UNS_ADMIN_PERM,
2b5f8b0b 14737 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4c476991 14738 NL80211_FLAG_NEED_RTNL,
5727ef1b
JB
14739 },
14740 {
14741 .cmd = NL80211_CMD_NEW_STATION,
ef6243ac 14742 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5727ef1b 14743 .doit = nl80211_new_station,
5617c6cd 14744 .flags = GENL_UNS_ADMIN_PERM,
41265714 14745 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4c476991 14746 NL80211_FLAG_NEED_RTNL,
5727ef1b
JB
14747 },
14748 {
14749 .cmd = NL80211_CMD_DEL_STATION,
ef6243ac 14750 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5727ef1b 14751 .doit = nl80211_del_station,
5617c6cd 14752 .flags = GENL_UNS_ADMIN_PERM,
2b5f8b0b 14753 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4c476991 14754 NL80211_FLAG_NEED_RTNL,
2ec600d6
LCC
14755 },
14756 {
14757 .cmd = NL80211_CMD_GET_MPATH,
ef6243ac 14758 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2ec600d6
LCC
14759 .doit = nl80211_get_mpath,
14760 .dumpit = nl80211_dump_mpath,
5617c6cd 14761 .flags = GENL_UNS_ADMIN_PERM,
41265714 14762 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4c476991 14763 NL80211_FLAG_NEED_RTNL,
2ec600d6 14764 },
66be7d2b
HR
14765 {
14766 .cmd = NL80211_CMD_GET_MPP,
ef6243ac 14767 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
66be7d2b
HR
14768 .doit = nl80211_get_mpp,
14769 .dumpit = nl80211_dump_mpp,
5617c6cd 14770 .flags = GENL_UNS_ADMIN_PERM,
66be7d2b
HR
14771 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
14772 NL80211_FLAG_NEED_RTNL,
14773 },
2ec600d6
LCC
14774 {
14775 .cmd = NL80211_CMD_SET_MPATH,
ef6243ac 14776 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2ec600d6 14777 .doit = nl80211_set_mpath,
5617c6cd 14778 .flags = GENL_UNS_ADMIN_PERM,
41265714 14779 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4c476991 14780 NL80211_FLAG_NEED_RTNL,
2ec600d6
LCC
14781 },
14782 {
14783 .cmd = NL80211_CMD_NEW_MPATH,
ef6243ac 14784 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2ec600d6 14785 .doit = nl80211_new_mpath,
5617c6cd 14786 .flags = GENL_UNS_ADMIN_PERM,
41265714 14787 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4c476991 14788 NL80211_FLAG_NEED_RTNL,
2ec600d6
LCC
14789 },
14790 {
14791 .cmd = NL80211_CMD_DEL_MPATH,
ef6243ac 14792 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2ec600d6 14793 .doit = nl80211_del_mpath,
5617c6cd 14794 .flags = GENL_UNS_ADMIN_PERM,
2b5f8b0b 14795 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4c476991 14796 NL80211_FLAG_NEED_RTNL,
9f1ba906
JM
14797 },
14798 {
14799 .cmd = NL80211_CMD_SET_BSS,
ef6243ac 14800 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9f1ba906 14801 .doit = nl80211_set_bss,
5617c6cd 14802 .flags = GENL_UNS_ADMIN_PERM,
2b5f8b0b 14803 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4c476991 14804 NL80211_FLAG_NEED_RTNL,
b2e1b302 14805 },
f130347c
LR
14806 {
14807 .cmd = NL80211_CMD_GET_REG,
ef6243ac 14808 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ad30ca2c
AN
14809 .doit = nl80211_get_reg_do,
14810 .dumpit = nl80211_get_reg_dump,
5fe231e8 14811 .internal_flags = NL80211_FLAG_NEED_RTNL,
f130347c
LR
14812 /* can be retrieved by unprivileged users */
14813 },
b6863036 14814#ifdef CONFIG_CFG80211_CRDA_SUPPORT
b2e1b302
LR
14815 {
14816 .cmd = NL80211_CMD_SET_REG,
ef6243ac 14817 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
b2e1b302 14818 .doit = nl80211_set_reg,
b2e1b302 14819 .flags = GENL_ADMIN_PERM,
5fe231e8 14820 .internal_flags = NL80211_FLAG_NEED_RTNL,
b2e1b302 14821 },
b6863036 14822#endif
b2e1b302
LR
14823 {
14824 .cmd = NL80211_CMD_REQ_SET_REG,
ef6243ac 14825 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
b2e1b302 14826 .doit = nl80211_req_set_reg,
93da9cc1 14827 .flags = GENL_ADMIN_PERM,
14828 },
1ea4ff3e
JB
14829 {
14830 .cmd = NL80211_CMD_RELOAD_REGDB,
ef6243ac 14831 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1ea4ff3e 14832 .doit = nl80211_reload_regdb,
1ea4ff3e
JB
14833 .flags = GENL_ADMIN_PERM,
14834 },
93da9cc1 14835 {
24bdd9f4 14836 .cmd = NL80211_CMD_GET_MESH_CONFIG,
ef6243ac 14837 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
24bdd9f4 14838 .doit = nl80211_get_mesh_config,
93da9cc1 14839 /* can be retrieved by unprivileged users */
2b5f8b0b 14840 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4c476991 14841 NL80211_FLAG_NEED_RTNL,
93da9cc1 14842 },
14843 {
24bdd9f4 14844 .cmd = NL80211_CMD_SET_MESH_CONFIG,
ef6243ac 14845 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
24bdd9f4 14846 .doit = nl80211_update_mesh_config,
5617c6cd 14847 .flags = GENL_UNS_ADMIN_PERM,
29cbe68c 14848 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4c476991 14849 NL80211_FLAG_NEED_RTNL,
9aed3cc1 14850 },
2a519311
JB
14851 {
14852 .cmd = NL80211_CMD_TRIGGER_SCAN,
ef6243ac 14853 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2a519311 14854 .doit = nl80211_trigger_scan,
5617c6cd 14855 .flags = GENL_UNS_ADMIN_PERM,
fd014284 14856 .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
4c476991 14857 NL80211_FLAG_NEED_RTNL,
2a519311 14858 },
91d3ab46
VK
14859 {
14860 .cmd = NL80211_CMD_ABORT_SCAN,
ef6243ac 14861 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
91d3ab46 14862 .doit = nl80211_abort_scan,
5617c6cd 14863 .flags = GENL_UNS_ADMIN_PERM,
91d3ab46
VK
14864 .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
14865 NL80211_FLAG_NEED_RTNL,
14866 },
2a519311
JB
14867 {
14868 .cmd = NL80211_CMD_GET_SCAN,
ef6243ac 14869 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2a519311
JB
14870 .dumpit = nl80211_dump_scan,
14871 },
807f8a8c
LC
14872 {
14873 .cmd = NL80211_CMD_START_SCHED_SCAN,
ef6243ac 14874 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
807f8a8c 14875 .doit = nl80211_start_sched_scan,
5617c6cd 14876 .flags = GENL_UNS_ADMIN_PERM,
807f8a8c
LC
14877 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
14878 NL80211_FLAG_NEED_RTNL,
14879 },
14880 {
14881 .cmd = NL80211_CMD_STOP_SCHED_SCAN,
ef6243ac 14882 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
807f8a8c 14883 .doit = nl80211_stop_sched_scan,
5617c6cd 14884 .flags = GENL_UNS_ADMIN_PERM,
807f8a8c
LC
14885 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
14886 NL80211_FLAG_NEED_RTNL,
14887 },
636a5d36
JM
14888 {
14889 .cmd = NL80211_CMD_AUTHENTICATE,
ef6243ac 14890 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
636a5d36 14891 .doit = nl80211_authenticate,
5617c6cd 14892 .flags = GENL_UNS_ADMIN_PERM,
41265714 14893 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
5393b917
JB
14894 NL80211_FLAG_NEED_RTNL |
14895 NL80211_FLAG_CLEAR_SKB,
636a5d36
JM
14896 },
14897 {
14898 .cmd = NL80211_CMD_ASSOCIATE,
ef6243ac 14899 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
636a5d36 14900 .doit = nl80211_associate,
5617c6cd 14901 .flags = GENL_UNS_ADMIN_PERM,
41265714 14902 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
d6db02a8
SD
14903 NL80211_FLAG_NEED_RTNL |
14904 NL80211_FLAG_CLEAR_SKB,
636a5d36
JM
14905 },
14906 {
14907 .cmd = NL80211_CMD_DEAUTHENTICATE,
ef6243ac 14908 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
636a5d36 14909 .doit = nl80211_deauthenticate,
5617c6cd 14910 .flags = GENL_UNS_ADMIN_PERM,
41265714 14911 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4c476991 14912 NL80211_FLAG_NEED_RTNL,
636a5d36
JM
14913 },
14914 {
14915 .cmd = NL80211_CMD_DISASSOCIATE,
ef6243ac 14916 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
636a5d36 14917 .doit = nl80211_disassociate,
5617c6cd 14918 .flags = GENL_UNS_ADMIN_PERM,
41265714 14919 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4c476991 14920 NL80211_FLAG_NEED_RTNL,
636a5d36 14921 },
04a773ad
JB
14922 {
14923 .cmd = NL80211_CMD_JOIN_IBSS,
ef6243ac 14924 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
04a773ad 14925 .doit = nl80211_join_ibss,
5617c6cd 14926 .flags = GENL_UNS_ADMIN_PERM,
41265714 14927 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4c476991 14928 NL80211_FLAG_NEED_RTNL,
04a773ad
JB
14929 },
14930 {
14931 .cmd = NL80211_CMD_LEAVE_IBSS,
ef6243ac 14932 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
04a773ad 14933 .doit = nl80211_leave_ibss,
5617c6cd 14934 .flags = GENL_UNS_ADMIN_PERM,
41265714 14935 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4c476991 14936 NL80211_FLAG_NEED_RTNL,
04a773ad 14937 },
aff89a9b
JB
14938#ifdef CONFIG_NL80211_TESTMODE
14939 {
14940 .cmd = NL80211_CMD_TESTMODE,
ef6243ac 14941 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
aff89a9b 14942 .doit = nl80211_testmode_do,
71063f0e 14943 .dumpit = nl80211_testmode_dump,
5617c6cd 14944 .flags = GENL_UNS_ADMIN_PERM,
4c476991
JB
14945 .internal_flags = NL80211_FLAG_NEED_WIPHY |
14946 NL80211_FLAG_NEED_RTNL,
aff89a9b
JB
14947 },
14948#endif
b23aa676
SO
14949 {
14950 .cmd = NL80211_CMD_CONNECT,
ef6243ac 14951 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
b23aa676 14952 .doit = nl80211_connect,
5617c6cd 14953 .flags = GENL_UNS_ADMIN_PERM,
41265714 14954 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
d6db02a8
SD
14955 NL80211_FLAG_NEED_RTNL |
14956 NL80211_FLAG_CLEAR_SKB,
b23aa676 14957 },
088e8df8 14958 {
14959 .cmd = NL80211_CMD_UPDATE_CONNECT_PARAMS,
ef6243ac 14960 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
088e8df8 14961 .doit = nl80211_update_connect_params,
088e8df8 14962 .flags = GENL_ADMIN_PERM,
14963 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
d6db02a8
SD
14964 NL80211_FLAG_NEED_RTNL |
14965 NL80211_FLAG_CLEAR_SKB,
088e8df8 14966 },
b23aa676
SO
14967 {
14968 .cmd = NL80211_CMD_DISCONNECT,
ef6243ac 14969 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
b23aa676 14970 .doit = nl80211_disconnect,
5617c6cd 14971 .flags = GENL_UNS_ADMIN_PERM,
41265714 14972 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4c476991 14973 NL80211_FLAG_NEED_RTNL,
b23aa676 14974 },
463d0183
JB
14975 {
14976 .cmd = NL80211_CMD_SET_WIPHY_NETNS,
ef6243ac 14977 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
463d0183 14978 .doit = nl80211_wiphy_netns,
5617c6cd 14979 .flags = GENL_UNS_ADMIN_PERM,
4c476991
JB
14980 .internal_flags = NL80211_FLAG_NEED_WIPHY |
14981 NL80211_FLAG_NEED_RTNL,
463d0183 14982 },
61fa713c
HS
14983 {
14984 .cmd = NL80211_CMD_GET_SURVEY,
ef6243ac 14985 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
61fa713c
HS
14986 .dumpit = nl80211_dump_survey,
14987 },
67fbb16b
SO
14988 {
14989 .cmd = NL80211_CMD_SET_PMKSA,
ef6243ac 14990 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
67fbb16b 14991 .doit = nl80211_setdel_pmksa,
5617c6cd 14992 .flags = GENL_UNS_ADMIN_PERM,
2b5f8b0b 14993 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
d6db02a8
SD
14994 NL80211_FLAG_NEED_RTNL |
14995 NL80211_FLAG_CLEAR_SKB,
67fbb16b
SO
14996 },
14997 {
14998 .cmd = NL80211_CMD_DEL_PMKSA,
ef6243ac 14999 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
67fbb16b 15000 .doit = nl80211_setdel_pmksa,
5617c6cd 15001 .flags = GENL_UNS_ADMIN_PERM,
2b5f8b0b 15002 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4c476991 15003 NL80211_FLAG_NEED_RTNL,
67fbb16b
SO
15004 },
15005 {
15006 .cmd = NL80211_CMD_FLUSH_PMKSA,
ef6243ac 15007 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
67fbb16b 15008 .doit = nl80211_flush_pmksa,
5617c6cd 15009 .flags = GENL_UNS_ADMIN_PERM,
2b5f8b0b 15010 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4c476991 15011 NL80211_FLAG_NEED_RTNL,
67fbb16b 15012 },
9588bbd5
JM
15013 {
15014 .cmd = NL80211_CMD_REMAIN_ON_CHANNEL,
ef6243ac 15015 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9588bbd5 15016 .doit = nl80211_remain_on_channel,
5617c6cd 15017 .flags = GENL_UNS_ADMIN_PERM,
71bbc994 15018 .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
4c476991 15019 NL80211_FLAG_NEED_RTNL,
9588bbd5
JM
15020 },
15021 {
15022 .cmd = NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL,
ef6243ac 15023 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9588bbd5 15024 .doit = nl80211_cancel_remain_on_channel,
5617c6cd 15025 .flags = GENL_UNS_ADMIN_PERM,
71bbc994 15026 .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
4c476991 15027 NL80211_FLAG_NEED_RTNL,
9588bbd5 15028 },
13ae75b1
JM
15029 {
15030 .cmd = NL80211_CMD_SET_TX_BITRATE_MASK,
ef6243ac 15031 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
13ae75b1 15032 .doit = nl80211_set_tx_bitrate_mask,
5617c6cd 15033 .flags = GENL_UNS_ADMIN_PERM,
4c476991
JB
15034 .internal_flags = NL80211_FLAG_NEED_NETDEV |
15035 NL80211_FLAG_NEED_RTNL,
13ae75b1 15036 },
026331c4 15037 {
2e161f78 15038 .cmd = NL80211_CMD_REGISTER_FRAME,
ef6243ac 15039 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2e161f78 15040 .doit = nl80211_register_mgmt,
5617c6cd 15041 .flags = GENL_UNS_ADMIN_PERM,
71bbc994 15042 .internal_flags = NL80211_FLAG_NEED_WDEV |
4c476991 15043 NL80211_FLAG_NEED_RTNL,
026331c4
JM
15044 },
15045 {
2e161f78 15046 .cmd = NL80211_CMD_FRAME,
ef6243ac 15047 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2e161f78 15048 .doit = nl80211_tx_mgmt,
5617c6cd 15049 .flags = GENL_UNS_ADMIN_PERM,
71bbc994 15050 .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
f7ca38df
JB
15051 NL80211_FLAG_NEED_RTNL,
15052 },
15053 {
15054 .cmd = NL80211_CMD_FRAME_WAIT_CANCEL,
ef6243ac 15055 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
f7ca38df 15056 .doit = nl80211_tx_mgmt_cancel_wait,
5617c6cd 15057 .flags = GENL_UNS_ADMIN_PERM,
71bbc994 15058 .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
4c476991 15059 NL80211_FLAG_NEED_RTNL,
026331c4 15060 },
ffb9eb3d
KV
15061 {
15062 .cmd = NL80211_CMD_SET_POWER_SAVE,
ef6243ac 15063 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ffb9eb3d 15064 .doit = nl80211_set_power_save,
5617c6cd 15065 .flags = GENL_UNS_ADMIN_PERM,
4c476991
JB
15066 .internal_flags = NL80211_FLAG_NEED_NETDEV |
15067 NL80211_FLAG_NEED_RTNL,
ffb9eb3d
KV
15068 },
15069 {
15070 .cmd = NL80211_CMD_GET_POWER_SAVE,
ef6243ac 15071 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ffb9eb3d 15072 .doit = nl80211_get_power_save,
ffb9eb3d 15073 /* can be retrieved by unprivileged users */
4c476991
JB
15074 .internal_flags = NL80211_FLAG_NEED_NETDEV |
15075 NL80211_FLAG_NEED_RTNL,
ffb9eb3d 15076 },
d6dc1a38
JO
15077 {
15078 .cmd = NL80211_CMD_SET_CQM,
ef6243ac 15079 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
d6dc1a38 15080 .doit = nl80211_set_cqm,
5617c6cd 15081 .flags = GENL_UNS_ADMIN_PERM,
4c476991
JB
15082 .internal_flags = NL80211_FLAG_NEED_NETDEV |
15083 NL80211_FLAG_NEED_RTNL,
d6dc1a38 15084 },
f444de05
JB
15085 {
15086 .cmd = NL80211_CMD_SET_CHANNEL,
ef6243ac 15087 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
f444de05 15088 .doit = nl80211_set_channel,
5617c6cd 15089 .flags = GENL_UNS_ADMIN_PERM,
4c476991
JB
15090 .internal_flags = NL80211_FLAG_NEED_NETDEV |
15091 NL80211_FLAG_NEED_RTNL,
f444de05 15092 },
e8347eba
BJ
15093 {
15094 .cmd = NL80211_CMD_SET_WDS_PEER,
ef6243ac 15095 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
e8347eba 15096 .doit = nl80211_set_wds_peer,
5617c6cd 15097 .flags = GENL_UNS_ADMIN_PERM,
43b19952
JB
15098 .internal_flags = NL80211_FLAG_NEED_NETDEV |
15099 NL80211_FLAG_NEED_RTNL,
e8347eba 15100 },
29cbe68c
JB
15101 {
15102 .cmd = NL80211_CMD_JOIN_MESH,
ef6243ac 15103 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
29cbe68c 15104 .doit = nl80211_join_mesh,
5617c6cd 15105 .flags = GENL_UNS_ADMIN_PERM,
29cbe68c
JB
15106 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
15107 NL80211_FLAG_NEED_RTNL,
15108 },
15109 {
15110 .cmd = NL80211_CMD_LEAVE_MESH,
ef6243ac 15111 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
29cbe68c 15112 .doit = nl80211_leave_mesh,
5617c6cd 15113 .flags = GENL_UNS_ADMIN_PERM,
29cbe68c
JB
15114 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
15115 NL80211_FLAG_NEED_RTNL,
15116 },
6e0bd6c3
RL
15117 {
15118 .cmd = NL80211_CMD_JOIN_OCB,
ef6243ac 15119 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6e0bd6c3 15120 .doit = nl80211_join_ocb,
5617c6cd 15121 .flags = GENL_UNS_ADMIN_PERM,
6e0bd6c3
RL
15122 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
15123 NL80211_FLAG_NEED_RTNL,
15124 },
15125 {
15126 .cmd = NL80211_CMD_LEAVE_OCB,
ef6243ac 15127 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6e0bd6c3 15128 .doit = nl80211_leave_ocb,
5617c6cd 15129 .flags = GENL_UNS_ADMIN_PERM,
6e0bd6c3
RL
15130 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
15131 NL80211_FLAG_NEED_RTNL,
15132 },
dfb89c56 15133#ifdef CONFIG_PM
ff1b6e69
JB
15134 {
15135 .cmd = NL80211_CMD_GET_WOWLAN,
ef6243ac 15136 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ff1b6e69 15137 .doit = nl80211_get_wowlan,
ff1b6e69
JB
15138 /* can be retrieved by unprivileged users */
15139 .internal_flags = NL80211_FLAG_NEED_WIPHY |
15140 NL80211_FLAG_NEED_RTNL,
15141 },
15142 {
15143 .cmd = NL80211_CMD_SET_WOWLAN,
ef6243ac 15144 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ff1b6e69 15145 .doit = nl80211_set_wowlan,
5617c6cd 15146 .flags = GENL_UNS_ADMIN_PERM,
ff1b6e69
JB
15147 .internal_flags = NL80211_FLAG_NEED_WIPHY |
15148 NL80211_FLAG_NEED_RTNL,
15149 },
dfb89c56 15150#endif
e5497d76
JB
15151 {
15152 .cmd = NL80211_CMD_SET_REKEY_OFFLOAD,
ef6243ac 15153 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
e5497d76 15154 .doit = nl80211_set_rekey_data,
5617c6cd 15155 .flags = GENL_UNS_ADMIN_PERM,
e5497d76 15156 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
5393b917
JB
15157 NL80211_FLAG_NEED_RTNL |
15158 NL80211_FLAG_CLEAR_SKB,
e5497d76 15159 },
109086ce
AN
15160 {
15161 .cmd = NL80211_CMD_TDLS_MGMT,
ef6243ac 15162 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
109086ce 15163 .doit = nl80211_tdls_mgmt,
5617c6cd 15164 .flags = GENL_UNS_ADMIN_PERM,
109086ce
AN
15165 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
15166 NL80211_FLAG_NEED_RTNL,
15167 },
15168 {
15169 .cmd = NL80211_CMD_TDLS_OPER,
ef6243ac 15170 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
109086ce 15171 .doit = nl80211_tdls_oper,
5617c6cd 15172 .flags = GENL_UNS_ADMIN_PERM,
109086ce
AN
15173 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
15174 NL80211_FLAG_NEED_RTNL,
15175 },
28946da7
JB
15176 {
15177 .cmd = NL80211_CMD_UNEXPECTED_FRAME,
ef6243ac 15178 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
28946da7 15179 .doit = nl80211_register_unexpected_frame,
5617c6cd 15180 .flags = GENL_UNS_ADMIN_PERM,
28946da7
JB
15181 .internal_flags = NL80211_FLAG_NEED_NETDEV |
15182 NL80211_FLAG_NEED_RTNL,
15183 },
7f6cf311
JB
15184 {
15185 .cmd = NL80211_CMD_PROBE_CLIENT,
ef6243ac 15186 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
7f6cf311 15187 .doit = nl80211_probe_client,
5617c6cd 15188 .flags = GENL_UNS_ADMIN_PERM,
2b5f8b0b 15189 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
7f6cf311
JB
15190 NL80211_FLAG_NEED_RTNL,
15191 },
5e760230
JB
15192 {
15193 .cmd = NL80211_CMD_REGISTER_BEACONS,
ef6243ac 15194 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5e760230 15195 .doit = nl80211_register_beacons,
5617c6cd 15196 .flags = GENL_UNS_ADMIN_PERM,
5e760230
JB
15197 .internal_flags = NL80211_FLAG_NEED_WIPHY |
15198 NL80211_FLAG_NEED_RTNL,
15199 },
1d9d9213
SW
15200 {
15201 .cmd = NL80211_CMD_SET_NOACK_MAP,
ef6243ac 15202 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1d9d9213 15203 .doit = nl80211_set_noack_map,
5617c6cd 15204 .flags = GENL_UNS_ADMIN_PERM,
1d9d9213
SW
15205 .internal_flags = NL80211_FLAG_NEED_NETDEV |
15206 NL80211_FLAG_NEED_RTNL,
15207 },
98104fde
JB
15208 {
15209 .cmd = NL80211_CMD_START_P2P_DEVICE,
ef6243ac 15210 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
98104fde 15211 .doit = nl80211_start_p2p_device,
5617c6cd 15212 .flags = GENL_UNS_ADMIN_PERM,
98104fde
JB
15213 .internal_flags = NL80211_FLAG_NEED_WDEV |
15214 NL80211_FLAG_NEED_RTNL,
15215 },
15216 {
15217 .cmd = NL80211_CMD_STOP_P2P_DEVICE,
ef6243ac 15218 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
98104fde 15219 .doit = nl80211_stop_p2p_device,
5617c6cd 15220 .flags = GENL_UNS_ADMIN_PERM,
98104fde
JB
15221 .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
15222 NL80211_FLAG_NEED_RTNL,
cb3b7d87
AB
15223 },
15224 {
15225 .cmd = NL80211_CMD_START_NAN,
ef6243ac 15226 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
cb3b7d87 15227 .doit = nl80211_start_nan,
cb3b7d87
AB
15228 .flags = GENL_ADMIN_PERM,
15229 .internal_flags = NL80211_FLAG_NEED_WDEV |
15230 NL80211_FLAG_NEED_RTNL,
15231 },
15232 {
15233 .cmd = NL80211_CMD_STOP_NAN,
ef6243ac 15234 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
cb3b7d87 15235 .doit = nl80211_stop_nan,
cb3b7d87
AB
15236 .flags = GENL_ADMIN_PERM,
15237 .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
15238 NL80211_FLAG_NEED_RTNL,
a442b761
AB
15239 },
15240 {
15241 .cmd = NL80211_CMD_ADD_NAN_FUNCTION,
ef6243ac 15242 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
a442b761 15243 .doit = nl80211_nan_add_func,
a442b761
AB
15244 .flags = GENL_ADMIN_PERM,
15245 .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
15246 NL80211_FLAG_NEED_RTNL,
15247 },
15248 {
15249 .cmd = NL80211_CMD_DEL_NAN_FUNCTION,
ef6243ac 15250 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
a442b761 15251 .doit = nl80211_nan_del_func,
a442b761
AB
15252 .flags = GENL_ADMIN_PERM,
15253 .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
15254 NL80211_FLAG_NEED_RTNL,
a5a9dcf2
AB
15255 },
15256 {
15257 .cmd = NL80211_CMD_CHANGE_NAN_CONFIG,
ef6243ac 15258 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
a5a9dcf2 15259 .doit = nl80211_nan_change_config,
a5a9dcf2
AB
15260 .flags = GENL_ADMIN_PERM,
15261 .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
15262 NL80211_FLAG_NEED_RTNL,
98104fde 15263 },
f4e583c8
AQ
15264 {
15265 .cmd = NL80211_CMD_SET_MCAST_RATE,
ef6243ac 15266 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
f4e583c8 15267 .doit = nl80211_set_mcast_rate,
5617c6cd 15268 .flags = GENL_UNS_ADMIN_PERM,
77765eaf
VT
15269 .internal_flags = NL80211_FLAG_NEED_NETDEV |
15270 NL80211_FLAG_NEED_RTNL,
15271 },
15272 {
15273 .cmd = NL80211_CMD_SET_MAC_ACL,
ef6243ac 15274 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
77765eaf 15275 .doit = nl80211_set_mac_acl,
5617c6cd 15276 .flags = GENL_UNS_ADMIN_PERM,
f4e583c8
AQ
15277 .internal_flags = NL80211_FLAG_NEED_NETDEV |
15278 NL80211_FLAG_NEED_RTNL,
15279 },
04f39047
SW
15280 {
15281 .cmd = NL80211_CMD_RADAR_DETECT,
ef6243ac 15282 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
04f39047 15283 .doit = nl80211_start_radar_detection,
5617c6cd 15284 .flags = GENL_UNS_ADMIN_PERM,
04f39047
SW
15285 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
15286 NL80211_FLAG_NEED_RTNL,
15287 },
3713b4e3
JB
15288 {
15289 .cmd = NL80211_CMD_GET_PROTOCOL_FEATURES,
ef6243ac 15290 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
3713b4e3 15291 .doit = nl80211_get_protocol_features,
3713b4e3 15292 },
355199e0
JM
15293 {
15294 .cmd = NL80211_CMD_UPDATE_FT_IES,
ef6243ac 15295 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
355199e0 15296 .doit = nl80211_update_ft_ies,
5617c6cd 15297 .flags = GENL_UNS_ADMIN_PERM,
355199e0
JM
15298 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
15299 NL80211_FLAG_NEED_RTNL,
15300 },
5de17984
AS
15301 {
15302 .cmd = NL80211_CMD_CRIT_PROTOCOL_START,
ef6243ac 15303 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5de17984 15304 .doit = nl80211_crit_protocol_start,
5617c6cd 15305 .flags = GENL_UNS_ADMIN_PERM,
5de17984
AS
15306 .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
15307 NL80211_FLAG_NEED_RTNL,
15308 },
15309 {
15310 .cmd = NL80211_CMD_CRIT_PROTOCOL_STOP,
ef6243ac 15311 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5de17984 15312 .doit = nl80211_crit_protocol_stop,
5617c6cd 15313 .flags = GENL_UNS_ADMIN_PERM,
5de17984
AS
15314 .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
15315 NL80211_FLAG_NEED_RTNL,
be29b99a
AK
15316 },
15317 {
15318 .cmd = NL80211_CMD_GET_COALESCE,
ef6243ac 15319 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
be29b99a 15320 .doit = nl80211_get_coalesce,
be29b99a
AK
15321 .internal_flags = NL80211_FLAG_NEED_WIPHY |
15322 NL80211_FLAG_NEED_RTNL,
15323 },
15324 {
15325 .cmd = NL80211_CMD_SET_COALESCE,
ef6243ac 15326 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
be29b99a 15327 .doit = nl80211_set_coalesce,
5617c6cd 15328 .flags = GENL_UNS_ADMIN_PERM,
be29b99a
AK
15329 .internal_flags = NL80211_FLAG_NEED_WIPHY |
15330 NL80211_FLAG_NEED_RTNL,
16ef1fe2
SW
15331 },
15332 {
15333 .cmd = NL80211_CMD_CHANNEL_SWITCH,
ef6243ac 15334 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
16ef1fe2 15335 .doit = nl80211_channel_switch,
5617c6cd 15336 .flags = GENL_UNS_ADMIN_PERM,
16ef1fe2
SW
15337 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
15338 NL80211_FLAG_NEED_RTNL,
15339 },
ad7e718c
JB
15340 {
15341 .cmd = NL80211_CMD_VENDOR,
ef6243ac 15342 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ad7e718c 15343 .doit = nl80211_vendor_cmd,
7bdbe400 15344 .dumpit = nl80211_vendor_cmd_dump,
5617c6cd 15345 .flags = GENL_UNS_ADMIN_PERM,
ad7e718c 15346 .internal_flags = NL80211_FLAG_NEED_WIPHY |
d6db02a8
SD
15347 NL80211_FLAG_NEED_RTNL |
15348 NL80211_FLAG_CLEAR_SKB,
ad7e718c 15349 },
fa9ffc74
KP
15350 {
15351 .cmd = NL80211_CMD_SET_QOS_MAP,
ef6243ac 15352 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
fa9ffc74 15353 .doit = nl80211_set_qos_map,
5617c6cd 15354 .flags = GENL_UNS_ADMIN_PERM,
fa9ffc74
KP
15355 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
15356 NL80211_FLAG_NEED_RTNL,
15357 },
960d01ac
JB
15358 {
15359 .cmd = NL80211_CMD_ADD_TX_TS,
ef6243ac 15360 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
960d01ac 15361 .doit = nl80211_add_tx_ts,
5617c6cd 15362 .flags = GENL_UNS_ADMIN_PERM,
960d01ac
JB
15363 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
15364 NL80211_FLAG_NEED_RTNL,
15365 },
15366 {
15367 .cmd = NL80211_CMD_DEL_TX_TS,
ef6243ac 15368 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
960d01ac 15369 .doit = nl80211_del_tx_ts,
5617c6cd 15370 .flags = GENL_UNS_ADMIN_PERM,
960d01ac
JB
15371 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
15372 NL80211_FLAG_NEED_RTNL,
15373 },
1057d35e
AN
15374 {
15375 .cmd = NL80211_CMD_TDLS_CHANNEL_SWITCH,
ef6243ac 15376 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1057d35e 15377 .doit = nl80211_tdls_channel_switch,
5617c6cd 15378 .flags = GENL_UNS_ADMIN_PERM,
1057d35e
AN
15379 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
15380 NL80211_FLAG_NEED_RTNL,
15381 },
15382 {
15383 .cmd = NL80211_CMD_TDLS_CANCEL_CHANNEL_SWITCH,
ef6243ac 15384 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1057d35e 15385 .doit = nl80211_tdls_cancel_channel_switch,
5617c6cd 15386 .flags = GENL_UNS_ADMIN_PERM,
1057d35e
AN
15387 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
15388 NL80211_FLAG_NEED_RTNL,
15389 },
ce0ce13a
MB
15390 {
15391 .cmd = NL80211_CMD_SET_MULTICAST_TO_UNICAST,
ef6243ac 15392 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ce0ce13a 15393 .doit = nl80211_set_multicast_to_unicast,
ce0ce13a
MB
15394 .flags = GENL_UNS_ADMIN_PERM,
15395 .internal_flags = NL80211_FLAG_NEED_NETDEV |
15396 NL80211_FLAG_NEED_RTNL,
15397 },
3a00df57
AS
15398 {
15399 .cmd = NL80211_CMD_SET_PMK,
ef6243ac 15400 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
3a00df57 15401 .doit = nl80211_set_pmk,
3a00df57 15402 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
d6db02a8
SD
15403 NL80211_FLAG_NEED_RTNL |
15404 NL80211_FLAG_CLEAR_SKB,
3a00df57
AS
15405 },
15406 {
15407 .cmd = NL80211_CMD_DEL_PMK,
ef6243ac 15408 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
3a00df57 15409 .doit = nl80211_del_pmk,
3a00df57
AS
15410 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
15411 NL80211_FLAG_NEED_RTNL,
15412 },
40cbfa90
SD
15413 {
15414 .cmd = NL80211_CMD_EXTERNAL_AUTH,
ef6243ac 15415 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
40cbfa90 15416 .doit = nl80211_external_auth,
40cbfa90
SD
15417 .flags = GENL_ADMIN_PERM,
15418 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
15419 NL80211_FLAG_NEED_RTNL,
15420 },
2576a9ac
DK
15421 {
15422 .cmd = NL80211_CMD_CONTROL_PORT_FRAME,
ef6243ac 15423 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2576a9ac 15424 .doit = nl80211_tx_control_port,
2576a9ac
DK
15425 .flags = GENL_UNS_ADMIN_PERM,
15426 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
15427 NL80211_FLAG_NEED_RTNL,
15428 },
81e54d08
PKC
15429 {
15430 .cmd = NL80211_CMD_GET_FTM_RESPONDER_STATS,
ef6243ac 15431 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
81e54d08 15432 .doit = nl80211_get_ftm_responder_stats,
81e54d08
PKC
15433 .internal_flags = NL80211_FLAG_NEED_NETDEV |
15434 NL80211_FLAG_NEED_RTNL,
15435 },
9bb7e0f2
JB
15436 {
15437 .cmd = NL80211_CMD_PEER_MEASUREMENT_START,
ef6243ac 15438 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9bb7e0f2 15439 .doit = nl80211_pmsr_start,
9bb7e0f2
JB
15440 .flags = GENL_UNS_ADMIN_PERM,
15441 .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
15442 NL80211_FLAG_NEED_RTNL,
15443 },
30c63115
S
15444 {
15445 .cmd = NL80211_CMD_NOTIFY_RADAR,
ef6243ac 15446 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
30c63115 15447 .doit = nl80211_notify_radar_detection,
30c63115
S
15448 .flags = GENL_UNS_ADMIN_PERM,
15449 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
15450 NL80211_FLAG_NEED_RTNL,
15451 },
cb74e977
SD
15452 {
15453 .cmd = NL80211_CMD_UPDATE_OWE_INFO,
15454 .doit = nl80211_update_owe_info,
15455 .flags = GENL_ADMIN_PERM,
5ab92e7f
RM
15456 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
15457 NL80211_FLAG_NEED_RTNL,
15458 },
15459 {
15460 .cmd = NL80211_CMD_PROBE_MESH_LINK,
15461 .doit = nl80211_probe_mesh_link,
15462 .flags = GENL_UNS_ADMIN_PERM,
cb74e977
SD
15463 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
15464 NL80211_FLAG_NEED_RTNL,
15465 },
77f576de
T
15466 {
15467 .cmd = NL80211_CMD_SET_TID_CONFIG,
15468 .doit = nl80211_set_tid_config,
15469 .flags = GENL_UNS_ADMIN_PERM,
15470 .internal_flags = NL80211_FLAG_NEED_NETDEV |
15471 NL80211_FLAG_NEED_RTNL,
15472 },
55682965 15473};
9588bbd5 15474
56989f6d 15475static struct genl_family nl80211_fam __ro_after_init = {
489111e5
JB
15476 .name = NL80211_GENL_NAME, /* have users key off the name instead */
15477 .hdrsize = 0, /* no private header */
15478 .version = 1, /* no particular meaning now */
15479 .maxattr = NL80211_ATTR_MAX,
3b0f31f2 15480 .policy = nl80211_policy,
489111e5
JB
15481 .netnsok = true,
15482 .pre_doit = nl80211_pre_doit,
15483 .post_doit = nl80211_post_doit,
15484 .module = THIS_MODULE,
15485 .ops = nl80211_ops,
15486 .n_ops = ARRAY_SIZE(nl80211_ops),
15487 .mcgrps = nl80211_mcgrps,
15488 .n_mcgrps = ARRAY_SIZE(nl80211_mcgrps),
50508d94 15489 .parallel_ops = true,
489111e5
JB
15490};
15491
55682965
JB
15492/* notification functions */
15493
3bb20556
JB
15494void nl80211_notify_wiphy(struct cfg80211_registered_device *rdev,
15495 enum nl80211_commands cmd)
55682965
JB
15496{
15497 struct sk_buff *msg;
86e8cf98 15498 struct nl80211_dump_wiphy_state state = {};
55682965 15499
3bb20556
JB
15500 WARN_ON(cmd != NL80211_CMD_NEW_WIPHY &&
15501 cmd != NL80211_CMD_DEL_WIPHY);
15502
fd2120ca 15503 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
55682965
JB
15504 if (!msg)
15505 return;
15506
3bb20556 15507 if (nl80211_send_wiphy(rdev, cmd, msg, 0, 0, 0, &state) < 0) {
55682965
JB
15508 nlmsg_free(msg);
15509 return;
15510 }
15511
68eb5503 15512 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 15513 NL80211_MCGRP_CONFIG, GFP_KERNEL);
55682965
JB
15514}
15515
896ff063
DK
15516void nl80211_notify_iface(struct cfg80211_registered_device *rdev,
15517 struct wireless_dev *wdev,
15518 enum nl80211_commands cmd)
15519{
15520 struct sk_buff *msg;
15521
896ff063
DK
15522 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
15523 if (!msg)
15524 return;
15525
3d1a5bbf 15526 if (nl80211_send_iface(msg, 0, 0, 0, rdev, wdev, cmd) < 0) {
896ff063
DK
15527 nlmsg_free(msg);
15528 return;
15529 }
15530
15531 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
15532 NL80211_MCGRP_CONFIG, GFP_KERNEL);
15533}
15534
362a415d
JB
15535static int nl80211_add_scan_req(struct sk_buff *msg,
15536 struct cfg80211_registered_device *rdev)
15537{
15538 struct cfg80211_scan_request *req = rdev->scan_req;
15539 struct nlattr *nest;
15540 int i;
c8cb5b85 15541 struct cfg80211_scan_info *info;
362a415d
JB
15542
15543 if (WARN_ON(!req))
15544 return 0;
15545
ae0be8de 15546 nest = nla_nest_start_noflag(msg, NL80211_ATTR_SCAN_SSIDS);
362a415d
JB
15547 if (!nest)
15548 goto nla_put_failure;
9360ffd1
DM
15549 for (i = 0; i < req->n_ssids; i++) {
15550 if (nla_put(msg, i, req->ssids[i].ssid_len, req->ssids[i].ssid))
15551 goto nla_put_failure;
15552 }
362a415d
JB
15553 nla_nest_end(msg, nest);
15554
2032f3b2
TP
15555 if (req->flags & NL80211_SCAN_FLAG_FREQ_KHZ) {
15556 nest = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQ_KHZ);
15557 if (!nest)
15558 goto nla_put_failure;
15559 for (i = 0; i < req->n_channels; i++) {
15560 if (nla_put_u32(msg, i,
15561 ieee80211_channel_to_khz(req->channels[i])))
15562 goto nla_put_failure;
15563 }
15564 nla_nest_end(msg, nest);
15565 } else {
15566 nest = nla_nest_start_noflag(msg,
15567 NL80211_ATTR_SCAN_FREQUENCIES);
15568 if (!nest)
9360ffd1 15569 goto nla_put_failure;
2032f3b2
TP
15570 for (i = 0; i < req->n_channels; i++) {
15571 if (nla_put_u32(msg, i, req->channels[i]->center_freq))
15572 goto nla_put_failure;
15573 }
15574 nla_nest_end(msg, nest);
9360ffd1 15575 }
362a415d 15576
9360ffd1
DM
15577 if (req->ie &&
15578 nla_put(msg, NL80211_ATTR_IE, req->ie_len, req->ie))
15579 goto nla_put_failure;
362a415d 15580
ae917c9f
JB
15581 if (req->flags &&
15582 nla_put_u32(msg, NL80211_ATTR_SCAN_FLAGS, req->flags))
15583 goto nla_put_failure;
ed473771 15584
c8cb5b85
TM
15585 info = rdev->int_scan_req ? &rdev->int_scan_req->info :
15586 &rdev->scan_req->info;
15587 if (info->scan_start_tsf &&
1d76250b 15588 (nla_put_u64_64bit(msg, NL80211_ATTR_SCAN_START_TIME_TSF,
c8cb5b85 15589 info->scan_start_tsf, NL80211_BSS_PAD) ||
1d76250b 15590 nla_put(msg, NL80211_ATTR_SCAN_START_TIME_TSF_BSSID, ETH_ALEN,
c8cb5b85 15591 info->tsf_bssid)))
1d76250b
AS
15592 goto nla_put_failure;
15593
362a415d
JB
15594 return 0;
15595 nla_put_failure:
15596 return -ENOBUFS;
15597}
15598
505a2e88 15599static int nl80211_prep_scan_msg(struct sk_buff *msg,
a538e2d5 15600 struct cfg80211_registered_device *rdev,
fd014284 15601 struct wireless_dev *wdev,
15e47304 15602 u32 portid, u32 seq, int flags,
a538e2d5 15603 u32 cmd)
2a519311
JB
15604{
15605 void *hdr;
15606
15e47304 15607 hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
2a519311
JB
15608 if (!hdr)
15609 return -1;
15610
9360ffd1 15611 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
fd014284
JB
15612 (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
15613 wdev->netdev->ifindex)) ||
2dad624e
ND
15614 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
15615 NL80211_ATTR_PAD))
9360ffd1 15616 goto nla_put_failure;
2a519311 15617
362a415d
JB
15618 /* ignore errors and send incomplete event anyway */
15619 nl80211_add_scan_req(msg, rdev);
2a519311 15620
053c095a
JB
15621 genlmsg_end(msg, hdr);
15622 return 0;
2a519311
JB
15623
15624 nla_put_failure:
15625 genlmsg_cancel(msg, hdr);
15626 return -EMSGSIZE;
15627}
15628
807f8a8c 15629static int
505a2e88 15630nl80211_prep_sched_scan_msg(struct sk_buff *msg,
96b08fd6 15631 struct cfg80211_sched_scan_request *req, u32 cmd)
807f8a8c
LC
15632{
15633 void *hdr;
15634
96b08fd6 15635 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
807f8a8c
LC
15636 if (!hdr)
15637 return -1;
15638
96b08fd6
AVS
15639 if (nla_put_u32(msg, NL80211_ATTR_WIPHY,
15640 wiphy_to_rdev(req->wiphy)->wiphy_idx) ||
15641 nla_put_u32(msg, NL80211_ATTR_IFINDEX, req->dev->ifindex) ||
15642 nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, req->reqid,
15643 NL80211_ATTR_PAD))
9360ffd1 15644 goto nla_put_failure;
807f8a8c 15645
053c095a
JB
15646 genlmsg_end(msg, hdr);
15647 return 0;
807f8a8c
LC
15648
15649 nla_put_failure:
15650 genlmsg_cancel(msg, hdr);
15651 return -EMSGSIZE;
15652}
15653
a538e2d5 15654void nl80211_send_scan_start(struct cfg80211_registered_device *rdev,
fd014284 15655 struct wireless_dev *wdev)
a538e2d5
JB
15656{
15657 struct sk_buff *msg;
15658
58050fce 15659 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
a538e2d5
JB
15660 if (!msg)
15661 return;
15662
505a2e88 15663 if (nl80211_prep_scan_msg(msg, rdev, wdev, 0, 0, 0,
a538e2d5
JB
15664 NL80211_CMD_TRIGGER_SCAN) < 0) {
15665 nlmsg_free(msg);
15666 return;
15667 }
15668
68eb5503 15669 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 15670 NL80211_MCGRP_SCAN, GFP_KERNEL);
a538e2d5
JB
15671}
15672
f9d15d16
JB
15673struct sk_buff *nl80211_build_scan_msg(struct cfg80211_registered_device *rdev,
15674 struct wireless_dev *wdev, bool aborted)
2a519311
JB
15675{
15676 struct sk_buff *msg;
15677
fd2120ca 15678 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2a519311 15679 if (!msg)
f9d15d16 15680 return NULL;
2a519311 15681
505a2e88 15682 if (nl80211_prep_scan_msg(msg, rdev, wdev, 0, 0, 0,
f9d15d16
JB
15683 aborted ? NL80211_CMD_SCAN_ABORTED :
15684 NL80211_CMD_NEW_SCAN_RESULTS) < 0) {
2a519311 15685 nlmsg_free(msg);
f9d15d16 15686 return NULL;
2a519311
JB
15687 }
15688
f9d15d16 15689 return msg;
2a519311
JB
15690}
15691
505a2e88
AVS
15692/* send message created by nl80211_build_scan_msg() */
15693void nl80211_send_scan_msg(struct cfg80211_registered_device *rdev,
15694 struct sk_buff *msg)
807f8a8c 15695{
807f8a8c
LC
15696 if (!msg)
15697 return;
15698
68eb5503 15699 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 15700 NL80211_MCGRP_SCAN, GFP_KERNEL);
807f8a8c
LC
15701}
15702
96b08fd6 15703void nl80211_send_sched_scan(struct cfg80211_sched_scan_request *req, u32 cmd)
807f8a8c
LC
15704{
15705 struct sk_buff *msg;
15706
58050fce 15707 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
807f8a8c
LC
15708 if (!msg)
15709 return;
15710
96b08fd6 15711 if (nl80211_prep_sched_scan_msg(msg, req, cmd) < 0) {
807f8a8c
LC
15712 nlmsg_free(msg);
15713 return;
15714 }
15715
96b08fd6 15716 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(req->wiphy), msg, 0,
2a94fe48 15717 NL80211_MCGRP_SCAN, GFP_KERNEL);
807f8a8c
LC
15718}
15719
b0d7aa59
JD
15720static bool nl80211_reg_change_event_fill(struct sk_buff *msg,
15721 struct regulatory_request *request)
73d54c9e 15722{
73d54c9e 15723 /* Userspace can always count this one always being set */
9360ffd1
DM
15724 if (nla_put_u8(msg, NL80211_ATTR_REG_INITIATOR, request->initiator))
15725 goto nla_put_failure;
15726
15727 if (request->alpha2[0] == '0' && request->alpha2[1] == '0') {
15728 if (nla_put_u8(msg, NL80211_ATTR_REG_TYPE,
15729 NL80211_REGDOM_TYPE_WORLD))
15730 goto nla_put_failure;
15731 } else if (request->alpha2[0] == '9' && request->alpha2[1] == '9') {
15732 if (nla_put_u8(msg, NL80211_ATTR_REG_TYPE,
15733 NL80211_REGDOM_TYPE_CUSTOM_WORLD))
15734 goto nla_put_failure;
15735 } else if ((request->alpha2[0] == '9' && request->alpha2[1] == '8') ||
15736 request->intersect) {
15737 if (nla_put_u8(msg, NL80211_ATTR_REG_TYPE,
15738 NL80211_REGDOM_TYPE_INTERSECTION))
15739 goto nla_put_failure;
15740 } else {
15741 if (nla_put_u8(msg, NL80211_ATTR_REG_TYPE,
15742 NL80211_REGDOM_TYPE_COUNTRY) ||
15743 nla_put_string(msg, NL80211_ATTR_REG_ALPHA2,
15744 request->alpha2))
15745 goto nla_put_failure;
15746 }
15747
ad30ca2c
AN
15748 if (request->wiphy_idx != WIPHY_IDX_INVALID) {
15749 struct wiphy *wiphy = wiphy_idx_to_wiphy(request->wiphy_idx);
15750
15751 if (wiphy &&
15752 nla_put_u32(msg, NL80211_ATTR_WIPHY, request->wiphy_idx))
15753 goto nla_put_failure;
1bdd716c
AN
15754
15755 if (wiphy &&
15756 wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED &&
15757 nla_put_flag(msg, NL80211_ATTR_WIPHY_SELF_MANAGED_REG))
15758 goto nla_put_failure;
ad30ca2c 15759 }
73d54c9e 15760
b0d7aa59
JD
15761 return true;
15762
15763nla_put_failure:
15764 return false;
15765}
15766
15767/*
15768 * This can happen on global regulatory changes or device specific settings
15769 * based on custom regulatory domains.
15770 */
15771void nl80211_common_reg_change_event(enum nl80211_commands cmd_id,
15772 struct regulatory_request *request)
15773{
15774 struct sk_buff *msg;
15775 void *hdr;
15776
15777 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
15778 if (!msg)
15779 return;
15780
15781 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd_id);
24f6d765 15782 if (!hdr)
15783 goto nla_put_failure;
b0d7aa59 15784
24f6d765 15785 if (!nl80211_reg_change_event_fill(msg, request))
b0d7aa59
JD
15786 goto nla_put_failure;
15787
3b7b72ee 15788 genlmsg_end(msg, hdr);
73d54c9e 15789
bc43b28c 15790 rcu_read_lock();
68eb5503 15791 genlmsg_multicast_allns(&nl80211_fam, msg, 0,
2a94fe48 15792 NL80211_MCGRP_REGULATORY, GFP_ATOMIC);
bc43b28c 15793 rcu_read_unlock();
73d54c9e
LR
15794
15795 return;
15796
15797nla_put_failure:
73d54c9e
LR
15798 nlmsg_free(msg);
15799}
15800
6039f6d2
JM
15801static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev,
15802 struct net_device *netdev,
15803 const u8 *buf, size_t len,
b0b6aa2c 15804 enum nl80211_commands cmd, gfp_t gfp,
4d9ec73d
JM
15805 int uapsd_queues, const u8 *req_ies,
15806 size_t req_ies_len)
6039f6d2
JM
15807{
15808 struct sk_buff *msg;
15809 void *hdr;
15810
4d9ec73d 15811 msg = nlmsg_new(100 + len + req_ies_len, gfp);
6039f6d2
JM
15812 if (!msg)
15813 return;
15814
15815 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
15816 if (!hdr) {
15817 nlmsg_free(msg);
15818 return;
15819 }
15820
9360ffd1
DM
15821 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
15822 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
4d9ec73d
JM
15823 nla_put(msg, NL80211_ATTR_FRAME, len, buf) ||
15824 (req_ies &&
15825 nla_put(msg, NL80211_ATTR_REQ_IE, req_ies_len, req_ies)))
9360ffd1 15826 goto nla_put_failure;
6039f6d2 15827
b0b6aa2c
EP
15828 if (uapsd_queues >= 0) {
15829 struct nlattr *nla_wmm =
ae0be8de 15830 nla_nest_start_noflag(msg, NL80211_ATTR_STA_WME);
b0b6aa2c
EP
15831 if (!nla_wmm)
15832 goto nla_put_failure;
15833
15834 if (nla_put_u8(msg, NL80211_STA_WME_UAPSD_QUEUES,
15835 uapsd_queues))
15836 goto nla_put_failure;
15837
15838 nla_nest_end(msg, nla_wmm);
15839 }
15840
3b7b72ee 15841 genlmsg_end(msg, hdr);
6039f6d2 15842
68eb5503 15843 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 15844 NL80211_MCGRP_MLME, gfp);
6039f6d2
JM
15845 return;
15846
15847 nla_put_failure:
6039f6d2
JM
15848 nlmsg_free(msg);
15849}
15850
15851void nl80211_send_rx_auth(struct cfg80211_registered_device *rdev,
e6d6e342
JB
15852 struct net_device *netdev, const u8 *buf,
15853 size_t len, gfp_t gfp)
6039f6d2
JM
15854{
15855 nl80211_send_mlme_event(rdev, netdev, buf, len,
4d9ec73d 15856 NL80211_CMD_AUTHENTICATE, gfp, -1, NULL, 0);
6039f6d2
JM
15857}
15858
15859void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev,
15860 struct net_device *netdev, const u8 *buf,
4d9ec73d
JM
15861 size_t len, gfp_t gfp, int uapsd_queues,
15862 const u8 *req_ies, size_t req_ies_len)
6039f6d2 15863{
e6d6e342 15864 nl80211_send_mlme_event(rdev, netdev, buf, len,
4d9ec73d
JM
15865 NL80211_CMD_ASSOCIATE, gfp, uapsd_queues,
15866 req_ies, req_ies_len);
6039f6d2
JM
15867}
15868
53b46b84 15869void nl80211_send_deauth(struct cfg80211_registered_device *rdev,
e6d6e342
JB
15870 struct net_device *netdev, const u8 *buf,
15871 size_t len, gfp_t gfp)
6039f6d2
JM
15872{
15873 nl80211_send_mlme_event(rdev, netdev, buf, len,
4d9ec73d 15874 NL80211_CMD_DEAUTHENTICATE, gfp, -1, NULL, 0);
6039f6d2
JM
15875}
15876
53b46b84
JM
15877void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,
15878 struct net_device *netdev, const u8 *buf,
e6d6e342 15879 size_t len, gfp_t gfp)
6039f6d2
JM
15880{
15881 nl80211_send_mlme_event(rdev, netdev, buf, len,
4d9ec73d 15882 NL80211_CMD_DISASSOCIATE, gfp, -1, NULL, 0);
6039f6d2
JM
15883}
15884
6ff57cf8
JB
15885void cfg80211_rx_unprot_mlme_mgmt(struct net_device *dev, const u8 *buf,
15886 size_t len)
cf4e594e 15887{
947add36
JB
15888 struct wireless_dev *wdev = dev->ieee80211_ptr;
15889 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 15890 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
6ff57cf8
JB
15891 const struct ieee80211_mgmt *mgmt = (void *)buf;
15892 u32 cmd;
947add36 15893
6ff57cf8
JB
15894 if (WARN_ON(len < 2))
15895 return;
cf4e594e 15896
4d797fce 15897 if (ieee80211_is_deauth(mgmt->frame_control)) {
6ff57cf8 15898 cmd = NL80211_CMD_UNPROT_DEAUTHENTICATE;
4d797fce 15899 } else if (ieee80211_is_disassoc(mgmt->frame_control)) {
6ff57cf8 15900 cmd = NL80211_CMD_UNPROT_DISASSOCIATE;
4d797fce
JM
15901 } else if (ieee80211_is_beacon(mgmt->frame_control)) {
15902 if (wdev->unprot_beacon_reported &&
15903 elapsed_jiffies_msecs(wdev->unprot_beacon_reported) < 10000)
15904 return;
15905 cmd = NL80211_CMD_UNPROT_BEACON;
15906 wdev->unprot_beacon_reported = jiffies;
15907 } else {
15908 return;
15909 }
947add36 15910
6ff57cf8 15911 trace_cfg80211_rx_unprot_mlme_mgmt(dev, buf, len);
4d9ec73d
JM
15912 nl80211_send_mlme_event(rdev, dev, buf, len, cmd, GFP_ATOMIC, -1,
15913 NULL, 0);
cf4e594e 15914}
6ff57cf8 15915EXPORT_SYMBOL(cfg80211_rx_unprot_mlme_mgmt);
cf4e594e 15916
1b06bb40
LR
15917static void nl80211_send_mlme_timeout(struct cfg80211_registered_device *rdev,
15918 struct net_device *netdev, int cmd,
e6d6e342 15919 const u8 *addr, gfp_t gfp)
1965c853
JM
15920{
15921 struct sk_buff *msg;
15922 void *hdr;
15923
e6d6e342 15924 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
1965c853
JM
15925 if (!msg)
15926 return;
15927
15928 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
15929 if (!hdr) {
15930 nlmsg_free(msg);
15931 return;
15932 }
15933
9360ffd1
DM
15934 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
15935 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
15936 nla_put_flag(msg, NL80211_ATTR_TIMED_OUT) ||
15937 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr))
15938 goto nla_put_failure;
1965c853 15939
3b7b72ee 15940 genlmsg_end(msg, hdr);
1965c853 15941
68eb5503 15942 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 15943 NL80211_MCGRP_MLME, gfp);
1965c853
JM
15944 return;
15945
15946 nla_put_failure:
1965c853
JM
15947 nlmsg_free(msg);
15948}
15949
15950void nl80211_send_auth_timeout(struct cfg80211_registered_device *rdev,
e6d6e342
JB
15951 struct net_device *netdev, const u8 *addr,
15952 gfp_t gfp)
1965c853
JM
15953{
15954 nl80211_send_mlme_timeout(rdev, netdev, NL80211_CMD_AUTHENTICATE,
e6d6e342 15955 addr, gfp);
1965c853
JM
15956}
15957
15958void nl80211_send_assoc_timeout(struct cfg80211_registered_device *rdev,
e6d6e342
JB
15959 struct net_device *netdev, const u8 *addr,
15960 gfp_t gfp)
1965c853 15961{
e6d6e342
JB
15962 nl80211_send_mlme_timeout(rdev, netdev, NL80211_CMD_ASSOCIATE,
15963 addr, gfp);
1965c853
JM
15964}
15965
b23aa676 15966void nl80211_send_connect_result(struct cfg80211_registered_device *rdev,
5349a0f7
VK
15967 struct net_device *netdev,
15968 struct cfg80211_connect_resp_params *cr,
3093ebbe 15969 gfp_t gfp)
b23aa676
SO
15970{
15971 struct sk_buff *msg;
15972 void *hdr;
15973
a3caf744 15974 msg = nlmsg_new(100 + cr->req_ie_len + cr->resp_ie_len +
76804d28
AVS
15975 cr->fils.kek_len + cr->fils.pmk_len +
15976 (cr->fils.pmkid ? WLAN_PMKID_LEN : 0), gfp);
b23aa676
SO
15977 if (!msg)
15978 return;
15979
15980 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CONNECT);
15981 if (!hdr) {
15982 nlmsg_free(msg);
15983 return;
15984 }
15985
9360ffd1
DM
15986 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
15987 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
5349a0f7
VK
15988 (cr->bssid &&
15989 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, cr->bssid)) ||
bf1ecd21 15990 nla_put_u16(msg, NL80211_ATTR_STATUS_CODE,
5349a0f7
VK
15991 cr->status < 0 ? WLAN_STATUS_UNSPECIFIED_FAILURE :
15992 cr->status) ||
15993 (cr->status < 0 &&
3093ebbe 15994 (nla_put_flag(msg, NL80211_ATTR_TIMED_OUT) ||
5349a0f7
VK
15995 nla_put_u32(msg, NL80211_ATTR_TIMEOUT_REASON,
15996 cr->timeout_reason))) ||
15997 (cr->req_ie &&
15998 nla_put(msg, NL80211_ATTR_REQ_IE, cr->req_ie_len, cr->req_ie)) ||
15999 (cr->resp_ie &&
16000 nla_put(msg, NL80211_ATTR_RESP_IE, cr->resp_ie_len,
a3caf744 16001 cr->resp_ie)) ||
76804d28 16002 (cr->fils.update_erp_next_seq_num &&
a3caf744 16003 nla_put_u16(msg, NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM,
76804d28 16004 cr->fils.erp_next_seq_num)) ||
a3caf744 16005 (cr->status == WLAN_STATUS_SUCCESS &&
76804d28
AVS
16006 ((cr->fils.kek &&
16007 nla_put(msg, NL80211_ATTR_FILS_KEK, cr->fils.kek_len,
16008 cr->fils.kek)) ||
16009 (cr->fils.pmk &&
16010 nla_put(msg, NL80211_ATTR_PMK, cr->fils.pmk_len, cr->fils.pmk)) ||
16011 (cr->fils.pmkid &&
16012 nla_put(msg, NL80211_ATTR_PMKID, WLAN_PMKID_LEN, cr->fils.pmkid)))))
9360ffd1 16013 goto nla_put_failure;
b23aa676 16014
3b7b72ee 16015 genlmsg_end(msg, hdr);
b23aa676 16016
68eb5503 16017 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 16018 NL80211_MCGRP_MLME, gfp);
b23aa676
SO
16019 return;
16020
16021 nla_put_failure:
b23aa676 16022 nlmsg_free(msg);
b23aa676
SO
16023}
16024
16025void nl80211_send_roamed(struct cfg80211_registered_device *rdev,
29ce6ecb
AS
16026 struct net_device *netdev,
16027 struct cfg80211_roam_info *info, gfp_t gfp)
b23aa676
SO
16028{
16029 struct sk_buff *msg;
16030 void *hdr;
29ce6ecb 16031 const u8 *bssid = info->bss ? info->bss->bssid : info->bssid;
b23aa676 16032
e841b7b1
AVS
16033 msg = nlmsg_new(100 + info->req_ie_len + info->resp_ie_len +
16034 info->fils.kek_len + info->fils.pmk_len +
16035 (info->fils.pmkid ? WLAN_PMKID_LEN : 0), gfp);
b23aa676
SO
16036 if (!msg)
16037 return;
16038
16039 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_ROAM);
16040 if (!hdr) {
16041 nlmsg_free(msg);
16042 return;
16043 }
16044
9360ffd1
DM
16045 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
16046 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
16047 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid) ||
29ce6ecb
AS
16048 (info->req_ie &&
16049 nla_put(msg, NL80211_ATTR_REQ_IE, info->req_ie_len,
16050 info->req_ie)) ||
16051 (info->resp_ie &&
16052 nla_put(msg, NL80211_ATTR_RESP_IE, info->resp_ie_len,
e841b7b1
AVS
16053 info->resp_ie)) ||
16054 (info->fils.update_erp_next_seq_num &&
16055 nla_put_u16(msg, NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM,
16056 info->fils.erp_next_seq_num)) ||
16057 (info->fils.kek &&
16058 nla_put(msg, NL80211_ATTR_FILS_KEK, info->fils.kek_len,
16059 info->fils.kek)) ||
16060 (info->fils.pmk &&
16061 nla_put(msg, NL80211_ATTR_PMK, info->fils.pmk_len, info->fils.pmk)) ||
16062 (info->fils.pmkid &&
16063 nla_put(msg, NL80211_ATTR_PMKID, WLAN_PMKID_LEN, info->fils.pmkid)))
9360ffd1 16064 goto nla_put_failure;
b23aa676 16065
3b7b72ee 16066 genlmsg_end(msg, hdr);
b23aa676 16067
68eb5503 16068 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 16069 NL80211_MCGRP_MLME, gfp);
b23aa676
SO
16070 return;
16071
503c1fb9 16072 nla_put_failure:
503c1fb9
AS
16073 nlmsg_free(msg);
16074}
16075
16076void nl80211_send_port_authorized(struct cfg80211_registered_device *rdev,
16077 struct net_device *netdev, const u8 *bssid)
16078{
16079 struct sk_buff *msg;
16080 void *hdr;
16081
16082 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
16083 if (!msg)
16084 return;
16085
16086 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_PORT_AUTHORIZED);
16087 if (!hdr) {
16088 nlmsg_free(msg);
16089 return;
16090 }
16091
f4d75993
CHH
16092 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
16093 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
16094 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid))
503c1fb9
AS
16095 goto nla_put_failure;
16096
16097 genlmsg_end(msg, hdr);
16098
16099 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
16100 NL80211_MCGRP_MLME, GFP_KERNEL);
16101 return;
16102
b23aa676 16103 nla_put_failure:
b23aa676 16104 nlmsg_free(msg);
b23aa676
SO
16105}
16106
16107void nl80211_send_disconnected(struct cfg80211_registered_device *rdev,
16108 struct net_device *netdev, u16 reason,
667503dd 16109 const u8 *ie, size_t ie_len, bool from_ap)
b23aa676
SO
16110{
16111 struct sk_buff *msg;
16112 void *hdr;
16113
4ef8c1c9 16114 msg = nlmsg_new(100 + ie_len, GFP_KERNEL);
b23aa676
SO
16115 if (!msg)
16116 return;
16117
16118 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_DISCONNECT);
16119 if (!hdr) {
16120 nlmsg_free(msg);
16121 return;
16122 }
16123
9360ffd1
DM
16124 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
16125 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
86b6c465 16126 (reason &&
9360ffd1
DM
16127 nla_put_u16(msg, NL80211_ATTR_REASON_CODE, reason)) ||
16128 (from_ap &&
16129 nla_put_flag(msg, NL80211_ATTR_DISCONNECTED_BY_AP)) ||
16130 (ie && nla_put(msg, NL80211_ATTR_IE, ie_len, ie)))
16131 goto nla_put_failure;
b23aa676 16132
3b7b72ee 16133 genlmsg_end(msg, hdr);
b23aa676 16134
68eb5503 16135 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 16136 NL80211_MCGRP_MLME, GFP_KERNEL);
b23aa676
SO
16137 return;
16138
16139 nla_put_failure:
b23aa676 16140 nlmsg_free(msg);
b23aa676
SO
16141}
16142
04a773ad
JB
16143void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev,
16144 struct net_device *netdev, const u8 *bssid,
16145 gfp_t gfp)
16146{
16147 struct sk_buff *msg;
16148 void *hdr;
16149
fd2120ca 16150 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
04a773ad
JB
16151 if (!msg)
16152 return;
16153
16154 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_JOIN_IBSS);
16155 if (!hdr) {
16156 nlmsg_free(msg);
16157 return;
16158 }
16159
9360ffd1
DM
16160 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
16161 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
16162 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid))
16163 goto nla_put_failure;
04a773ad 16164
3b7b72ee 16165 genlmsg_end(msg, hdr);
04a773ad 16166
68eb5503 16167 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 16168 NL80211_MCGRP_MLME, gfp);
04a773ad
JB
16169 return;
16170
16171 nla_put_failure:
04a773ad
JB
16172 nlmsg_free(msg);
16173}
16174
947add36 16175void cfg80211_notify_new_peer_candidate(struct net_device *dev, const u8 *addr,
ecbc12ad
BC
16176 const u8 *ie, u8 ie_len,
16177 int sig_dbm, gfp_t gfp)
c93b5e71 16178{
947add36 16179 struct wireless_dev *wdev = dev->ieee80211_ptr;
f26cbf40 16180 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
c93b5e71
JC
16181 struct sk_buff *msg;
16182 void *hdr;
16183
947add36
JB
16184 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_MESH_POINT))
16185 return;
16186
16187 trace_cfg80211_notify_new_peer_candidate(dev, addr);
16188
4ef8c1c9 16189 msg = nlmsg_new(100 + ie_len, gfp);
c93b5e71
JC
16190 if (!msg)
16191 return;
16192
16193 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NEW_PEER_CANDIDATE);
16194 if (!hdr) {
16195 nlmsg_free(msg);
16196 return;
16197 }
16198
9360ffd1 16199 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
947add36
JB
16200 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
16201 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
9360ffd1 16202 (ie_len && ie &&
ecbc12ad
BC
16203 nla_put(msg, NL80211_ATTR_IE, ie_len, ie)) ||
16204 (sig_dbm &&
16205 nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)))
9360ffd1 16206 goto nla_put_failure;
c93b5e71 16207
3b7b72ee 16208 genlmsg_end(msg, hdr);
c93b5e71 16209
68eb5503 16210 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 16211 NL80211_MCGRP_MLME, gfp);
c93b5e71
JC
16212 return;
16213
16214 nla_put_failure:
c93b5e71
JC
16215 nlmsg_free(msg);
16216}
947add36 16217EXPORT_SYMBOL(cfg80211_notify_new_peer_candidate);
c93b5e71 16218
a3b8b056
JM
16219void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev,
16220 struct net_device *netdev, const u8 *addr,
16221 enum nl80211_key_type key_type, int key_id,
e6d6e342 16222 const u8 *tsc, gfp_t gfp)
a3b8b056
JM
16223{
16224 struct sk_buff *msg;
16225 void *hdr;
16226
e6d6e342 16227 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
a3b8b056
JM
16228 if (!msg)
16229 return;
16230
16231 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_MICHAEL_MIC_FAILURE);
16232 if (!hdr) {
16233 nlmsg_free(msg);
16234 return;
16235 }
16236
9360ffd1
DM
16237 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
16238 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
16239 (addr && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) ||
16240 nla_put_u32(msg, NL80211_ATTR_KEY_TYPE, key_type) ||
16241 (key_id != -1 &&
16242 nla_put_u8(msg, NL80211_ATTR_KEY_IDX, key_id)) ||
16243 (tsc && nla_put(msg, NL80211_ATTR_KEY_SEQ, 6, tsc)))
16244 goto nla_put_failure;
a3b8b056 16245
3b7b72ee 16246 genlmsg_end(msg, hdr);
a3b8b056 16247
68eb5503 16248 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 16249 NL80211_MCGRP_MLME, gfp);
a3b8b056
JM
16250 return;
16251
16252 nla_put_failure:
a3b8b056
JM
16253 nlmsg_free(msg);
16254}
16255
6bad8766
LR
16256void nl80211_send_beacon_hint_event(struct wiphy *wiphy,
16257 struct ieee80211_channel *channel_before,
16258 struct ieee80211_channel *channel_after)
16259{
16260 struct sk_buff *msg;
16261 void *hdr;
16262 struct nlattr *nl_freq;
16263
fd2120ca 16264 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
6bad8766
LR
16265 if (!msg)
16266 return;
16267
16268 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_REG_BEACON_HINT);
16269 if (!hdr) {
16270 nlmsg_free(msg);
16271 return;
16272 }
16273
16274 /*
16275 * Since we are applying the beacon hint to a wiphy we know its
16276 * wiphy_idx is valid
16277 */
9360ffd1
DM
16278 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, get_wiphy_idx(wiphy)))
16279 goto nla_put_failure;
6bad8766
LR
16280
16281 /* Before */
ae0be8de 16282 nl_freq = nla_nest_start_noflag(msg, NL80211_ATTR_FREQ_BEFORE);
6bad8766
LR
16283 if (!nl_freq)
16284 goto nla_put_failure;
50f32718
HD
16285
16286 if (nl80211_msg_put_channel(msg, wiphy, channel_before, false))
6bad8766
LR
16287 goto nla_put_failure;
16288 nla_nest_end(msg, nl_freq);
16289
16290 /* After */
ae0be8de 16291 nl_freq = nla_nest_start_noflag(msg, NL80211_ATTR_FREQ_AFTER);
6bad8766
LR
16292 if (!nl_freq)
16293 goto nla_put_failure;
50f32718
HD
16294
16295 if (nl80211_msg_put_channel(msg, wiphy, channel_after, false))
6bad8766
LR
16296 goto nla_put_failure;
16297 nla_nest_end(msg, nl_freq);
16298
3b7b72ee 16299 genlmsg_end(msg, hdr);
6bad8766 16300
463d0183 16301 rcu_read_lock();
68eb5503 16302 genlmsg_multicast_allns(&nl80211_fam, msg, 0,
2a94fe48 16303 NL80211_MCGRP_REGULATORY, GFP_ATOMIC);
463d0183 16304 rcu_read_unlock();
6bad8766
LR
16305
16306 return;
16307
16308nla_put_failure:
6bad8766
LR
16309 nlmsg_free(msg);
16310}
16311
9588bbd5
JM
16312static void nl80211_send_remain_on_chan_event(
16313 int cmd, struct cfg80211_registered_device *rdev,
71bbc994 16314 struct wireless_dev *wdev, u64 cookie,
9588bbd5 16315 struct ieee80211_channel *chan,
9588bbd5
JM
16316 unsigned int duration, gfp_t gfp)
16317{
16318 struct sk_buff *msg;
16319 void *hdr;
16320
16321 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
16322 if (!msg)
16323 return;
16324
16325 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
16326 if (!hdr) {
16327 nlmsg_free(msg);
16328 return;
16329 }
16330
9360ffd1 16331 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
71bbc994
JB
16332 (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
16333 wdev->netdev->ifindex)) ||
2dad624e
ND
16334 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
16335 NL80211_ATTR_PAD) ||
9360ffd1 16336 nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, chan->center_freq) ||
42d97a59
JB
16337 nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
16338 NL80211_CHAN_NO_HT) ||
2dad624e
ND
16339 nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
16340 NL80211_ATTR_PAD))
9360ffd1 16341 goto nla_put_failure;
9588bbd5 16342
9360ffd1
DM
16343 if (cmd == NL80211_CMD_REMAIN_ON_CHANNEL &&
16344 nla_put_u32(msg, NL80211_ATTR_DURATION, duration))
16345 goto nla_put_failure;
9588bbd5 16346
3b7b72ee 16347 genlmsg_end(msg, hdr);
9588bbd5 16348
68eb5503 16349 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 16350 NL80211_MCGRP_MLME, gfp);
9588bbd5
JM
16351 return;
16352
16353 nla_put_failure:
9588bbd5
JM
16354 nlmsg_free(msg);
16355}
16356
947add36
JB
16357void cfg80211_ready_on_channel(struct wireless_dev *wdev, u64 cookie,
16358 struct ieee80211_channel *chan,
16359 unsigned int duration, gfp_t gfp)
9588bbd5 16360{
947add36 16361 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 16362 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
947add36
JB
16363
16364 trace_cfg80211_ready_on_channel(wdev, cookie, chan, duration);
9588bbd5 16365 nl80211_send_remain_on_chan_event(NL80211_CMD_REMAIN_ON_CHANNEL,
71bbc994 16366 rdev, wdev, cookie, chan,
42d97a59 16367 duration, gfp);
9588bbd5 16368}
947add36 16369EXPORT_SYMBOL(cfg80211_ready_on_channel);
9588bbd5 16370
947add36
JB
16371void cfg80211_remain_on_channel_expired(struct wireless_dev *wdev, u64 cookie,
16372 struct ieee80211_channel *chan,
16373 gfp_t gfp)
9588bbd5 16374{
947add36 16375 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 16376 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
947add36
JB
16377
16378 trace_cfg80211_ready_on_channel_expired(wdev, cookie, chan);
9588bbd5 16379 nl80211_send_remain_on_chan_event(NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL,
42d97a59 16380 rdev, wdev, cookie, chan, 0, gfp);
9588bbd5 16381}
947add36 16382EXPORT_SYMBOL(cfg80211_remain_on_channel_expired);
9588bbd5 16383
1c38c7f2
JP
16384void cfg80211_tx_mgmt_expired(struct wireless_dev *wdev, u64 cookie,
16385 struct ieee80211_channel *chan,
16386 gfp_t gfp)
16387{
16388 struct wiphy *wiphy = wdev->wiphy;
16389 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
16390
16391 trace_cfg80211_tx_mgmt_expired(wdev, cookie, chan);
16392 nl80211_send_remain_on_chan_event(NL80211_CMD_FRAME_WAIT_CANCEL,
16393 rdev, wdev, cookie, chan, 0, gfp);
16394}
16395EXPORT_SYMBOL(cfg80211_tx_mgmt_expired);
16396
947add36
JB
16397void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr,
16398 struct station_info *sinfo, gfp_t gfp)
98b62183 16399{
947add36 16400 struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
f26cbf40 16401 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
98b62183
JB
16402 struct sk_buff *msg;
16403
947add36
JB
16404 trace_cfg80211_new_sta(dev, mac_addr, sinfo);
16405
58050fce 16406 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
98b62183
JB
16407 if (!msg)
16408 return;
16409
cf5ead82 16410 if (nl80211_send_station(msg, NL80211_CMD_NEW_STATION, 0, 0, 0,
66266b3a 16411 rdev, dev, mac_addr, sinfo) < 0) {
98b62183
JB
16412 nlmsg_free(msg);
16413 return;
16414 }
16415
68eb5503 16416 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 16417 NL80211_MCGRP_MLME, gfp);
98b62183 16418}
947add36 16419EXPORT_SYMBOL(cfg80211_new_sta);
98b62183 16420
cf5ead82
JB
16421void cfg80211_del_sta_sinfo(struct net_device *dev, const u8 *mac_addr,
16422 struct station_info *sinfo, gfp_t gfp)
ec15e68b 16423{
947add36 16424 struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
f26cbf40 16425 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
ec15e68b 16426 struct sk_buff *msg;
73887fd9 16427 struct station_info empty_sinfo = {};
cf5ead82 16428
73887fd9
JB
16429 if (!sinfo)
16430 sinfo = &empty_sinfo;
ec15e68b 16431
947add36
JB
16432 trace_cfg80211_del_sta(dev, mac_addr);
16433
58050fce 16434 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
7ea3e110
JB
16435 if (!msg) {
16436 cfg80211_sinfo_release_content(sinfo);
73887fd9 16437 return;
7ea3e110 16438 }
ec15e68b 16439
cf5ead82 16440 if (nl80211_send_station(msg, NL80211_CMD_DEL_STATION, 0, 0, 0,
57007121 16441 rdev, dev, mac_addr, sinfo) < 0) {
ec15e68b 16442 nlmsg_free(msg);
73887fd9 16443 return;
ec15e68b
JM
16444 }
16445
68eb5503 16446 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 16447 NL80211_MCGRP_MLME, gfp);
ec15e68b 16448}
cf5ead82 16449EXPORT_SYMBOL(cfg80211_del_sta_sinfo);
ec15e68b 16450
947add36
JB
16451void cfg80211_conn_failed(struct net_device *dev, const u8 *mac_addr,
16452 enum nl80211_connect_failed_reason reason,
16453 gfp_t gfp)
ed44a951 16454{
947add36 16455 struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
f26cbf40 16456 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
ed44a951
PP
16457 struct sk_buff *msg;
16458 void *hdr;
16459
16460 msg = nlmsg_new(NLMSG_GOODSIZE, gfp);
16461 if (!msg)
16462 return;
16463
16464 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CONN_FAILED);
16465 if (!hdr) {
16466 nlmsg_free(msg);
16467 return;
16468 }
16469
16470 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
16471 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr) ||
16472 nla_put_u32(msg, NL80211_ATTR_CONN_FAILED_REASON, reason))
16473 goto nla_put_failure;
16474
16475 genlmsg_end(msg, hdr);
16476
68eb5503 16477 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 16478 NL80211_MCGRP_MLME, gfp);
ed44a951
PP
16479 return;
16480
16481 nla_put_failure:
ed44a951
PP
16482 nlmsg_free(msg);
16483}
947add36 16484EXPORT_SYMBOL(cfg80211_conn_failed);
ed44a951 16485
b92ab5d8
JB
16486static bool __nl80211_unexpected_frame(struct net_device *dev, u8 cmd,
16487 const u8 *addr, gfp_t gfp)
28946da7
JB
16488{
16489 struct wireless_dev *wdev = dev->ieee80211_ptr;
f26cbf40 16490 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
28946da7
JB
16491 struct sk_buff *msg;
16492 void *hdr;
6aa7de05 16493 u32 nlportid = READ_ONCE(wdev->ap_unexpected_nlportid);
28946da7 16494
15e47304 16495 if (!nlportid)
28946da7
JB
16496 return false;
16497
16498 msg = nlmsg_new(100, gfp);
16499 if (!msg)
16500 return true;
16501
b92ab5d8 16502 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
28946da7
JB
16503 if (!hdr) {
16504 nlmsg_free(msg);
16505 return true;
16506 }
16507
9360ffd1
DM
16508 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
16509 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
16510 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr))
16511 goto nla_put_failure;
28946da7 16512
9c90a9f6 16513 genlmsg_end(msg, hdr);
15e47304 16514 genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid);
28946da7
JB
16515 return true;
16516
16517 nla_put_failure:
28946da7
JB
16518 nlmsg_free(msg);
16519 return true;
16520}
16521
947add36
JB
16522bool cfg80211_rx_spurious_frame(struct net_device *dev,
16523 const u8 *addr, gfp_t gfp)
b92ab5d8 16524{
947add36
JB
16525 struct wireless_dev *wdev = dev->ieee80211_ptr;
16526 bool ret;
16527
16528 trace_cfg80211_rx_spurious_frame(dev, addr);
16529
16530 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
16531 wdev->iftype != NL80211_IFTYPE_P2P_GO)) {
16532 trace_cfg80211_return_bool(false);
16533 return false;
16534 }
16535 ret = __nl80211_unexpected_frame(dev, NL80211_CMD_UNEXPECTED_FRAME,
16536 addr, gfp);
16537 trace_cfg80211_return_bool(ret);
16538 return ret;
b92ab5d8 16539}
947add36 16540EXPORT_SYMBOL(cfg80211_rx_spurious_frame);
b92ab5d8 16541
947add36
JB
16542bool cfg80211_rx_unexpected_4addr_frame(struct net_device *dev,
16543 const u8 *addr, gfp_t gfp)
b92ab5d8 16544{
947add36
JB
16545 struct wireless_dev *wdev = dev->ieee80211_ptr;
16546 bool ret;
16547
16548 trace_cfg80211_rx_unexpected_4addr_frame(dev, addr);
16549
16550 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
16551 wdev->iftype != NL80211_IFTYPE_P2P_GO &&
16552 wdev->iftype != NL80211_IFTYPE_AP_VLAN)) {
16553 trace_cfg80211_return_bool(false);
16554 return false;
16555 }
16556 ret = __nl80211_unexpected_frame(dev,
16557 NL80211_CMD_UNEXPECTED_4ADDR_FRAME,
16558 addr, gfp);
16559 trace_cfg80211_return_bool(ret);
16560 return ret;
b92ab5d8 16561}
947add36 16562EXPORT_SYMBOL(cfg80211_rx_unexpected_4addr_frame);
b92ab5d8 16563
2e161f78 16564int nl80211_send_mgmt(struct cfg80211_registered_device *rdev,
15e47304 16565 struct wireless_dev *wdev, u32 nlportid,
804483e9 16566 int freq, int sig_dbm,
19504cf5 16567 const u8 *buf, size_t len, u32 flags, gfp_t gfp)
026331c4 16568{
71bbc994 16569 struct net_device *netdev = wdev->netdev;
026331c4
JM
16570 struct sk_buff *msg;
16571 void *hdr;
026331c4 16572
4ef8c1c9 16573 msg = nlmsg_new(100 + len, gfp);
026331c4
JM
16574 if (!msg)
16575 return -ENOMEM;
16576
2e161f78 16577 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FRAME);
026331c4
JM
16578 if (!hdr) {
16579 nlmsg_free(msg);
16580 return -ENOMEM;
16581 }
16582
9360ffd1 16583 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
71bbc994
JB
16584 (netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
16585 netdev->ifindex)) ||
2dad624e
ND
16586 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
16587 NL80211_ATTR_PAD) ||
e76fede8 16588 nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, KHZ_TO_MHZ(freq)) ||
942ba88b 16589 nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ_OFFSET, freq % 1000) ||
9360ffd1
DM
16590 (sig_dbm &&
16591 nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)) ||
19504cf5
VK
16592 nla_put(msg, NL80211_ATTR_FRAME, len, buf) ||
16593 (flags &&
16594 nla_put_u32(msg, NL80211_ATTR_RXMGMT_FLAGS, flags)))
9360ffd1 16595 goto nla_put_failure;
026331c4 16596
3b7b72ee 16597 genlmsg_end(msg, hdr);
026331c4 16598
15e47304 16599 return genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid);
026331c4
JM
16600
16601 nla_put_failure:
026331c4
JM
16602 nlmsg_free(msg);
16603 return -ENOBUFS;
16604}
16605
dca9ca2d
MT
16606static void nl80211_frame_tx_status(struct wireless_dev *wdev, u64 cookie,
16607 const u8 *buf, size_t len, bool ack,
16608 gfp_t gfp, enum nl80211_commands command)
026331c4 16609{
947add36 16610 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 16611 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
71bbc994 16612 struct net_device *netdev = wdev->netdev;
026331c4
JM
16613 struct sk_buff *msg;
16614 void *hdr;
16615
dca9ca2d
MT
16616 if (command == NL80211_CMD_FRAME_TX_STATUS)
16617 trace_cfg80211_mgmt_tx_status(wdev, cookie, ack);
16618 else
16619 trace_cfg80211_control_port_tx_status(wdev, cookie, ack);
947add36 16620
4ef8c1c9 16621 msg = nlmsg_new(100 + len, gfp);
026331c4
JM
16622 if (!msg)
16623 return;
16624
dca9ca2d 16625 hdr = nl80211hdr_put(msg, 0, 0, 0, command);
026331c4
JM
16626 if (!hdr) {
16627 nlmsg_free(msg);
16628 return;
16629 }
16630
9360ffd1 16631 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
71bbc994
JB
16632 (netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
16633 netdev->ifindex)) ||
2dad624e
ND
16634 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
16635 NL80211_ATTR_PAD) ||
9360ffd1 16636 nla_put(msg, NL80211_ATTR_FRAME, len, buf) ||
2dad624e
ND
16637 nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
16638 NL80211_ATTR_PAD) ||
9360ffd1
DM
16639 (ack && nla_put_flag(msg, NL80211_ATTR_ACK)))
16640 goto nla_put_failure;
026331c4 16641
3b7b72ee 16642 genlmsg_end(msg, hdr);
026331c4 16643
68eb5503 16644 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 16645 NL80211_MCGRP_MLME, gfp);
026331c4
JM
16646 return;
16647
dca9ca2d 16648nla_put_failure:
026331c4
JM
16649 nlmsg_free(msg);
16650}
dca9ca2d
MT
16651
16652void cfg80211_control_port_tx_status(struct wireless_dev *wdev, u64 cookie,
16653 const u8 *buf, size_t len, bool ack,
16654 gfp_t gfp)
16655{
16656 nl80211_frame_tx_status(wdev, cookie, buf, len, ack, gfp,
16657 NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS);
16658}
16659EXPORT_SYMBOL(cfg80211_control_port_tx_status);
16660
16661void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,
16662 const u8 *buf, size_t len, bool ack, gfp_t gfp)
16663{
16664 nl80211_frame_tx_status(wdev, cookie, buf, len, ack, gfp,
16665 NL80211_CMD_FRAME_TX_STATUS);
16666}
947add36 16667EXPORT_SYMBOL(cfg80211_mgmt_tx_status);
026331c4 16668
6a671a50 16669static int __nl80211_rx_control_port(struct net_device *dev,
a948f713 16670 struct sk_buff *skb,
6a671a50
DK
16671 bool unencrypted, gfp_t gfp)
16672{
16673 struct wireless_dev *wdev = dev->ieee80211_ptr;
16674 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
a948f713 16675 struct ethhdr *ehdr = eth_hdr(skb);
8d74a623 16676 const u8 *addr = ehdr->h_source;
a948f713 16677 u16 proto = be16_to_cpu(skb->protocol);
6a671a50
DK
16678 struct sk_buff *msg;
16679 void *hdr;
a948f713
DK
16680 struct nlattr *frame;
16681
6a671a50
DK
16682 u32 nlportid = READ_ONCE(wdev->conn_owner_nlportid);
16683
16684 if (!nlportid)
16685 return -ENOENT;
16686
a948f713 16687 msg = nlmsg_new(100 + skb->len, gfp);
6a671a50
DK
16688 if (!msg)
16689 return -ENOMEM;
16690
16691 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CONTROL_PORT_FRAME);
16692 if (!hdr) {
16693 nlmsg_free(msg);
16694 return -ENOBUFS;
16695 }
16696
16697 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
16698 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
16699 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
16700 NL80211_ATTR_PAD) ||
8d74a623 16701 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
6a671a50
DK
16702 nla_put_u16(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE, proto) ||
16703 (unencrypted && nla_put_flag(msg,
16704 NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT)))
16705 goto nla_put_failure;
16706
a948f713
DK
16707 frame = nla_reserve(msg, NL80211_ATTR_FRAME, skb->len);
16708 if (!frame)
16709 goto nla_put_failure;
16710
16711 skb_copy_bits(skb, 0, nla_data(frame), skb->len);
6a671a50
DK
16712 genlmsg_end(msg, hdr);
16713
16714 return genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid);
16715
16716 nla_put_failure:
16717 nlmsg_free(msg);
16718 return -ENOBUFS;
16719}
16720
16721bool cfg80211_rx_control_port(struct net_device *dev,
a948f713 16722 struct sk_buff *skb, bool unencrypted)
6a671a50
DK
16723{
16724 int ret;
16725
a948f713
DK
16726 trace_cfg80211_rx_control_port(dev, skb, unencrypted);
16727 ret = __nl80211_rx_control_port(dev, skb, unencrypted, GFP_ATOMIC);
6a671a50
DK
16728 trace_cfg80211_return_bool(ret == 0);
16729 return ret == 0;
16730}
16731EXPORT_SYMBOL(cfg80211_rx_control_port);
16732
5b97f49d
JB
16733static struct sk_buff *cfg80211_prepare_cqm(struct net_device *dev,
16734 const char *mac, gfp_t gfp)
d6dc1a38 16735{
947add36 16736 struct wireless_dev *wdev = dev->ieee80211_ptr;
5b97f49d
JB
16737 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
16738 struct sk_buff *msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
16739 void **cb;
947add36 16740
d6dc1a38 16741 if (!msg)
5b97f49d 16742 return NULL;
d6dc1a38 16743
5b97f49d
JB
16744 cb = (void **)msg->cb;
16745
16746 cb[0] = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NOTIFY_CQM);
16747 if (!cb[0]) {
d6dc1a38 16748 nlmsg_free(msg);
5b97f49d 16749 return NULL;
d6dc1a38
JO
16750 }
16751
9360ffd1 16752 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
947add36 16753 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
9360ffd1 16754 goto nla_put_failure;
d6dc1a38 16755
5b97f49d 16756 if (mac && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac))
d6dc1a38
JO
16757 goto nla_put_failure;
16758
ae0be8de 16759 cb[1] = nla_nest_start_noflag(msg, NL80211_ATTR_CQM);
5b97f49d 16760 if (!cb[1])
9360ffd1 16761 goto nla_put_failure;
d6dc1a38 16762
5b97f49d 16763 cb[2] = rdev;
d6dc1a38 16764
5b97f49d
JB
16765 return msg;
16766 nla_put_failure:
16767 nlmsg_free(msg);
16768 return NULL;
16769}
16770
16771static void cfg80211_send_cqm(struct sk_buff *msg, gfp_t gfp)
16772{
16773 void **cb = (void **)msg->cb;
16774 struct cfg80211_registered_device *rdev = cb[2];
16775
16776 nla_nest_end(msg, cb[1]);
16777 genlmsg_end(msg, cb[0]);
16778
16779 memset(msg->cb, 0, sizeof(msg->cb));
d6dc1a38 16780
68eb5503 16781 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 16782 NL80211_MCGRP_MLME, gfp);
5b97f49d
JB
16783}
16784
16785void cfg80211_cqm_rssi_notify(struct net_device *dev,
16786 enum nl80211_cqm_rssi_threshold_event rssi_event,
bee427b8 16787 s32 rssi_level, gfp_t gfp)
5b97f49d
JB
16788{
16789 struct sk_buff *msg;
4a4b8169
AZ
16790 struct wireless_dev *wdev = dev->ieee80211_ptr;
16791 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
5b97f49d 16792
bee427b8 16793 trace_cfg80211_cqm_rssi_notify(dev, rssi_event, rssi_level);
5b97f49d 16794
98f03342
JB
16795 if (WARN_ON(rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW &&
16796 rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH))
16797 return;
16798
4a4b8169
AZ
16799 if (wdev->cqm_config) {
16800 wdev->cqm_config->last_rssi_event_value = rssi_level;
16801
16802 cfg80211_cqm_rssi_update(rdev, dev);
16803
16804 if (rssi_level == 0)
16805 rssi_level = wdev->cqm_config->last_rssi_event_value;
16806 }
16807
5b97f49d
JB
16808 msg = cfg80211_prepare_cqm(dev, NULL, gfp);
16809 if (!msg)
16810 return;
16811
16812 if (nla_put_u32(msg, NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT,
16813 rssi_event))
16814 goto nla_put_failure;
16815
bee427b8
AZ
16816 if (rssi_level && nla_put_s32(msg, NL80211_ATTR_CQM_RSSI_LEVEL,
16817 rssi_level))
16818 goto nla_put_failure;
16819
5b97f49d
JB
16820 cfg80211_send_cqm(msg, gfp);
16821
d6dc1a38
JO
16822 return;
16823
16824 nla_put_failure:
d6dc1a38
JO
16825 nlmsg_free(msg);
16826}
947add36 16827EXPORT_SYMBOL(cfg80211_cqm_rssi_notify);
d6dc1a38 16828
5b97f49d
JB
16829void cfg80211_cqm_txe_notify(struct net_device *dev,
16830 const u8 *peer, u32 num_packets,
16831 u32 rate, u32 intvl, gfp_t gfp)
16832{
16833 struct sk_buff *msg;
16834
16835 msg = cfg80211_prepare_cqm(dev, peer, gfp);
16836 if (!msg)
16837 return;
16838
16839 if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_PKTS, num_packets))
16840 goto nla_put_failure;
16841
16842 if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_RATE, rate))
16843 goto nla_put_failure;
16844
16845 if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_INTVL, intvl))
16846 goto nla_put_failure;
16847
16848 cfg80211_send_cqm(msg, gfp);
16849 return;
16850
16851 nla_put_failure:
16852 nlmsg_free(msg);
16853}
16854EXPORT_SYMBOL(cfg80211_cqm_txe_notify);
16855
16856void cfg80211_cqm_pktloss_notify(struct net_device *dev,
16857 const u8 *peer, u32 num_packets, gfp_t gfp)
16858{
16859 struct sk_buff *msg;
16860
16861 trace_cfg80211_cqm_pktloss_notify(dev, peer, num_packets);
16862
16863 msg = cfg80211_prepare_cqm(dev, peer, gfp);
16864 if (!msg)
16865 return;
16866
16867 if (nla_put_u32(msg, NL80211_ATTR_CQM_PKT_LOSS_EVENT, num_packets))
16868 goto nla_put_failure;
16869
16870 cfg80211_send_cqm(msg, gfp);
16871 return;
16872
16873 nla_put_failure:
16874 nlmsg_free(msg);
16875}
16876EXPORT_SYMBOL(cfg80211_cqm_pktloss_notify);
16877
98f03342
JB
16878void cfg80211_cqm_beacon_loss_notify(struct net_device *dev, gfp_t gfp)
16879{
16880 struct sk_buff *msg;
16881
16882 msg = cfg80211_prepare_cqm(dev, NULL, gfp);
16883 if (!msg)
16884 return;
16885
16886 if (nla_put_flag(msg, NL80211_ATTR_CQM_BEACON_LOSS_EVENT))
16887 goto nla_put_failure;
16888
16889 cfg80211_send_cqm(msg, gfp);
16890 return;
16891
16892 nla_put_failure:
16893 nlmsg_free(msg);
16894}
16895EXPORT_SYMBOL(cfg80211_cqm_beacon_loss_notify);
16896
947add36
JB
16897static void nl80211_gtk_rekey_notify(struct cfg80211_registered_device *rdev,
16898 struct net_device *netdev, const u8 *bssid,
16899 const u8 *replay_ctr, gfp_t gfp)
e5497d76
JB
16900{
16901 struct sk_buff *msg;
16902 struct nlattr *rekey_attr;
16903 void *hdr;
16904
58050fce 16905 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
e5497d76
JB
16906 if (!msg)
16907 return;
16908
16909 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_SET_REKEY_OFFLOAD);
16910 if (!hdr) {
16911 nlmsg_free(msg);
16912 return;
16913 }
16914
9360ffd1
DM
16915 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
16916 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
16917 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid))
16918 goto nla_put_failure;
e5497d76 16919
ae0be8de 16920 rekey_attr = nla_nest_start_noflag(msg, NL80211_ATTR_REKEY_DATA);
e5497d76
JB
16921 if (!rekey_attr)
16922 goto nla_put_failure;
16923
9360ffd1
DM
16924 if (nla_put(msg, NL80211_REKEY_DATA_REPLAY_CTR,
16925 NL80211_REPLAY_CTR_LEN, replay_ctr))
16926 goto nla_put_failure;
e5497d76
JB
16927
16928 nla_nest_end(msg, rekey_attr);
16929
3b7b72ee 16930 genlmsg_end(msg, hdr);
e5497d76 16931
68eb5503 16932 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 16933 NL80211_MCGRP_MLME, gfp);
e5497d76
JB
16934 return;
16935
16936 nla_put_failure:
e5497d76
JB
16937 nlmsg_free(msg);
16938}
16939
947add36
JB
16940void cfg80211_gtk_rekey_notify(struct net_device *dev, const u8 *bssid,
16941 const u8 *replay_ctr, gfp_t gfp)
16942{
16943 struct wireless_dev *wdev = dev->ieee80211_ptr;
16944 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 16945 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
947add36
JB
16946
16947 trace_cfg80211_gtk_rekey_notify(dev, bssid);
16948 nl80211_gtk_rekey_notify(rdev, dev, bssid, replay_ctr, gfp);
16949}
16950EXPORT_SYMBOL(cfg80211_gtk_rekey_notify);
16951
16952static void
16953nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev,
16954 struct net_device *netdev, int index,
16955 const u8 *bssid, bool preauth, gfp_t gfp)
c9df56b4
JM
16956{
16957 struct sk_buff *msg;
16958 struct nlattr *attr;
16959 void *hdr;
16960
58050fce 16961 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
c9df56b4
JM
16962 if (!msg)
16963 return;
16964
16965 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_PMKSA_CANDIDATE);
16966 if (!hdr) {
16967 nlmsg_free(msg);
16968 return;
16969 }
16970
9360ffd1
DM
16971 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
16972 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex))
16973 goto nla_put_failure;
c9df56b4 16974
ae0be8de 16975 attr = nla_nest_start_noflag(msg, NL80211_ATTR_PMKSA_CANDIDATE);
c9df56b4
JM
16976 if (!attr)
16977 goto nla_put_failure;
16978
9360ffd1
DM
16979 if (nla_put_u32(msg, NL80211_PMKSA_CANDIDATE_INDEX, index) ||
16980 nla_put(msg, NL80211_PMKSA_CANDIDATE_BSSID, ETH_ALEN, bssid) ||
16981 (preauth &&
16982 nla_put_flag(msg, NL80211_PMKSA_CANDIDATE_PREAUTH)))
16983 goto nla_put_failure;
c9df56b4
JM
16984
16985 nla_nest_end(msg, attr);
16986
3b7b72ee 16987 genlmsg_end(msg, hdr);
c9df56b4 16988
68eb5503 16989 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 16990 NL80211_MCGRP_MLME, gfp);
c9df56b4
JM
16991 return;
16992
16993 nla_put_failure:
c9df56b4
JM
16994 nlmsg_free(msg);
16995}
16996
947add36
JB
16997void cfg80211_pmksa_candidate_notify(struct net_device *dev, int index,
16998 const u8 *bssid, bool preauth, gfp_t gfp)
16999{
17000 struct wireless_dev *wdev = dev->ieee80211_ptr;
17001 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 17002 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
947add36
JB
17003
17004 trace_cfg80211_pmksa_candidate_notify(dev, index, bssid, preauth);
17005 nl80211_pmksa_candidate_notify(rdev, dev, index, bssid, preauth, gfp);
17006}
17007EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify);
17008
17009static void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
17010 struct net_device *netdev,
17011 struct cfg80211_chan_def *chandef,
f8d7552e
LC
17012 gfp_t gfp,
17013 enum nl80211_commands notif,
17014 u8 count)
5314526b
TP
17015{
17016 struct sk_buff *msg;
17017 void *hdr;
17018
58050fce 17019 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
5314526b
TP
17020 if (!msg)
17021 return;
17022
f8d7552e 17023 hdr = nl80211hdr_put(msg, 0, 0, 0, notif);
5314526b
TP
17024 if (!hdr) {
17025 nlmsg_free(msg);
17026 return;
17027 }
17028
683b6d3b
JB
17029 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex))
17030 goto nla_put_failure;
17031
17032 if (nl80211_send_chandef(msg, chandef))
7eab0f64 17033 goto nla_put_failure;
5314526b 17034
f8d7552e
LC
17035 if ((notif == NL80211_CMD_CH_SWITCH_STARTED_NOTIFY) &&
17036 (nla_put_u32(msg, NL80211_ATTR_CH_SWITCH_COUNT, count)))
17037 goto nla_put_failure;
17038
5314526b
TP
17039 genlmsg_end(msg, hdr);
17040
68eb5503 17041 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17042 NL80211_MCGRP_MLME, gfp);
5314526b
TP
17043 return;
17044
17045 nla_put_failure:
5314526b
TP
17046 nlmsg_free(msg);
17047}
17048
947add36
JB
17049void cfg80211_ch_switch_notify(struct net_device *dev,
17050 struct cfg80211_chan_def *chandef)
84f10708 17051{
947add36
JB
17052 struct wireless_dev *wdev = dev->ieee80211_ptr;
17053 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 17054 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
947add36 17055
e487eaeb 17056 ASSERT_WDEV_LOCK(wdev);
947add36 17057
e487eaeb 17058 trace_cfg80211_ch_switch_notify(dev, chandef);
947add36 17059
9e0e2961 17060 wdev->chandef = *chandef;
96f55f12 17061 wdev->preset_chandef = *chandef;
5dc8cdce
SM
17062
17063 if (wdev->iftype == NL80211_IFTYPE_STATION &&
17064 !WARN_ON(!wdev->current_bss))
0afd425b 17065 cfg80211_update_assoc_bss_entry(wdev, chandef->chan);
5dc8cdce 17066
d34990bb
MV
17067 cfg80211_sched_dfs_chan_update(rdev);
17068
f8d7552e
LC
17069 nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL,
17070 NL80211_CMD_CH_SWITCH_NOTIFY, 0);
947add36
JB
17071}
17072EXPORT_SYMBOL(cfg80211_ch_switch_notify);
17073
f8d7552e
LC
17074void cfg80211_ch_switch_started_notify(struct net_device *dev,
17075 struct cfg80211_chan_def *chandef,
17076 u8 count)
17077{
17078 struct wireless_dev *wdev = dev->ieee80211_ptr;
17079 struct wiphy *wiphy = wdev->wiphy;
17080 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
17081
17082 trace_cfg80211_ch_switch_started_notify(dev, chandef);
17083
17084 nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL,
17085 NL80211_CMD_CH_SWITCH_STARTED_NOTIFY, count);
17086}
17087EXPORT_SYMBOL(cfg80211_ch_switch_started_notify);
17088
04f39047
SW
17089void
17090nl80211_radar_notify(struct cfg80211_registered_device *rdev,
d2859df5 17091 const struct cfg80211_chan_def *chandef,
04f39047
SW
17092 enum nl80211_radar_event event,
17093 struct net_device *netdev, gfp_t gfp)
17094{
17095 struct sk_buff *msg;
17096 void *hdr;
17097
17098 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
17099 if (!msg)
17100 return;
17101
17102 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_RADAR_DETECT);
17103 if (!hdr) {
17104 nlmsg_free(msg);
17105 return;
17106 }
17107
17108 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx))
17109 goto nla_put_failure;
17110
17111 /* NOP and radar events don't need a netdev parameter */
17112 if (netdev) {
17113 struct wireless_dev *wdev = netdev->ieee80211_ptr;
17114
17115 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
2dad624e
ND
17116 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
17117 NL80211_ATTR_PAD))
04f39047
SW
17118 goto nla_put_failure;
17119 }
17120
17121 if (nla_put_u32(msg, NL80211_ATTR_RADAR_EVENT, event))
17122 goto nla_put_failure;
17123
17124 if (nl80211_send_chandef(msg, chandef))
17125 goto nla_put_failure;
17126
9c90a9f6 17127 genlmsg_end(msg, hdr);
04f39047 17128
68eb5503 17129 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17130 NL80211_MCGRP_MLME, gfp);
04f39047
SW
17131 return;
17132
17133 nla_put_failure:
04f39047
SW
17134 nlmsg_free(msg);
17135}
17136
466b9936 17137void cfg80211_sta_opmode_change_notify(struct net_device *dev, const u8 *mac,
17138 struct sta_opmode_info *sta_opmode,
17139 gfp_t gfp)
17140{
17141 struct sk_buff *msg;
17142 struct wireless_dev *wdev = dev->ieee80211_ptr;
17143 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
17144 void *hdr;
17145
17146 if (WARN_ON(!mac))
17147 return;
17148
17149 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
17150 if (!msg)
17151 return;
17152
17153 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_STA_OPMODE_CHANGED);
17154 if (!hdr) {
17155 nlmsg_free(msg);
17156 return;
17157 }
17158
17159 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx))
17160 goto nla_put_failure;
17161
17162 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
17163 goto nla_put_failure;
17164
17165 if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac))
17166 goto nla_put_failure;
17167
17168 if ((sta_opmode->changed & STA_OPMODE_SMPS_MODE_CHANGED) &&
17169 nla_put_u8(msg, NL80211_ATTR_SMPS_MODE, sta_opmode->smps_mode))
17170 goto nla_put_failure;
17171
17172 if ((sta_opmode->changed & STA_OPMODE_MAX_BW_CHANGED) &&
0016d320 17173 nla_put_u32(msg, NL80211_ATTR_CHANNEL_WIDTH, sta_opmode->bw))
466b9936 17174 goto nla_put_failure;
17175
17176 if ((sta_opmode->changed & STA_OPMODE_N_SS_CHANGED) &&
17177 nla_put_u8(msg, NL80211_ATTR_NSS, sta_opmode->rx_nss))
17178 goto nla_put_failure;
17179
17180 genlmsg_end(msg, hdr);
17181
17182 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
17183 NL80211_MCGRP_MLME, gfp);
17184
17185 return;
17186
17187nla_put_failure:
17188 nlmsg_free(msg);
17189}
17190EXPORT_SYMBOL(cfg80211_sta_opmode_change_notify);
17191
7f6cf311 17192void cfg80211_probe_status(struct net_device *dev, const u8 *addr,
c4b50cd3
VN
17193 u64 cookie, bool acked, s32 ack_signal,
17194 bool is_valid_ack_signal, gfp_t gfp)
7f6cf311
JB
17195{
17196 struct wireless_dev *wdev = dev->ieee80211_ptr;
f26cbf40 17197 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
7f6cf311
JB
17198 struct sk_buff *msg;
17199 void *hdr;
7f6cf311 17200
4ee3e063
BL
17201 trace_cfg80211_probe_status(dev, addr, cookie, acked);
17202
58050fce 17203 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
4ee3e063 17204
7f6cf311
JB
17205 if (!msg)
17206 return;
17207
17208 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_PROBE_CLIENT);
17209 if (!hdr) {
17210 nlmsg_free(msg);
17211 return;
17212 }
17213
9360ffd1
DM
17214 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
17215 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
17216 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
2dad624e
ND
17217 nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
17218 NL80211_ATTR_PAD) ||
c4b50cd3
VN
17219 (acked && nla_put_flag(msg, NL80211_ATTR_ACK)) ||
17220 (is_valid_ack_signal && nla_put_s32(msg, NL80211_ATTR_ACK_SIGNAL,
17221 ack_signal)))
9360ffd1 17222 goto nla_put_failure;
7f6cf311 17223
9c90a9f6 17224 genlmsg_end(msg, hdr);
7f6cf311 17225
68eb5503 17226 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17227 NL80211_MCGRP_MLME, gfp);
7f6cf311
JB
17228 return;
17229
17230 nla_put_failure:
7f6cf311
JB
17231 nlmsg_free(msg);
17232}
17233EXPORT_SYMBOL(cfg80211_probe_status);
17234
e76fede8
TP
17235void cfg80211_report_obss_beacon_khz(struct wiphy *wiphy, const u8 *frame,
17236 size_t len, int freq, int sig_dbm)
5e760230 17237{
f26cbf40 17238 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
5e760230
JB
17239 struct sk_buff *msg;
17240 void *hdr;
37c73b5f 17241 struct cfg80211_beacon_registration *reg;
5e760230 17242
4ee3e063
BL
17243 trace_cfg80211_report_obss_beacon(wiphy, frame, len, freq, sig_dbm);
17244
37c73b5f
BG
17245 spin_lock_bh(&rdev->beacon_registrations_lock);
17246 list_for_each_entry(reg, &rdev->beacon_registrations, list) {
17247 msg = nlmsg_new(len + 100, GFP_ATOMIC);
17248 if (!msg) {
17249 spin_unlock_bh(&rdev->beacon_registrations_lock);
17250 return;
17251 }
5e760230 17252
37c73b5f
BG
17253 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FRAME);
17254 if (!hdr)
17255 goto nla_put_failure;
5e760230 17256
37c73b5f
BG
17257 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
17258 (freq &&
942ba88b
TP
17259 (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
17260 KHZ_TO_MHZ(freq)) ||
17261 nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ_OFFSET,
17262 freq % 1000))) ||
37c73b5f
BG
17263 (sig_dbm &&
17264 nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)) ||
17265 nla_put(msg, NL80211_ATTR_FRAME, len, frame))
17266 goto nla_put_failure;
5e760230 17267
37c73b5f 17268 genlmsg_end(msg, hdr);
5e760230 17269
37c73b5f
BG
17270 genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, reg->nlportid);
17271 }
17272 spin_unlock_bh(&rdev->beacon_registrations_lock);
5e760230
JB
17273 return;
17274
17275 nla_put_failure:
37c73b5f 17276 spin_unlock_bh(&rdev->beacon_registrations_lock);
5e760230
JB
17277 nlmsg_free(msg);
17278}
e76fede8 17279EXPORT_SYMBOL(cfg80211_report_obss_beacon_khz);
5e760230 17280
cd8f7cb4 17281#ifdef CONFIG_PM
8cd4d456
LC
17282static int cfg80211_net_detect_results(struct sk_buff *msg,
17283 struct cfg80211_wowlan_wakeup *wakeup)
17284{
17285 struct cfg80211_wowlan_nd_info *nd = wakeup->net_detect;
17286 struct nlattr *nl_results, *nl_match, *nl_freqs;
17287 int i, j;
17288
ae0be8de
MK
17289 nl_results = nla_nest_start_noflag(msg,
17290 NL80211_WOWLAN_TRIG_NET_DETECT_RESULTS);
8cd4d456
LC
17291 if (!nl_results)
17292 return -EMSGSIZE;
17293
17294 for (i = 0; i < nd->n_matches; i++) {
17295 struct cfg80211_wowlan_nd_match *match = nd->matches[i];
17296
ae0be8de 17297 nl_match = nla_nest_start_noflag(msg, i);
8cd4d456
LC
17298 if (!nl_match)
17299 break;
17300
17301 /* The SSID attribute is optional in nl80211, but for
17302 * simplicity reasons it's always present in the
17303 * cfg80211 structure. If a driver can't pass the
17304 * SSID, that needs to be changed. A zero length SSID
17305 * is still a valid SSID (wildcard), so it cannot be
17306 * used for this purpose.
17307 */
17308 if (nla_put(msg, NL80211_ATTR_SSID, match->ssid.ssid_len,
17309 match->ssid.ssid)) {
17310 nla_nest_cancel(msg, nl_match);
17311 goto out;
17312 }
17313
17314 if (match->n_channels) {
ae0be8de
MK
17315 nl_freqs = nla_nest_start_noflag(msg,
17316 NL80211_ATTR_SCAN_FREQUENCIES);
8cd4d456
LC
17317 if (!nl_freqs) {
17318 nla_nest_cancel(msg, nl_match);
17319 goto out;
17320 }
17321
17322 for (j = 0; j < match->n_channels; j++) {
5528fae8 17323 if (nla_put_u32(msg, j, match->channels[j])) {
8cd4d456
LC
17324 nla_nest_cancel(msg, nl_freqs);
17325 nla_nest_cancel(msg, nl_match);
17326 goto out;
17327 }
17328 }
17329
17330 nla_nest_end(msg, nl_freqs);
17331 }
17332
17333 nla_nest_end(msg, nl_match);
17334 }
17335
17336out:
17337 nla_nest_end(msg, nl_results);
17338 return 0;
17339}
17340
cd8f7cb4
JB
17341void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev,
17342 struct cfg80211_wowlan_wakeup *wakeup,
17343 gfp_t gfp)
17344{
f26cbf40 17345 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
cd8f7cb4
JB
17346 struct sk_buff *msg;
17347 void *hdr;
9c90a9f6 17348 int size = 200;
cd8f7cb4
JB
17349
17350 trace_cfg80211_report_wowlan_wakeup(wdev->wiphy, wdev, wakeup);
17351
17352 if (wakeup)
17353 size += wakeup->packet_present_len;
17354
17355 msg = nlmsg_new(size, gfp);
17356 if (!msg)
17357 return;
17358
17359 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_SET_WOWLAN);
17360 if (!hdr)
17361 goto free_msg;
17362
17363 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
2dad624e
ND
17364 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
17365 NL80211_ATTR_PAD))
cd8f7cb4
JB
17366 goto free_msg;
17367
17368 if (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
17369 wdev->netdev->ifindex))
17370 goto free_msg;
17371
17372 if (wakeup) {
17373 struct nlattr *reasons;
17374
ae0be8de
MK
17375 reasons = nla_nest_start_noflag(msg,
17376 NL80211_ATTR_WOWLAN_TRIGGERS);
7fa322c8
JB
17377 if (!reasons)
17378 goto free_msg;
cd8f7cb4
JB
17379
17380 if (wakeup->disconnect &&
17381 nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT))
17382 goto free_msg;
17383 if (wakeup->magic_pkt &&
17384 nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT))
17385 goto free_msg;
17386 if (wakeup->gtk_rekey_failure &&
17387 nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE))
17388 goto free_msg;
17389 if (wakeup->eap_identity_req &&
17390 nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST))
17391 goto free_msg;
17392 if (wakeup->four_way_handshake &&
17393 nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE))
17394 goto free_msg;
17395 if (wakeup->rfkill_release &&
17396 nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE))
17397 goto free_msg;
17398
17399 if (wakeup->pattern_idx >= 0 &&
17400 nla_put_u32(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN,
17401 wakeup->pattern_idx))
17402 goto free_msg;
17403
ae917c9f
JB
17404 if (wakeup->tcp_match &&
17405 nla_put_flag(msg, NL80211_WOWLAN_TRIG_WAKEUP_TCP_MATCH))
17406 goto free_msg;
2a0e047e 17407
ae917c9f
JB
17408 if (wakeup->tcp_connlost &&
17409 nla_put_flag(msg, NL80211_WOWLAN_TRIG_WAKEUP_TCP_CONNLOST))
17410 goto free_msg;
2a0e047e 17411
ae917c9f
JB
17412 if (wakeup->tcp_nomoretokens &&
17413 nla_put_flag(msg,
17414 NL80211_WOWLAN_TRIG_WAKEUP_TCP_NOMORETOKENS))
17415 goto free_msg;
2a0e047e 17416
cd8f7cb4
JB
17417 if (wakeup->packet) {
17418 u32 pkt_attr = NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211;
17419 u32 len_attr = NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN;
17420
17421 if (!wakeup->packet_80211) {
17422 pkt_attr =
17423 NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023;
17424 len_attr =
17425 NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023_LEN;
17426 }
17427
17428 if (wakeup->packet_len &&
17429 nla_put_u32(msg, len_attr, wakeup->packet_len))
17430 goto free_msg;
17431
17432 if (nla_put(msg, pkt_attr, wakeup->packet_present_len,
17433 wakeup->packet))
17434 goto free_msg;
17435 }
17436
8cd4d456
LC
17437 if (wakeup->net_detect &&
17438 cfg80211_net_detect_results(msg, wakeup))
17439 goto free_msg;
17440
cd8f7cb4
JB
17441 nla_nest_end(msg, reasons);
17442 }
17443
9c90a9f6 17444 genlmsg_end(msg, hdr);
cd8f7cb4 17445
68eb5503 17446 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17447 NL80211_MCGRP_MLME, gfp);
cd8f7cb4
JB
17448 return;
17449
17450 free_msg:
17451 nlmsg_free(msg);
17452}
17453EXPORT_SYMBOL(cfg80211_report_wowlan_wakeup);
17454#endif
17455
3475b094
JM
17456void cfg80211_tdls_oper_request(struct net_device *dev, const u8 *peer,
17457 enum nl80211_tdls_operation oper,
17458 u16 reason_code, gfp_t gfp)
17459{
17460 struct wireless_dev *wdev = dev->ieee80211_ptr;
f26cbf40 17461 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
3475b094
JM
17462 struct sk_buff *msg;
17463 void *hdr;
3475b094
JM
17464
17465 trace_cfg80211_tdls_oper_request(wdev->wiphy, dev, peer, oper,
17466 reason_code);
17467
17468 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
17469 if (!msg)
17470 return;
17471
17472 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_TDLS_OPER);
17473 if (!hdr) {
17474 nlmsg_free(msg);
17475 return;
17476 }
17477
17478 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
17479 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
17480 nla_put_u8(msg, NL80211_ATTR_TDLS_OPERATION, oper) ||
17481 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, peer) ||
17482 (reason_code > 0 &&
17483 nla_put_u16(msg, NL80211_ATTR_REASON_CODE, reason_code)))
17484 goto nla_put_failure;
17485
9c90a9f6 17486 genlmsg_end(msg, hdr);
3475b094 17487
68eb5503 17488 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17489 NL80211_MCGRP_MLME, gfp);
3475b094
JM
17490 return;
17491
17492 nla_put_failure:
3475b094
JM
17493 nlmsg_free(msg);
17494}
17495EXPORT_SYMBOL(cfg80211_tdls_oper_request);
17496
026331c4
JM
17497static int nl80211_netlink_notify(struct notifier_block * nb,
17498 unsigned long state,
17499 void *_notify)
17500{
17501 struct netlink_notify *notify = _notify;
17502 struct cfg80211_registered_device *rdev;
17503 struct wireless_dev *wdev;
37c73b5f 17504 struct cfg80211_beacon_registration *reg, *tmp;
026331c4 17505
8f815cdd 17506 if (state != NETLINK_URELEASE || notify->protocol != NETLINK_GENERIC)
026331c4
JM
17507 return NOTIFY_DONE;
17508
17509 rcu_read_lock();
17510
5e760230 17511 list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) {
ca986ad9 17512 struct cfg80211_sched_scan_request *sched_scan_req;
753aacfd 17513
ca986ad9
AVS
17514 list_for_each_entry_rcu(sched_scan_req,
17515 &rdev->sched_scan_req_list,
17516 list) {
17517 if (sched_scan_req->owner_nlportid == notify->portid) {
17518 sched_scan_req->nl_owner_dead = true;
753aacfd 17519 schedule_work(&rdev->sched_scan_stop_wk);
ca986ad9 17520 }
753aacfd 17521 }
78f22b6a 17522
53873f13 17523 list_for_each_entry_rcu(wdev, &rdev->wiphy.wdev_list, list) {
15e47304 17524 cfg80211_mlme_unregister_socket(wdev, notify->portid);
37c73b5f 17525
ab81007a
JB
17526 if (wdev->owner_nlportid == notify->portid) {
17527 wdev->nl_owner_dead = true;
17528 schedule_work(&rdev->destroy_work);
17529 } else if (wdev->conn_owner_nlportid == notify->portid) {
bd2522b1 17530 schedule_work(&wdev->disconnect_wk);
ab81007a 17531 }
9bb7e0f2
JB
17532
17533 cfg80211_release_pmsr(wdev, notify->portid);
78f22b6a
JB
17534 }
17535
37c73b5f
BG
17536 spin_lock_bh(&rdev->beacon_registrations_lock);
17537 list_for_each_entry_safe(reg, tmp, &rdev->beacon_registrations,
17538 list) {
17539 if (reg->nlportid == notify->portid) {
17540 list_del(&reg->list);
17541 kfree(reg);
17542 break;
17543 }
17544 }
17545 spin_unlock_bh(&rdev->beacon_registrations_lock);
5e760230 17546 }
026331c4
JM
17547
17548 rcu_read_unlock();
17549
05050753
I
17550 /*
17551 * It is possible that the user space process that is controlling the
17552 * indoor setting disappeared, so notify the regulatory core.
17553 */
17554 regulatory_netlink_notify(notify->portid);
6784c7db 17555 return NOTIFY_OK;
026331c4
JM
17556}
17557
17558static struct notifier_block nl80211_netlink_notifier = {
17559 .notifier_call = nl80211_netlink_notify,
17560};
17561
355199e0
JM
17562void cfg80211_ft_event(struct net_device *netdev,
17563 struct cfg80211_ft_event_params *ft_event)
17564{
17565 struct wiphy *wiphy = netdev->ieee80211_ptr->wiphy;
f26cbf40 17566 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
355199e0
JM
17567 struct sk_buff *msg;
17568 void *hdr;
355199e0
JM
17569
17570 trace_cfg80211_ft_event(wiphy, netdev, ft_event);
17571
17572 if (!ft_event->target_ap)
17573 return;
17574
1039d081
DL
17575 msg = nlmsg_new(100 + ft_event->ies_len + ft_event->ric_ies_len,
17576 GFP_KERNEL);
355199e0
JM
17577 if (!msg)
17578 return;
17579
17580 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FT_EVENT);
ae917c9f
JB
17581 if (!hdr)
17582 goto out;
355199e0 17583
ae917c9f
JB
17584 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
17585 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
17586 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, ft_event->target_ap))
17587 goto out;
355199e0 17588
ae917c9f
JB
17589 if (ft_event->ies &&
17590 nla_put(msg, NL80211_ATTR_IE, ft_event->ies_len, ft_event->ies))
17591 goto out;
17592 if (ft_event->ric_ies &&
17593 nla_put(msg, NL80211_ATTR_IE_RIC, ft_event->ric_ies_len,
17594 ft_event->ric_ies))
17595 goto out;
355199e0 17596
9c90a9f6 17597 genlmsg_end(msg, hdr);
355199e0 17598
68eb5503 17599 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17600 NL80211_MCGRP_MLME, GFP_KERNEL);
ae917c9f
JB
17601 return;
17602 out:
17603 nlmsg_free(msg);
355199e0
JM
17604}
17605EXPORT_SYMBOL(cfg80211_ft_event);
17606
5de17984
AS
17607void cfg80211_crit_proto_stopped(struct wireless_dev *wdev, gfp_t gfp)
17608{
17609 struct cfg80211_registered_device *rdev;
17610 struct sk_buff *msg;
17611 void *hdr;
17612 u32 nlportid;
17613
f26cbf40 17614 rdev = wiphy_to_rdev(wdev->wiphy);
5de17984
AS
17615 if (!rdev->crit_proto_nlportid)
17616 return;
17617
17618 nlportid = rdev->crit_proto_nlportid;
17619 rdev->crit_proto_nlportid = 0;
17620
17621 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
17622 if (!msg)
17623 return;
17624
17625 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CRIT_PROTOCOL_STOP);
17626 if (!hdr)
17627 goto nla_put_failure;
17628
17629 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
2dad624e
ND
17630 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
17631 NL80211_ATTR_PAD))
5de17984
AS
17632 goto nla_put_failure;
17633
17634 genlmsg_end(msg, hdr);
17635
17636 genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid);
17637 return;
17638
17639 nla_put_failure:
5de17984 17640 nlmsg_free(msg);
5de17984
AS
17641}
17642EXPORT_SYMBOL(cfg80211_crit_proto_stopped);
17643
348baf0e
JB
17644void nl80211_send_ap_stopped(struct wireless_dev *wdev)
17645{
17646 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 17647 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
348baf0e
JB
17648 struct sk_buff *msg;
17649 void *hdr;
17650
17651 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
17652 if (!msg)
17653 return;
17654
17655 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_STOP_AP);
17656 if (!hdr)
17657 goto out;
17658
17659 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
17660 nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex) ||
2dad624e
ND
17661 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
17662 NL80211_ATTR_PAD))
348baf0e
JB
17663 goto out;
17664
17665 genlmsg_end(msg, hdr);
17666
17667 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(wiphy), msg, 0,
17668 NL80211_MCGRP_MLME, GFP_KERNEL);
17669 return;
17670 out:
17671 nlmsg_free(msg);
17672}
17673
40cbfa90
SD
17674int cfg80211_external_auth_request(struct net_device *dev,
17675 struct cfg80211_external_auth_params *params,
17676 gfp_t gfp)
17677{
17678 struct wireless_dev *wdev = dev->ieee80211_ptr;
17679 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
17680 struct sk_buff *msg;
17681 void *hdr;
17682
17683 if (!wdev->conn_owner_nlportid)
17684 return -EINVAL;
17685
17686 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
17687 if (!msg)
17688 return -ENOMEM;
17689
17690 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_EXTERNAL_AUTH);
17691 if (!hdr)
17692 goto nla_put_failure;
17693
17694 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
17695 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
17696 nla_put_u32(msg, NL80211_ATTR_AKM_SUITES, params->key_mgmt_suite) ||
17697 nla_put_u32(msg, NL80211_ATTR_EXTERNAL_AUTH_ACTION,
17698 params->action) ||
17699 nla_put(msg, NL80211_ATTR_BSSID, ETH_ALEN, params->bssid) ||
17700 nla_put(msg, NL80211_ATTR_SSID, params->ssid.ssid_len,
17701 params->ssid.ssid))
17702 goto nla_put_failure;
17703
17704 genlmsg_end(msg, hdr);
17705 genlmsg_unicast(wiphy_net(&rdev->wiphy), msg,
17706 wdev->conn_owner_nlportid);
17707 return 0;
17708
17709 nla_put_failure:
17710 nlmsg_free(msg);
17711 return -ENOBUFS;
17712}
17713EXPORT_SYMBOL(cfg80211_external_auth_request);
17714
cb74e977
SD
17715void cfg80211_update_owe_info_event(struct net_device *netdev,
17716 struct cfg80211_update_owe_info *owe_info,
17717 gfp_t gfp)
17718{
17719 struct wiphy *wiphy = netdev->ieee80211_ptr->wiphy;
17720 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
17721 struct sk_buff *msg;
17722 void *hdr;
17723
17724 trace_cfg80211_update_owe_info_event(wiphy, netdev, owe_info);
17725
17726 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
17727 if (!msg)
17728 return;
17729
17730 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_UPDATE_OWE_INFO);
17731 if (!hdr)
17732 goto nla_put_failure;
17733
17734 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
17735 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
17736 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, owe_info->peer))
17737 goto nla_put_failure;
17738
17739 if (!owe_info->ie_len ||
17740 nla_put(msg, NL80211_ATTR_IE, owe_info->ie_len, owe_info->ie))
17741 goto nla_put_failure;
17742
17743 genlmsg_end(msg, hdr);
17744
17745 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
17746 NL80211_MCGRP_MLME, gfp);
17747 return;
17748
17749nla_put_failure:
17750 genlmsg_cancel(msg, hdr);
17751 nlmsg_free(msg);
17752}
17753EXPORT_SYMBOL(cfg80211_update_owe_info_event);
17754
55682965
JB
17755/* initialisation/exit functions */
17756
56989f6d 17757int __init nl80211_init(void)
55682965 17758{
0d63cbb5 17759 int err;
55682965 17760
489111e5 17761 err = genl_register_family(&nl80211_fam);
55682965
JB
17762 if (err)
17763 return err;
17764
026331c4
JM
17765 err = netlink_register_notifier(&nl80211_netlink_notifier);
17766 if (err)
17767 goto err_out;
17768
55682965
JB
17769 return 0;
17770 err_out:
17771 genl_unregister_family(&nl80211_fam);
17772 return err;
17773}
17774
17775void nl80211_exit(void)
17776{
026331c4 17777 netlink_unregister_notifier(&nl80211_netlink_notifier);
55682965
JB
17778 genl_unregister_family(&nl80211_fam);
17779}