Merge wireless into wireless-next
[linux-2.6-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
57d1b463 8 * Copyright (C) 2018-2024 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 *
a05829a7
JB
67__cfg80211_wdev_from_attrs(struct cfg80211_registered_device *rdev,
68 struct net *netns, struct nlattr **attrs)
55682965 69{
89a54e48
JB
70 struct wireless_dev *result = NULL;
71 bool have_ifidx = attrs[NL80211_ATTR_IFINDEX];
72 bool have_wdev_id = attrs[NL80211_ATTR_WDEV];
239729a2 73 u64 wdev_id = 0;
89a54e48
JB
74 int wiphy_idx = -1;
75 int ifidx = -1;
55682965 76
89a54e48
JB
77 if (!have_ifidx && !have_wdev_id)
78 return ERR_PTR(-EINVAL);
55682965 79
89a54e48
JB
80 if (have_ifidx)
81 ifidx = nla_get_u32(attrs[NL80211_ATTR_IFINDEX]);
82 if (have_wdev_id) {
83 wdev_id = nla_get_u64(attrs[NL80211_ATTR_WDEV]);
84 wiphy_idx = wdev_id >> 32;
55682965
JB
85 }
86
a05829a7
JB
87 if (rdev) {
88 struct wireless_dev *wdev;
89
90 lockdep_assert_held(&rdev->wiphy.mtx);
91
92 list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
93 if (have_ifidx && wdev->netdev &&
94 wdev->netdev->ifindex == ifidx) {
95 result = wdev;
96 break;
97 }
98 if (have_wdev_id && wdev->identifier == (u32)wdev_id) {
99 result = wdev;
100 break;
101 }
102 }
103
104 return result ?: ERR_PTR(-ENODEV);
105 }
106
107 ASSERT_RTNL();
108
7483a214 109 for_each_rdev(rdev) {
89a54e48
JB
110 struct wireless_dev *wdev;
111
112 if (wiphy_net(&rdev->wiphy) != netns)
113 continue;
114
115 if (have_wdev_id && rdev->wiphy_idx != wiphy_idx)
116 continue;
117
53873f13 118 list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
89a54e48
JB
119 if (have_ifidx && wdev->netdev &&
120 wdev->netdev->ifindex == ifidx) {
121 result = wdev;
122 break;
123 }
124 if (have_wdev_id && wdev->identifier == (u32)wdev_id) {
125 result = wdev;
126 break;
127 }
128 }
89a54e48
JB
129
130 if (result)
131 break;
132 }
133
134 if (result)
135 return result;
136 return ERR_PTR(-ENODEV);
55682965
JB
137}
138
a9455408 139static struct cfg80211_registered_device *
878d9ec7 140__cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
a9455408 141{
7fee4778
JB
142 struct cfg80211_registered_device *rdev = NULL, *tmp;
143 struct net_device *netdev;
a9455408 144
5fe231e8 145 ASSERT_RTNL();
a9455408 146
878d9ec7 147 if (!attrs[NL80211_ATTR_WIPHY] &&
89a54e48
JB
148 !attrs[NL80211_ATTR_IFINDEX] &&
149 !attrs[NL80211_ATTR_WDEV])
7fee4778
JB
150 return ERR_PTR(-EINVAL);
151
878d9ec7 152 if (attrs[NL80211_ATTR_WIPHY])
7fee4778 153 rdev = cfg80211_rdev_by_wiphy_idx(
878d9ec7 154 nla_get_u32(attrs[NL80211_ATTR_WIPHY]));
a9455408 155
89a54e48
JB
156 if (attrs[NL80211_ATTR_WDEV]) {
157 u64 wdev_id = nla_get_u64(attrs[NL80211_ATTR_WDEV]);
158 struct wireless_dev *wdev;
159 bool found = false;
160
161 tmp = cfg80211_rdev_by_wiphy_idx(wdev_id >> 32);
162 if (tmp) {
163 /* make sure wdev exists */
53873f13 164 list_for_each_entry(wdev, &tmp->wiphy.wdev_list, list) {
89a54e48
JB
165 if (wdev->identifier != (u32)wdev_id)
166 continue;
167 found = true;
168 break;
169 }
89a54e48
JB
170
171 if (!found)
172 tmp = NULL;
173
174 if (rdev && tmp != rdev)
175 return ERR_PTR(-EINVAL);
176 rdev = tmp;
177 }
178 }
179
878d9ec7
JB
180 if (attrs[NL80211_ATTR_IFINDEX]) {
181 int ifindex = nla_get_u32(attrs[NL80211_ATTR_IFINDEX]);
7a087e74 182
7f2b8562 183 netdev = __dev_get_by_index(netns, ifindex);
7fee4778
JB
184 if (netdev) {
185 if (netdev->ieee80211_ptr)
f26cbf40
ZG
186 tmp = wiphy_to_rdev(
187 netdev->ieee80211_ptr->wiphy);
7fee4778
JB
188 else
189 tmp = NULL;
190
7fee4778
JB
191 /* not wireless device -- return error */
192 if (!tmp)
193 return ERR_PTR(-EINVAL);
194
195 /* mismatch -- return error */
196 if (rdev && tmp != rdev)
197 return ERR_PTR(-EINVAL);
198
199 rdev = tmp;
a9455408 200 }
a9455408 201 }
a9455408 202
4f7eff10
JB
203 if (!rdev)
204 return ERR_PTR(-ENODEV);
a9455408 205
4f7eff10
JB
206 if (netns != wiphy_net(&rdev->wiphy))
207 return ERR_PTR(-ENODEV);
208
209 return rdev;
a9455408
JB
210}
211
212/*
213 * This function returns a pointer to the driver
214 * that the genl_info item that is passed refers to.
a9455408
JB
215 *
216 * The result of this can be a PTR_ERR and hence must
217 * be checked with IS_ERR() for errors.
218 */
219static struct cfg80211_registered_device *
4f7eff10 220cfg80211_get_dev_from_info(struct net *netns, struct genl_info *info)
a9455408 221{
5fe231e8 222 return __cfg80211_rdev_from_attrs(netns, info->attrs);
a9455408
JB
223}
224
f88eb7c0
JB
225static int validate_beacon_head(const struct nlattr *attr,
226 struct netlink_ext_ack *extack)
227{
228 const u8 *data = nla_data(attr);
229 unsigned int len = nla_len(attr);
230 const struct element *elem;
231 const struct ieee80211_mgmt *mgmt = (void *)data;
1d47f119 232 unsigned int fixedlen, hdrlen;
9a6847ba 233 bool s1g_bcn;
1d47f119 234
9a6847ba
JB
235 if (len < offsetofend(typeof(*mgmt), frame_control))
236 goto err;
237
238 s1g_bcn = ieee80211_is_s1g_beacon(mgmt->frame_control);
1d47f119
TP
239 if (s1g_bcn) {
240 fixedlen = offsetof(struct ieee80211_ext,
241 u.s1g_beacon.variable);
242 hdrlen = offsetof(struct ieee80211_ext, u.s1g_beacon);
243 } else {
244 fixedlen = offsetof(struct ieee80211_mgmt,
245 u.beacon.variable);
246 hdrlen = offsetof(struct ieee80211_mgmt, u.beacon);
247 }
f88eb7c0
JB
248
249 if (len < fixedlen)
250 goto err;
251
1d47f119 252 if (ieee80211_hdrlen(mgmt->frame_control) != hdrlen)
f88eb7c0
JB
253 goto err;
254
255 data += fixedlen;
256 len -= fixedlen;
257
258 for_each_element(elem, data, len) {
259 /* nothing */
260 }
261
262 if (for_each_element_completed(elem, data, len))
263 return 0;
264
265err:
266 NL_SET_ERR_MSG_ATTR(extack, attr, "malformed beacon head");
267 return -EINVAL;
268}
269
3d7af878
JB
270static int validate_ie_attr(const struct nlattr *attr,
271 struct netlink_ext_ack *extack)
272{
9f308616
JB
273 const u8 *data = nla_data(attr);
274 unsigned int len = nla_len(attr);
7388afe0 275 const struct element *elem;
3d7af878 276
9f308616
JB
277 for_each_element(elem, data, len) {
278 /* nothing */
3d7af878
JB
279 }
280
9f308616
JB
281 if (for_each_element_completed(elem, data, len))
282 return 0;
283
3d7af878
JB
284 NL_SET_ERR_MSG_ATTR(extack, attr, "malformed information elements");
285 return -EINVAL;
286}
287
a3a20feb
JB
288static int validate_he_capa(const struct nlattr *attr,
289 struct netlink_ext_ack *extack)
290{
291 if (!ieee80211_he_capa_size_ok(nla_data(attr), nla_len(attr)))
292 return -EINVAL;
293
294 return 0;
295}
296
55682965 297/* policy for the attributes */
d15da2a2
JB
298static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR];
299
81e54d08
PKC
300static const struct nla_policy
301nl80211_ftm_responder_policy[NL80211_FTM_RESP_ATTR_MAX + 1] = {
302 [NL80211_FTM_RESP_ATTR_ENABLED] = { .type = NLA_FLAG, },
303 [NL80211_FTM_RESP_ATTR_LCI] = { .type = NLA_BINARY,
304 .len = U8_MAX },
305 [NL80211_FTM_RESP_ATTR_CIVICLOC] = { .type = NLA_BINARY,
306 .len = U8_MAX },
307};
308
9bb7e0f2
JB
309static const struct nla_policy
310nl80211_pmsr_ftm_req_attr_policy[NL80211_PMSR_FTM_REQ_ATTR_MAX + 1] = {
311 [NL80211_PMSR_FTM_REQ_ATTR_ASAP] = { .type = NLA_FLAG },
312 [NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE] = { .type = NLA_U32 },
313 [NL80211_PMSR_FTM_REQ_ATTR_NUM_BURSTS_EXP] =
314 NLA_POLICY_MAX(NLA_U8, 15),
315 [NL80211_PMSR_FTM_REQ_ATTR_BURST_PERIOD] = { .type = NLA_U16 },
316 [NL80211_PMSR_FTM_REQ_ATTR_BURST_DURATION] =
317 NLA_POLICY_MAX(NLA_U8, 15),
318 [NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST] =
ea18709a 319 NLA_POLICY_MAX(NLA_U8, 31),
9bb7e0f2
JB
320 [NL80211_PMSR_FTM_REQ_ATTR_NUM_FTMR_RETRIES] = { .type = NLA_U8 },
321 [NL80211_PMSR_FTM_REQ_ATTR_REQUEST_LCI] = { .type = NLA_FLAG },
322 [NL80211_PMSR_FTM_REQ_ATTR_REQUEST_CIVICLOC] = { .type = NLA_FLAG },
efb5520d
AS
323 [NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED] = { .type = NLA_FLAG },
324 [NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED] = { .type = NLA_FLAG },
73807523 325 [NL80211_PMSR_FTM_REQ_ATTR_LMR_FEEDBACK] = { .type = NLA_FLAG },
218d690c 326 [NL80211_PMSR_FTM_REQ_ATTR_BSS_COLOR] = { .type = NLA_U8 },
9bb7e0f2
JB
327};
328
329static const struct nla_policy
330nl80211_pmsr_req_data_policy[NL80211_PMSR_TYPE_MAX + 1] = {
331 [NL80211_PMSR_TYPE_FTM] =
23323289 332 NLA_POLICY_NESTED(nl80211_pmsr_ftm_req_attr_policy),
9bb7e0f2
JB
333};
334
335static const struct nla_policy
336nl80211_pmsr_req_attr_policy[NL80211_PMSR_REQ_ATTR_MAX + 1] = {
337 [NL80211_PMSR_REQ_ATTR_DATA] =
23323289 338 NLA_POLICY_NESTED(nl80211_pmsr_req_data_policy),
9bb7e0f2
JB
339 [NL80211_PMSR_REQ_ATTR_GET_AP_TSF] = { .type = NLA_FLAG },
340};
341
342static const struct nla_policy
aeddc05f 343nl80211_pmsr_peer_attr_policy[NL80211_PMSR_PEER_ATTR_MAX + 1] = {
9bb7e0f2 344 [NL80211_PMSR_PEER_ATTR_ADDR] = NLA_POLICY_ETH_ADDR,
d15da2a2 345 [NL80211_PMSR_PEER_ATTR_CHAN] = NLA_POLICY_NESTED(nl80211_policy),
9bb7e0f2 346 [NL80211_PMSR_PEER_ATTR_REQ] =
23323289 347 NLA_POLICY_NESTED(nl80211_pmsr_req_attr_policy),
9bb7e0f2
JB
348 [NL80211_PMSR_PEER_ATTR_RESP] = { .type = NLA_REJECT },
349};
350
351static const struct nla_policy
352nl80211_pmsr_attr_policy[NL80211_PMSR_ATTR_MAX + 1] = {
353 [NL80211_PMSR_ATTR_MAX_PEERS] = { .type = NLA_REJECT },
354 [NL80211_PMSR_ATTR_REPORT_AP_TSF] = { .type = NLA_REJECT },
355 [NL80211_PMSR_ATTR_RANDOMIZE_MAC_ADDR] = { .type = NLA_REJECT },
356 [NL80211_PMSR_ATTR_TYPE_CAPA] = { .type = NLA_REJECT },
357 [NL80211_PMSR_ATTR_PEERS] =
aeddc05f 358 NLA_POLICY_NESTED_ARRAY(nl80211_pmsr_peer_attr_policy),
9bb7e0f2
JB
359};
360
796e90f4
JC
361static const struct nla_policy
362he_obss_pd_policy[NL80211_HE_OBSS_PD_ATTR_MAX + 1] = {
363 [NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET] =
364 NLA_POLICY_RANGE(NLA_U8, 1, 20),
365 [NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET] =
366 NLA_POLICY_RANGE(NLA_U8, 1, 20),
f5bec330
RM
367 [NL80211_HE_OBSS_PD_ATTR_NON_SRG_MAX_OFFSET] =
368 NLA_POLICY_RANGE(NLA_U8, 1, 20),
369 [NL80211_HE_OBSS_PD_ATTR_BSS_COLOR_BITMAP] =
370 NLA_POLICY_EXACT_LEN(8),
371 [NL80211_HE_OBSS_PD_ATTR_PARTIAL_BSSID_BITMAP] =
372 NLA_POLICY_EXACT_LEN(8),
373 [NL80211_HE_OBSS_PD_ATTR_SR_CTRL] = { .type = NLA_U8 },
796e90f4
JC
374};
375
5c5e52d1
JC
376static const struct nla_policy
377he_bss_color_policy[NL80211_HE_BSS_COLOR_ATTR_MAX + 1] = {
378 [NL80211_HE_BSS_COLOR_ATTR_COLOR] = NLA_POLICY_RANGE(NLA_U8, 1, 63),
379 [NL80211_HE_BSS_COLOR_ATTR_DISABLED] = { .type = NLA_FLAG },
380 [NL80211_HE_BSS_COLOR_ATTR_PARTIAL] = { .type = NLA_FLAG },
381};
382
9a5f6488
TC
383static const struct nla_policy nl80211_txattr_policy[NL80211_TXRATE_MAX + 1] = {
384 [NL80211_TXRATE_LEGACY] = { .type = NLA_BINARY,
385 .len = NL80211_MAX_SUPP_RATES },
386 [NL80211_TXRATE_HT] = { .type = NLA_BINARY,
387 .len = NL80211_MAX_SUPP_HT_RATES },
388 [NL80211_TXRATE_VHT] = NLA_POLICY_EXACT_LEN_WARN(sizeof(struct nl80211_txrate_vht)),
389 [NL80211_TXRATE_GI] = { .type = NLA_U8 },
eb89a6a6
MH
390 [NL80211_TXRATE_HE] = NLA_POLICY_EXACT_LEN(sizeof(struct nl80211_txrate_he)),
391 [NL80211_TXRATE_HE_GI] = NLA_POLICY_RANGE(NLA_U8,
392 NL80211_RATE_INFO_HE_GI_0_8,
393 NL80211_RATE_INFO_HE_GI_3_2),
394 [NL80211_TXRATE_HE_LTF] = NLA_POLICY_RANGE(NLA_U8,
395 NL80211_RATE_INFO_HE_1XLTF,
396 NL80211_RATE_INFO_HE_4XLTF),
9a5f6488
TC
397};
398
77f576de
T
399static const struct nla_policy
400nl80211_tid_config_attr_policy[NL80211_TID_CONFIG_ATTR_MAX + 1] = {
3710a8a6
JB
401 [NL80211_TID_CONFIG_ATTR_VIF_SUPP] = { .type = NLA_U64 },
402 [NL80211_TID_CONFIG_ATTR_PEER_SUPP] = { .type = NLA_U64 },
77f576de 403 [NL80211_TID_CONFIG_ATTR_OVERRIDE] = { .type = NLA_FLAG },
3710a8a6 404 [NL80211_TID_CONFIG_ATTR_TIDS] = NLA_POLICY_RANGE(NLA_U16, 1, 0xff),
77f576de
T
405 [NL80211_TID_CONFIG_ATTR_NOACK] =
406 NLA_POLICY_MAX(NLA_U8, NL80211_TID_CONFIG_DISABLE),
6a21d16c
T
407 [NL80211_TID_CONFIG_ATTR_RETRY_SHORT] = NLA_POLICY_MIN(NLA_U8, 1),
408 [NL80211_TID_CONFIG_ATTR_RETRY_LONG] = NLA_POLICY_MIN(NLA_U8, 1),
ade274b2
T
409 [NL80211_TID_CONFIG_ATTR_AMPDU_CTRL] =
410 NLA_POLICY_MAX(NLA_U8, NL80211_TID_CONFIG_DISABLE),
04f7d142
T
411 [NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL] =
412 NLA_POLICY_MAX(NLA_U8, NL80211_TID_CONFIG_DISABLE),
33462e68
SM
413 [NL80211_TID_CONFIG_ATTR_AMSDU_CTRL] =
414 NLA_POLICY_MAX(NLA_U8, NL80211_TID_CONFIG_DISABLE),
9a5f6488
TC
415 [NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE] =
416 NLA_POLICY_MAX(NLA_U8, NL80211_TX_RATE_FIXED),
417 [NL80211_TID_CONFIG_ATTR_TX_RATE] =
418 NLA_POLICY_NESTED(nl80211_txattr_policy),
77f576de
T
419};
420
291c49de
AD
421static const struct nla_policy
422nl80211_fils_discovery_policy[NL80211_FILS_DISCOVERY_ATTR_MAX + 1] = {
423 [NL80211_FILS_DISCOVERY_ATTR_INT_MIN] = NLA_POLICY_MAX(NLA_U32, 10000),
424 [NL80211_FILS_DISCOVERY_ATTR_INT_MAX] = NLA_POLICY_MAX(NLA_U32, 10000),
272cd0e8
AD
425 [NL80211_FILS_DISCOVERY_ATTR_TMPL] =
426 NLA_POLICY_RANGE(NLA_BINARY,
427 NL80211_FILS_DISCOVERY_TMPL_MIN_LEN,
428 IEEE80211_MAX_DATA_LEN),
291c49de
AD
429};
430
7443dcd1
AD
431static const struct nla_policy
432nl80211_unsol_bcast_probe_resp_policy[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_MAX + 1] = {
433 [NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INT] = NLA_POLICY_MAX(NLA_U32, 20),
434 [NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL] = { .type = NLA_BINARY,
435 .len = IEEE80211_MAX_DATA_LEN }
436};
437
6bdb68ce
CH
438static const struct nla_policy
439sar_specs_policy[NL80211_SAR_ATTR_SPECS_MAX + 1] = {
440 [NL80211_SAR_ATTR_SPECS_POWER] = { .type = NLA_S32 },
441 [NL80211_SAR_ATTR_SPECS_RANGE_INDEX] = {.type = NLA_U32 },
442};
443
444static const struct nla_policy
445sar_policy[NL80211_SAR_ATTR_MAX + 1] = {
446 [NL80211_SAR_ATTR_TYPE] = NLA_POLICY_MAX(NLA_U32, NUM_NL80211_SAR_TYPE),
447 [NL80211_SAR_ATTR_SPECS] = NLA_POLICY_NESTED_ARRAY(sar_specs_policy),
448};
449
dc1e3cb8
JC
450static const struct nla_policy
451nl80211_mbssid_config_policy[NL80211_MBSSID_CONFIG_ATTR_MAX + 1] = {
452 [NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES] = NLA_POLICY_MIN(NLA_U8, 2),
453 [NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY] =
454 NLA_POLICY_MIN(NLA_U8, 1),
455 [NL80211_MBSSID_CONFIG_ATTR_INDEX] = { .type = NLA_U8 },
456 [NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX] = { .type = NLA_U32 },
457 [NL80211_MBSSID_CONFIG_ATTR_EMA] = { .type = NLA_FLAG },
458};
459
ff5c4dc4
JB
460static const struct nla_policy
461nl80211_sta_wme_policy[NL80211_STA_WME_MAX + 1] = {
462 [NL80211_STA_WME_UAPSD_QUEUES] = { .type = NLA_U8 },
463 [NL80211_STA_WME_MAX_SP] = { .type = NLA_U8 },
464};
465
ea23fbd2 466static const struct netlink_range_validation nl80211_punct_bitmap_range = {
b27f07c5
JB
467 .min = 0,
468 .max = 0xffff,
469};
470
d15da2a2 471static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
6d4dd4ef 472 [0] = { .strict_start_type = NL80211_ATTR_HE_OBSS_PD },
55682965
JB
473 [NL80211_ATTR_WIPHY] = { .type = NLA_U32 },
474 [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING,
079e24ed 475 .len = 20-1 },
31888487 476 [NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED },
3d9d1d66 477
72bdcf34 478 [NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 },
094d05dc 479 [NL80211_ATTR_WIPHY_CHANNEL_TYPE] = { .type = NLA_U32 },
2a38075c
AAL
480 [NL80211_ATTR_WIPHY_EDMG_CHANNELS] = NLA_POLICY_RANGE(NLA_U8,
481 NL80211_EDMG_CHANNELS_MIN,
482 NL80211_EDMG_CHANNELS_MAX),
483 [NL80211_ATTR_WIPHY_EDMG_BW_CONFIG] = NLA_POLICY_RANGE(NLA_U8,
484 NL80211_EDMG_BW_CONFIG_MIN,
485 NL80211_EDMG_BW_CONFIG_MAX),
486
3d9d1d66
JB
487 [NL80211_ATTR_CHANNEL_WIDTH] = { .type = NLA_U32 },
488 [NL80211_ATTR_CENTER_FREQ1] = { .type = NLA_U32 },
942ba88b 489 [NL80211_ATTR_CENTER_FREQ1_OFFSET] = NLA_POLICY_RANGE(NLA_U32, 0, 999),
3d9d1d66
JB
490 [NL80211_ATTR_CENTER_FREQ2] = { .type = NLA_U32 },
491
ab0d76f6
JB
492 [NL80211_ATTR_WIPHY_RETRY_SHORT] = NLA_POLICY_MIN(NLA_U8, 1),
493 [NL80211_ATTR_WIPHY_RETRY_LONG] = NLA_POLICY_MIN(NLA_U8, 1),
b9a5f8ca
JM
494 [NL80211_ATTR_WIPHY_FRAG_THRESHOLD] = { .type = NLA_U32 },
495 [NL80211_ATTR_WIPHY_RTS_THRESHOLD] = { .type = NLA_U32 },
81077e82 496 [NL80211_ATTR_WIPHY_COVERAGE_CLASS] = { .type = NLA_U8 },
3057dbfd 497 [NL80211_ATTR_WIPHY_DYN_ACK] = { .type = NLA_FLAG },
55682965 498
ab0d76f6 499 [NL80211_ATTR_IFTYPE] = NLA_POLICY_MAX(NLA_U32, NL80211_IFTYPE_MAX),
55682965
JB
500 [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 },
501 [NL80211_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 },
41ade00f 502
c7721c05
JB
503 [NL80211_ATTR_MAC] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
504 [NL80211_ATTR_PREV_BSSID] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
41ade00f 505
b9454e83 506 [NL80211_ATTR_KEY] = { .type = NLA_NESTED, },
41ade00f
JB
507 [NL80211_ATTR_KEY_DATA] = { .type = NLA_BINARY,
508 .len = WLAN_MAX_KEY_LEN },
56be393f 509 [NL80211_ATTR_KEY_IDX] = NLA_POLICY_MAX(NLA_U8, 7),
41ade00f
JB
510 [NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 },
511 [NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG },
81962267 512 [NL80211_ATTR_KEY_SEQ] = { .type = NLA_BINARY, .len = 16 },
ab0d76f6
JB
513 [NL80211_ATTR_KEY_TYPE] =
514 NLA_POLICY_MAX(NLA_U32, NUM_NL80211_KEYTYPES),
ed1b6cc7
JB
515
516 [NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 },
517 [NL80211_ATTR_DTIM_PERIOD] = { .type = NLA_U32 },
f88eb7c0
JB
518 [NL80211_ATTR_BEACON_HEAD] =
519 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_beacon_head,
520 IEEE80211_MAX_DATA_LEN),
3d7af878
JB
521 [NL80211_ATTR_BEACON_TAIL] =
522 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr,
523 IEEE80211_MAX_DATA_LEN),
ab0d76f6
JB
524 [NL80211_ATTR_STA_AID] =
525 NLA_POLICY_RANGE(NLA_U16, 1, IEEE80211_MAX_AID),
5727ef1b
JB
526 [NL80211_ATTR_STA_FLAGS] = { .type = NLA_NESTED },
527 [NL80211_ATTR_STA_LISTEN_INTERVAL] = { .type = NLA_U16 },
528 [NL80211_ATTR_STA_SUPPORTED_RATES] = { .type = NLA_BINARY,
529 .len = NL80211_MAX_SUPP_RATES },
ab0d76f6
JB
530 [NL80211_ATTR_STA_PLINK_ACTION] =
531 NLA_POLICY_MAX(NLA_U8, NUM_NL80211_PLINK_ACTIONS - 1),
e96d1cd2
ARN
532 [NL80211_ATTR_STA_TX_POWER_SETTING] =
533 NLA_POLICY_RANGE(NLA_U8,
534 NL80211_TX_POWER_AUTOMATIC,
535 NL80211_TX_POWER_FIXED),
536 [NL80211_ATTR_STA_TX_POWER] = { .type = NLA_S16 },
5727ef1b 537 [NL80211_ATTR_STA_VLAN] = { .type = NLA_U32 },
0a9542ee 538 [NL80211_ATTR_MNTR_FLAGS] = { /* NLA_NESTED can't be empty */ },
2ec600d6 539 [NL80211_ATTR_MESH_ID] = { .type = NLA_BINARY,
a4f606ea 540 .len = IEEE80211_MAX_MESH_ID_LEN },
1fab1b89 541 [NL80211_ATTR_MPATH_NEXT_HOP] = NLA_POLICY_ETH_ADDR_COMPAT,
9f1ba906 542
6624bb34
JB
543 /* allow 3 for NUL-termination, we used to declare this NLA_STRING */
544 [NL80211_ATTR_REG_ALPHA2] = NLA_POLICY_RANGE(NLA_BINARY, 2, 3),
b2e1b302
LR
545 [NL80211_ATTR_REG_RULES] = { .type = NLA_NESTED },
546
9f1ba906
JM
547 [NL80211_ATTR_BSS_CTS_PROT] = { .type = NLA_U8 },
548 [NL80211_ATTR_BSS_SHORT_PREAMBLE] = { .type = NLA_U8 },
549 [NL80211_ATTR_BSS_SHORT_SLOT_TIME] = { .type = NLA_U8 },
90c97a04
JM
550 [NL80211_ATTR_BSS_BASIC_RATES] = { .type = NLA_BINARY,
551 .len = NL80211_MAX_SUPP_RATES },
50b12f59 552 [NL80211_ATTR_BSS_HT_OPMODE] = { .type = NLA_U16 },
36aedc90 553
24bdd9f4 554 [NL80211_ATTR_MESH_CONFIG] = { .type = NLA_NESTED },
15d5dda6 555 [NL80211_ATTR_SUPPORT_MESH_AUTH] = { .type = NLA_FLAG },
93da9cc1 556
c7721c05 557 [NL80211_ATTR_HT_CAPABILITY] = NLA_POLICY_EXACT_LEN_WARN(NL80211_HT_CAPABILITY_LEN),
9aed3cc1
JM
558
559 [NL80211_ATTR_MGMT_SUBTYPE] = { .type = NLA_U8 },
3d7af878
JB
560 [NL80211_ATTR_IE] = NLA_POLICY_VALIDATE_FN(NLA_BINARY,
561 validate_ie_attr,
562 IEEE80211_MAX_DATA_LEN),
2a519311
JB
563 [NL80211_ATTR_SCAN_FREQUENCIES] = { .type = NLA_NESTED },
564 [NL80211_ATTR_SCAN_SSIDS] = { .type = NLA_NESTED },
636a5d36
JM
565
566 [NL80211_ATTR_SSID] = { .type = NLA_BINARY,
567 .len = IEEE80211_MAX_SSID_LEN },
568 [NL80211_ATTR_AUTH_TYPE] = { .type = NLA_U32 },
569 [NL80211_ATTR_REASON_CODE] = { .type = NLA_U16 },
04a773ad 570 [NL80211_ATTR_FREQ_FIXED] = { .type = NLA_FLAG },
1965c853 571 [NL80211_ATTR_TIMED_OUT] = { .type = NLA_FLAG },
ab0d76f6
JB
572 [NL80211_ATTR_USE_MFP] = NLA_POLICY_RANGE(NLA_U32,
573 NL80211_MFP_NO,
574 NL80211_MFP_OPTIONAL),
ff5c4dc4
JB
575 [NL80211_ATTR_STA_FLAGS2] =
576 NLA_POLICY_EXACT_LEN_WARN(sizeof(struct nl80211_sta_flag_update)),
3f77316c 577 [NL80211_ATTR_CONTROL_PORT] = { .type = NLA_FLAG },
c0692b8f
JB
578 [NL80211_ATTR_CONTROL_PORT_ETHERTYPE] = { .type = NLA_U16 },
579 [NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT] = { .type = NLA_FLAG },
64bf3d4b 580 [NL80211_ATTR_CONTROL_PORT_OVER_NL80211] = { .type = NLA_FLAG },
b23aa676 581 [NL80211_ATTR_PRIVACY] = { .type = NLA_FLAG },
ea750801 582 [NL80211_ATTR_STATUS_CODE] = { .type = NLA_U16 },
b23aa676 583 [NL80211_ATTR_CIPHER_SUITE_GROUP] = { .type = NLA_U32 },
57d1b463
JB
584 [NL80211_ATTR_WPA_VERSIONS] =
585 NLA_POLICY_RANGE(NLA_U32, 0,
586 NL80211_WPA_VERSION_1 |
587 NL80211_WPA_VERSION_2 |
588 NL80211_WPA_VERSION_3),
463d0183 589 [NL80211_ATTR_PID] = { .type = NLA_U32 },
8b787643 590 [NL80211_ATTR_4ADDR] = { .type = NLA_U8 },
c7721c05 591 [NL80211_ATTR_PMKID] = NLA_POLICY_EXACT_LEN_WARN(WLAN_PMKID_LEN),
9588bbd5
JM
592 [NL80211_ATTR_DURATION] = { .type = NLA_U32 },
593 [NL80211_ATTR_COOKIE] = { .type = NLA_U64 },
13ae75b1 594 [NL80211_ATTR_TX_RATES] = { .type = NLA_NESTED },
026331c4
JM
595 [NL80211_ATTR_FRAME] = { .type = NLA_BINARY,
596 .len = IEEE80211_MAX_DATA_LEN },
597 [NL80211_ATTR_FRAME_MATCH] = { .type = NLA_BINARY, },
ab0d76f6
JB
598 [NL80211_ATTR_PS_STATE] = NLA_POLICY_RANGE(NLA_U32,
599 NL80211_PS_DISABLED,
600 NL80211_PS_ENABLED),
d6dc1a38 601 [NL80211_ATTR_CQM] = { .type = NLA_NESTED, },
d5cdfacb 602 [NL80211_ATTR_LOCAL_STATE_CHANGE] = { .type = NLA_FLAG },
fd8aaaf3 603 [NL80211_ATTR_AP_ISOLATE] = { .type = NLA_U8 },
98d2ff8b
JO
604 [NL80211_ATTR_WIPHY_TX_POWER_SETTING] = { .type = NLA_U32 },
605 [NL80211_ATTR_WIPHY_TX_POWER_LEVEL] = { .type = NLA_U32 },
2e161f78 606 [NL80211_ATTR_FRAME_TYPE] = { .type = NLA_U16 },
afe0cbf8
BR
607 [NL80211_ATTR_WIPHY_ANTENNA_TX] = { .type = NLA_U32 },
608 [NL80211_ATTR_WIPHY_ANTENNA_RX] = { .type = NLA_U32 },
885a46d0 609 [NL80211_ATTR_MCAST_RATE] = { .type = NLA_U32 },
f7ca38df 610 [NL80211_ATTR_OFFCHANNEL_TX_OK] = { .type = NLA_FLAG },
dbd2fd65 611 [NL80211_ATTR_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED },
ff1b6e69 612 [NL80211_ATTR_WOWLAN_TRIGGERS] = { .type = NLA_NESTED },
ab0d76f6
JB
613 [NL80211_ATTR_STA_PLINK_STATE] =
614 NLA_POLICY_MAX(NLA_U8, NUM_NL80211_PLINK_STATES - 1),
056e9375
JK
615 [NL80211_ATTR_MEASUREMENT_DURATION] = { .type = NLA_U16 },
616 [NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY] = { .type = NLA_FLAG },
ab0d76f6
JB
617 [NL80211_ATTR_MESH_PEER_AID] =
618 NLA_POLICY_RANGE(NLA_U16, 1, IEEE80211_MAX_AID),
bbe6ad6d 619 [NL80211_ATTR_SCHED_SCAN_INTERVAL] = { .type = NLA_U32 },
e5497d76 620 [NL80211_ATTR_REKEY_DATA] = { .type = NLA_NESTED },
34850ab2 621 [NL80211_ATTR_SCAN_SUPP_RATES] = { .type = NLA_NESTED },
ab0d76f6
JB
622 [NL80211_ATTR_HIDDEN_SSID] =
623 NLA_POLICY_RANGE(NLA_U32,
624 NL80211_HIDDEN_SSID_NOT_IN_USE,
625 NL80211_HIDDEN_SSID_ZERO_CONTENTS),
3d7af878
JB
626 [NL80211_ATTR_IE_PROBE_RESP] =
627 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr,
628 IEEE80211_MAX_DATA_LEN),
629 [NL80211_ATTR_IE_ASSOC_RESP] =
630 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr,
631 IEEE80211_MAX_DATA_LEN),
f4b34b55 632 [NL80211_ATTR_ROAM_SUPPORT] = { .type = NLA_FLAG },
ff5c4dc4 633 [NL80211_ATTR_STA_WME] = NLA_POLICY_NESTED(nl80211_sta_wme_policy),
a1f1c21c 634 [NL80211_ATTR_SCHED_SCAN_MATCH] = { .type = NLA_NESTED },
e9f935e3 635 [NL80211_ATTR_TX_NO_CCK_RATE] = { .type = NLA_FLAG },
109086ce
AN
636 [NL80211_ATTR_TDLS_ACTION] = { .type = NLA_U8 },
637 [NL80211_ATTR_TDLS_DIALOG_TOKEN] = { .type = NLA_U8 },
638 [NL80211_ATTR_TDLS_OPERATION] = { .type = NLA_U8 },
639 [NL80211_ATTR_TDLS_SUPPORT] = { .type = NLA_FLAG },
640 [NL80211_ATTR_TDLS_EXTERNAL_SETUP] = { .type = NLA_FLAG },
31fa97c5 641 [NL80211_ATTR_TDLS_INITIATOR] = { .type = NLA_FLAG },
e247bd90 642 [NL80211_ATTR_DONT_WAIT_FOR_ACK] = { .type = NLA_FLAG },
00f740e1
AN
643 [NL80211_ATTR_PROBE_RESP] = { .type = NLA_BINARY,
644 .len = IEEE80211_MAX_DATA_LEN },
8b60b078 645 [NL80211_ATTR_DFS_REGION] = { .type = NLA_U8 },
7e7c8926
BG
646 [NL80211_ATTR_DISABLE_HT] = { .type = NLA_FLAG },
647 [NL80211_ATTR_HT_CAPABILITY_MASK] = {
648 .len = NL80211_HT_CAPABILITY_LEN
649 },
1d9d9213 650 [NL80211_ATTR_NOACK_MAP] = { .type = NLA_U16 },
1b658f11 651 [NL80211_ATTR_INACTIVITY_TIMEOUT] = { .type = NLA_U16 },
4486ea98 652 [NL80211_ATTR_BG_SCAN_PERIOD] = { .type = NLA_U16 },
89a54e48 653 [NL80211_ATTR_WDEV] = { .type = NLA_U64 },
57b5ce07 654 [NL80211_ATTR_USER_REG_HINT_TYPE] = { .type = NLA_U32 },
cb9abd48
JB
655
656 /* need to include at least Auth Transaction and Status Code */
657 [NL80211_ATTR_AUTH_DATA] = NLA_POLICY_MIN_LEN(4),
658
c7721c05 659 [NL80211_ATTR_VHT_CAPABILITY] = NLA_POLICY_EXACT_LEN_WARN(NL80211_VHT_CAPABILITY_LEN),
ed473771 660 [NL80211_ATTR_SCAN_FLAGS] = { .type = NLA_U32 },
ab0d76f6
JB
661 [NL80211_ATTR_P2P_CTWINDOW] = NLA_POLICY_MAX(NLA_U8, 127),
662 [NL80211_ATTR_P2P_OPPPS] = NLA_POLICY_MAX(NLA_U8, 1),
663 [NL80211_ATTR_LOCAL_MESH_POWER_MODE] =
664 NLA_POLICY_RANGE(NLA_U32,
665 NL80211_MESH_POWER_UNKNOWN + 1,
666 NL80211_MESH_POWER_MAX),
77765eaf
VT
667 [NL80211_ATTR_ACL_POLICY] = {. type = NLA_U32 },
668 [NL80211_ATTR_MAC_ADDRS] = { .type = NLA_NESTED },
9d62a986
JM
669 [NL80211_ATTR_STA_CAPABILITY] = { .type = NLA_U16 },
670 [NL80211_ATTR_STA_EXT_CAPABILITY] = { .type = NLA_BINARY, },
3713b4e3 671 [NL80211_ATTR_SPLIT_WIPHY_DUMP] = { .type = NLA_FLAG, },
ee2aca34
JB
672 [NL80211_ATTR_DISABLE_VHT] = { .type = NLA_FLAG },
673 [NL80211_ATTR_VHT_CAPABILITY_MASK] = {
674 .len = NL80211_VHT_CAPABILITY_LEN,
675 },
355199e0
JM
676 [NL80211_ATTR_MDID] = { .type = NLA_U16 },
677 [NL80211_ATTR_IE_RIC] = { .type = NLA_BINARY,
678 .len = IEEE80211_MAX_DATA_LEN },
0e1a1d85 679 [NL80211_ATTR_CRIT_PROT_ID] = { .type = NLA_U16 },
cb9abd48
JB
680 [NL80211_ATTR_MAX_CRIT_PROT_DURATION] =
681 NLA_POLICY_MAX(NLA_U16, NL80211_CRIT_PROTO_MAX_DURATION),
ab0d76f6
JB
682 [NL80211_ATTR_PEER_AID] =
683 NLA_POLICY_RANGE(NLA_U16, 1, IEEE80211_MAX_AID),
16ef1fe2
SW
684 [NL80211_ATTR_CH_SWITCH_COUNT] = { .type = NLA_U32 },
685 [NL80211_ATTR_CH_SWITCH_BLOCK_TX] = { .type = NLA_FLAG },
686 [NL80211_ATTR_CSA_IES] = { .type = NLA_NESTED },
00c207ed
JC
687 [NL80211_ATTR_CNTDWN_OFFS_BEACON] = { .type = NLA_BINARY },
688 [NL80211_ATTR_CNTDWN_OFFS_PRESP] = { .type = NLA_BINARY },
cb9abd48 689 [NL80211_ATTR_STA_SUPPORTED_CHANNELS] = NLA_POLICY_MIN_LEN(2),
c8b82802
JB
690 /*
691 * The value of the Length field of the Supported Operating
692 * Classes element is between 2 and 253.
693 */
694 [NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES] =
695 NLA_POLICY_RANGE(NLA_BINARY, 2, 253),
5336fa88 696 [NL80211_ATTR_HANDLE_DFS] = { .type = NLA_FLAG },
60f4a7b1 697 [NL80211_ATTR_OPMODE_NOTIF] = { .type = NLA_U8 },
ad7e718c
JB
698 [NL80211_ATTR_VENDOR_ID] = { .type = NLA_U32 },
699 [NL80211_ATTR_VENDOR_SUBCMD] = { .type = NLA_U32 },
700 [NL80211_ATTR_VENDOR_DATA] = { .type = NLA_BINARY },
c8b82802
JB
701 [NL80211_ATTR_QOS_MAP] = NLA_POLICY_RANGE(NLA_BINARY,
702 IEEE80211_QOS_MAP_LEN_MIN,
703 IEEE80211_QOS_MAP_LEN_MAX),
c7721c05 704 [NL80211_ATTR_MAC_HINT] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
1df4a510 705 [NL80211_ATTR_WIPHY_FREQ_HINT] = { .type = NLA_U32 },
df942e7b 706 [NL80211_ATTR_TDLS_PEER_CAPABILITY] = { .type = NLA_U32 },
18e5ca65 707 [NL80211_ATTR_SOCKET_OWNER] = { .type = NLA_FLAG },
34d22ce2 708 [NL80211_ATTR_CSA_C_OFFSETS_TX] = { .type = NLA_BINARY },
bab5ab7d 709 [NL80211_ATTR_USE_RRM] = { .type = NLA_FLAG },
ab0d76f6
JB
710 [NL80211_ATTR_TSID] = NLA_POLICY_MAX(NLA_U8, IEEE80211_NUM_TIDS - 1),
711 [NL80211_ATTR_USER_PRIO] =
712 NLA_POLICY_MAX(NLA_U8, IEEE80211_NUM_UPS - 1),
960d01ac 713 [NL80211_ATTR_ADMITTED_TIME] = { .type = NLA_U16 },
18998c38 714 [NL80211_ATTR_SMPS_MODE] = { .type = NLA_U8 },
5cde05c6 715 [NL80211_ATTR_OPER_CLASS] = { .type = NLA_U8 },
c7721c05 716 [NL80211_ATTR_MAC_MASK] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
1bdd716c 717 [NL80211_ATTR_WIPHY_SELF_MANAGED_REG] = { .type = NLA_FLAG },
4b681c82 718 [NL80211_ATTR_NETNS_FD] = { .type = NLA_U32 },
9c748934 719 [NL80211_ATTR_SCHED_SCAN_DELAY] = { .type = NLA_U32 },
05050753 720 [NL80211_ATTR_REG_INDOOR] = { .type = NLA_FLAG },
34d50519 721 [NL80211_ATTR_PBSS] = { .type = NLA_FLAG },
38de03d2 722 [NL80211_ATTR_BSS_SELECT] = { .type = NLA_NESTED },
ab0d76f6
JB
723 [NL80211_ATTR_STA_SUPPORT_P2P_PS] =
724 NLA_POLICY_MAX(NLA_U8, NUM_NL80211_P2P_PS_STATUS - 1),
c6e6a0c8
AE
725 [NL80211_ATTR_MU_MIMO_GROUP_DATA] = {
726 .len = VHT_MUMIMO_GROUPS_DATA_LEN
727 },
c7721c05 728 [NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
ab0d76f6 729 [NL80211_ATTR_NAN_MASTER_PREF] = NLA_POLICY_MIN(NLA_U8, 1),
8585989d 730 [NL80211_ATTR_BANDS] = { .type = NLA_U32 },
a442b761 731 [NL80211_ATTR_NAN_FUNC] = { .type = NLA_NESTED },
348bd456
JM
732 [NL80211_ATTR_FILS_KEK] = { .type = NLA_BINARY,
733 .len = FILS_MAX_KEK_LEN },
c7721c05 734 [NL80211_ATTR_FILS_NONCES] = NLA_POLICY_EXACT_LEN_WARN(2 * FILS_NONCE_LEN),
ce0ce13a 735 [NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED] = { .type = NLA_FLAG, },
c7721c05 736 [NL80211_ATTR_BSSID] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
bf95ecdb 737 [NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI] = { .type = NLA_S8 },
738 [NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST] = {
739 .len = sizeof(struct nl80211_bss_select_rssi_adjust)
740 },
3093ebbe 741 [NL80211_ATTR_TIMEOUT_REASON] = { .type = NLA_U32 },
a3caf744
VK
742 [NL80211_ATTR_FILS_ERP_USERNAME] = { .type = NLA_BINARY,
743 .len = FILS_ERP_MAX_USERNAME_LEN },
744 [NL80211_ATTR_FILS_ERP_REALM] = { .type = NLA_BINARY,
745 .len = FILS_ERP_MAX_REALM_LEN },
746 [NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] = { .type = NLA_U16 },
747 [NL80211_ATTR_FILS_ERP_RRK] = { .type = NLA_BINARY,
748 .len = FILS_ERP_MAX_RRK_LEN },
c7721c05 749 [NL80211_ATTR_FILS_CACHE_ID] = NLA_POLICY_EXACT_LEN_WARN(2),
a3caf744 750 [NL80211_ATTR_PMK] = { .type = NLA_BINARY, .len = PMK_MAX_LEN },
cb9abd48 751 [NL80211_ATTR_PMKR0_NAME] = NLA_POLICY_EXACT_LEN(WLAN_PMK_NAME_LEN),
ca986ad9 752 [NL80211_ATTR_SCHED_SCAN_MULTI] = { .type = NLA_FLAG },
40cbfa90 753 [NL80211_ATTR_EXTERNAL_AUTH_SUPPORT] = { .type = NLA_FLAG },
52539ca8
THJ
754
755 [NL80211_ATTR_TXQ_LIMIT] = { .type = NLA_U32 },
756 [NL80211_ATTR_TXQ_MEMORY_LIMIT] = { .type = NLA_U32 },
757 [NL80211_ATTR_TXQ_QUANTUM] = { .type = NLA_U32 },
c8b82802 758 [NL80211_ATTR_HE_CAPABILITY] =
a3a20feb
JB
759 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_he_capa,
760 NL80211_HE_MAX_CAPABILITY_LEN),
0e012b4e
JB
761 [NL80211_ATTR_FTM_RESPONDER] =
762 NLA_POLICY_NESTED(nl80211_ftm_responder_policy),
9bb7e0f2
JB
763 [NL80211_ATTR_TIMEOUT] = NLA_POLICY_MIN(NLA_U32, 1),
764 [NL80211_ATTR_PEER_MEASUREMENTS] =
23323289 765 NLA_POLICY_NESTED(nl80211_pmsr_attr_policy),
36647055 766 [NL80211_ATTR_AIRTIME_WEIGHT] = NLA_POLICY_MIN(NLA_U16, 1),
26f7044e
CHH
767 [NL80211_ATTR_SAE_PASSWORD] = { .type = NLA_BINARY,
768 .len = SAE_PASSWORD_MAX_LEN },
a0de1ca3 769 [NL80211_ATTR_TWT_RESPONDER] = { .type = NLA_FLAG },
796e90f4 770 [NL80211_ATTR_HE_OBSS_PD] = NLA_POLICY_NESTED(he_obss_pd_policy),
14f34e36 771 [NL80211_ATTR_VLAN_ID] = NLA_POLICY_RANGE(NLA_U16, 1, VLAN_N_VID - 2),
5c5e52d1 772 [NL80211_ATTR_HE_BSS_COLOR] = NLA_POLICY_NESTED(he_bss_color_policy),
77f576de
T
773 [NL80211_ATTR_TID_CONFIG] =
774 NLA_POLICY_NESTED_ARRAY(nl80211_tid_config_attr_policy),
5631d96a 775 [NL80211_ATTR_CONTROL_PORT_NO_PREAUTH] = { .type = NLA_FLAG },
7fc82af8
VJ
776 [NL80211_ATTR_PMK_LIFETIME] = NLA_POLICY_MIN(NLA_U32, 1),
777 [NL80211_ATTR_PMK_REAUTH_THRESHOLD] = NLA_POLICY_RANGE(NLA_U8, 1, 100),
9dba48a6 778 [NL80211_ATTR_RECEIVE_MULTICAST] = { .type = NLA_FLAG },
942ba88b 779 [NL80211_ATTR_WIPHY_FREQ_OFFSET] = NLA_POLICY_RANGE(NLA_U32, 0, 999),
2032f3b2 780 [NL80211_ATTR_SCAN_FREQ_KHZ] = { .type = NLA_NESTED },
8140860c
JB
781 [NL80211_ATTR_HE_6GHZ_CAPABILITY] =
782 NLA_POLICY_EXACT_LEN(sizeof(struct ieee80211_he_6ghz_capa)),
291c49de
AD
783 [NL80211_ATTR_FILS_DISCOVERY] =
784 NLA_POLICY_NESTED(nl80211_fils_discovery_policy),
7443dcd1
AD
785 [NL80211_ATTR_UNSOL_BCAST_PROBE_RESP] =
786 NLA_POLICY_NESTED(nl80211_unsol_bcast_probe_resp_policy),
d2b7588a
TP
787 [NL80211_ATTR_S1G_CAPABILITY] =
788 NLA_POLICY_EXACT_LEN(IEEE80211_S1G_CAPABILITY_LEN),
789 [NL80211_ATTR_S1G_CAPABILITY_MASK] =
790 NLA_POLICY_EXACT_LEN(IEEE80211_S1G_CAPABILITY_LEN),
9f0ffa41
RD
791 [NL80211_ATTR_SAE_PWE] =
792 NLA_POLICY_RANGE(NLA_U8, NL80211_SAE_PWE_HUNT_AND_PECK,
793 NL80211_SAE_PWE_BOTH),
3bb02143 794 [NL80211_ATTR_RECONNECT_REQUESTED] = { .type = NLA_REJECT },
6bdb68ce 795 [NL80211_ATTR_SAR_SPEC] = NLA_POLICY_NESTED(sar_policy),
b6db0f89 796 [NL80211_ATTR_DISABLE_HE] = { .type = NLA_FLAG },
0d2ab3ae
JC
797 [NL80211_ATTR_OBSS_COLOR_BITMAP] = { .type = NLA_U64 },
798 [NL80211_ATTR_COLOR_CHANGE_COUNT] = { .type = NLA_U8 },
799 [NL80211_ATTR_COLOR_CHANGE_COLOR] = { .type = NLA_U8 },
800 [NL80211_ATTR_COLOR_CHANGE_ELEMS] = NLA_POLICY_NESTED(nl80211_policy),
dc1e3cb8
JC
801 [NL80211_ATTR_MBSSID_CONFIG] =
802 NLA_POLICY_NESTED(nl80211_mbssid_config_policy),
803 [NL80211_ATTR_MBSSID_ELEMS] = { .type = NLA_NESTED },
a95bfb87 804 [NL80211_ATTR_RADAR_BACKGROUND] = { .type = NLA_FLAG },
47301a74 805 [NL80211_ATTR_AP_SETTINGS_FLAGS] = { .type = NLA_U32 },
ea05fd35
IP
806 [NL80211_ATTR_EHT_CAPABILITY] =
807 NLA_POLICY_RANGE(NLA_BINARY,
808 NL80211_EHT_MIN_CAPABILITY_LEN,
809 NL80211_EHT_MAX_CAPABILITY_LEN),
36f84235 810 [NL80211_ATTR_DISABLE_EHT] = { .type = NLA_FLAG },
7b0a0e3c
JB
811 [NL80211_ATTR_MLO_LINKS] =
812 NLA_POLICY_NESTED_ARRAY(nl80211_policy),
813 [NL80211_ATTR_MLO_LINK_ID] =
814 NLA_POLICY_RANGE(NLA_U8, 0, IEEE80211_MLD_MAX_NUM_LINKS),
d648c230 815 [NL80211_ATTR_MLD_ADDR] = NLA_POLICY_EXACT_LEN(ETH_ALEN),
efbabc11 816 [NL80211_ATTR_MLO_SUPPORT] = { .type = NLA_FLAG },
ecad3b0b 817 [NL80211_ATTR_MAX_NUM_AKM_SUITES] = { .type = NLA_REJECT },
b27f07c5
JB
818 [NL80211_ATTR_PUNCT_BITMAP] =
819 NLA_POLICY_FULL_RANGE(NLA_U32, &nl80211_punct_bitmap_range),
cbbaf2bb
AS
820
821 [NL80211_ATTR_MAX_HW_TIMESTAMP_PEERS] = { .type = NLA_U16 },
822 [NL80211_ATTR_HW_TIMESTAMP_ENABLED] = { .type = NLA_FLAG },
dbbb27e1 823 [NL80211_ATTR_EMA_RNR_ELEMS] = { .type = NLA_NESTED },
6cf963ed 824 [NL80211_ATTR_MLO_LINK_DISABLED] = { .type = NLA_FLAG },
d02a12b8 825 [NL80211_ATTR_BSS_DUMP_INCLUDE_USE_DATA] = { .type = NLA_FLAG },
b61e6b41
IP
826 [NL80211_ATTR_MLO_TTLM_DLINK] = NLA_POLICY_EXACT_LEN(sizeof(u16) * 8),
827 [NL80211_ATTR_MLO_TTLM_ULINK] = NLA_POLICY_EXACT_LEN(sizeof(u16) * 8),
2518e89d 828 [NL80211_ATTR_ASSOC_SPP_AMSDU] = { .type = NLA_FLAG },
55682965
JB
829};
830
e31b8213 831/* policy for the key attributes */
b54452b0 832static const struct nla_policy nl80211_key_policy[NL80211_KEY_MAX + 1] = {
fffd0934 833 [NL80211_KEY_DATA] = { .type = NLA_BINARY, .len = WLAN_MAX_KEY_LEN },
b9454e83
JB
834 [NL80211_KEY_IDX] = { .type = NLA_U8 },
835 [NL80211_KEY_CIPHER] = { .type = NLA_U32 },
81962267 836 [NL80211_KEY_SEQ] = { .type = NLA_BINARY, .len = 16 },
b9454e83
JB
837 [NL80211_KEY_DEFAULT] = { .type = NLA_FLAG },
838 [NL80211_KEY_DEFAULT_MGMT] = { .type = NLA_FLAG },
ab0d76f6 839 [NL80211_KEY_TYPE] = NLA_POLICY_MAX(NLA_U32, NUM_NL80211_KEYTYPES - 1),
dbd2fd65 840 [NL80211_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED },
6cdd3979 841 [NL80211_KEY_MODE] = NLA_POLICY_RANGE(NLA_U8, 0, NL80211_KEY_SET_TX),
dbd2fd65
JB
842};
843
844/* policy for the key default flags */
845static const struct nla_policy
846nl80211_key_default_policy[NUM_NL80211_KEY_DEFAULT_TYPES] = {
847 [NL80211_KEY_DEFAULT_TYPE_UNICAST] = { .type = NLA_FLAG },
848 [NL80211_KEY_DEFAULT_TYPE_MULTICAST] = { .type = NLA_FLAG },
b9454e83
JB
849};
850
f83ace3b 851#ifdef CONFIG_PM
ff1b6e69
JB
852/* policy for WoWLAN attributes */
853static const struct nla_policy
854nl80211_wowlan_policy[NUM_NL80211_WOWLAN_TRIG] = {
855 [NL80211_WOWLAN_TRIG_ANY] = { .type = NLA_FLAG },
856 [NL80211_WOWLAN_TRIG_DISCONNECT] = { .type = NLA_FLAG },
857 [NL80211_WOWLAN_TRIG_MAGIC_PKT] = { .type = NLA_FLAG },
858 [NL80211_WOWLAN_TRIG_PKT_PATTERN] = { .type = NLA_NESTED },
77dbbb13
JB
859 [NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE] = { .type = NLA_FLAG },
860 [NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST] = { .type = NLA_FLAG },
861 [NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE] = { .type = NLA_FLAG },
862 [NL80211_WOWLAN_TRIG_RFKILL_RELEASE] = { .type = NLA_FLAG },
2a0e047e 863 [NL80211_WOWLAN_TRIG_TCP_CONNECTION] = { .type = NLA_NESTED },
8cd4d456 864 [NL80211_WOWLAN_TRIG_NET_DETECT] = { .type = NLA_NESTED },
2a0e047e
JB
865};
866
867static const struct nla_policy
868nl80211_wowlan_tcp_policy[NUM_NL80211_WOWLAN_TCP] = {
869 [NL80211_WOWLAN_TCP_SRC_IPV4] = { .type = NLA_U32 },
870 [NL80211_WOWLAN_TCP_DST_IPV4] = { .type = NLA_U32 },
c7721c05 871 [NL80211_WOWLAN_TCP_DST_MAC] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
2a0e047e
JB
872 [NL80211_WOWLAN_TCP_SRC_PORT] = { .type = NLA_U16 },
873 [NL80211_WOWLAN_TCP_DST_PORT] = { .type = NLA_U16 },
bc043585 874 [NL80211_WOWLAN_TCP_DATA_PAYLOAD] = NLA_POLICY_MIN_LEN(1),
2a0e047e
JB
875 [NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ] = {
876 .len = sizeof(struct nl80211_wowlan_tcp_data_seq)
877 },
878 [NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN] = {
879 .len = sizeof(struct nl80211_wowlan_tcp_data_token)
880 },
881 [NL80211_WOWLAN_TCP_DATA_INTERVAL] = { .type = NLA_U32 },
bc043585
JB
882 [NL80211_WOWLAN_TCP_WAKE_PAYLOAD] = NLA_POLICY_MIN_LEN(1),
883 [NL80211_WOWLAN_TCP_WAKE_MASK] = NLA_POLICY_MIN_LEN(1),
ff1b6e69 884};
f83ace3b 885#endif /* CONFIG_PM */
ff1b6e69 886
be29b99a
AK
887/* policy for coalesce rule attributes */
888static const struct nla_policy
889nl80211_coalesce_policy[NUM_NL80211_ATTR_COALESCE_RULE] = {
890 [NL80211_ATTR_COALESCE_RULE_DELAY] = { .type = NLA_U32 },
ab0d76f6
JB
891 [NL80211_ATTR_COALESCE_RULE_CONDITION] =
892 NLA_POLICY_RANGE(NLA_U32,
893 NL80211_COALESCE_CONDITION_MATCH,
894 NL80211_COALESCE_CONDITION_NO_MATCH),
be29b99a
AK
895 [NL80211_ATTR_COALESCE_RULE_PKT_PATTERN] = { .type = NLA_NESTED },
896};
897
e5497d76
JB
898/* policy for GTK rekey offload attributes */
899static const struct nla_policy
900nl80211_rekey_policy[NUM_NL80211_REKEY_DATA] = {
093a48d2
NE
901 [NL80211_REKEY_DATA_KEK] = {
902 .type = NLA_BINARY,
903 .len = NL80211_KEK_EXT_LEN
904 },
905 [NL80211_REKEY_DATA_KCK] = {
906 .type = NLA_BINARY,
648fba79 907 .len = NL80211_KCK_EXT_LEN_32
093a48d2 908 },
cb9abd48 909 [NL80211_REKEY_DATA_REPLAY_CTR] = NLA_POLICY_EXACT_LEN(NL80211_REPLAY_CTR_LEN),
093a48d2 910 [NL80211_REKEY_DATA_AKM] = { .type = NLA_U32 },
e5497d76
JB
911};
912
a1f1c21c
LC
913static const struct nla_policy
914nl80211_match_policy[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1] = {
4a4ab0d7 915 [NL80211_SCHED_SCAN_MATCH_ATTR_SSID] = { .type = NLA_BINARY,
a1f1c21c 916 .len = IEEE80211_MAX_SSID_LEN },
c7721c05 917 [NL80211_SCHED_SCAN_MATCH_ATTR_BSSID] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
88e920b4 918 [NL80211_SCHED_SCAN_MATCH_ATTR_RSSI] = { .type = NLA_U32 },
a1f1c21c
LC
919};
920
3b06d277
AS
921static const struct nla_policy
922nl80211_plan_policy[NL80211_SCHED_SCAN_PLAN_MAX + 1] = {
923 [NL80211_SCHED_SCAN_PLAN_INTERVAL] = { .type = NLA_U32 },
924 [NL80211_SCHED_SCAN_PLAN_ITERATIONS] = { .type = NLA_U32 },
925};
926
38de03d2
AS
927static const struct nla_policy
928nl80211_bss_select_policy[NL80211_BSS_SELECT_ATTR_MAX + 1] = {
929 [NL80211_BSS_SELECT_ATTR_RSSI] = { .type = NLA_FLAG },
930 [NL80211_BSS_SELECT_ATTR_BAND_PREF] = { .type = NLA_U32 },
931 [NL80211_BSS_SELECT_ATTR_RSSI_ADJUST] = {
932 .len = sizeof(struct nl80211_bss_select_rssi_adjust)
933 },
934};
935
a442b761
AB
936/* policy for NAN function attributes */
937static const struct nla_policy
938nl80211_nan_func_policy[NL80211_NAN_FUNC_ATTR_MAX + 1] = {
cb9abd48
JB
939 [NL80211_NAN_FUNC_TYPE] =
940 NLA_POLICY_MAX(NLA_U8, NL80211_NAN_FUNC_MAX_TYPE),
0a27844c 941 [NL80211_NAN_FUNC_SERVICE_ID] = {
a442b761
AB
942 .len = NL80211_NAN_FUNC_SERVICE_ID_LEN },
943 [NL80211_NAN_FUNC_PUBLISH_TYPE] = { .type = NLA_U8 },
944 [NL80211_NAN_FUNC_PUBLISH_BCAST] = { .type = NLA_FLAG },
945 [NL80211_NAN_FUNC_SUBSCRIBE_ACTIVE] = { .type = NLA_FLAG },
946 [NL80211_NAN_FUNC_FOLLOW_UP_ID] = { .type = NLA_U8 },
947 [NL80211_NAN_FUNC_FOLLOW_UP_REQ_ID] = { .type = NLA_U8 },
c7721c05 948 [NL80211_NAN_FUNC_FOLLOW_UP_DEST] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
a442b761
AB
949 [NL80211_NAN_FUNC_CLOSE_RANGE] = { .type = NLA_FLAG },
950 [NL80211_NAN_FUNC_TTL] = { .type = NLA_U32 },
951 [NL80211_NAN_FUNC_SERVICE_INFO] = { .type = NLA_BINARY,
952 .len = NL80211_NAN_FUNC_SERVICE_SPEC_INFO_MAX_LEN },
953 [NL80211_NAN_FUNC_SRF] = { .type = NLA_NESTED },
954 [NL80211_NAN_FUNC_RX_MATCH_FILTER] = { .type = NLA_NESTED },
955 [NL80211_NAN_FUNC_TX_MATCH_FILTER] = { .type = NLA_NESTED },
956 [NL80211_NAN_FUNC_INSTANCE_ID] = { .type = NLA_U8 },
957 [NL80211_NAN_FUNC_TERM_REASON] = { .type = NLA_U8 },
958};
959
960/* policy for Service Response Filter attributes */
961static const struct nla_policy
962nl80211_nan_srf_policy[NL80211_NAN_SRF_ATTR_MAX + 1] = {
963 [NL80211_NAN_SRF_INCLUDE] = { .type = NLA_FLAG },
964 [NL80211_NAN_SRF_BF] = { .type = NLA_BINARY,
965 .len = NL80211_NAN_FUNC_SRF_MAX_LEN },
966 [NL80211_NAN_SRF_BF_IDX] = { .type = NLA_U8 },
967 [NL80211_NAN_SRF_MAC_ADDRS] = { .type = NLA_NESTED },
968};
969
ad670233
PX
970/* policy for packet pattern attributes */
971static const struct nla_policy
972nl80211_packet_pattern_policy[MAX_NL80211_PKTPAT + 1] = {
973 [NL80211_PKTPAT_MASK] = { .type = NLA_BINARY, },
974 [NL80211_PKTPAT_PATTERN] = { .type = NLA_BINARY, },
975 [NL80211_PKTPAT_OFFSET] = { .type = NLA_U32 },
976};
977
ce6b6974
JB
978static int nl80211_prepare_wdev_dump(struct netlink_callback *cb,
979 struct cfg80211_registered_device **rdev,
980 struct wireless_dev **wdev,
981 struct nlattr **attrbuf)
a043897a 982{
97990a06 983 int err;
a043897a 984
97990a06 985 if (!cb->args[0]) {
ce6b6974
JB
986 struct nlattr **attrbuf_free = NULL;
987
988 if (!attrbuf) {
989 attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf),
990 GFP_KERNEL);
991 if (!attrbuf)
992 return -ENOMEM;
993 attrbuf_free = attrbuf;
994 }
50508d94 995
8cb08174
JB
996 err = nlmsg_parse_deprecated(cb->nlh,
997 GENL_HDRLEN + nl80211_fam.hdrsize,
50508d94 998 attrbuf, nl80211_fam.maxattr,
8cb08174 999 nl80211_policy, NULL);
50508d94 1000 if (err) {
ce6b6974 1001 kfree(attrbuf_free);
ea90e0dc 1002 return err;
50508d94 1003 }
67748893 1004
a05829a7
JB
1005 rtnl_lock();
1006 *wdev = __cfg80211_wdev_from_attrs(NULL, sock_net(cb->skb->sk),
50508d94 1007 attrbuf);
ce6b6974 1008 kfree(attrbuf_free);
a05829a7
JB
1009 if (IS_ERR(*wdev)) {
1010 rtnl_unlock();
ea90e0dc 1011 return PTR_ERR(*wdev);
a05829a7 1012 }
f26cbf40 1013 *rdev = wiphy_to_rdev((*wdev)->wiphy);
a05829a7
JB
1014 mutex_lock(&(*rdev)->wiphy.mtx);
1015 rtnl_unlock();
c319d50b
JB
1016 /* 0 is the first index - add 1 to parse only once */
1017 cb->args[0] = (*rdev)->wiphy_idx + 1;
97990a06
JB
1018 cb->args[1] = (*wdev)->identifier;
1019 } else {
c319d50b 1020 /* subtract the 1 again here */
a05829a7 1021 struct wiphy *wiphy;
97990a06 1022 struct wireless_dev *tmp;
67748893 1023
a05829a7
JB
1024 rtnl_lock();
1025 wiphy = wiphy_idx_to_wiphy(cb->args[0] - 1);
1026 if (!wiphy) {
1027 rtnl_unlock();
ea90e0dc 1028 return -ENODEV;
a05829a7 1029 }
f26cbf40 1030 *rdev = wiphy_to_rdev(wiphy);
97990a06 1031 *wdev = NULL;
67748893 1032
53873f13 1033 list_for_each_entry(tmp, &(*rdev)->wiphy.wdev_list, list) {
97990a06
JB
1034 if (tmp->identifier == cb->args[1]) {
1035 *wdev = tmp;
1036 break;
1037 }
1038 }
67748893 1039
a05829a7
JB
1040 if (!*wdev) {
1041 rtnl_unlock();
ea90e0dc 1042 return -ENODEV;
a05829a7
JB
1043 }
1044 mutex_lock(&(*rdev)->wiphy.mtx);
1045 rtnl_unlock();
67748893
JB
1046 }
1047
67748893 1048 return 0;
67748893
JB
1049}
1050
55682965 1051/* message building helper */
9bb7e0f2
JB
1052void *nl80211hdr_put(struct sk_buff *skb, u32 portid, u32 seq,
1053 int flags, u8 cmd)
55682965
JB
1054{
1055 /* since there is no private header just add the generic one */
15e47304 1056 return genlmsg_put(skb, portid, seq, &nl80211_fam, flags, cmd);
55682965
JB
1057}
1058
50f32718
HD
1059static int nl80211_msg_put_wmm_rules(struct sk_buff *msg,
1060 const struct ieee80211_reg_rule *rule)
1061{
1062 int j;
1063 struct nlattr *nl_wmm_rules =
ae0be8de 1064 nla_nest_start_noflag(msg, NL80211_FREQUENCY_ATTR_WMM);
50f32718
HD
1065
1066 if (!nl_wmm_rules)
1067 goto nla_put_failure;
1068
1069 for (j = 0; j < IEEE80211_NUM_ACS; j++) {
ae0be8de 1070 struct nlattr *nl_wmm_rule = nla_nest_start_noflag(msg, j);
50f32718
HD
1071
1072 if (!nl_wmm_rule)
1073 goto nla_put_failure;
1074
1075 if (nla_put_u16(msg, NL80211_WMMR_CW_MIN,
38cb87ee 1076 rule->wmm_rule.client[j].cw_min) ||
50f32718 1077 nla_put_u16(msg, NL80211_WMMR_CW_MAX,
38cb87ee 1078 rule->wmm_rule.client[j].cw_max) ||
50f32718 1079 nla_put_u8(msg, NL80211_WMMR_AIFSN,
38cb87ee 1080 rule->wmm_rule.client[j].aifsn) ||
d3c89bbc
HD
1081 nla_put_u16(msg, NL80211_WMMR_TXOP,
1082 rule->wmm_rule.client[j].cot))
50f32718
HD
1083 goto nla_put_failure;
1084
1085 nla_nest_end(msg, nl_wmm_rule);
1086 }
1087 nla_nest_end(msg, nl_wmm_rules);
1088
1089 return 0;
1090
1091nla_put_failure:
1092 return -ENOBUFS;
1093}
1094
1095static int nl80211_msg_put_channel(struct sk_buff *msg, struct wiphy *wiphy,
cdc89b97
JB
1096 struct ieee80211_channel *chan,
1097 bool large)
5dab3b8a 1098{
ea077c1c
RL
1099 /* Some channels must be completely excluded from the
1100 * list to protect old user-space tools from breaking
1101 */
1102 if (!large && chan->flags &
1103 (IEEE80211_CHAN_NO_10MHZ | IEEE80211_CHAN_NO_20MHZ))
1104 return 0;
f8d504ca
JB
1105 if (!large && chan->freq_offset)
1106 return 0;
ea077c1c 1107
9360ffd1
DM
1108 if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_FREQ,
1109 chan->center_freq))
1110 goto nla_put_failure;
5dab3b8a 1111
942ba88b
TP
1112 if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_OFFSET, chan->freq_offset))
1113 goto nla_put_failure;
1114
ddd7f45c
WG
1115 if ((chan->flags & IEEE80211_CHAN_PSD) &&
1116 nla_put_s8(msg, NL80211_FREQUENCY_ATTR_PSD, chan->psd))
1117 goto nla_put_failure;
1118
9360ffd1
DM
1119 if ((chan->flags & IEEE80211_CHAN_DISABLED) &&
1120 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_DISABLED))
1121 goto nla_put_failure;
8fe02e16
LR
1122 if (chan->flags & IEEE80211_CHAN_NO_IR) {
1123 if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_IR))
1124 goto nla_put_failure;
1125 if (nla_put_flag(msg, __NL80211_FREQUENCY_ATTR_NO_IBSS))
1126 goto nla_put_failure;
1127 }
cdc89b97
JB
1128 if (chan->flags & IEEE80211_CHAN_RADAR) {
1129 if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR))
1130 goto nla_put_failure;
1131 if (large) {
1132 u32 time;
1133
1134 time = elapsed_jiffies_msecs(chan->dfs_state_entered);
1135
1136 if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_STATE,
1137 chan->dfs_state))
1138 goto nla_put_failure;
1139 if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_TIME,
1140 time))
1141 goto nla_put_failure;
089027e5
JD
1142 if (nla_put_u32(msg,
1143 NL80211_FREQUENCY_ATTR_DFS_CAC_TIME,
1144 chan->dfs_cac_ms))
1145 goto nla_put_failure;
cdc89b97
JB
1146 }
1147 }
5dab3b8a 1148
fe1abafd
JB
1149 if (large) {
1150 if ((chan->flags & IEEE80211_CHAN_NO_HT40MINUS) &&
1151 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HT40_MINUS))
1152 goto nla_put_failure;
1153 if ((chan->flags & IEEE80211_CHAN_NO_HT40PLUS) &&
1154 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HT40_PLUS))
1155 goto nla_put_failure;
1156 if ((chan->flags & IEEE80211_CHAN_NO_80MHZ) &&
1157 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_80MHZ))
1158 goto nla_put_failure;
1159 if ((chan->flags & IEEE80211_CHAN_NO_160MHZ) &&
1160 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_160MHZ))
1161 goto nla_put_failure;
570dbde1
DS
1162 if ((chan->flags & IEEE80211_CHAN_INDOOR_ONLY) &&
1163 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_INDOOR_ONLY))
1164 goto nla_put_failure;
06f207fc
AN
1165 if ((chan->flags & IEEE80211_CHAN_IR_CONCURRENT) &&
1166 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_IR_CONCURRENT))
570dbde1 1167 goto nla_put_failure;
ea077c1c
RL
1168 if ((chan->flags & IEEE80211_CHAN_NO_20MHZ) &&
1169 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_20MHZ))
1170 goto nla_put_failure;
1171 if ((chan->flags & IEEE80211_CHAN_NO_10MHZ) &&
1172 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_10MHZ))
1173 goto nla_put_failure;
1e61d82c
HD
1174 if ((chan->flags & IEEE80211_CHAN_NO_HE) &&
1175 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HE))
1176 goto nla_put_failure;
d65a9770
TP
1177 if ((chan->flags & IEEE80211_CHAN_1MHZ) &&
1178 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_1MHZ))
1179 goto nla_put_failure;
1180 if ((chan->flags & IEEE80211_CHAN_2MHZ) &&
1181 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_2MHZ))
1182 goto nla_put_failure;
1183 if ((chan->flags & IEEE80211_CHAN_4MHZ) &&
1184 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_4MHZ))
1185 goto nla_put_failure;
1186 if ((chan->flags & IEEE80211_CHAN_8MHZ) &&
1187 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_8MHZ))
1188 goto nla_put_failure;
1189 if ((chan->flags & IEEE80211_CHAN_16MHZ) &&
1190 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_16MHZ))
1191 goto nla_put_failure;
c2b3d769
S
1192 if ((chan->flags & IEEE80211_CHAN_NO_320MHZ) &&
1193 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_320MHZ))
1194 goto nla_put_failure;
31846b65
IP
1195 if ((chan->flags & IEEE80211_CHAN_NO_EHT) &&
1196 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_EHT))
1197 goto nla_put_failure;
41a313d8
AO
1198 if ((chan->flags & IEEE80211_CHAN_DFS_CONCURRENT) &&
1199 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_DFS_CONCURRENT))
1200 goto nla_put_failure;
7b5e25b8
JB
1201 if ((chan->flags & IEEE80211_CHAN_NO_6GHZ_VLP_CLIENT) &&
1202 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_6GHZ_VLP_CLIENT))
645f3d85 1203 goto nla_put_failure;
7b5e25b8
JB
1204 if ((chan->flags & IEEE80211_CHAN_NO_6GHZ_AFC_CLIENT) &&
1205 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_6GHZ_AFC_CLIENT))
645f3d85 1206 goto nla_put_failure;
fe1abafd
JB
1207 }
1208
9360ffd1
DM
1209 if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER,
1210 DBM_TO_MBM(chan->max_power)))
1211 goto nla_put_failure;
5dab3b8a 1212
50f32718
HD
1213 if (large) {
1214 const struct ieee80211_reg_rule *rule =
b88d26d9 1215 freq_reg_info(wiphy, MHZ_TO_KHZ(chan->center_freq));
50f32718 1216
38cb87ee 1217 if (!IS_ERR_OR_NULL(rule) && rule->has_wmm) {
50f32718
HD
1218 if (nl80211_msg_put_wmm_rules(msg, rule))
1219 goto nla_put_failure;
1220 }
1221 }
1222
5dab3b8a
LR
1223 return 0;
1224
1225 nla_put_failure:
1226 return -ENOBUFS;
1227}
1228
52539ca8
THJ
1229static bool nl80211_put_txq_stats(struct sk_buff *msg,
1230 struct cfg80211_txq_stats *txqstats,
1231 int attrtype)
1232{
1233 struct nlattr *txqattr;
1234
1235#define PUT_TXQVAL_U32(attr, memb) do { \
1236 if (txqstats->filled & BIT(NL80211_TXQ_STATS_ ## attr) && \
1237 nla_put_u32(msg, NL80211_TXQ_STATS_ ## attr, txqstats->memb)) \
1238 return false; \
1239 } while (0)
1240
ae0be8de 1241 txqattr = nla_nest_start_noflag(msg, attrtype);
52539ca8
THJ
1242 if (!txqattr)
1243 return false;
1244
1245 PUT_TXQVAL_U32(BACKLOG_BYTES, backlog_bytes);
1246 PUT_TXQVAL_U32(BACKLOG_PACKETS, backlog_packets);
1247 PUT_TXQVAL_U32(FLOWS, flows);
1248 PUT_TXQVAL_U32(DROPS, drops);
1249 PUT_TXQVAL_U32(ECN_MARKS, ecn_marks);
1250 PUT_TXQVAL_U32(OVERLIMIT, overlimit);
1251 PUT_TXQVAL_U32(OVERMEMORY, overmemory);
1252 PUT_TXQVAL_U32(COLLISIONS, collisions);
1253 PUT_TXQVAL_U32(TX_BYTES, tx_bytes);
1254 PUT_TXQVAL_U32(TX_PACKETS, tx_packets);
1255 PUT_TXQVAL_U32(MAX_FLOWS, max_flows);
1256 nla_nest_end(msg, txqattr);
1257
1258#undef PUT_TXQVAL_U32
1259 return true;
1260}
1261
55682965
JB
1262/* netlink command implementations */
1263
7b0a0e3c
JB
1264/**
1265 * nl80211_link_id - return link ID
1266 * @attrs: attributes to look at
1267 *
1268 * Returns: the link ID or 0 if not given
1269 *
1270 * Note this function doesn't do any validation of the link
1271 * ID validity wrt. links that were actually added, so it must
1272 * be called only from ops with %NL80211_FLAG_MLO_VALID_LINK_ID
1273 * or if additional validation is done.
1274 */
1275static unsigned int nl80211_link_id(struct nlattr **attrs)
1276{
1277 struct nlattr *linkid = attrs[NL80211_ATTR_MLO_LINK_ID];
1278
1279 if (!linkid)
1280 return 0;
1281
1282 return nla_get_u8(linkid);
1283}
1284
1285static int nl80211_link_id_or_invalid(struct nlattr **attrs)
1286{
1287 struct nlattr *linkid = attrs[NL80211_ATTR_MLO_LINK_ID];
1288
1289 if (!linkid)
1290 return -1;
1291
1292 return nla_get_u8(linkid);
1293}
1294
b9454e83
JB
1295struct key_parse {
1296 struct key_params p;
1297 int idx;
e31b8213 1298 int type;
56be393f 1299 bool def, defmgmt, defbeacon;
dbd2fd65 1300 bool def_uni, def_multi;
b9454e83
JB
1301};
1302
768075eb
JB
1303static int nl80211_parse_key_new(struct genl_info *info, struct nlattr *key,
1304 struct key_parse *k)
b9454e83
JB
1305{
1306 struct nlattr *tb[NL80211_KEY_MAX + 1];
8cb08174
JB
1307 int err = nla_parse_nested_deprecated(tb, NL80211_KEY_MAX, key,
1308 nl80211_key_policy,
1309 info->extack);
b9454e83
JB
1310 if (err)
1311 return err;
1312
1313 k->def = !!tb[NL80211_KEY_DEFAULT];
1314 k->defmgmt = !!tb[NL80211_KEY_DEFAULT_MGMT];
56be393f 1315 k->defbeacon = !!tb[NL80211_KEY_DEFAULT_BEACON];
b9454e83 1316
dbd2fd65
JB
1317 if (k->def) {
1318 k->def_uni = true;
1319 k->def_multi = true;
1320 }
56be393f 1321 if (k->defmgmt || k->defbeacon)
dbd2fd65
JB
1322 k->def_multi = true;
1323
b9454e83
JB
1324 if (tb[NL80211_KEY_IDX])
1325 k->idx = nla_get_u8(tb[NL80211_KEY_IDX]);
1326
1327 if (tb[NL80211_KEY_DATA]) {
1328 k->p.key = nla_data(tb[NL80211_KEY_DATA]);
1329 k->p.key_len = nla_len(tb[NL80211_KEY_DATA]);
1330 }
1331
1332 if (tb[NL80211_KEY_SEQ]) {
1333 k->p.seq = nla_data(tb[NL80211_KEY_SEQ]);
1334 k->p.seq_len = nla_len(tb[NL80211_KEY_SEQ]);
1335 }
1336
1337 if (tb[NL80211_KEY_CIPHER])
1338 k->p.cipher = nla_get_u32(tb[NL80211_KEY_CIPHER]);
1339
ab0d76f6 1340 if (tb[NL80211_KEY_TYPE])
e31b8213 1341 k->type = nla_get_u32(tb[NL80211_KEY_TYPE]);
e31b8213 1342
dbd2fd65
JB
1343 if (tb[NL80211_KEY_DEFAULT_TYPES]) {
1344 struct nlattr *kdt[NUM_NL80211_KEY_DEFAULT_TYPES];
7a087e74 1345
8cb08174
JB
1346 err = nla_parse_nested_deprecated(kdt,
1347 NUM_NL80211_KEY_DEFAULT_TYPES - 1,
1348 tb[NL80211_KEY_DEFAULT_TYPES],
1349 nl80211_key_default_policy,
1350 info->extack);
dbd2fd65
JB
1351 if (err)
1352 return err;
1353
1354 k->def_uni = kdt[NL80211_KEY_DEFAULT_TYPE_UNICAST];
1355 k->def_multi = kdt[NL80211_KEY_DEFAULT_TYPE_MULTICAST];
1356 }
1357
6cdd3979
AW
1358 if (tb[NL80211_KEY_MODE])
1359 k->p.mode = nla_get_u8(tb[NL80211_KEY_MODE]);
1360
b9454e83
JB
1361 return 0;
1362}
1363
1364static int nl80211_parse_key_old(struct genl_info *info, struct key_parse *k)
1365{
1366 if (info->attrs[NL80211_ATTR_KEY_DATA]) {
1367 k->p.key = nla_data(info->attrs[NL80211_ATTR_KEY_DATA]);
1368 k->p.key_len = nla_len(info->attrs[NL80211_ATTR_KEY_DATA]);
1369 }
1370
1371 if (info->attrs[NL80211_ATTR_KEY_SEQ]) {
1372 k->p.seq = nla_data(info->attrs[NL80211_ATTR_KEY_SEQ]);
1373 k->p.seq_len = nla_len(info->attrs[NL80211_ATTR_KEY_SEQ]);
1374 }
1375
1376 if (info->attrs[NL80211_ATTR_KEY_IDX])
1377 k->idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
1378
1379 if (info->attrs[NL80211_ATTR_KEY_CIPHER])
1380 k->p.cipher = nla_get_u32(info->attrs[NL80211_ATTR_KEY_CIPHER]);
1381
1382 k->def = !!info->attrs[NL80211_ATTR_KEY_DEFAULT];
1383 k->defmgmt = !!info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT];
1384
dbd2fd65
JB
1385 if (k->def) {
1386 k->def_uni = true;
1387 k->def_multi = true;
1388 }
1389 if (k->defmgmt)
1390 k->def_multi = true;
1391
ab0d76f6 1392 if (info->attrs[NL80211_ATTR_KEY_TYPE])
e31b8213 1393 k->type = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]);
e31b8213 1394
dbd2fd65
JB
1395 if (info->attrs[NL80211_ATTR_KEY_DEFAULT_TYPES]) {
1396 struct nlattr *kdt[NUM_NL80211_KEY_DEFAULT_TYPES];
8cb08174
JB
1397 int err = nla_parse_nested_deprecated(kdt,
1398 NUM_NL80211_KEY_DEFAULT_TYPES - 1,
1399 info->attrs[NL80211_ATTR_KEY_DEFAULT_TYPES],
1400 nl80211_key_default_policy,
1401 info->extack);
dbd2fd65
JB
1402 if (err)
1403 return err;
1404
1405 k->def_uni = kdt[NL80211_KEY_DEFAULT_TYPE_UNICAST];
1406 k->def_multi = kdt[NL80211_KEY_DEFAULT_TYPE_MULTICAST];
1407 }
1408
b9454e83
JB
1409 return 0;
1410}
1411
1412static int nl80211_parse_key(struct genl_info *info, struct key_parse *k)
1413{
1414 int err;
1415
1416 memset(k, 0, sizeof(*k));
1417 k->idx = -1;
e31b8213 1418 k->type = -1;
b9454e83
JB
1419
1420 if (info->attrs[NL80211_ATTR_KEY])
768075eb 1421 err = nl80211_parse_key_new(info, info->attrs[NL80211_ATTR_KEY], k);
b9454e83
JB
1422 else
1423 err = nl80211_parse_key_old(info, k);
1424
1425 if (err)
1426 return err;
1427
56be393f
JM
1428 if ((k->def ? 1 : 0) + (k->defmgmt ? 1 : 0) +
1429 (k->defbeacon ? 1 : 0) > 1) {
1430 GENL_SET_ERR_MSG(info,
1431 "key with multiple default flags is invalid");
b9454e83 1432 return -EINVAL;
768075eb 1433 }
b9454e83 1434
56be393f 1435 if (k->defmgmt || k->defbeacon) {
768075eb 1436 if (k->def_uni || !k->def_multi) {
56be393f
JM
1437 GENL_SET_ERR_MSG(info,
1438 "defmgmt/defbeacon key must be mcast");
dbd2fd65 1439 return -EINVAL;
768075eb 1440 }
dbd2fd65
JB
1441 }
1442
b9454e83
JB
1443 if (k->idx != -1) {
1444 if (k->defmgmt) {
768075eb
JB
1445 if (k->idx < 4 || k->idx > 5) {
1446 GENL_SET_ERR_MSG(info,
1447 "defmgmt key idx not 4 or 5");
b9454e83 1448 return -EINVAL;
768075eb 1449 }
56be393f
JM
1450 } else if (k->defbeacon) {
1451 if (k->idx < 6 || k->idx > 7) {
1452 GENL_SET_ERR_MSG(info,
1453 "defbeacon key idx not 6 or 7");
1454 return -EINVAL;
1455 }
b9454e83 1456 } else if (k->def) {
768075eb
JB
1457 if (k->idx < 0 || k->idx > 3) {
1458 GENL_SET_ERR_MSG(info, "def key idx not 0-3");
b9454e83 1459 return -EINVAL;
768075eb 1460 }
b9454e83 1461 } else {
56be393f
JM
1462 if (k->idx < 0 || k->idx > 7) {
1463 GENL_SET_ERR_MSG(info, "key idx not 0-7");
b9454e83 1464 return -EINVAL;
768075eb 1465 }
b9454e83
JB
1466 }
1467 }
1468
1469 return 0;
1470}
1471
fffd0934
JB
1472static struct cfg80211_cached_keys *
1473nl80211_parse_connkeys(struct cfg80211_registered_device *rdev,
768075eb 1474 struct genl_info *info, bool *no_ht)
fffd0934 1475{
768075eb 1476 struct nlattr *keys = info->attrs[NL80211_ATTR_KEYS];
fffd0934
JB
1477 struct key_parse parse;
1478 struct nlattr *key;
1479 struct cfg80211_cached_keys *result;
1480 int rem, err, def = 0;
f1c1f17a
JB
1481 bool have_key = false;
1482
1483 nla_for_each_nested(key, keys, rem) {
1484 have_key = true;
1485 break;
1486 }
1487
1488 if (!have_key)
1489 return NULL;
fffd0934
JB
1490
1491 result = kzalloc(sizeof(*result), GFP_KERNEL);
1492 if (!result)
1493 return ERR_PTR(-ENOMEM);
1494
1495 result->def = -1;
fffd0934
JB
1496
1497 nla_for_each_nested(key, keys, rem) {
1498 memset(&parse, 0, sizeof(parse));
1499 parse.idx = -1;
1500
768075eb 1501 err = nl80211_parse_key_new(info, key, &parse);
fffd0934
JB
1502 if (err)
1503 goto error;
1504 err = -EINVAL;
1505 if (!parse.p.key)
1506 goto error;
768075eb
JB
1507 if (parse.idx < 0 || parse.idx > 3) {
1508 GENL_SET_ERR_MSG(info, "key index out of range [0-3]");
fffd0934 1509 goto error;
768075eb 1510 }
fffd0934 1511 if (parse.def) {
768075eb
JB
1512 if (def) {
1513 GENL_SET_ERR_MSG(info,
1514 "only one key can be default");
fffd0934 1515 goto error;
768075eb 1516 }
fffd0934
JB
1517 def = 1;
1518 result->def = parse.idx;
dbd2fd65
JB
1519 if (!parse.def_uni || !parse.def_multi)
1520 goto error;
fffd0934
JB
1521 } else if (parse.defmgmt)
1522 goto error;
1523 err = cfg80211_validate_key_settings(rdev, &parse.p,
e31b8213 1524 parse.idx, false, NULL);
fffd0934
JB
1525 if (err)
1526 goto error;
386b1f27
JB
1527 if (parse.p.cipher != WLAN_CIPHER_SUITE_WEP40 &&
1528 parse.p.cipher != WLAN_CIPHER_SUITE_WEP104) {
768075eb 1529 GENL_SET_ERR_MSG(info, "connect key must be WEP");
386b1f27
JB
1530 err = -EINVAL;
1531 goto error;
1532 }
fffd0934
JB
1533 result->params[parse.idx].cipher = parse.p.cipher;
1534 result->params[parse.idx].key_len = parse.p.key_len;
1535 result->params[parse.idx].key = result->data[parse.idx];
1536 memcpy(result->data[parse.idx], parse.p.key, parse.p.key_len);
de7044ee 1537
386b1f27
JB
1538 /* must be WEP key if we got here */
1539 if (no_ht)
1540 *no_ht = true;
fffd0934
JB
1541 }
1542
f1c1f17a
JB
1543 if (result->def < 0) {
1544 err = -EINVAL;
768075eb 1545 GENL_SET_ERR_MSG(info, "need a default/TX key");
f1c1f17a
JB
1546 goto error;
1547 }
1548
fffd0934
JB
1549 return result;
1550 error:
1551 kfree(result);
1552 return ERR_PTR(err);
1553}
1554
1555static int nl80211_key_allowed(struct wireless_dev *wdev)
1556{
076fc877 1557 lockdep_assert_wiphy(wdev->wiphy);
fffd0934 1558
fffd0934
JB
1559 switch (wdev->iftype) {
1560 case NL80211_IFTYPE_AP:
1561 case NL80211_IFTYPE_AP_VLAN:
074ac8df 1562 case NL80211_IFTYPE_P2P_GO:
ff973af7 1563 case NL80211_IFTYPE_MESH_POINT:
fffd0934
JB
1564 break;
1565 case NL80211_IFTYPE_ADHOC:
7b0a0e3c
JB
1566 if (wdev->u.ibss.current_bss)
1567 return 0;
1568 return -ENOLINK;
fffd0934 1569 case NL80211_IFTYPE_STATION:
074ac8df 1570 case NL80211_IFTYPE_P2P_CLIENT:
7b0a0e3c
JB
1571 if (wdev->connected)
1572 return 0;
1573 return -ENOLINK;
9b89495e
VG
1574 case NL80211_IFTYPE_NAN:
1575 if (wiphy_ext_feature_isset(wdev->wiphy,
1576 NL80211_EXT_FEATURE_SECURE_NAN))
1577 return 0;
1578 return -EINVAL;
de4fcbad 1579 case NL80211_IFTYPE_UNSPECIFIED:
6e0bd6c3 1580 case NL80211_IFTYPE_OCB:
de4fcbad
JB
1581 case NL80211_IFTYPE_MONITOR:
1582 case NL80211_IFTYPE_P2P_DEVICE:
1583 case NL80211_IFTYPE_WDS:
1584 case NUM_NL80211_IFTYPES:
fffd0934
JB
1585 return -EINVAL;
1586 }
1587
1588 return 0;
1589}
1590
664834de 1591static struct ieee80211_channel *nl80211_get_valid_chan(struct wiphy *wiphy,
942ba88b 1592 u32 freq)
664834de
JM
1593{
1594 struct ieee80211_channel *chan;
1595
942ba88b 1596 chan = ieee80211_get_channel_khz(wiphy, freq);
664834de
JM
1597 if (!chan || chan->flags & IEEE80211_CHAN_DISABLED)
1598 return NULL;
1599 return chan;
1600}
1601
7527a782
JB
1602static int nl80211_put_iftypes(struct sk_buff *msg, u32 attr, u16 ifmodes)
1603{
ae0be8de 1604 struct nlattr *nl_modes = nla_nest_start_noflag(msg, attr);
7527a782
JB
1605 int i;
1606
1607 if (!nl_modes)
1608 goto nla_put_failure;
1609
1610 i = 0;
1611 while (ifmodes) {
9360ffd1
DM
1612 if ((ifmodes & 1) && nla_put_flag(msg, i))
1613 goto nla_put_failure;
7527a782
JB
1614 ifmodes >>= 1;
1615 i++;
1616 }
1617
1618 nla_nest_end(msg, nl_modes);
1619 return 0;
1620
1621nla_put_failure:
1622 return -ENOBUFS;
1623}
1624
1625static int nl80211_put_iface_combinations(struct wiphy *wiphy,
cdc89b97
JB
1626 struct sk_buff *msg,
1627 bool large)
7527a782
JB
1628{
1629 struct nlattr *nl_combis;
1630 int i, j;
1631
ae0be8de
MK
1632 nl_combis = nla_nest_start_noflag(msg,
1633 NL80211_ATTR_INTERFACE_COMBINATIONS);
7527a782
JB
1634 if (!nl_combis)
1635 goto nla_put_failure;
1636
1637 for (i = 0; i < wiphy->n_iface_combinations; i++) {
1638 const struct ieee80211_iface_combination *c;
1639 struct nlattr *nl_combi, *nl_limits;
1640
1641 c = &wiphy->iface_combinations[i];
1642
ae0be8de 1643 nl_combi = nla_nest_start_noflag(msg, i + 1);
7527a782
JB
1644 if (!nl_combi)
1645 goto nla_put_failure;
1646
ae0be8de
MK
1647 nl_limits = nla_nest_start_noflag(msg,
1648 NL80211_IFACE_COMB_LIMITS);
7527a782
JB
1649 if (!nl_limits)
1650 goto nla_put_failure;
1651
1652 for (j = 0; j < c->n_limits; j++) {
1653 struct nlattr *nl_limit;
1654
ae0be8de 1655 nl_limit = nla_nest_start_noflag(msg, j + 1);
7527a782
JB
1656 if (!nl_limit)
1657 goto nla_put_failure;
9360ffd1
DM
1658 if (nla_put_u32(msg, NL80211_IFACE_LIMIT_MAX,
1659 c->limits[j].max))
1660 goto nla_put_failure;
7527a782
JB
1661 if (nl80211_put_iftypes(msg, NL80211_IFACE_LIMIT_TYPES,
1662 c->limits[j].types))
1663 goto nla_put_failure;
1664 nla_nest_end(msg, nl_limit);
1665 }
1666
1667 nla_nest_end(msg, nl_limits);
1668
9360ffd1
DM
1669 if (c->beacon_int_infra_match &&
1670 nla_put_flag(msg, NL80211_IFACE_COMB_STA_AP_BI_MATCH))
1671 goto nla_put_failure;
1672 if (nla_put_u32(msg, NL80211_IFACE_COMB_NUM_CHANNELS,
1673 c->num_different_channels) ||
1674 nla_put_u32(msg, NL80211_IFACE_COMB_MAXNUM,
1675 c->max_interfaces))
1676 goto nla_put_failure;
cdc89b97 1677 if (large &&
8c48b50a
FF
1678 (nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS,
1679 c->radar_detect_widths) ||
1680 nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_REGIONS,
1681 c->radar_detect_regions)))
cdc89b97 1682 goto nla_put_failure;
0c317a02
PK
1683 if (c->beacon_int_min_gcd &&
1684 nla_put_u32(msg, NL80211_IFACE_COMB_BI_MIN_GCD,
1685 c->beacon_int_min_gcd))
1686 goto nla_put_failure;
7527a782
JB
1687
1688 nla_nest_end(msg, nl_combi);
1689 }
1690
1691 nla_nest_end(msg, nl_combis);
1692
1693 return 0;
1694nla_put_failure:
1695 return -ENOBUFS;
1696}
1697
3713b4e3 1698#ifdef CONFIG_PM
b56cf720
JB
1699static int nl80211_send_wowlan_tcp_caps(struct cfg80211_registered_device *rdev,
1700 struct sk_buff *msg)
1701{
964dc9e2 1702 const struct wiphy_wowlan_tcp_support *tcp = rdev->wiphy.wowlan->tcp;
b56cf720
JB
1703 struct nlattr *nl_tcp;
1704
1705 if (!tcp)
1706 return 0;
1707
ae0be8de
MK
1708 nl_tcp = nla_nest_start_noflag(msg,
1709 NL80211_WOWLAN_TRIG_TCP_CONNECTION);
b56cf720
JB
1710 if (!nl_tcp)
1711 return -ENOBUFS;
1712
1713 if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD,
1714 tcp->data_payload_max))
1715 return -ENOBUFS;
1716
1717 if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD,
1718 tcp->data_payload_max))
1719 return -ENOBUFS;
1720
1721 if (tcp->seq && nla_put_flag(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ))
1722 return -ENOBUFS;
1723
1724 if (tcp->tok && nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN,
1725 sizeof(*tcp->tok), tcp->tok))
1726 return -ENOBUFS;
1727
1728 if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_INTERVAL,
1729 tcp->data_interval_max))
1730 return -ENOBUFS;
1731
1732 if (nla_put_u32(msg, NL80211_WOWLAN_TCP_WAKE_PAYLOAD,
1733 tcp->wake_payload_max))
1734 return -ENOBUFS;
1735
1736 nla_nest_end(msg, nl_tcp);
1737 return 0;
1738}
1739
3713b4e3 1740static int nl80211_send_wowlan(struct sk_buff *msg,
1b8ec87a 1741 struct cfg80211_registered_device *rdev,
b56cf720 1742 bool large)
55682965 1743{
3713b4e3 1744 struct nlattr *nl_wowlan;
55682965 1745
1b8ec87a 1746 if (!rdev->wiphy.wowlan)
3713b4e3 1747 return 0;
55682965 1748
ae0be8de
MK
1749 nl_wowlan = nla_nest_start_noflag(msg,
1750 NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED);
3713b4e3
JB
1751 if (!nl_wowlan)
1752 return -ENOBUFS;
9360ffd1 1753
1b8ec87a 1754 if (((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_ANY) &&
3713b4e3 1755 nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) ||
1b8ec87a 1756 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_DISCONNECT) &&
3713b4e3 1757 nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) ||
1b8ec87a 1758 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_MAGIC_PKT) &&
3713b4e3 1759 nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) ||
1b8ec87a 1760 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_SUPPORTS_GTK_REKEY) &&
3713b4e3 1761 nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED)) ||
1b8ec87a 1762 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE) &&
3713b4e3 1763 nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) ||
1b8ec87a 1764 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ) &&
3713b4e3 1765 nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) ||
1b8ec87a 1766 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_4WAY_HANDSHAKE) &&
3713b4e3 1767 nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) ||
1b8ec87a 1768 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_RFKILL_RELEASE) &&
3713b4e3
JB
1769 nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE)))
1770 return -ENOBUFS;
9360ffd1 1771
1b8ec87a 1772 if (rdev->wiphy.wowlan->n_patterns) {
50ac6607 1773 struct nl80211_pattern_support pat = {
1b8ec87a
ZG
1774 .max_patterns = rdev->wiphy.wowlan->n_patterns,
1775 .min_pattern_len = rdev->wiphy.wowlan->pattern_min_len,
1776 .max_pattern_len = rdev->wiphy.wowlan->pattern_max_len,
1777 .max_pkt_offset = rdev->wiphy.wowlan->max_pkt_offset,
3713b4e3 1778 };
9360ffd1 1779
3713b4e3
JB
1780 if (nla_put(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN,
1781 sizeof(pat), &pat))
1782 return -ENOBUFS;
1783 }
9360ffd1 1784
75453ccb
LC
1785 if ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_NET_DETECT) &&
1786 nla_put_u32(msg, NL80211_WOWLAN_TRIG_NET_DETECT,
1787 rdev->wiphy.wowlan->max_nd_match_sets))
1788 return -ENOBUFS;
1789
1b8ec87a 1790 if (large && nl80211_send_wowlan_tcp_caps(rdev, msg))
b56cf720
JB
1791 return -ENOBUFS;
1792
3713b4e3 1793 nla_nest_end(msg, nl_wowlan);
9360ffd1 1794
3713b4e3
JB
1795 return 0;
1796}
1797#endif
9360ffd1 1798
be29b99a 1799static int nl80211_send_coalesce(struct sk_buff *msg,
1b8ec87a 1800 struct cfg80211_registered_device *rdev)
be29b99a
AK
1801{
1802 struct nl80211_coalesce_rule_support rule;
1803
1b8ec87a 1804 if (!rdev->wiphy.coalesce)
be29b99a
AK
1805 return 0;
1806
1b8ec87a
ZG
1807 rule.max_rules = rdev->wiphy.coalesce->n_rules;
1808 rule.max_delay = rdev->wiphy.coalesce->max_delay;
1809 rule.pat.max_patterns = rdev->wiphy.coalesce->n_patterns;
1810 rule.pat.min_pattern_len = rdev->wiphy.coalesce->pattern_min_len;
1811 rule.pat.max_pattern_len = rdev->wiphy.coalesce->pattern_max_len;
1812 rule.pat.max_pkt_offset = rdev->wiphy.coalesce->max_pkt_offset;
be29b99a
AK
1813
1814 if (nla_put(msg, NL80211_ATTR_COALESCE_RULE, sizeof(rule), &rule))
1815 return -ENOBUFS;
1816
1817 return 0;
1818}
1819
c4cbaf79
LC
1820static int
1821nl80211_send_iftype_data(struct sk_buff *msg,
22395217 1822 const struct ieee80211_supported_band *sband,
c4cbaf79
LC
1823 const struct ieee80211_sband_iftype_data *iftdata)
1824{
1825 const struct ieee80211_sta_he_cap *he_cap = &iftdata->he_cap;
5cd5a8a3 1826 const struct ieee80211_sta_eht_cap *eht_cap = &iftdata->eht_cap;
c4cbaf79
LC
1827
1828 if (nl80211_put_iftypes(msg, NL80211_BAND_IFTYPE_ATTR_IFTYPES,
1829 iftdata->types_mask))
1830 return -ENOBUFS;
1831
1832 if (he_cap->has_he) {
1833 if (nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_CAP_MAC,
1834 sizeof(he_cap->he_cap_elem.mac_cap_info),
1835 he_cap->he_cap_elem.mac_cap_info) ||
1836 nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY,
1837 sizeof(he_cap->he_cap_elem.phy_cap_info),
1838 he_cap->he_cap_elem.phy_cap_info) ||
1839 nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET,
1840 sizeof(he_cap->he_mcs_nss_supp),
1841 &he_cap->he_mcs_nss_supp) ||
1842 nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE,
1843 sizeof(he_cap->ppe_thres), he_cap->ppe_thres))
1844 return -ENOBUFS;
1845 }
1846
5cd5a8a3
IP
1847 if (eht_cap->has_eht && he_cap->has_he) {
1848 u8 mcs_nss_size, ppe_thresh_size;
1849 u16 ppe_thres_hdr;
ea5cba26
JB
1850 bool is_ap;
1851
1852 is_ap = iftdata->types_mask & BIT(NL80211_IFTYPE_AP) ||
1853 iftdata->types_mask & BIT(NL80211_IFTYPE_P2P_GO);
5cd5a8a3
IP
1854
1855 mcs_nss_size =
1856 ieee80211_eht_mcs_nss_size(&he_cap->he_cap_elem,
ea5cba26
JB
1857 &eht_cap->eht_cap_elem,
1858 is_ap);
5cd5a8a3
IP
1859
1860 ppe_thres_hdr = get_unaligned_le16(&eht_cap->eht_ppe_thres[0]);
1861 ppe_thresh_size =
1862 ieee80211_eht_ppe_size(ppe_thres_hdr,
1863 eht_cap->eht_cap_elem.phy_cap_info);
1864
1865 if (nla_put(msg, NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MAC,
1866 sizeof(eht_cap->eht_cap_elem.mac_cap_info),
1867 eht_cap->eht_cap_elem.mac_cap_info) ||
1868 nla_put(msg, NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY,
1869 sizeof(eht_cap->eht_cap_elem.phy_cap_info),
1870 eht_cap->eht_cap_elem.phy_cap_info) ||
1871 nla_put(msg, NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MCS_SET,
1872 mcs_nss_size, &eht_cap->eht_mcs_nss_supp) ||
1873 nla_put(msg, NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PPE,
1874 ppe_thresh_size, eht_cap->eht_ppe_thres))
1875 return -ENOBUFS;
1876 }
1877
22395217
JB
1878 if (sband->band == NL80211_BAND_6GHZ &&
1879 nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA,
1880 sizeof(iftdata->he_6ghz_capa),
1881 &iftdata->he_6ghz_capa))
1882 return -ENOBUFS;
1883
f4f86505
JB
1884 if (iftdata->vendor_elems.data && iftdata->vendor_elems.len &&
1885 nla_put(msg, NL80211_BAND_IFTYPE_ATTR_VENDOR_ELEMS,
1886 iftdata->vendor_elems.len, iftdata->vendor_elems.data))
1887 return -ENOBUFS;
1888
c4cbaf79
LC
1889 return 0;
1890}
1891
3713b4e3 1892static int nl80211_send_band_rateinfo(struct sk_buff *msg,
f8d504ca
JB
1893 struct ieee80211_supported_band *sband,
1894 bool large)
3713b4e3
JB
1895{
1896 struct nlattr *nl_rates, *nl_rate;
1897 struct ieee80211_rate *rate;
1898 int i;
87bbbe22 1899
3713b4e3
JB
1900 /* add HT info */
1901 if (sband->ht_cap.ht_supported &&
1902 (nla_put(msg, NL80211_BAND_ATTR_HT_MCS_SET,
1903 sizeof(sband->ht_cap.mcs),
1904 &sband->ht_cap.mcs) ||
1905 nla_put_u16(msg, NL80211_BAND_ATTR_HT_CAPA,
1906 sband->ht_cap.cap) ||
1907 nla_put_u8(msg, NL80211_BAND_ATTR_HT_AMPDU_FACTOR,
1908 sband->ht_cap.ampdu_factor) ||
1909 nla_put_u8(msg, NL80211_BAND_ATTR_HT_AMPDU_DENSITY,
1910 sband->ht_cap.ampdu_density)))
1911 return -ENOBUFS;
afe0cbf8 1912
3713b4e3
JB
1913 /* add VHT info */
1914 if (sband->vht_cap.vht_supported &&
1915 (nla_put(msg, NL80211_BAND_ATTR_VHT_MCS_SET,
1916 sizeof(sband->vht_cap.vht_mcs),
1917 &sband->vht_cap.vht_mcs) ||
1918 nla_put_u32(msg, NL80211_BAND_ATTR_VHT_CAPA,
1919 sband->vht_cap.cap)))
1920 return -ENOBUFS;
f59ac048 1921
f8d504ca 1922 if (large && sband->n_iftype_data) {
c4cbaf79 1923 struct nlattr *nl_iftype_data =
ae0be8de
MK
1924 nla_nest_start_noflag(msg,
1925 NL80211_BAND_ATTR_IFTYPE_DATA);
e8c18412 1926 const struct ieee80211_sband_iftype_data *iftd;
c4cbaf79
LC
1927 int err;
1928
1929 if (!nl_iftype_data)
1930 return -ENOBUFS;
1931
e8c18412 1932 for_each_sband_iftype_data(sband, i, iftd) {
c4cbaf79
LC
1933 struct nlattr *iftdata;
1934
ae0be8de 1935 iftdata = nla_nest_start_noflag(msg, i + 1);
c4cbaf79
LC
1936 if (!iftdata)
1937 return -ENOBUFS;
1938
e8c18412 1939 err = nl80211_send_iftype_data(msg, sband, iftd);
c4cbaf79
LC
1940 if (err)
1941 return err;
1942
1943 nla_nest_end(msg, iftdata);
1944 }
1945
1946 nla_nest_end(msg, nl_iftype_data);
1947 }
1948
2a38075c 1949 /* add EDMG info */
f8d504ca 1950 if (large && sband->edmg_cap.channels &&
2a38075c
AAL
1951 (nla_put_u8(msg, NL80211_BAND_ATTR_EDMG_CHANNELS,
1952 sband->edmg_cap.channels) ||
1953 nla_put_u8(msg, NL80211_BAND_ATTR_EDMG_BW_CONFIG,
1954 sband->edmg_cap.bw_config)))
1955
1956 return -ENOBUFS;
1957
3713b4e3 1958 /* add bitrates */
ae0be8de 1959 nl_rates = nla_nest_start_noflag(msg, NL80211_BAND_ATTR_RATES);
3713b4e3
JB
1960 if (!nl_rates)
1961 return -ENOBUFS;
ee688b00 1962
3713b4e3 1963 for (i = 0; i < sband->n_bitrates; i++) {
ae0be8de 1964 nl_rate = nla_nest_start_noflag(msg, i);
3713b4e3
JB
1965 if (!nl_rate)
1966 return -ENOBUFS;
ee688b00 1967
3713b4e3
JB
1968 rate = &sband->bitrates[i];
1969 if (nla_put_u32(msg, NL80211_BITRATE_ATTR_RATE,
1970 rate->bitrate))
1971 return -ENOBUFS;
1972 if ((rate->flags & IEEE80211_RATE_SHORT_PREAMBLE) &&
1973 nla_put_flag(msg,
1974 NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE))
1975 return -ENOBUFS;
ee688b00 1976
3713b4e3
JB
1977 nla_nest_end(msg, nl_rate);
1978 }
d51626df 1979
3713b4e3 1980 nla_nest_end(msg, nl_rates);
bf0c111e 1981
9a8aac92
KF
1982 /* S1G capabilities */
1983 if (sband->band == NL80211_BAND_S1GHZ && sband->s1g_cap.s1g &&
1984 (nla_put(msg, NL80211_BAND_ATTR_S1G_CAPA,
1985 sizeof(sband->s1g_cap.cap),
1986 sband->s1g_cap.cap) ||
1987 nla_put(msg, NL80211_BAND_ATTR_S1G_MCS_NSS_SET,
1988 sizeof(sband->s1g_cap.nss_mcs),
1989 sband->s1g_cap.nss_mcs)))
1990 return -ENOBUFS;
1991
3713b4e3
JB
1992 return 0;
1993}
ee688b00 1994
3713b4e3
JB
1995static int
1996nl80211_send_mgmt_stypes(struct sk_buff *msg,
1997 const struct ieee80211_txrx_stypes *mgmt_stypes)
1998{
1999 u16 stypes;
2000 struct nlattr *nl_ftypes, *nl_ifs;
2001 enum nl80211_iftype ift;
2002 int i;
ee688b00 2003
3713b4e3
JB
2004 if (!mgmt_stypes)
2005 return 0;
5dab3b8a 2006
ae0be8de 2007 nl_ifs = nla_nest_start_noflag(msg, NL80211_ATTR_TX_FRAME_TYPES);
3713b4e3
JB
2008 if (!nl_ifs)
2009 return -ENOBUFS;
e2f367f2 2010
3713b4e3 2011 for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) {
ae0be8de 2012 nl_ftypes = nla_nest_start_noflag(msg, ift);
3713b4e3
JB
2013 if (!nl_ftypes)
2014 return -ENOBUFS;
2015 i = 0;
2016 stypes = mgmt_stypes[ift].tx;
2017 while (stypes) {
2018 if ((stypes & 1) &&
2019 nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE,
2020 (i << 4) | IEEE80211_FTYPE_MGMT))
2021 return -ENOBUFS;
2022 stypes >>= 1;
2023 i++;
ee688b00 2024 }
3713b4e3
JB
2025 nla_nest_end(msg, nl_ftypes);
2026 }
ee688b00 2027
3713b4e3 2028 nla_nest_end(msg, nl_ifs);
ee688b00 2029
ae0be8de 2030 nl_ifs = nla_nest_start_noflag(msg, NL80211_ATTR_RX_FRAME_TYPES);
3713b4e3
JB
2031 if (!nl_ifs)
2032 return -ENOBUFS;
ee688b00 2033
3713b4e3 2034 for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) {
ae0be8de 2035 nl_ftypes = nla_nest_start_noflag(msg, ift);
3713b4e3
JB
2036 if (!nl_ftypes)
2037 return -ENOBUFS;
2038 i = 0;
2039 stypes = mgmt_stypes[ift].rx;
2040 while (stypes) {
2041 if ((stypes & 1) &&
2042 nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE,
2043 (i << 4) | IEEE80211_FTYPE_MGMT))
2044 return -ENOBUFS;
2045 stypes >>= 1;
2046 i++;
2047 }
2048 nla_nest_end(msg, nl_ftypes);
2049 }
2050 nla_nest_end(msg, nl_ifs);
ee688b00 2051
3713b4e3
JB
2052 return 0;
2053}
ee688b00 2054
1794899e
JB
2055#define CMD(op, n) \
2056 do { \
2057 if (rdev->ops->op) { \
2058 i++; \
2059 if (nla_put_u32(msg, i, NL80211_CMD_ ## n)) \
2060 goto nla_put_failure; \
2061 } \
2062 } while (0)
2063
2064static int nl80211_add_commands_unsplit(struct cfg80211_registered_device *rdev,
2065 struct sk_buff *msg)
2066{
2067 int i = 0;
2068
2069 /*
2070 * do *NOT* add anything into this function, new things need to be
2071 * advertised only to new versions of userspace that can deal with
2072 * the split (and they can't possibly care about new features...
2073 */
2074 CMD(add_virtual_intf, NEW_INTERFACE);
2075 CMD(change_virtual_intf, SET_INTERFACE);
2076 CMD(add_key, NEW_KEY);
2077 CMD(start_ap, START_AP);
2078 CMD(add_station, NEW_STATION);
2079 CMD(add_mpath, NEW_MPATH);
2080 CMD(update_mesh_config, SET_MESH_CONFIG);
2081 CMD(change_bss, SET_BSS);
2082 CMD(auth, AUTHENTICATE);
2083 CMD(assoc, ASSOCIATE);
2084 CMD(deauth, DEAUTHENTICATE);
2085 CMD(disassoc, DISASSOCIATE);
2086 CMD(join_ibss, JOIN_IBSS);
2087 CMD(join_mesh, JOIN_MESH);
2088 CMD(set_pmksa, SET_PMKSA);
2089 CMD(del_pmksa, DEL_PMKSA);
2090 CMD(flush_pmksa, FLUSH_PMKSA);
2091 if (rdev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL)
2092 CMD(remain_on_channel, REMAIN_ON_CHANNEL);
2093 CMD(set_bitrate_mask, SET_TX_BITRATE_MASK);
2094 CMD(mgmt_tx, FRAME);
2095 CMD(mgmt_tx_cancel_wait, FRAME_WAIT_CANCEL);
2096 if (rdev->wiphy.flags & WIPHY_FLAG_NETNS_OK) {
2097 i++;
2098 if (nla_put_u32(msg, i, NL80211_CMD_SET_WIPHY_NETNS))
2099 goto nla_put_failure;
2100 }
2101 if (rdev->ops->set_monitor_channel || rdev->ops->start_ap ||
2102 rdev->ops->join_mesh) {
2103 i++;
2104 if (nla_put_u32(msg, i, NL80211_CMD_SET_CHANNEL))
2105 goto nla_put_failure;
2106 }
1794899e
JB
2107 if (rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) {
2108 CMD(tdls_mgmt, TDLS_MGMT);
2109 CMD(tdls_oper, TDLS_OPER);
2110 }
ca986ad9 2111 if (rdev->wiphy.max_sched_scan_reqs)
1794899e
JB
2112 CMD(sched_scan_start, START_SCHED_SCAN);
2113 CMD(probe_client, PROBE_CLIENT);
2114 CMD(set_noack_map, SET_NOACK_MAP);
2115 if (rdev->wiphy.flags & WIPHY_FLAG_REPORTS_OBSS) {
2116 i++;
2117 if (nla_put_u32(msg, i, NL80211_CMD_REGISTER_BEACONS))
2118 goto nla_put_failure;
2119 }
2120 CMD(start_p2p_device, START_P2P_DEVICE);
2121 CMD(set_mcast_rate, SET_MCAST_RATE);
2122#ifdef CONFIG_NL80211_TESTMODE
2123 CMD(testmode_cmd, TESTMODE);
2124#endif
2125
2126 if (rdev->ops->connect || rdev->ops->auth) {
2127 i++;
2128 if (nla_put_u32(msg, i, NL80211_CMD_CONNECT))
2129 goto nla_put_failure;
2130 }
2131
2132 if (rdev->ops->disconnect || rdev->ops->deauth) {
2133 i++;
2134 if (nla_put_u32(msg, i, NL80211_CMD_DISCONNECT))
2135 goto nla_put_failure;
2136 }
2137
2138 return i;
2139 nla_put_failure:
2140 return -ENOBUFS;
2141}
2142
9bb7e0f2
JB
2143static int
2144nl80211_send_pmsr_ftm_capa(const struct cfg80211_pmsr_capabilities *cap,
2145 struct sk_buff *msg)
2146{
2147 struct nlattr *ftm;
2148
2149 if (!cap->ftm.supported)
2150 return 0;
2151
ae0be8de 2152 ftm = nla_nest_start_noflag(msg, NL80211_PMSR_TYPE_FTM);
9bb7e0f2
JB
2153 if (!ftm)
2154 return -ENOBUFS;
2155
2156 if (cap->ftm.asap && nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_ASAP))
2157 return -ENOBUFS;
2158 if (cap->ftm.non_asap &&
2159 nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_NON_ASAP))
2160 return -ENOBUFS;
2161 if (cap->ftm.request_lci &&
2162 nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_REQ_LCI))
2163 return -ENOBUFS;
2164 if (cap->ftm.request_civicloc &&
2165 nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_REQ_CIVICLOC))
2166 return -ENOBUFS;
2167 if (nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_PREAMBLES,
2168 cap->ftm.preambles))
2169 return -ENOBUFS;
2170 if (nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_BANDWIDTHS,
2171 cap->ftm.bandwidths))
2172 return -ENOBUFS;
2173 if (cap->ftm.max_bursts_exponent >= 0 &&
2174 nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_MAX_BURSTS_EXPONENT,
2175 cap->ftm.max_bursts_exponent))
2176 return -ENOBUFS;
2177 if (cap->ftm.max_ftms_per_burst &&
2178 nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_MAX_FTMS_PER_BURST,
2179 cap->ftm.max_ftms_per_burst))
2180 return -ENOBUFS;
efb5520d
AS
2181 if (cap->ftm.trigger_based &&
2182 nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_TRIGGER_BASED))
2183 return -ENOBUFS;
2184 if (cap->ftm.non_trigger_based &&
2185 nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_NON_TRIGGER_BASED))
2186 return -ENOBUFS;
9bb7e0f2
JB
2187
2188 nla_nest_end(msg, ftm);
2189 return 0;
2190}
2191
2192static int nl80211_send_pmsr_capa(struct cfg80211_registered_device *rdev,
2193 struct sk_buff *msg)
2194{
2195 const struct cfg80211_pmsr_capabilities *cap = rdev->wiphy.pmsr_capa;
2196 struct nlattr *pmsr, *caps;
2197
2198 if (!cap)
2199 return 0;
2200
2201 /*
2202 * we don't need to clean up anything here since the caller
2203 * will genlmsg_cancel() if we fail
2204 */
2205
ae0be8de 2206 pmsr = nla_nest_start_noflag(msg, NL80211_ATTR_PEER_MEASUREMENTS);
9bb7e0f2
JB
2207 if (!pmsr)
2208 return -ENOBUFS;
2209
2210 if (nla_put_u32(msg, NL80211_PMSR_ATTR_MAX_PEERS, cap->max_peers))
2211 return -ENOBUFS;
2212
2213 if (cap->report_ap_tsf &&
2214 nla_put_flag(msg, NL80211_PMSR_ATTR_REPORT_AP_TSF))
2215 return -ENOBUFS;
2216
2217 if (cap->randomize_mac_addr &&
2218 nla_put_flag(msg, NL80211_PMSR_ATTR_RANDOMIZE_MAC_ADDR))
2219 return -ENOBUFS;
2220
ae0be8de 2221 caps = nla_nest_start_noflag(msg, NL80211_PMSR_ATTR_TYPE_CAPA);
9bb7e0f2
JB
2222 if (!caps)
2223 return -ENOBUFS;
2224
2225 if (nl80211_send_pmsr_ftm_capa(cap, msg))
2226 return -ENOBUFS;
2227
2228 nla_nest_end(msg, caps);
2229 nla_nest_end(msg, pmsr);
2230
2231 return 0;
2232}
2233
d6039a34
VJ
2234static int
2235nl80211_put_iftype_akm_suites(struct cfg80211_registered_device *rdev,
2236 struct sk_buff *msg)
2237{
2238 int i;
2239 struct nlattr *nested, *nested_akms;
2240 const struct wiphy_iftype_akm_suites *iftype_akms;
2241
2242 if (!rdev->wiphy.num_iftype_akm_suites ||
2243 !rdev->wiphy.iftype_akm_suites)
2244 return 0;
2245
2246 nested = nla_nest_start(msg, NL80211_ATTR_IFTYPE_AKM_SUITES);
2247 if (!nested)
2248 return -ENOBUFS;
2249
2250 for (i = 0; i < rdev->wiphy.num_iftype_akm_suites; i++) {
2251 nested_akms = nla_nest_start(msg, i + 1);
2252 if (!nested_akms)
2253 return -ENOBUFS;
2254
2255 iftype_akms = &rdev->wiphy.iftype_akm_suites[i];
2256
2257 if (nl80211_put_iftypes(msg, NL80211_IFTYPE_AKM_ATTR_IFTYPES,
2258 iftype_akms->iftypes_mask))
2259 return -ENOBUFS;
2260
2261 if (nla_put(msg, NL80211_IFTYPE_AKM_ATTR_SUITES,
2262 sizeof(u32) * iftype_akms->n_akm_suites,
2263 iftype_akms->akm_suites)) {
2264 return -ENOBUFS;
2265 }
2266 nla_nest_end(msg, nested_akms);
2267 }
2268
2269 nla_nest_end(msg, nested);
2270
2271 return 0;
2272}
2273
3710a8a6
JB
2274static int
2275nl80211_put_tid_config_support(struct cfg80211_registered_device *rdev,
2276 struct sk_buff *msg)
2277{
2278 struct nlattr *supp;
2279
2280 if (!rdev->wiphy.tid_config_support.vif &&
2281 !rdev->wiphy.tid_config_support.peer)
2282 return 0;
2283
2284 supp = nla_nest_start(msg, NL80211_ATTR_TID_CONFIG);
2285 if (!supp)
2286 return -ENOSPC;
2287
2288 if (rdev->wiphy.tid_config_support.vif &&
2289 nla_put_u64_64bit(msg, NL80211_TID_CONFIG_ATTR_VIF_SUPP,
2290 rdev->wiphy.tid_config_support.vif,
2291 NL80211_TID_CONFIG_ATTR_PAD))
2292 goto fail;
2293
2294 if (rdev->wiphy.tid_config_support.peer &&
2295 nla_put_u64_64bit(msg, NL80211_TID_CONFIG_ATTR_PEER_SUPP,
2296 rdev->wiphy.tid_config_support.peer,
2297 NL80211_TID_CONFIG_ATTR_PAD))
2298 goto fail;
2299
6a21d16c
T
2300 /* for now we just use the same value ... makes more sense */
2301 if (nla_put_u8(msg, NL80211_TID_CONFIG_ATTR_RETRY_SHORT,
2302 rdev->wiphy.tid_config_support.max_retry))
2303 goto fail;
2304 if (nla_put_u8(msg, NL80211_TID_CONFIG_ATTR_RETRY_LONG,
2305 rdev->wiphy.tid_config_support.max_retry))
2306 goto fail;
2307
3710a8a6
JB
2308 nla_nest_end(msg, supp);
2309
2310 return 0;
2311fail:
2312 nla_nest_cancel(msg, supp);
2313 return -ENOBUFS;
2314}
2315
6bdb68ce
CH
2316static int
2317nl80211_put_sar_specs(struct cfg80211_registered_device *rdev,
2318 struct sk_buff *msg)
2319{
2320 struct nlattr *sar_capa, *specs, *sub_freq_range;
2321 u8 num_freq_ranges;
2322 int i;
2323
2324 if (!rdev->wiphy.sar_capa)
2325 return 0;
2326
2327 num_freq_ranges = rdev->wiphy.sar_capa->num_freq_ranges;
2328
2329 sar_capa = nla_nest_start(msg, NL80211_ATTR_SAR_SPEC);
2330 if (!sar_capa)
2331 return -ENOSPC;
2332
2333 if (nla_put_u32(msg, NL80211_SAR_ATTR_TYPE, rdev->wiphy.sar_capa->type))
2334 goto fail;
2335
2336 specs = nla_nest_start(msg, NL80211_SAR_ATTR_SPECS);
2337 if (!specs)
2338 goto fail;
2339
2340 /* report supported freq_ranges */
2341 for (i = 0; i < num_freq_ranges; i++) {
2342 sub_freq_range = nla_nest_start(msg, i + 1);
2343 if (!sub_freq_range)
2344 goto fail;
2345
2346 if (nla_put_u32(msg, NL80211_SAR_ATTR_SPECS_START_FREQ,
2347 rdev->wiphy.sar_capa->freq_ranges[i].start_freq))
2348 goto fail;
2349
2350 if (nla_put_u32(msg, NL80211_SAR_ATTR_SPECS_END_FREQ,
2351 rdev->wiphy.sar_capa->freq_ranges[i].end_freq))
2352 goto fail;
2353
2354 nla_nest_end(msg, sub_freq_range);
2355 }
2356
2357 nla_nest_end(msg, specs);
2358 nla_nest_end(msg, sar_capa);
2359
2360 return 0;
2361fail:
2362 nla_nest_cancel(msg, sar_capa);
2363 return -ENOBUFS;
2364}
2365
dc1e3cb8
JC
2366static int nl80211_put_mbssid_support(struct wiphy *wiphy, struct sk_buff *msg)
2367{
2368 struct nlattr *config;
2369
2370 if (!wiphy->mbssid_max_interfaces)
2371 return 0;
2372
2373 config = nla_nest_start(msg, NL80211_ATTR_MBSSID_CONFIG);
2374 if (!config)
2375 return -ENOBUFS;
2376
2377 if (nla_put_u8(msg, NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES,
2378 wiphy->mbssid_max_interfaces))
2379 goto fail;
2380
2381 if (wiphy->ema_max_profile_periodicity &&
2382 nla_put_u8(msg,
2383 NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY,
2384 wiphy->ema_max_profile_periodicity))
2385 goto fail;
2386
2387 nla_nest_end(msg, config);
2388 return 0;
2389
2390fail:
2391 nla_nest_cancel(msg, config);
2392 return -ENOBUFS;
2393}
2394
86e8cf98
JB
2395struct nl80211_dump_wiphy_state {
2396 s64 filter_wiphy;
2397 long start;
019ae3a9 2398 long split_start, band_start, chan_start, capa_start;
86e8cf98
JB
2399 bool split;
2400};
2401
1b8ec87a 2402static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
3bb20556 2403 enum nl80211_commands cmd,
3713b4e3 2404 struct sk_buff *msg, u32 portid, u32 seq,
86e8cf98 2405 int flags, struct nl80211_dump_wiphy_state *state)
3713b4e3
JB
2406{
2407 void *hdr;
2408 struct nlattr *nl_bands, *nl_band;
2409 struct nlattr *nl_freqs, *nl_freq;
2410 struct nlattr *nl_cmds;
57fbcce3 2411 enum nl80211_band band;
3713b4e3
JB
2412 struct ieee80211_channel *chan;
2413 int i;
2414 const struct ieee80211_txrx_stypes *mgmt_stypes =
1b8ec87a 2415 rdev->wiphy.mgmt_stypes;
fe1abafd 2416 u32 features;
ee688b00 2417
3bb20556 2418 hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
3713b4e3
JB
2419 if (!hdr)
2420 return -ENOBUFS;
ee688b00 2421
86e8cf98
JB
2422 if (WARN_ON(!state))
2423 return -EINVAL;
ee688b00 2424
1b8ec87a 2425 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
3713b4e3 2426 nla_put_string(msg, NL80211_ATTR_WIPHY_NAME,
1b8ec87a 2427 wiphy_name(&rdev->wiphy)) ||
3713b4e3
JB
2428 nla_put_u32(msg, NL80211_ATTR_GENERATION,
2429 cfg80211_rdev_list_generation))
8fdc621d
JB
2430 goto nla_put_failure;
2431
3bb20556
JB
2432 if (cmd != NL80211_CMD_NEW_WIPHY)
2433 goto finish;
2434
86e8cf98 2435 switch (state->split_start) {
3713b4e3
JB
2436 case 0:
2437 if (nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_SHORT,
1b8ec87a 2438 rdev->wiphy.retry_short) ||
3713b4e3 2439 nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_LONG,
1b8ec87a 2440 rdev->wiphy.retry_long) ||
3713b4e3 2441 nla_put_u32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD,
1b8ec87a 2442 rdev->wiphy.frag_threshold) ||
3713b4e3 2443 nla_put_u32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD,
1b8ec87a 2444 rdev->wiphy.rts_threshold) ||
3713b4e3 2445 nla_put_u8(msg, NL80211_ATTR_WIPHY_COVERAGE_CLASS,
1b8ec87a 2446 rdev->wiphy.coverage_class) ||
3713b4e3 2447 nla_put_u8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS,
1b8ec87a 2448 rdev->wiphy.max_scan_ssids) ||
3713b4e3 2449 nla_put_u8(msg, NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS,
1b8ec87a 2450 rdev->wiphy.max_sched_scan_ssids) ||
3713b4e3 2451 nla_put_u16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN,
1b8ec87a 2452 rdev->wiphy.max_scan_ie_len) ||
3713b4e3 2453 nla_put_u16(msg, NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN,
1b8ec87a 2454 rdev->wiphy.max_sched_scan_ie_len) ||
3713b4e3 2455 nla_put_u8(msg, NL80211_ATTR_MAX_MATCH_SETS,
f8d504ca 2456 rdev->wiphy.max_match_sets))
9360ffd1 2457 goto nla_put_failure;
3713b4e3 2458
1b8ec87a 2459 if ((rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN) &&
3713b4e3 2460 nla_put_flag(msg, NL80211_ATTR_SUPPORT_IBSS_RSN))
aa430da4 2461 goto nla_put_failure;
1b8ec87a 2462 if ((rdev->wiphy.flags & WIPHY_FLAG_MESH_AUTH) &&
3713b4e3
JB
2463 nla_put_flag(msg, NL80211_ATTR_SUPPORT_MESH_AUTH))
2464 goto nla_put_failure;
1b8ec87a 2465 if ((rdev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) &&
3713b4e3
JB
2466 nla_put_flag(msg, NL80211_ATTR_SUPPORT_AP_UAPSD))
2467 goto nla_put_failure;
1b8ec87a 2468 if ((rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_FW_ROAM) &&
3713b4e3
JB
2469 nla_put_flag(msg, NL80211_ATTR_ROAM_SUPPORT))
2470 goto nla_put_failure;
1b8ec87a 2471 if ((rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) &&
3713b4e3
JB
2472 nla_put_flag(msg, NL80211_ATTR_TDLS_SUPPORT))
2473 goto nla_put_failure;
1b8ec87a 2474 if ((rdev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP) &&
3713b4e3 2475 nla_put_flag(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP))
9360ffd1 2476 goto nla_put_failure;
86e8cf98
JB
2477 state->split_start++;
2478 if (state->split)
3713b4e3 2479 break;
7b506ff6 2480 fallthrough;
3713b4e3
JB
2481 case 1:
2482 if (nla_put(msg, NL80211_ATTR_CIPHER_SUITES,
1b8ec87a
ZG
2483 sizeof(u32) * rdev->wiphy.n_cipher_suites,
2484 rdev->wiphy.cipher_suites))
3713b4e3 2485 goto nla_put_failure;
4745fc09 2486
3713b4e3 2487 if (nla_put_u8(msg, NL80211_ATTR_MAX_NUM_PMKIDS,
1b8ec87a 2488 rdev->wiphy.max_num_pmkids))
3713b4e3 2489 goto nla_put_failure;
b23aa676 2490
1b8ec87a 2491 if ((rdev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) &&
3713b4e3 2492 nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE))
9360ffd1 2493 goto nla_put_failure;
b23aa676 2494
3713b4e3 2495 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX,
1b8ec87a 2496 rdev->wiphy.available_antennas_tx) ||
3713b4e3 2497 nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX,
1b8ec87a 2498 rdev->wiphy.available_antennas_rx))
9360ffd1 2499 goto nla_put_failure;
b23aa676 2500
1b8ec87a 2501 if ((rdev->wiphy.flags & WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD) &&
3713b4e3 2502 nla_put_u32(msg, NL80211_ATTR_PROBE_RESP_OFFLOAD,
1b8ec87a 2503 rdev->wiphy.probe_resp_offload))
3713b4e3 2504 goto nla_put_failure;
8fdc621d 2505
1b8ec87a
ZG
2506 if ((rdev->wiphy.available_antennas_tx ||
2507 rdev->wiphy.available_antennas_rx) &&
2508 rdev->ops->get_antenna) {
3713b4e3
JB
2509 u32 tx_ant = 0, rx_ant = 0;
2510 int res;
7a087e74 2511
1b8ec87a 2512 res = rdev_get_antenna(rdev, &tx_ant, &rx_ant);
3713b4e3
JB
2513 if (!res) {
2514 if (nla_put_u32(msg,
2515 NL80211_ATTR_WIPHY_ANTENNA_TX,
2516 tx_ant) ||
2517 nla_put_u32(msg,
2518 NL80211_ATTR_WIPHY_ANTENNA_RX,
2519 rx_ant))
2520 goto nla_put_failure;
2521 }
2522 }
a293911d 2523
86e8cf98
JB
2524 state->split_start++;
2525 if (state->split)
3713b4e3 2526 break;
7b506ff6 2527 fallthrough;
3713b4e3
JB
2528 case 2:
2529 if (nl80211_put_iftypes(msg, NL80211_ATTR_SUPPORTED_IFTYPES,
1b8ec87a 2530 rdev->wiphy.interface_modes))
3713b4e3 2531 goto nla_put_failure;
86e8cf98
JB
2532 state->split_start++;
2533 if (state->split)
3713b4e3 2534 break;
7b506ff6 2535 fallthrough;
3713b4e3 2536 case 3:
ae0be8de
MK
2537 nl_bands = nla_nest_start_noflag(msg,
2538 NL80211_ATTR_WIPHY_BANDS);
3713b4e3
JB
2539 if (!nl_bands)
2540 goto nla_put_failure;
f7ca38df 2541
86e8cf98 2542 for (band = state->band_start;
0d059964
JB
2543 band < (state->split ?
2544 NUM_NL80211_BANDS :
2545 NL80211_BAND_60GHZ + 1);
2546 band++) {
3713b4e3 2547 struct ieee80211_supported_band *sband;
2e161f78 2548
f8d504ca
JB
2549 /* omit higher bands for ancient software */
2550 if (band > NL80211_BAND_5GHZ && !state->split)
2551 break;
2552
1b8ec87a 2553 sband = rdev->wiphy.bands[band];
2e161f78 2554
3713b4e3
JB
2555 if (!sband)
2556 continue;
2557
ae0be8de 2558 nl_band = nla_nest_start_noflag(msg, band);
3713b4e3 2559 if (!nl_band)
2e161f78 2560 goto nla_put_failure;
3713b4e3 2561
86e8cf98 2562 switch (state->chan_start) {
3713b4e3 2563 case 0:
f8d504ca
JB
2564 if (nl80211_send_band_rateinfo(msg, sband,
2565 state->split))
9360ffd1 2566 goto nla_put_failure;
86e8cf98
JB
2567 state->chan_start++;
2568 if (state->split)
3713b4e3 2569 break;
7b506ff6 2570 fallthrough;
3713b4e3
JB
2571 default:
2572 /* add frequencies */
ae0be8de
MK
2573 nl_freqs = nla_nest_start_noflag(msg,
2574 NL80211_BAND_ATTR_FREQS);
3713b4e3
JB
2575 if (!nl_freqs)
2576 goto nla_put_failure;
2577
86e8cf98 2578 for (i = state->chan_start - 1;
3713b4e3
JB
2579 i < sband->n_channels;
2580 i++) {
ae0be8de
MK
2581 nl_freq = nla_nest_start_noflag(msg,
2582 i);
3713b4e3
JB
2583 if (!nl_freq)
2584 goto nla_put_failure;
2585
2586 chan = &sband->channels[i];
2587
86e8cf98 2588 if (nl80211_msg_put_channel(
50f32718 2589 msg, &rdev->wiphy, chan,
86e8cf98 2590 state->split))
3713b4e3
JB
2591 goto nla_put_failure;
2592
2593 nla_nest_end(msg, nl_freq);
86e8cf98 2594 if (state->split)
3713b4e3
JB
2595 break;
2596 }
2597 if (i < sband->n_channels)
86e8cf98 2598 state->chan_start = i + 2;
3713b4e3 2599 else
86e8cf98 2600 state->chan_start = 0;
3713b4e3
JB
2601 nla_nest_end(msg, nl_freqs);
2602 }
2603
2604 nla_nest_end(msg, nl_band);
2605
86e8cf98 2606 if (state->split) {
3713b4e3 2607 /* start again here */
86e8cf98 2608 if (state->chan_start)
3713b4e3
JB
2609 band--;
2610 break;
2e161f78 2611 }
2e161f78 2612 }
3713b4e3 2613 nla_nest_end(msg, nl_bands);
2e161f78 2614
57fbcce3 2615 if (band < NUM_NL80211_BANDS)
86e8cf98 2616 state->band_start = band + 1;
3713b4e3 2617 else
86e8cf98 2618 state->band_start = 0;
74b70a4e 2619
3713b4e3 2620 /* if bands & channels are done, continue outside */
86e8cf98
JB
2621 if (state->band_start == 0 && state->chan_start == 0)
2622 state->split_start++;
2623 if (state->split)
3713b4e3 2624 break;
7b506ff6 2625 fallthrough;
3713b4e3 2626 case 4:
ae0be8de
MK
2627 nl_cmds = nla_nest_start_noflag(msg,
2628 NL80211_ATTR_SUPPORTED_COMMANDS);
3713b4e3 2629 if (!nl_cmds)
2e161f78
JB
2630 goto nla_put_failure;
2631
1794899e
JB
2632 i = nl80211_add_commands_unsplit(rdev, msg);
2633 if (i < 0)
2634 goto nla_put_failure;
86e8cf98 2635 if (state->split) {
5de17984
AS
2636 CMD(crit_proto_start, CRIT_PROTOCOL_START);
2637 CMD(crit_proto_stop, CRIT_PROTOCOL_STOP);
1b8ec87a 2638 if (rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH)
16ef1fe2 2639 CMD(channel_switch, CHANNEL_SWITCH);
02df00eb 2640 CMD(set_qos_map, SET_QOS_MAP);
723e73ac
JB
2641 if (rdev->wiphy.features &
2642 NL80211_FEATURE_SUPPORTS_WMM_ADMISSION)
960d01ac 2643 CMD(add_tx_ts, ADD_TX_TS);
ce0ce13a 2644 CMD(set_multicast_to_unicast, SET_MULTICAST_TO_UNICAST);
088e8df8 2645 CMD(update_connect_params, UPDATE_CONNECT_PARAMS);
7010998c 2646 CMD(update_ft_ies, UPDATE_FT_IES);
6bdb68ce
CH
2647 if (rdev->wiphy.sar_capa)
2648 CMD(set_sar_specs, SET_SAR_SPECS);
5de17984 2649 }
3713b4e3 2650#undef CMD
ff1b6e69 2651
3713b4e3 2652 nla_nest_end(msg, nl_cmds);
86e8cf98
JB
2653 state->split_start++;
2654 if (state->split)
3713b4e3 2655 break;
7b506ff6 2656 fallthrough;
3713b4e3 2657 case 5:
1b8ec87a
ZG
2658 if (rdev->ops->remain_on_channel &&
2659 (rdev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL) &&
3713b4e3
JB
2660 nla_put_u32(msg,
2661 NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION,
1b8ec87a 2662 rdev->wiphy.max_remain_on_channel_duration))
3713b4e3
JB
2663 goto nla_put_failure;
2664
1b8ec87a 2665 if ((rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX) &&
3713b4e3
JB
2666 nla_put_flag(msg, NL80211_ATTR_OFFCHANNEL_TX_OK))
2667 goto nla_put_failure;
2668
86e8cf98
JB
2669 state->split_start++;
2670 if (state->split)
3713b4e3 2671 break;
7b506ff6 2672 fallthrough;
3713b4e3
JB
2673 case 6:
2674#ifdef CONFIG_PM
1b8ec87a 2675 if (nl80211_send_wowlan(msg, rdev, state->split))
3713b4e3 2676 goto nla_put_failure;
86e8cf98
JB
2677 state->split_start++;
2678 if (state->split)
3713b4e3
JB
2679 break;
2680#else
86e8cf98 2681 state->split_start++;
dfb89c56 2682#endif
7b506ff6 2683 fallthrough;
3713b4e3
JB
2684 case 7:
2685 if (nl80211_put_iftypes(msg, NL80211_ATTR_SOFTWARE_IFTYPES,
1b8ec87a 2686 rdev->wiphy.software_iftypes))
3713b4e3 2687 goto nla_put_failure;
ff1b6e69 2688
1b8ec87a 2689 if (nl80211_put_iface_combinations(&rdev->wiphy, msg,
86e8cf98 2690 state->split))
3713b4e3 2691 goto nla_put_failure;
7527a782 2692
86e8cf98
JB
2693 state->split_start++;
2694 if (state->split)
3713b4e3 2695 break;
7b506ff6 2696 fallthrough;
3713b4e3 2697 case 8:
1b8ec87a 2698 if ((rdev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME) &&
3713b4e3 2699 nla_put_u32(msg, NL80211_ATTR_DEVICE_AP_SME,
1b8ec87a 2700 rdev->wiphy.ap_sme_capa))
3713b4e3 2701 goto nla_put_failure;
7527a782 2702
1b8ec87a 2703 features = rdev->wiphy.features;
fe1abafd
JB
2704 /*
2705 * We can only add the per-channel limit information if the
2706 * dump is split, otherwise it makes it too big. Therefore
2707 * only advertise it in that case.
2708 */
86e8cf98 2709 if (state->split)
fe1abafd
JB
2710 features |= NL80211_FEATURE_ADVERTISE_CHAN_LIMITS;
2711 if (nla_put_u32(msg, NL80211_ATTR_FEATURE_FLAGS, features))
3713b4e3 2712 goto nla_put_failure;
562a7480 2713
1b8ec87a 2714 if (rdev->wiphy.ht_capa_mod_mask &&
3713b4e3 2715 nla_put(msg, NL80211_ATTR_HT_CAPABILITY_MASK,
1b8ec87a
ZG
2716 sizeof(*rdev->wiphy.ht_capa_mod_mask),
2717 rdev->wiphy.ht_capa_mod_mask))
3713b4e3 2718 goto nla_put_failure;
1f074bd8 2719
1b8ec87a
ZG
2720 if (rdev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME &&
2721 rdev->wiphy.max_acl_mac_addrs &&
3713b4e3 2722 nla_put_u32(msg, NL80211_ATTR_MAC_ACL_MAX,
1b8ec87a 2723 rdev->wiphy.max_acl_mac_addrs))
3713b4e3 2724 goto nla_put_failure;
7e7c8926 2725
3713b4e3
JB
2726 /*
2727 * Any information below this point is only available to
2728 * applications that can deal with it being split. This
2729 * helps ensure that newly added capabilities don't break
2730 * older tools by overrunning their buffers.
2731 *
2732 * We still increment split_start so that in the split
2733 * case we'll continue with more data in the next round,
2734 * but break unconditionally so unsplit data stops here.
2735 */
ab10c22b
JB
2736 if (state->split)
2737 state->split_start++;
2738 else
2739 state->split_start = 0;
3713b4e3
JB
2740 break;
2741 case 9:
f8d504ca
JB
2742 if (nl80211_send_mgmt_stypes(msg, mgmt_stypes))
2743 goto nla_put_failure;
2744
2745 if (nla_put_u32(msg, NL80211_ATTR_MAX_NUM_SCHED_SCAN_PLANS,
2746 rdev->wiphy.max_sched_scan_plans) ||
2747 nla_put_u32(msg, NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL,
2748 rdev->wiphy.max_sched_scan_plan_interval) ||
2749 nla_put_u32(msg, NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS,
2750 rdev->wiphy.max_sched_scan_plan_iterations))
2751 goto nla_put_failure;
2752
1b8ec87a 2753 if (rdev->wiphy.extended_capabilities &&
fe1abafd 2754 (nla_put(msg, NL80211_ATTR_EXT_CAPA,
1b8ec87a
ZG
2755 rdev->wiphy.extended_capabilities_len,
2756 rdev->wiphy.extended_capabilities) ||
fe1abafd 2757 nla_put(msg, NL80211_ATTR_EXT_CAPA_MASK,
1b8ec87a
ZG
2758 rdev->wiphy.extended_capabilities_len,
2759 rdev->wiphy.extended_capabilities_mask)))
fe1abafd 2760 goto nla_put_failure;
a50df0c4 2761
1b8ec87a 2762 if (rdev->wiphy.vht_capa_mod_mask &&
ee2aca34 2763 nla_put(msg, NL80211_ATTR_VHT_CAPABILITY_MASK,
1b8ec87a
ZG
2764 sizeof(*rdev->wiphy.vht_capa_mod_mask),
2765 rdev->wiphy.vht_capa_mod_mask))
ee2aca34
JB
2766 goto nla_put_failure;
2767
ae6fa4d5
DK
2768 if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN,
2769 rdev->wiphy.perm_addr))
2770 goto nla_put_failure;
2771
2772 if (!is_zero_ether_addr(rdev->wiphy.addr_mask) &&
2773 nla_put(msg, NL80211_ATTR_MAC_MASK, ETH_ALEN,
2774 rdev->wiphy.addr_mask))
2775 goto nla_put_failure;
2776
2777 if (rdev->wiphy.n_addresses > 1) {
2778 void *attr;
2779
2780 attr = nla_nest_start(msg, NL80211_ATTR_MAC_ADDRS);
2781 if (!attr)
2782 goto nla_put_failure;
2783
2784 for (i = 0; i < rdev->wiphy.n_addresses; i++)
2785 if (nla_put(msg, i + 1, ETH_ALEN,
2786 rdev->wiphy.addresses[i].addr))
2787 goto nla_put_failure;
2788
2789 nla_nest_end(msg, attr);
2790 }
2791
be29b99a
AK
2792 state->split_start++;
2793 break;
2794 case 10:
1b8ec87a 2795 if (nl80211_send_coalesce(msg, rdev))
be29b99a
AK
2796 goto nla_put_failure;
2797
1b8ec87a 2798 if ((rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_5_10_MHZ) &&
01e0daa4
FF
2799 (nla_put_flag(msg, NL80211_ATTR_SUPPORT_5_MHZ) ||
2800 nla_put_flag(msg, NL80211_ATTR_SUPPORT_10_MHZ)))
2801 goto nla_put_failure;
b43504cf 2802
1b8ec87a 2803 if (rdev->wiphy.max_ap_assoc_sta &&
b43504cf 2804 nla_put_u32(msg, NL80211_ATTR_MAX_AP_ASSOC_STA,
1b8ec87a 2805 rdev->wiphy.max_ap_assoc_sta))
b43504cf
JM
2806 goto nla_put_failure;
2807
ad7e718c
JB
2808 state->split_start++;
2809 break;
2810 case 11:
1b8ec87a 2811 if (rdev->wiphy.n_vendor_commands) {
567ffc35
JB
2812 const struct nl80211_vendor_cmd_info *info;
2813 struct nlattr *nested;
2814
ae0be8de
MK
2815 nested = nla_nest_start_noflag(msg,
2816 NL80211_ATTR_VENDOR_DATA);
567ffc35
JB
2817 if (!nested)
2818 goto nla_put_failure;
2819
1b8ec87a
ZG
2820 for (i = 0; i < rdev->wiphy.n_vendor_commands; i++) {
2821 info = &rdev->wiphy.vendor_commands[i].info;
567ffc35
JB
2822 if (nla_put(msg, i + 1, sizeof(*info), info))
2823 goto nla_put_failure;
2824 }
2825 nla_nest_end(msg, nested);
2826 }
2827
1b8ec87a 2828 if (rdev->wiphy.n_vendor_events) {
567ffc35
JB
2829 const struct nl80211_vendor_cmd_info *info;
2830 struct nlattr *nested;
ad7e718c 2831
ae0be8de
MK
2832 nested = nla_nest_start_noflag(msg,
2833 NL80211_ATTR_VENDOR_EVENTS);
567ffc35 2834 if (!nested)
ad7e718c 2835 goto nla_put_failure;
567ffc35 2836
1b8ec87a
ZG
2837 for (i = 0; i < rdev->wiphy.n_vendor_events; i++) {
2838 info = &rdev->wiphy.vendor_events[i];
567ffc35
JB
2839 if (nla_put(msg, i + 1, sizeof(*info), info))
2840 goto nla_put_failure;
2841 }
2842 nla_nest_end(msg, nested);
2843 }
9a774c78
AO
2844 state->split_start++;
2845 break;
2846 case 12:
2847 if (rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH &&
2848 nla_put_u8(msg, NL80211_ATTR_MAX_CSA_COUNTERS,
2849 rdev->wiphy.max_num_csa_counters))
2850 goto nla_put_failure;
01e0daa4 2851
1bdd716c
AN
2852 if (rdev->wiphy.regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED &&
2853 nla_put_flag(msg, NL80211_ATTR_WIPHY_SELF_MANAGED_REG))
2854 goto nla_put_failure;
2855
ca986ad9
AVS
2856 if (rdev->wiphy.max_sched_scan_reqs &&
2857 nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_MAX_REQS,
2858 rdev->wiphy.max_sched_scan_reqs))
2859 goto nla_put_failure;
2860
d75bb06b
GKS
2861 if (nla_put(msg, NL80211_ATTR_EXT_FEATURES,
2862 sizeof(rdev->wiphy.ext_features),
2863 rdev->wiphy.ext_features))
2864 goto nla_put_failure;
2865
38de03d2
AS
2866 if (rdev->wiphy.bss_select_support) {
2867 struct nlattr *nested;
2868 u32 bss_select_support = rdev->wiphy.bss_select_support;
2869
ae0be8de
MK
2870 nested = nla_nest_start_noflag(msg,
2871 NL80211_ATTR_BSS_SELECT);
38de03d2
AS
2872 if (!nested)
2873 goto nla_put_failure;
2874
2875 i = 0;
2876 while (bss_select_support) {
2877 if ((bss_select_support & 1) &&
2878 nla_put_flag(msg, i))
2879 goto nla_put_failure;
2880 i++;
2881 bss_select_support >>= 1;
2882 }
2883 nla_nest_end(msg, nested);
2884 }
2885
019ae3a9
KV
2886 state->split_start++;
2887 break;
2888 case 13:
2889 if (rdev->wiphy.num_iftype_ext_capab &&
2890 rdev->wiphy.iftype_ext_capab) {
2891 struct nlattr *nested_ext_capab, *nested;
2892
ae0be8de
MK
2893 nested = nla_nest_start_noflag(msg,
2894 NL80211_ATTR_IFTYPE_EXT_CAPA);
019ae3a9
KV
2895 if (!nested)
2896 goto nla_put_failure;
2897
2898 for (i = state->capa_start;
2899 i < rdev->wiphy.num_iftype_ext_capab; i++) {
2900 const struct wiphy_iftype_ext_capab *capab;
2901
2902 capab = &rdev->wiphy.iftype_ext_capab[i];
2903
ae0be8de
MK
2904 nested_ext_capab = nla_nest_start_noflag(msg,
2905 i);
019ae3a9
KV
2906 if (!nested_ext_capab ||
2907 nla_put_u32(msg, NL80211_ATTR_IFTYPE,
2908 capab->iftype) ||
2909 nla_put(msg, NL80211_ATTR_EXT_CAPA,
2910 capab->extended_capabilities_len,
2911 capab->extended_capabilities) ||
2912 nla_put(msg, NL80211_ATTR_EXT_CAPA_MASK,
2913 capab->extended_capabilities_len,
2914 capab->extended_capabilities_mask))
2915 goto nla_put_failure;
2916
4e9c3af3
JB
2917 if (rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_MLO &&
2918 (nla_put_u16(msg,
2919 NL80211_ATTR_EML_CAPABILITY,
2920 capab->eml_capabilities) ||
2921 nla_put_u16(msg,
2922 NL80211_ATTR_MLD_CAPA_AND_OPS,
2923 capab->mld_capa_and_ops)))
2924 goto nla_put_failure;
2925
019ae3a9
KV
2926 nla_nest_end(msg, nested_ext_capab);
2927 if (state->split)
2928 break;
2929 }
2930 nla_nest_end(msg, nested);
2931 if (i < rdev->wiphy.num_iftype_ext_capab) {
2932 state->capa_start = i + 1;
2933 break;
2934 }
2935 }
2936
8585989d
LC
2937 if (nla_put_u32(msg, NL80211_ATTR_BANDS,
2938 rdev->wiphy.nan_supported_bands))
2939 goto nla_put_failure;
2940
52539ca8
THJ
2941 if (wiphy_ext_feature_isset(&rdev->wiphy,
2942 NL80211_EXT_FEATURE_TXQS)) {
2943 struct cfg80211_txq_stats txqstats = {};
2944 int res;
2945
2946 res = rdev_get_txq_stats(rdev, NULL, &txqstats);
2947 if (!res &&
2948 !nl80211_put_txq_stats(msg, &txqstats,
2949 NL80211_ATTR_TXQ_STATS))
2950 goto nla_put_failure;
2951
2952 if (nla_put_u32(msg, NL80211_ATTR_TXQ_LIMIT,
2953 rdev->wiphy.txq_limit))
2954 goto nla_put_failure;
2955 if (nla_put_u32(msg, NL80211_ATTR_TXQ_MEMORY_LIMIT,
2956 rdev->wiphy.txq_memory_limit))
2957 goto nla_put_failure;
2958 if (nla_put_u32(msg, NL80211_ATTR_TXQ_QUANTUM,
2959 rdev->wiphy.txq_quantum))
2960 goto nla_put_failure;
2961 }
2962
9bb7e0f2
JB
2963 state->split_start++;
2964 break;
2965 case 14:
2966 if (nl80211_send_pmsr_capa(rdev, msg))
2967 goto nla_put_failure;
2968
ab4dfa20
VJ
2969 state->split_start++;
2970 break;
2971 case 15:
2972 if (rdev->wiphy.akm_suites &&
2973 nla_put(msg, NL80211_ATTR_AKM_SUITES,
2974 sizeof(u32) * rdev->wiphy.n_akm_suites,
2975 rdev->wiphy.akm_suites))
2976 goto nla_put_failure;
2977
d6039a34
VJ
2978 if (nl80211_put_iftype_akm_suites(rdev, msg))
2979 goto nla_put_failure;
2980
3710a8a6
JB
2981 if (nl80211_put_tid_config_support(rdev, msg))
2982 goto nla_put_failure;
6bdb68ce
CH
2983 state->split_start++;
2984 break;
2985 case 16:
2986 if (nl80211_put_sar_specs(rdev, msg))
2987 goto nla_put_failure;
3710a8a6 2988
dc1e3cb8
JC
2989 if (nl80211_put_mbssid_support(&rdev->wiphy, msg))
2990 goto nla_put_failure;
2991
ecad3b0b
VJ
2992 if (nla_put_u16(msg, NL80211_ATTR_MAX_NUM_AKM_SUITES,
2993 rdev->wiphy.max_num_akm_suites))
2994 goto nla_put_failure;
2995
fa2ca639
JB
2996 if (rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_MLO)
2997 nla_put_flag(msg, NL80211_ATTR_MLO_SUPPORT);
2998
cbbaf2bb
AS
2999 if (rdev->wiphy.hw_timestamp_max_peers &&
3000 nla_put_u16(msg, NL80211_ATTR_MAX_HW_TIMESTAMP_PEERS,
3001 rdev->wiphy.hw_timestamp_max_peers))
3002 goto nla_put_failure;
3003
3713b4e3 3004 /* done */
86e8cf98 3005 state->split_start = 0;
3713b4e3
JB
3006 break;
3007 }
3bb20556 3008 finish:
053c095a
JB
3009 genlmsg_end(msg, hdr);
3010 return 0;
55682965
JB
3011
3012 nla_put_failure:
bc3ed28c
TG
3013 genlmsg_cancel(msg, hdr);
3014 return -EMSGSIZE;
55682965
JB
3015}
3016
86e8cf98
JB
3017static int nl80211_dump_wiphy_parse(struct sk_buff *skb,
3018 struct netlink_callback *cb,
3019 struct nl80211_dump_wiphy_state *state)
3020{
50508d94
JB
3021 struct nlattr **tb = kcalloc(NUM_NL80211_ATTR, sizeof(*tb), GFP_KERNEL);
3022 int ret;
3023
3024 if (!tb)
3025 return -ENOMEM;
3026
3027 ret = nlmsg_parse_deprecated(cb->nlh,
3028 GENL_HDRLEN + nl80211_fam.hdrsize,
3029 tb, nl80211_fam.maxattr,
3030 nl80211_policy, NULL);
86e8cf98 3031 /* ignore parse errors for backward compatibility */
50508d94
JB
3032 if (ret) {
3033 ret = 0;
3034 goto out;
3035 }
86e8cf98
JB
3036
3037 state->split = tb[NL80211_ATTR_SPLIT_WIPHY_DUMP];
3038 if (tb[NL80211_ATTR_WIPHY])
3039 state->filter_wiphy = nla_get_u32(tb[NL80211_ATTR_WIPHY]);
3040 if (tb[NL80211_ATTR_WDEV])
3041 state->filter_wiphy = nla_get_u64(tb[NL80211_ATTR_WDEV]) >> 32;
3042 if (tb[NL80211_ATTR_IFINDEX]) {
3043 struct net_device *netdev;
3044 struct cfg80211_registered_device *rdev;
3045 int ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
3046
7f2b8562 3047 netdev = __dev_get_by_index(sock_net(skb->sk), ifidx);
50508d94
JB
3048 if (!netdev) {
3049 ret = -ENODEV;
3050 goto out;
3051 }
86e8cf98 3052 if (netdev->ieee80211_ptr) {
f26cbf40 3053 rdev = wiphy_to_rdev(
86e8cf98
JB
3054 netdev->ieee80211_ptr->wiphy);
3055 state->filter_wiphy = rdev->wiphy_idx;
3056 }
86e8cf98
JB
3057 }
3058
50508d94
JB
3059 ret = 0;
3060out:
3061 kfree(tb);
3062 return ret;
86e8cf98
JB
3063}
3064
55682965
JB
3065static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
3066{
645e77de 3067 int idx = 0, ret;
86e8cf98 3068 struct nl80211_dump_wiphy_state *state = (void *)cb->args[0];
1b8ec87a 3069 struct cfg80211_registered_device *rdev;
3a5a423b 3070
5fe231e8 3071 rtnl_lock();
86e8cf98
JB
3072 if (!state) {
3073 state = kzalloc(sizeof(*state), GFP_KERNEL);
57ed5cd6
JL
3074 if (!state) {
3075 rtnl_unlock();
86e8cf98 3076 return -ENOMEM;
3713b4e3 3077 }
86e8cf98
JB
3078 state->filter_wiphy = -1;
3079 ret = nl80211_dump_wiphy_parse(skb, cb, state);
3080 if (ret) {
3081 kfree(state);
3082 rtnl_unlock();
3083 return ret;
3713b4e3 3084 }
86e8cf98 3085 cb->args[0] = (long)state;
3713b4e3
JB
3086 }
3087
7483a214 3088 for_each_rdev(rdev) {
1b8ec87a 3089 if (!net_eq(wiphy_net(&rdev->wiphy), sock_net(skb->sk)))
463d0183 3090 continue;
86e8cf98 3091 if (++idx <= state->start)
55682965 3092 continue;
86e8cf98 3093 if (state->filter_wiphy != -1 &&
1b8ec87a 3094 state->filter_wiphy != rdev->wiphy_idx)
3713b4e3 3095 continue;
4d45145b 3096 wiphy_lock(&rdev->wiphy);
3713b4e3
JB
3097 /* attempt to fit multiple wiphy data chunks into the skb */
3098 do {
3bb20556
JB
3099 ret = nl80211_send_wiphy(rdev, NL80211_CMD_NEW_WIPHY,
3100 skb,
3713b4e3
JB
3101 NETLINK_CB(cb->skb).portid,
3102 cb->nlh->nlmsg_seq,
86e8cf98 3103 NLM_F_MULTI, state);
3713b4e3
JB
3104 if (ret < 0) {
3105 /*
3106 * If sending the wiphy data didn't fit (ENOBUFS
3107 * or EMSGSIZE returned), this SKB is still
3108 * empty (so it's not too big because another
3109 * wiphy dataset is already in the skb) and
3110 * we've not tried to adjust the dump allocation
3111 * yet ... then adjust the alloc size to be
3112 * bigger, and return 1 but with the empty skb.
3113 * This results in an empty message being RX'ed
3114 * in userspace, but that is ignored.
3115 *
3116 * We can then retry with the larger buffer.
3117 */
3118 if ((ret == -ENOBUFS || ret == -EMSGSIZE) &&
f12cb289 3119 !skb->len && !state->split &&
3713b4e3
JB
3120 cb->min_dump_alloc < 4096) {
3121 cb->min_dump_alloc = 4096;
f12cb289 3122 state->split_start = 0;
4d45145b 3123 wiphy_unlock(&rdev->wiphy);
d98cae64 3124 rtnl_unlock();
3713b4e3
JB
3125 return 1;
3126 }
3127 idx--;
3128 break;
645e77de 3129 }
86e8cf98 3130 } while (state->split_start > 0);
4d45145b 3131 wiphy_unlock(&rdev->wiphy);
3713b4e3 3132 break;
55682965 3133 }
5fe231e8 3134 rtnl_unlock();
55682965 3135
86e8cf98 3136 state->start = idx;
55682965
JB
3137
3138 return skb->len;
3139}
3140
86e8cf98
JB
3141static int nl80211_dump_wiphy_done(struct netlink_callback *cb)
3142{
3143 kfree((void *)cb->args[0]);
3144 return 0;
3145}
3146
55682965
JB
3147static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info)
3148{
3149 struct sk_buff *msg;
1b8ec87a 3150 struct cfg80211_registered_device *rdev = info->user_ptr[0];
86e8cf98 3151 struct nl80211_dump_wiphy_state state = {};
55682965 3152
645e77de 3153 msg = nlmsg_new(4096, GFP_KERNEL);
55682965 3154 if (!msg)
4c476991 3155 return -ENOMEM;
55682965 3156
3bb20556
JB
3157 if (nl80211_send_wiphy(rdev, NL80211_CMD_NEW_WIPHY, msg,
3158 info->snd_portid, info->snd_seq, 0,
86e8cf98 3159 &state) < 0) {
4c476991
JB
3160 nlmsg_free(msg);
3161 return -ENOBUFS;
3162 }
55682965 3163
134e6375 3164 return genlmsg_reply(msg, info);
55682965
JB
3165}
3166
31888487
JM
3167static const struct nla_policy txq_params_policy[NL80211_TXQ_ATTR_MAX + 1] = {
3168 [NL80211_TXQ_ATTR_QUEUE] = { .type = NLA_U8 },
3169 [NL80211_TXQ_ATTR_TXOP] = { .type = NLA_U16 },
3170 [NL80211_TXQ_ATTR_CWMIN] = { .type = NLA_U16 },
3171 [NL80211_TXQ_ATTR_CWMAX] = { .type = NLA_U16 },
3172 [NL80211_TXQ_ATTR_AIFS] = { .type = NLA_U8 },
3173};
3174
3175static int parse_txq_params(struct nlattr *tb[],
3176 struct ieee80211_txq_params *txq_params)
3177{
259d8c1e
DW
3178 u8 ac;
3179
a3304b0a 3180 if (!tb[NL80211_TXQ_ATTR_AC] || !tb[NL80211_TXQ_ATTR_TXOP] ||
31888487
JM
3181 !tb[NL80211_TXQ_ATTR_CWMIN] || !tb[NL80211_TXQ_ATTR_CWMAX] ||
3182 !tb[NL80211_TXQ_ATTR_AIFS])
3183 return -EINVAL;
3184
259d8c1e 3185 ac = nla_get_u8(tb[NL80211_TXQ_ATTR_AC]);
31888487
JM
3186 txq_params->txop = nla_get_u16(tb[NL80211_TXQ_ATTR_TXOP]);
3187 txq_params->cwmin = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMIN]);
3188 txq_params->cwmax = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMAX]);
3189 txq_params->aifs = nla_get_u8(tb[NL80211_TXQ_ATTR_AIFS]);
3190
259d8c1e 3191 if (ac >= NL80211_NUM_ACS)
a3304b0a 3192 return -EINVAL;
259d8c1e 3193 txq_params->ac = array_index_nospec(ac, NL80211_NUM_ACS);
31888487
JM
3194 return 0;
3195}
3196
f444de05
JB
3197static bool nl80211_can_set_dev_channel(struct wireless_dev *wdev)
3198{
3199 /*
e7e0517c
JB
3200 * You can only set the channel explicitly for some interfaces,
3201 * most have their channel managed via their respective
cc1d2806
JB
3202 * "establish a connection" command (connect, join, ...)
3203 *
3204 * For AP/GO and mesh mode, the channel can be set with the
3205 * channel userspace API, but is only stored and passed to the
3206 * low-level driver when the AP starts or the mesh is joined.
3207 * This is for backward compatibility, userspace can also give
3208 * the channel in the start-ap or join-mesh commands instead.
f444de05
JB
3209 *
3210 * Monitors are special as they are normally slaved to
e8c9bd5b
JB
3211 * whatever else is going on, so they have their own special
3212 * operation to set the monitor channel if possible.
f444de05
JB
3213 */
3214 return !wdev ||
3215 wdev->iftype == NL80211_IFTYPE_AP ||
f444de05 3216 wdev->iftype == NL80211_IFTYPE_MESH_POINT ||
074ac8df
JB
3217 wdev->iftype == NL80211_IFTYPE_MONITOR ||
3218 wdev->iftype == NL80211_IFTYPE_P2P_GO;
f444de05
JB
3219}
3220
a110a3b7
JB
3221static int _nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
3222 struct genl_info *info, bool monitor,
3223 struct cfg80211_chan_def *chandef)
683b6d3b 3224{
49f9cf0e
JB
3225 struct netlink_ext_ack *extack = info->extack;
3226 struct nlattr **attrs = info->attrs;
dbeca2ea 3227 u32 control_freq;
683b6d3b 3228
90b2c3cc
JK
3229 if (!attrs[NL80211_ATTR_WIPHY_FREQ]) {
3230 NL_SET_ERR_MSG_ATTR(extack, attrs[NL80211_ATTR_WIPHY_FREQ],
3231 "Frequency is missing");
683b6d3b 3232 return -EINVAL;
90b2c3cc 3233 }
683b6d3b 3234
942ba88b
TP
3235 control_freq = MHZ_TO_KHZ(
3236 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
3237 if (info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET])
3238 control_freq +=
3239 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET]);
683b6d3b 3240
f43e5210 3241 memset(chandef, 0, sizeof(*chandef));
942ba88b 3242 chandef->chan = ieee80211_get_channel_khz(&rdev->wiphy, control_freq);
3d9d1d66 3243 chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
942ba88b
TP
3244 chandef->center_freq1 = KHZ_TO_MHZ(control_freq);
3245 chandef->freq1_offset = control_freq % 1000;
3d9d1d66 3246 chandef->center_freq2 = 0;
683b6d3b 3247
a110a3b7 3248 if (!chandef->chan) {
49f9cf0e 3249 NL_SET_ERR_MSG_ATTR(extack, attrs[NL80211_ATTR_WIPHY_FREQ],
a110a3b7 3250 "Unknown channel");
683b6d3b 3251 return -EINVAL;
49f9cf0e 3252 }
683b6d3b 3253
49f9cf0e 3254 if (attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
3d9d1d66
JB
3255 enum nl80211_channel_type chantype;
3256
49f9cf0e 3257 chantype = nla_get_u32(attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
3d9d1d66
JB
3258
3259 switch (chantype) {
3260 case NL80211_CHAN_NO_HT:
3261 case NL80211_CHAN_HT20:
3262 case NL80211_CHAN_HT40PLUS:
3263 case NL80211_CHAN_HT40MINUS:
3264 cfg80211_chandef_create(chandef, chandef->chan,
3265 chantype);
ffa4629e 3266 /* user input for center_freq is incorrect */
49f9cf0e
JB
3267 if (attrs[NL80211_ATTR_CENTER_FREQ1] &&
3268 chandef->center_freq1 != nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ1])) {
3269 NL_SET_ERR_MSG_ATTR(extack,
3270 attrs[NL80211_ATTR_CENTER_FREQ1],
3271 "bad center frequency 1");
ffa4629e 3272 return -EINVAL;
49f9cf0e 3273 }
ffa4629e 3274 /* center_freq2 must be zero */
49f9cf0e
JB
3275 if (attrs[NL80211_ATTR_CENTER_FREQ2] &&
3276 nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ2])) {
3277 NL_SET_ERR_MSG_ATTR(extack,
3278 attrs[NL80211_ATTR_CENTER_FREQ2],
3279 "center frequency 2 can't be used");
ffa4629e 3280 return -EINVAL;
49f9cf0e 3281 }
3d9d1d66
JB
3282 break;
3283 default:
49f9cf0e
JB
3284 NL_SET_ERR_MSG_ATTR(extack,
3285 attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE],
3286 "invalid channel type");
3d9d1d66
JB
3287 return -EINVAL;
3288 }
49f9cf0e 3289 } else if (attrs[NL80211_ATTR_CHANNEL_WIDTH]) {
3d9d1d66 3290 chandef->width =
49f9cf0e 3291 nla_get_u32(attrs[NL80211_ATTR_CHANNEL_WIDTH]);
5d087aa7
KF
3292 if (chandef->chan->band == NL80211_BAND_S1GHZ) {
3293 /* User input error for channel width doesn't match channel */
3294 if (chandef->width != ieee80211_s1g_channel_width(chandef->chan)) {
3295 NL_SET_ERR_MSG_ATTR(extack,
3296 attrs[NL80211_ATTR_CHANNEL_WIDTH],
3297 "bad channel width");
3298 return -EINVAL;
3299 }
3300 }
942ba88b 3301 if (attrs[NL80211_ATTR_CENTER_FREQ1]) {
3d9d1d66 3302 chandef->center_freq1 =
49f9cf0e 3303 nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ1]);
942ba88b
TP
3304 if (attrs[NL80211_ATTR_CENTER_FREQ1_OFFSET])
3305 chandef->freq1_offset = nla_get_u32(
3306 attrs[NL80211_ATTR_CENTER_FREQ1_OFFSET]);
3307 else
3308 chandef->freq1_offset = 0;
3309 }
49f9cf0e 3310 if (attrs[NL80211_ATTR_CENTER_FREQ2])
3d9d1d66 3311 chandef->center_freq2 =
49f9cf0e 3312 nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ2]);
3d9d1d66
JB
3313 }
3314
2a38075c
AAL
3315 if (info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]) {
3316 chandef->edmg.channels =
3317 nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]);
3318
3319 if (info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG])
3320 chandef->edmg.bw_config =
3321 nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG]);
3322 } else {
3323 chandef->edmg.bw_config = 0;
3324 chandef->edmg.channels = 0;
3325 }
3326
b82730bf
JB
3327 if (info->attrs[NL80211_ATTR_PUNCT_BITMAP]) {
3328 chandef->punctured =
3329 nla_get_u32(info->attrs[NL80211_ATTR_PUNCT_BITMAP]);
3330
3331 if (chandef->punctured &&
3332 !wiphy_ext_feature_isset(&rdev->wiphy,
3333 NL80211_EXT_FEATURE_PUNCT)) {
3334 NL_SET_ERR_MSG(extack,
3335 "driver doesn't support puncturing");
3336 return -EINVAL;
3337 }
3338 }
3339
49f9cf0e
JB
3340 if (!cfg80211_chandef_valid(chandef)) {
3341 NL_SET_ERR_MSG(extack, "invalid channel definition");
3d9d1d66 3342 return -EINVAL;
49f9cf0e 3343 }
3d9d1d66 3344
a110a3b7
JB
3345 if (!_cfg80211_chandef_usable(&rdev->wiphy, chandef,
3346 IEEE80211_CHAN_DISABLED,
3347 monitor)) {
49f9cf0e 3348 NL_SET_ERR_MSG(extack, "(extension) channel is disabled");
3d9d1d66 3349 return -EINVAL;
49f9cf0e 3350 }
3d9d1d66 3351
2f301ab2
SW
3352 if ((chandef->width == NL80211_CHAN_WIDTH_5 ||
3353 chandef->width == NL80211_CHAN_WIDTH_10) &&
49f9cf0e
JB
3354 !(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_5_10_MHZ)) {
3355 NL_SET_ERR_MSG(extack, "5/10 MHz not supported");
2f301ab2 3356 return -EINVAL;
49f9cf0e 3357 }
2f301ab2 3358
683b6d3b
JB
3359 return 0;
3360}
3361
a110a3b7
JB
3362int nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
3363 struct genl_info *info,
3364 struct cfg80211_chan_def *chandef)
3365{
3366 return _nl80211_parse_chandef(rdev, info, false, chandef);
3367}
3368
f444de05 3369static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
e16821bc 3370 struct net_device *dev,
7b0a0e3c
JB
3371 struct genl_info *info,
3372 int _link_id)
f444de05 3373{
683b6d3b 3374 struct cfg80211_chan_def chandef;
f444de05 3375 int result;
e8c9bd5b 3376 enum nl80211_iftype iftype = NL80211_IFTYPE_MONITOR;
e16821bc 3377 struct wireless_dev *wdev = NULL;
7b0a0e3c 3378 int link_id = _link_id;
e8c9bd5b 3379
e16821bc
JM
3380 if (dev)
3381 wdev = dev->ieee80211_ptr;
f444de05
JB
3382 if (!nl80211_can_set_dev_channel(wdev))
3383 return -EOPNOTSUPP;
e16821bc
JM
3384 if (wdev)
3385 iftype = wdev->iftype;
f444de05 3386
7b0a0e3c
JB
3387 if (link_id < 0) {
3388 if (wdev && wdev->valid_links)
3389 return -EINVAL;
3390 link_id = 0;
3391 }
3392
a110a3b7
JB
3393 result = _nl80211_parse_chandef(rdev, info,
3394 iftype == NL80211_IFTYPE_MONITOR,
3395 &chandef);
683b6d3b
JB
3396 if (result)
3397 return result;
f444de05 3398
e8c9bd5b 3399 switch (iftype) {
aa430da4
JB
3400 case NL80211_IFTYPE_AP:
3401 case NL80211_IFTYPE_P2P_GO:
923b352f 3402 if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &chandef,
7b0a0e3c
JB
3403 iftype))
3404 return -EINVAL;
3405 if (wdev->links[link_id].ap.beacon_interval) {
3406 struct ieee80211_channel *cur_chan;
3407
e16821bc
JM
3408 if (!dev || !rdev->ops->set_ap_chanwidth ||
3409 !(rdev->wiphy.features &
7b0a0e3c
JB
3410 NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE))
3411 return -EBUSY;
e16821bc
JM
3412
3413 /* Only allow dynamic channel width changes */
7b0a0e3c
JB
3414 cur_chan = wdev->links[link_id].ap.chandef.chan;
3415 if (chandef.chan != cur_chan)
3416 return -EBUSY;
3417
3418 result = rdev_set_ap_chanwidth(rdev, dev, link_id,
3419 &chandef);
e16821bc 3420 if (result)
7b0a0e3c
JB
3421 return result;
3422 wdev->links[link_id].ap.chandef = chandef;
3423 } else {
3424 wdev->u.ap.preset_chandef = chandef;
e16821bc 3425 }
7b0a0e3c 3426 return 0;
cc1d2806 3427 case NL80211_IFTYPE_MESH_POINT:
7b0a0e3c 3428 return cfg80211_set_mesh_channel(rdev, wdev, &chandef);
e8c9bd5b 3429 case NL80211_IFTYPE_MONITOR:
7b0a0e3c 3430 return cfg80211_set_monitor_channel(rdev, &chandef);
aa430da4 3431 default:
7b0a0e3c 3432 break;
f444de05 3433 }
f444de05 3434
7b0a0e3c 3435 return -EINVAL;
f444de05
JB
3436}
3437
3438static int nl80211_set_channel(struct sk_buff *skb, struct genl_info *info)
3439{
4c476991 3440 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7b0a0e3c 3441 int link_id = nl80211_link_id_or_invalid(info->attrs);
4c476991 3442 struct net_device *netdev = info->user_ptr[1];
f444de05 3443
076fc877 3444 return __nl80211_set_channel(rdev, netdev, info, link_id);
f444de05
JB
3445}
3446
55682965
JB
3447static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
3448{
a05829a7 3449 struct cfg80211_registered_device *rdev = NULL;
f444de05
JB
3450 struct net_device *netdev = NULL;
3451 struct wireless_dev *wdev;
a1e567c8 3452 int result = 0, rem_txq_params = 0;
31888487 3453 struct nlattr *nl_txq_params;
b9a5f8ca
JM
3454 u32 changed;
3455 u8 retry_short = 0, retry_long = 0;
3456 u32 frag_threshold = 0, rts_threshold = 0;
81077e82 3457 u8 coverage_class = 0;
52539ca8 3458 u32 txq_limit = 0, txq_memory_limit = 0, txq_quantum = 0;
55682965 3459
a05829a7 3460 rtnl_lock();
f444de05
JB
3461 /*
3462 * Try to find the wiphy and netdev. Normally this
3463 * function shouldn't need the netdev, but this is
3464 * done for backward compatibility -- previously
3465 * setting the channel was done per wiphy, but now
3466 * it is per netdev. Previous userland like hostapd
3467 * also passed a netdev to set_wiphy, so that it is
3468 * possible to let that go to the right netdev!
3469 */
4bbf4d56 3470
f444de05
JB
3471 if (info->attrs[NL80211_ATTR_IFINDEX]) {
3472 int ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]);
3473
7f2b8562 3474 netdev = __dev_get_by_index(genl_info_net(info), ifindex);
5fe231e8 3475 if (netdev && netdev->ieee80211_ptr)
f26cbf40 3476 rdev = wiphy_to_rdev(netdev->ieee80211_ptr->wiphy);
5fe231e8 3477 else
f444de05 3478 netdev = NULL;
4bbf4d56
JB
3479 }
3480
f444de05 3481 if (!netdev) {
878d9ec7
JB
3482 rdev = __cfg80211_rdev_from_attrs(genl_info_net(info),
3483 info->attrs);
a05829a7
JB
3484 if (IS_ERR(rdev)) {
3485 rtnl_unlock();
4c476991 3486 return PTR_ERR(rdev);
a05829a7 3487 }
f444de05
JB
3488 wdev = NULL;
3489 netdev = NULL;
3490 result = 0;
71fe96bf 3491 } else
f444de05 3492 wdev = netdev->ieee80211_ptr;
f444de05 3493
a05829a7 3494 wiphy_lock(&rdev->wiphy);
a05829a7 3495
f444de05
JB
3496 /*
3497 * end workaround code, by now the rdev is available
3498 * and locked, and wdev may or may not be NULL.
3499 */
4bbf4d56
JB
3500
3501 if (info->attrs[NL80211_ATTR_WIPHY_NAME])
31888487
JM
3502 result = cfg80211_dev_rename(
3503 rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME]));
0391a45c 3504 rtnl_unlock();
4bbf4d56 3505
4bbf4d56 3506 if (result)
a05829a7 3507 goto out;
31888487
JM
3508
3509 if (info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS]) {
3510 struct ieee80211_txq_params txq_params;
3511 struct nlattr *tb[NL80211_TXQ_ATTR_MAX + 1];
3512
a05829a7
JB
3513 if (!rdev->ops->set_txq_params) {
3514 result = -EOPNOTSUPP;
3515 goto out;
3516 }
31888487 3517
a05829a7
JB
3518 if (!netdev) {
3519 result = -EINVAL;
3520 goto out;
3521 }
f70f01c2 3522
133a3ff2 3523 if (netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
a05829a7
JB
3524 netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
3525 result = -EINVAL;
3526 goto out;
3527 }
133a3ff2 3528
a05829a7
JB
3529 if (!netif_running(netdev)) {
3530 result = -ENETDOWN;
3531 goto out;
3532 }
2b5f8b0b 3533
31888487
JM
3534 nla_for_each_nested(nl_txq_params,
3535 info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS],
3536 rem_txq_params) {
8cb08174
JB
3537 result = nla_parse_nested_deprecated(tb,
3538 NL80211_TXQ_ATTR_MAX,
3539 nl_txq_params,
3540 txq_params_policy,
3541 info->extack);
ae811e21 3542 if (result)
a05829a7 3543 goto out;
31888487
JM
3544 result = parse_txq_params(tb, &txq_params);
3545 if (result)
a05829a7 3546 goto out;
31888487 3547
9d2bb84d
ST
3548 txq_params.link_id =
3549 nl80211_link_id_or_invalid(info->attrs);
3550
9d2bb84d
ST
3551 if (txq_params.link_id >= 0 &&
3552 !(netdev->ieee80211_ptr->valid_links &
3553 BIT(txq_params.link_id)))
3554 result = -ENOLINK;
3555 else if (txq_params.link_id >= 0 &&
3556 !netdev->ieee80211_ptr->valid_links)
3557 result = -EINVAL;
3558 else
3559 result = rdev_set_txq_params(rdev, netdev,
3560 &txq_params);
31888487 3561 if (result)
a05829a7 3562 goto out;
31888487
JM
3563 }
3564 }
55682965 3565
72bdcf34 3566 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
69c3f2d3
IP
3567 int link_id = nl80211_link_id_or_invalid(info->attrs);
3568
4e2f3d67 3569 if (wdev) {
4e2f3d67
JB
3570 result = __nl80211_set_channel(
3571 rdev,
3572 nl80211_can_set_dev_channel(wdev) ? netdev : NULL,
69c3f2d3 3573 info, link_id);
4e2f3d67 3574 } else {
69c3f2d3 3575 result = __nl80211_set_channel(rdev, netdev, info, link_id);
4e2f3d67 3576 }
69c3f2d3 3577
72bdcf34 3578 if (result)
a05829a7 3579 goto out;
72bdcf34
JM
3580 }
3581
98d2ff8b 3582 if (info->attrs[NL80211_ATTR_WIPHY_TX_POWER_SETTING]) {
c8442118 3583 struct wireless_dev *txp_wdev = wdev;
98d2ff8b
JO
3584 enum nl80211_tx_power_setting type;
3585 int idx, mbm = 0;
3586
c8442118
JB
3587 if (!(rdev->wiphy.features & NL80211_FEATURE_VIF_TXPOWER))
3588 txp_wdev = NULL;
3589
a05829a7
JB
3590 if (!rdev->ops->set_tx_power) {
3591 result = -EOPNOTSUPP;
3592 goto out;
3593 }
98d2ff8b
JO
3594
3595 idx = NL80211_ATTR_WIPHY_TX_POWER_SETTING;
3596 type = nla_get_u32(info->attrs[idx]);
3597
3598 if (!info->attrs[NL80211_ATTR_WIPHY_TX_POWER_LEVEL] &&
a05829a7
JB
3599 (type != NL80211_TX_POWER_AUTOMATIC)) {
3600 result = -EINVAL;
3601 goto out;
3602 }
98d2ff8b
JO
3603
3604 if (type != NL80211_TX_POWER_AUTOMATIC) {
3605 idx = NL80211_ATTR_WIPHY_TX_POWER_LEVEL;
3606 mbm = nla_get_u32(info->attrs[idx]);
3607 }
3608
c8442118 3609 result = rdev_set_tx_power(rdev, txp_wdev, type, mbm);
98d2ff8b 3610 if (result)
a05829a7 3611 goto out;
98d2ff8b
JO
3612 }
3613
afe0cbf8
BR
3614 if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX] &&
3615 info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]) {
3616 u32 tx_ant, rx_ant;
7a087e74 3617
7f531e03
BR
3618 if ((!rdev->wiphy.available_antennas_tx &&
3619 !rdev->wiphy.available_antennas_rx) ||
a05829a7
JB
3620 !rdev->ops->set_antenna) {
3621 result = -EOPNOTSUPP;
3622 goto out;
3623 }
afe0cbf8
BR
3624
3625 tx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX]);
3626 rx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]);
3627
a7ffac95 3628 /* reject antenna configurations which don't match the
7f531e03
BR
3629 * available antenna masks, except for the "all" mask */
3630 if ((~tx_ant && (tx_ant & ~rdev->wiphy.available_antennas_tx)) ||
a05829a7
JB
3631 (~rx_ant && (rx_ant & ~rdev->wiphy.available_antennas_rx))) {
3632 result = -EINVAL;
3633 goto out;
3634 }
a7ffac95 3635
7f531e03
BR
3636 tx_ant = tx_ant & rdev->wiphy.available_antennas_tx;
3637 rx_ant = rx_ant & rdev->wiphy.available_antennas_rx;
a7ffac95 3638
e35e4d28 3639 result = rdev_set_antenna(rdev, tx_ant, rx_ant);
afe0cbf8 3640 if (result)
a05829a7 3641 goto out;
afe0cbf8
BR
3642 }
3643
b9a5f8ca
JM
3644 changed = 0;
3645
3646 if (info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]) {
3647 retry_short = nla_get_u8(
3648 info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]);
7f2b8562 3649
b9a5f8ca
JM
3650 changed |= WIPHY_PARAM_RETRY_SHORT;
3651 }
3652
3653 if (info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]) {
3654 retry_long = nla_get_u8(
3655 info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]);
7f2b8562 3656
b9a5f8ca
JM
3657 changed |= WIPHY_PARAM_RETRY_LONG;
3658 }
3659
3660 if (info->attrs[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]) {
3661 frag_threshold = nla_get_u32(
3662 info->attrs[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]);
a05829a7
JB
3663 if (frag_threshold < 256) {
3664 result = -EINVAL;
3665 goto out;
3666 }
7f2b8562 3667
b9a5f8ca
JM
3668 if (frag_threshold != (u32) -1) {
3669 /*
3670 * Fragments (apart from the last one) are required to
3671 * have even length. Make the fragmentation code
3672 * simpler by stripping LSB should someone try to use
3673 * odd threshold value.
3674 */
3675 frag_threshold &= ~0x1;
3676 }
3677 changed |= WIPHY_PARAM_FRAG_THRESHOLD;
3678 }
3679
3680 if (info->attrs[NL80211_ATTR_WIPHY_RTS_THRESHOLD]) {
3681 rts_threshold = nla_get_u32(
3682 info->attrs[NL80211_ATTR_WIPHY_RTS_THRESHOLD]);
3683 changed |= WIPHY_PARAM_RTS_THRESHOLD;
3684 }
3685
81077e82 3686 if (info->attrs[NL80211_ATTR_WIPHY_COVERAGE_CLASS]) {
a05829a7
JB
3687 if (info->attrs[NL80211_ATTR_WIPHY_DYN_ACK]) {
3688 result = -EINVAL;
3689 goto out;
3690 }
3057dbfd 3691
81077e82
LT
3692 coverage_class = nla_get_u8(
3693 info->attrs[NL80211_ATTR_WIPHY_COVERAGE_CLASS]);
3694 changed |= WIPHY_PARAM_COVERAGE_CLASS;
3695 }
3696
3057dbfd 3697 if (info->attrs[NL80211_ATTR_WIPHY_DYN_ACK]) {
a05829a7
JB
3698 if (!(rdev->wiphy.features & NL80211_FEATURE_ACKTO_ESTIMATION)) {
3699 result = -EOPNOTSUPP;
3700 goto out;
3701 }
3057dbfd
LB
3702
3703 changed |= WIPHY_PARAM_DYN_ACK;
81077e82
LT
3704 }
3705
52539ca8
THJ
3706 if (info->attrs[NL80211_ATTR_TXQ_LIMIT]) {
3707 if (!wiphy_ext_feature_isset(&rdev->wiphy,
a05829a7
JB
3708 NL80211_EXT_FEATURE_TXQS)) {
3709 result = -EOPNOTSUPP;
3710 goto out;
3711 }
52539ca8
THJ
3712 txq_limit = nla_get_u32(
3713 info->attrs[NL80211_ATTR_TXQ_LIMIT]);
3714 changed |= WIPHY_PARAM_TXQ_LIMIT;
3715 }
3716
3717 if (info->attrs[NL80211_ATTR_TXQ_MEMORY_LIMIT]) {
3718 if (!wiphy_ext_feature_isset(&rdev->wiphy,
a05829a7
JB
3719 NL80211_EXT_FEATURE_TXQS)) {
3720 result = -EOPNOTSUPP;
3721 goto out;
3722 }
52539ca8
THJ
3723 txq_memory_limit = nla_get_u32(
3724 info->attrs[NL80211_ATTR_TXQ_MEMORY_LIMIT]);
3725 changed |= WIPHY_PARAM_TXQ_MEMORY_LIMIT;
3726 }
3727
3728 if (info->attrs[NL80211_ATTR_TXQ_QUANTUM]) {
3729 if (!wiphy_ext_feature_isset(&rdev->wiphy,
a05829a7
JB
3730 NL80211_EXT_FEATURE_TXQS)) {
3731 result = -EOPNOTSUPP;
3732 goto out;
3733 }
52539ca8
THJ
3734 txq_quantum = nla_get_u32(
3735 info->attrs[NL80211_ATTR_TXQ_QUANTUM]);
3736 changed |= WIPHY_PARAM_TXQ_QUANTUM;
3737 }
3738
b9a5f8ca
JM
3739 if (changed) {
3740 u8 old_retry_short, old_retry_long;
3741 u32 old_frag_threshold, old_rts_threshold;
81077e82 3742 u8 old_coverage_class;
52539ca8 3743 u32 old_txq_limit, old_txq_memory_limit, old_txq_quantum;
b9a5f8ca 3744
a05829a7
JB
3745 if (!rdev->ops->set_wiphy_params) {
3746 result = -EOPNOTSUPP;
3747 goto out;
3748 }
b9a5f8ca
JM
3749
3750 old_retry_short = rdev->wiphy.retry_short;
3751 old_retry_long = rdev->wiphy.retry_long;
3752 old_frag_threshold = rdev->wiphy.frag_threshold;
3753 old_rts_threshold = rdev->wiphy.rts_threshold;
81077e82 3754 old_coverage_class = rdev->wiphy.coverage_class;
52539ca8
THJ
3755 old_txq_limit = rdev->wiphy.txq_limit;
3756 old_txq_memory_limit = rdev->wiphy.txq_memory_limit;
3757 old_txq_quantum = rdev->wiphy.txq_quantum;
b9a5f8ca
JM
3758
3759 if (changed & WIPHY_PARAM_RETRY_SHORT)
3760 rdev->wiphy.retry_short = retry_short;
3761 if (changed & WIPHY_PARAM_RETRY_LONG)
3762 rdev->wiphy.retry_long = retry_long;
3763 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
3764 rdev->wiphy.frag_threshold = frag_threshold;
3765 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
3766 rdev->wiphy.rts_threshold = rts_threshold;
81077e82
LT
3767 if (changed & WIPHY_PARAM_COVERAGE_CLASS)
3768 rdev->wiphy.coverage_class = coverage_class;
52539ca8
THJ
3769 if (changed & WIPHY_PARAM_TXQ_LIMIT)
3770 rdev->wiphy.txq_limit = txq_limit;
3771 if (changed & WIPHY_PARAM_TXQ_MEMORY_LIMIT)
3772 rdev->wiphy.txq_memory_limit = txq_memory_limit;
3773 if (changed & WIPHY_PARAM_TXQ_QUANTUM)
3774 rdev->wiphy.txq_quantum = txq_quantum;
b9a5f8ca 3775
e35e4d28 3776 result = rdev_set_wiphy_params(rdev, changed);
b9a5f8ca
JM
3777 if (result) {
3778 rdev->wiphy.retry_short = old_retry_short;
3779 rdev->wiphy.retry_long = old_retry_long;
3780 rdev->wiphy.frag_threshold = old_frag_threshold;
3781 rdev->wiphy.rts_threshold = old_rts_threshold;
81077e82 3782 rdev->wiphy.coverage_class = old_coverage_class;
52539ca8
THJ
3783 rdev->wiphy.txq_limit = old_txq_limit;
3784 rdev->wiphy.txq_memory_limit = old_txq_memory_limit;
3785 rdev->wiphy.txq_quantum = old_txq_quantum;
a05829a7 3786 goto out;
b9a5f8ca
JM
3787 }
3788 }
a05829a7
JB
3789
3790 result = 0;
3791
3792out:
3793 wiphy_unlock(&rdev->wiphy);
3794 return result;
55682965
JB
3795}
3796
5097f844 3797int nl80211_send_chandef(struct sk_buff *msg, const struct cfg80211_chan_def *chandef)
683b6d3b 3798{
601555cd
JB
3799 if (WARN_ON(!cfg80211_chandef_valid(chandef)))
3800 return -EINVAL;
3d9d1d66 3801
683b6d3b
JB
3802 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
3803 chandef->chan->center_freq))
3804 return -ENOBUFS;
942ba88b
TP
3805 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ_OFFSET,
3806 chandef->chan->freq_offset))
3807 return -ENOBUFS;
3d9d1d66
JB
3808 switch (chandef->width) {
3809 case NL80211_CHAN_WIDTH_20_NOHT:
3810 case NL80211_CHAN_WIDTH_20:
3811 case NL80211_CHAN_WIDTH_40:
3812 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
3813 cfg80211_get_chandef_type(chandef)))
3814 return -ENOBUFS;
3815 break;
3816 default:
3817 break;
3818 }
3819 if (nla_put_u32(msg, NL80211_ATTR_CHANNEL_WIDTH, chandef->width))
3820 return -ENOBUFS;
3821 if (nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ1, chandef->center_freq1))
3822 return -ENOBUFS;
3823 if (chandef->center_freq2 &&
3824 nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ2, chandef->center_freq2))
683b6d3b 3825 return -ENOBUFS;
b82730bf
JB
3826 if (chandef->punctured &&
3827 nla_put_u32(msg, NL80211_ATTR_PUNCT_BITMAP, chandef->punctured))
3828 return -ENOBUFS;
3829
683b6d3b
JB
3830 return 0;
3831}
5097f844 3832EXPORT_SYMBOL(nl80211_send_chandef);
683b6d3b 3833
15e47304 3834static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flags,
d726405a 3835 struct cfg80211_registered_device *rdev,
3d1a5bbf
AZ
3836 struct wireless_dev *wdev,
3837 enum nl80211_commands cmd)
55682965 3838{
72fb2abc 3839 struct net_device *dev = wdev->netdev;
55682965
JB
3840 void *hdr;
3841
10331767
JB
3842 lockdep_assert_wiphy(&rdev->wiphy);
3843
3d1a5bbf
AZ
3844 WARN_ON(cmd != NL80211_CMD_NEW_INTERFACE &&
3845 cmd != NL80211_CMD_DEL_INTERFACE &&
3846 cmd != NL80211_CMD_SET_INTERFACE);
8f894be2
TB
3847
3848 hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
55682965
JB
3849 if (!hdr)
3850 return -1;
3851
72fb2abc
JB
3852 if (dev &&
3853 (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
98104fde 3854 nla_put_string(msg, NL80211_ATTR_IFNAME, dev->name)))
72fb2abc
JB
3855 goto nla_put_failure;
3856
3857 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
3858 nla_put_u32(msg, NL80211_ATTR_IFTYPE, wdev->iftype) ||
2dad624e
ND
3859 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
3860 NL80211_ATTR_PAD) ||
98104fde 3861 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, wdev_address(wdev)) ||
9360ffd1
DM
3862 nla_put_u32(msg, NL80211_ATTR_GENERATION,
3863 rdev->devlist_generation ^
446faa15
AQ
3864 (cfg80211_rdev_list_generation << 2)) ||
3865 nla_put_u8(msg, NL80211_ATTR_4ADDR, wdev->use_4addr))
9360ffd1 3866 goto nla_put_failure;
f5ea9120 3867
7b0a0e3c 3868 if (rdev->ops->get_channel && !wdev->valid_links) {
f43e5210 3869 struct cfg80211_chan_def chandef = {};
7b0a0e3c 3870 int ret;
683b6d3b 3871
7b0a0e3c
JB
3872 ret = rdev_get_channel(rdev, wdev, 0, &chandef);
3873 if (ret == 0 && nl80211_send_chandef(msg, &chandef))
3874 goto nla_put_failure;
d91df0e3
PF
3875 }
3876
d55d0d59
RM
3877 if (rdev->ops->get_tx_power) {
3878 int dbm, ret;
3879
3880 ret = rdev_get_tx_power(rdev, wdev, &dbm);
3881 if (ret == 0 &&
3882 nla_put_u32(msg, NL80211_ATTR_WIPHY_TX_POWER_LEVEL,
3883 DBM_TO_MBM(dbm)))
3884 goto nla_put_failure;
3885 }
3886
44905265
JB
3887 switch (wdev->iftype) {
3888 case NL80211_IFTYPE_AP:
a75971bc 3889 case NL80211_IFTYPE_P2P_GO:
7b0a0e3c
JB
3890 if (wdev->u.ap.ssid_len &&
3891 nla_put(msg, NL80211_ATTR_SSID, wdev->u.ap.ssid_len,
3892 wdev->u.ap.ssid))
076fc877 3893 goto nla_put_failure;
44905265
JB
3894 break;
3895 case NL80211_IFTYPE_STATION:
3896 case NL80211_IFTYPE_P2P_CLIENT:
7b0a0e3c
JB
3897 if (wdev->u.client.ssid_len &&
3898 nla_put(msg, NL80211_ATTR_SSID, wdev->u.client.ssid_len,
3899 wdev->u.client.ssid))
076fc877 3900 goto nla_put_failure;
7b0a0e3c
JB
3901 break;
3902 case NL80211_IFTYPE_ADHOC:
3903 if (wdev->u.ibss.ssid_len &&
3904 nla_put(msg, NL80211_ATTR_SSID, wdev->u.ibss.ssid_len,
3905 wdev->u.ibss.ssid))
076fc877 3906 goto nla_put_failure;
44905265 3907 break;
44905265
JB
3908 default:
3909 /* nothing */
3910 break;
b84e7a05
AQ
3911 }
3912
52539ca8
THJ
3913 if (rdev->ops->get_txq_stats) {
3914 struct cfg80211_txq_stats txqstats = {};
3915 int ret = rdev_get_txq_stats(rdev, wdev, &txqstats);
3916
3917 if (ret == 0 &&
3918 !nl80211_put_txq_stats(msg, &txqstats,
3919 NL80211_ATTR_TXQ_STATS))
3920 goto nla_put_failure;
3921 }
3922
ce08cd34
JB
3923 if (wdev->valid_links) {
3924 unsigned int link_id;
3925 struct nlattr *links = nla_nest_start(msg,
3926 NL80211_ATTR_MLO_LINKS);
3927
3928 if (!links)
3929 goto nla_put_failure;
3930
3931 for_each_valid_link(wdev, link_id) {
3932 struct nlattr *link = nla_nest_start(msg, link_id + 1);
7a77cd47
VJ
3933 struct cfg80211_chan_def chandef = {};
3934 int ret;
ce08cd34 3935
5cc58b37
YC
3936 if (!link)
3937 goto nla_put_failure;
3938
ce08cd34
JB
3939 if (nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id))
3940 goto nla_put_failure;
3941 if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN,
3942 wdev->links[link_id].addr))
3943 goto nla_put_failure;
7a77cd47
VJ
3944
3945 ret = rdev_get_channel(rdev, wdev, link_id, &chandef);
3946 if (ret == 0 && nl80211_send_chandef(msg, &chandef))
3947 goto nla_put_failure;
3948
ce08cd34
JB
3949 nla_nest_end(msg, link);
3950 }
3951
3952 nla_nest_end(msg, links);
3953 }
3954
053c095a
JB
3955 genlmsg_end(msg, hdr);
3956 return 0;
55682965
JB
3957
3958 nla_put_failure:
bc3ed28c
TG
3959 genlmsg_cancel(msg, hdr);
3960 return -EMSGSIZE;
55682965
JB
3961}
3962
3963static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *cb)
3964{
3965 int wp_idx = 0;
3966 int if_idx = 0;
3967 int wp_start = cb->args[0];
3968 int if_start = cb->args[1];
b7fb44da 3969 int filter_wiphy = -1;
f5ea9120 3970 struct cfg80211_registered_device *rdev;
55682965 3971 struct wireless_dev *wdev;
ea90e0dc 3972 int ret;
55682965 3973
5fe231e8 3974 rtnl_lock();
b7fb44da
DK
3975 if (!cb->args[2]) {
3976 struct nl80211_dump_wiphy_state state = {
3977 .filter_wiphy = -1,
3978 };
b7fb44da
DK
3979
3980 ret = nl80211_dump_wiphy_parse(skb, cb, &state);
3981 if (ret)
ea90e0dc 3982 goto out_unlock;
b7fb44da
DK
3983
3984 filter_wiphy = state.filter_wiphy;
3985
3986 /*
3987 * if filtering, set cb->args[2] to +1 since 0 is the default
3988 * value needed to determine that parsing is necessary.
3989 */
3990 if (filter_wiphy >= 0)
3991 cb->args[2] = filter_wiphy + 1;
3992 else
3993 cb->args[2] = -1;
3994 } else if (cb->args[2] > 0) {
3995 filter_wiphy = cb->args[2] - 1;
3996 }
3997
7483a214 3998 for_each_rdev(rdev) {
f5ea9120 3999 if (!net_eq(wiphy_net(&rdev->wiphy), sock_net(skb->sk)))
463d0183 4000 continue;
bba95fef
JB
4001 if (wp_idx < wp_start) {
4002 wp_idx++;
55682965 4003 continue;
bba95fef 4004 }
b7fb44da
DK
4005
4006 if (filter_wiphy >= 0 && filter_wiphy != rdev->wiphy_idx)
4007 continue;
4008
55682965
JB
4009 if_idx = 0;
4010
10331767 4011 wiphy_lock(&rdev->wiphy);
53873f13 4012 list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
bba95fef
JB
4013 if (if_idx < if_start) {
4014 if_idx++;
55682965 4015 continue;
bba95fef 4016 }
15e47304 4017 if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).portid,
55682965 4018 cb->nlh->nlmsg_seq, NLM_F_MULTI,
3d1a5bbf
AZ
4019 rdev, wdev,
4020 NL80211_CMD_NEW_INTERFACE) < 0) {
10331767 4021 wiphy_unlock(&rdev->wiphy);
bba95fef
JB
4022 goto out;
4023 }
4024 if_idx++;
55682965 4025 }
10331767 4026 wiphy_unlock(&rdev->wiphy);
bba95fef 4027
a6e4f85d 4028 if_start = 0;
bba95fef 4029 wp_idx++;
55682965 4030 }
bba95fef 4031 out:
55682965
JB
4032 cb->args[0] = wp_idx;
4033 cb->args[1] = if_idx;
4034
ea90e0dc
JB
4035 ret = skb->len;
4036 out_unlock:
4037 rtnl_unlock();
4038
4039 return ret;
55682965
JB
4040}
4041
4042static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info)
4043{
4044 struct sk_buff *msg;
1b8ec87a 4045 struct cfg80211_registered_device *rdev = info->user_ptr[0];
72fb2abc 4046 struct wireless_dev *wdev = info->user_ptr[1];
55682965 4047
fd2120ca 4048 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
55682965 4049 if (!msg)
4c476991 4050 return -ENOMEM;
55682965 4051
15e47304 4052 if (nl80211_send_iface(msg, info->snd_portid, info->snd_seq, 0,
3d1a5bbf 4053 rdev, wdev, NL80211_CMD_NEW_INTERFACE) < 0) {
4c476991
JB
4054 nlmsg_free(msg);
4055 return -ENOBUFS;
4056 }
55682965 4057
134e6375 4058 return genlmsg_reply(msg, info);
55682965
JB
4059}
4060
66f7ac50
MW
4061static const struct nla_policy mntr_flags_policy[NL80211_MNTR_FLAG_MAX + 1] = {
4062 [NL80211_MNTR_FLAG_FCSFAIL] = { .type = NLA_FLAG },
4063 [NL80211_MNTR_FLAG_PLCPFAIL] = { .type = NLA_FLAG },
4064 [NL80211_MNTR_FLAG_CONTROL] = { .type = NLA_FLAG },
4065 [NL80211_MNTR_FLAG_OTHER_BSS] = { .type = NLA_FLAG },
4066 [NL80211_MNTR_FLAG_COOK_FRAMES] = { .type = NLA_FLAG },
e057d3c3 4067 [NL80211_MNTR_FLAG_ACTIVE] = { .type = NLA_FLAG },
66f7ac50
MW
4068};
4069
4070static int parse_monitor_flags(struct nlattr *nla, u32 *mntrflags)
4071{
4072 struct nlattr *flags[NL80211_MNTR_FLAG_MAX + 1];
4073 int flag;
4074
4075 *mntrflags = 0;
4076
4077 if (!nla)
4078 return -EINVAL;
4079
8cb08174 4080 if (nla_parse_nested_deprecated(flags, NL80211_MNTR_FLAG_MAX, nla, mntr_flags_policy, NULL))
66f7ac50
MW
4081 return -EINVAL;
4082
4083 for (flag = 1; flag <= NL80211_MNTR_FLAG_MAX; flag++)
4084 if (flags[flag])
4085 *mntrflags |= (1<<flag);
4086
818a986e
JB
4087 *mntrflags |= MONITOR_FLAG_CHANGED;
4088
66f7ac50
MW
4089 return 0;
4090}
4091
1db77596
JB
4092static int nl80211_parse_mon_options(struct cfg80211_registered_device *rdev,
4093 enum nl80211_iftype type,
4094 struct genl_info *info,
4095 struct vif_params *params)
4096{
4097 bool change = false;
4098 int err;
4099
4100 if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) {
4101 if (type != NL80211_IFTYPE_MONITOR)
4102 return -EINVAL;
4103
4104 err = parse_monitor_flags(info->attrs[NL80211_ATTR_MNTR_FLAGS],
4105 &params->flags);
4106 if (err)
4107 return err;
4108
4109 change = true;
4110 }
4111
4112 if (params->flags & MONITOR_FLAG_ACTIVE &&
4113 !(rdev->wiphy.features & NL80211_FEATURE_ACTIVE_MONITOR))
4114 return -EOPNOTSUPP;
4115
4116 if (info->attrs[NL80211_ATTR_MU_MIMO_GROUP_DATA]) {
4117 const u8 *mumimo_groups;
4118 u32 cap_flag = NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER;
4119
4120 if (type != NL80211_IFTYPE_MONITOR)
4121 return -EINVAL;
4122
4123 if (!wiphy_ext_feature_isset(&rdev->wiphy, cap_flag))
4124 return -EOPNOTSUPP;
4125
4126 mumimo_groups =
4127 nla_data(info->attrs[NL80211_ATTR_MU_MIMO_GROUP_DATA]);
4128
4129 /* bits 0 and 63 are reserved and must be zero */
4954601f
JB
4130 if ((mumimo_groups[0] & BIT(0)) ||
4131 (mumimo_groups[VHT_MUMIMO_GROUPS_DATA_LEN - 1] & BIT(7)))
1db77596
JB
4132 return -EINVAL;
4133
4134 params->vht_mumimo_groups = mumimo_groups;
4135 change = true;
4136 }
4137
4138 if (info->attrs[NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR]) {
4139 u32 cap_flag = NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER;
4140
4141 if (type != NL80211_IFTYPE_MONITOR)
4142 return -EINVAL;
4143
4144 if (!wiphy_ext_feature_isset(&rdev->wiphy, cap_flag))
4145 return -EOPNOTSUPP;
4146
4147 params->vht_mumimo_follow_addr =
4148 nla_data(info->attrs[NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR]);
4149 change = true;
4150 }
4151
4152 return change ? 1 : 0;
4153}
4154
9bc383de 4155static int nl80211_valid_4addr(struct cfg80211_registered_device *rdev,
ad4bb6f8
JB
4156 struct net_device *netdev, u8 use_4addr,
4157 enum nl80211_iftype iftype)
9bc383de 4158{
ad4bb6f8 4159 if (!use_4addr) {
2e92a2d0 4160 if (netdev && netif_is_bridge_port(netdev))
ad4bb6f8 4161 return -EBUSY;
9bc383de 4162 return 0;
ad4bb6f8 4163 }
9bc383de
JB
4164
4165 switch (iftype) {
4166 case NL80211_IFTYPE_AP_VLAN:
4167 if (rdev->wiphy.flags & WIPHY_FLAG_4ADDR_AP)
4168 return 0;
4169 break;
4170 case NL80211_IFTYPE_STATION:
4171 if (rdev->wiphy.flags & WIPHY_FLAG_4ADDR_STATION)
4172 return 0;
4173 break;
4174 default:
4175 break;
4176 }
4177
4178 return -EOPNOTSUPP;
4179}
4180
55682965
JB
4181static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
4182{
4c476991 4183 struct cfg80211_registered_device *rdev = info->user_ptr[0];
2ec600d6 4184 struct vif_params params;
e36d56b6 4185 int err;
04a773ad 4186 enum nl80211_iftype otype, ntype;
4c476991 4187 struct net_device *dev = info->user_ptr[1];
ac7f9cfa 4188 bool change = false;
55682965 4189
2ec600d6
LCC
4190 memset(&params, 0, sizeof(params));
4191
04a773ad 4192 otype = ntype = dev->ieee80211_ptr->iftype;
55682965 4193
723b038d 4194 if (info->attrs[NL80211_ATTR_IFTYPE]) {
ac7f9cfa 4195 ntype = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
04a773ad 4196 if (otype != ntype)
ac7f9cfa 4197 change = true;
723b038d
JB
4198 }
4199
92ffe055 4200 if (info->attrs[NL80211_ATTR_MESH_ID]) {
29cbe68c
JB
4201 struct wireless_dev *wdev = dev->ieee80211_ptr;
4202
4c476991
JB
4203 if (ntype != NL80211_IFTYPE_MESH_POINT)
4204 return -EINVAL;
f78c1375
JB
4205 if (otype != NL80211_IFTYPE_MESH_POINT)
4206 return -EINVAL;
29cbe68c
JB
4207 if (netif_running(dev))
4208 return -EBUSY;
4209
7b0a0e3c 4210 wdev->u.mesh.id_up_len =
29cbe68c 4211 nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
7b0a0e3c
JB
4212 memcpy(wdev->u.mesh.id,
4213 nla_data(info->attrs[NL80211_ATTR_MESH_ID]),
4214 wdev->u.mesh.id_up_len);
2ec600d6
LCC
4215 }
4216
8b787643
FF
4217 if (info->attrs[NL80211_ATTR_4ADDR]) {
4218 params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]);
4219 change = true;
ad4bb6f8 4220 err = nl80211_valid_4addr(rdev, dev, params.use_4addr, ntype);
9bc383de 4221 if (err)
4c476991 4222 return err;
8b787643
FF
4223 } else {
4224 params.use_4addr = -1;
4225 }
4226
1db77596
JB
4227 err = nl80211_parse_mon_options(rdev, ntype, info, &params);
4228 if (err < 0)
4229 return err;
4230 if (err > 0)
c6e6a0c8 4231 change = true;
e057d3c3 4232
ac7f9cfa 4233 if (change)
818a986e 4234 err = cfg80211_change_iface(rdev, dev, ntype, &params);
ac7f9cfa
JB
4235 else
4236 err = 0;
60719ffd 4237
9bc383de
JB
4238 if (!err && params.use_4addr != -1)
4239 dev->ieee80211_ptr->use_4addr = params.use_4addr;
4240
3d1a5bbf
AZ
4241 if (change && !err) {
4242 struct wireless_dev *wdev = dev->ieee80211_ptr;
4243
4244 nl80211_notify_iface(rdev, wdev, NL80211_CMD_SET_INTERFACE);
4245 }
4246
55682965
JB
4247 return err;
4248}
4249
ea6b2098 4250static int _nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
55682965 4251{
4c476991 4252 struct cfg80211_registered_device *rdev = info->user_ptr[0];
2ec600d6 4253 struct vif_params params;
84efbb84 4254 struct wireless_dev *wdev;
896ff063 4255 struct sk_buff *msg;
55682965
JB
4256 int err;
4257 enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED;
4258
2ec600d6
LCC
4259 memset(&params, 0, sizeof(params));
4260
55682965
JB
4261 if (!info->attrs[NL80211_ATTR_IFNAME])
4262 return -EINVAL;
4263
ab0d76f6 4264 if (info->attrs[NL80211_ATTR_IFTYPE])
55682965 4265 type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
55682965 4266
33d915d9 4267 if (!rdev->ops->add_virtual_intf)
4c476991 4268 return -EOPNOTSUPP;
55682965 4269
cb3b7d87 4270 if ((type == NL80211_IFTYPE_P2P_DEVICE || type == NL80211_IFTYPE_NAN ||
e8f479b1
BG
4271 rdev->wiphy.features & NL80211_FEATURE_MAC_ON_CREATE) &&
4272 info->attrs[NL80211_ATTR_MAC]) {
1c18f145
AS
4273 nla_memcpy(params.macaddr, info->attrs[NL80211_ATTR_MAC],
4274 ETH_ALEN);
4275 if (!is_valid_ether_addr(params.macaddr))
4276 return -EADDRNOTAVAIL;
4277 }
4278
9bc383de 4279 if (info->attrs[NL80211_ATTR_4ADDR]) {
8b787643 4280 params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]);
ad4bb6f8 4281 err = nl80211_valid_4addr(rdev, NULL, params.use_4addr, type);
9bc383de 4282 if (err)
4c476991 4283 return err;
9bc383de 4284 }
8b787643 4285
e6f40511 4286 if (!cfg80211_iftype_allowed(&rdev->wiphy, type, params.use_4addr, 0))
33d915d9
MP
4287 return -EOPNOTSUPP;
4288
1db77596
JB
4289 err = nl80211_parse_mon_options(rdev, type, info, &params);
4290 if (err < 0)
4291 return err;
e057d3c3 4292
a18c7192
JB
4293 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4294 if (!msg)
4295 return -ENOMEM;
4296
e35e4d28
HG
4297 wdev = rdev_add_virtual_intf(rdev,
4298 nla_data(info->attrs[NL80211_ATTR_IFNAME]),
818a986e 4299 NET_NAME_USER, type, &params);
d687cbb7
RM
4300 if (WARN_ON(!wdev)) {
4301 nlmsg_free(msg);
4302 return -EPROTO;
4303 } else if (IS_ERR(wdev)) {
1c90f9d4 4304 nlmsg_free(msg);
84efbb84 4305 return PTR_ERR(wdev);
1c90f9d4 4306 }
2ec600d6 4307
18e5ca65 4308 if (info->attrs[NL80211_ATTR_SOCKET_OWNER])
78f22b6a
JB
4309 wdev->owner_nlportid = info->snd_portid;
4310
98104fde
JB
4311 switch (type) {
4312 case NL80211_IFTYPE_MESH_POINT:
4313 if (!info->attrs[NL80211_ATTR_MESH_ID])
4314 break;
7b0a0e3c 4315 wdev->u.mesh.id_up_len =
29cbe68c 4316 nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
7b0a0e3c
JB
4317 memcpy(wdev->u.mesh.id,
4318 nla_data(info->attrs[NL80211_ATTR_MESH_ID]),
4319 wdev->u.mesh.id_up_len);
98104fde 4320 break;
cb3b7d87 4321 case NL80211_IFTYPE_NAN:
98104fde
JB
4322 case NL80211_IFTYPE_P2P_DEVICE:
4323 /*
cb3b7d87 4324 * P2P Device and NAN do not have a netdev, so don't go
98104fde
JB
4325 * through the netdev notifier and must be added here
4326 */
9bdaf3b9
JB
4327 cfg80211_init_wdev(wdev);
4328 cfg80211_register_wdev(rdev, wdev);
98104fde
JB
4329 break;
4330 default:
4331 break;
29cbe68c
JB
4332 }
4333
15e47304 4334 if (nl80211_send_iface(msg, info->snd_portid, info->snd_seq, 0,
3d1a5bbf 4335 rdev, wdev, NL80211_CMD_NEW_INTERFACE) < 0) {
1c90f9d4
JB
4336 nlmsg_free(msg);
4337 return -ENOBUFS;
4338 }
4339
4340 return genlmsg_reply(msg, info);
55682965
JB
4341}
4342
ea6b2098
JB
4343static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
4344{
4345 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4346 int ret;
4347
4348 /* to avoid failing a new interface creation due to pending removal */
4349 cfg80211_destroy_ifaces(rdev);
4350
4351 wiphy_lock(&rdev->wiphy);
4352 ret = _nl80211_new_interface(skb, info);
4353 wiphy_unlock(&rdev->wiphy);
4354
4355 return ret;
4356}
4357
55682965
JB
4358static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
4359{
4c476991 4360 struct cfg80211_registered_device *rdev = info->user_ptr[0];
84efbb84 4361 struct wireless_dev *wdev = info->user_ptr[1];
55682965 4362
4c476991
JB
4363 if (!rdev->ops->del_virtual_intf)
4364 return -EOPNOTSUPP;
55682965 4365
a05829a7
JB
4366 /*
4367 * We hold RTNL, so this is safe, without RTNL opencount cannot
4368 * reach 0, and thus the rdev cannot be deleted.
4369 *
4370 * We need to do it for the dev_close(), since that will call
4371 * the netdev notifiers, and we need to acquire the mutex there
4372 * but don't know if we get there from here or from some other
4373 * place (e.g. "ip link set ... down").
4374 */
4375 mutex_unlock(&rdev->wiphy.mtx);
4376
84efbb84
JB
4377 /*
4378 * If we remove a wireless device without a netdev then clear
4379 * user_ptr[1] so that nl80211_post_doit won't dereference it
4380 * to check if it needs to do dev_put(). Otherwise it crashes
4381 * since the wdev has been freed, unlike with a netdev where
4382 * we need the dev_put() for the netdev to really be freed.
4383 */
4384 if (!wdev->netdev)
4385 info->user_ptr[1] = NULL;
a05829a7
JB
4386 else
4387 dev_close(wdev->netdev);
4388
4389 mutex_lock(&rdev->wiphy.mtx);
84efbb84 4390
cdf0a0a8 4391 return cfg80211_remove_virtual_intf(rdev, wdev);
55682965
JB
4392}
4393
1d9d9213
SW
4394static int nl80211_set_noack_map(struct sk_buff *skb, struct genl_info *info)
4395{
4396 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4397 struct net_device *dev = info->user_ptr[1];
4398 u16 noack_map;
4399
4400 if (!info->attrs[NL80211_ATTR_NOACK_MAP])
4401 return -EINVAL;
4402
4403 if (!rdev->ops->set_noack_map)
4404 return -EOPNOTSUPP;
4405
4406 noack_map = nla_get_u16(info->attrs[NL80211_ATTR_NOACK_MAP]);
4407
e35e4d28 4408 return rdev_set_noack_map(rdev, dev, noack_map);
1d9d9213
SW
4409}
4410
e7a7b84e
VJ
4411static int nl80211_validate_key_link_id(struct genl_info *info,
4412 struct wireless_dev *wdev,
4413 int link_id, bool pairwise)
4414{
4415 if (pairwise) {
4416 if (link_id != -1) {
4417 GENL_SET_ERR_MSG(info,
4418 "link ID not allowed for pairwise key");
4419 return -EINVAL;
4420 }
4421
4422 return 0;
4423 }
4424
4425 if (wdev->valid_links) {
4426 if (link_id == -1) {
4427 GENL_SET_ERR_MSG(info,
4428 "link ID must for MLO group key");
4429 return -EINVAL;
4430 }
4431 if (!(wdev->valid_links & BIT(link_id))) {
4432 GENL_SET_ERR_MSG(info, "invalid link ID for MLO group key");
4433 return -EINVAL;
4434 }
4435 } else if (link_id != -1) {
4436 GENL_SET_ERR_MSG(info, "link ID not allowed for non-MLO group key");
4437 return -EINVAL;
4438 }
4439
4440 return 0;
4441}
4442
41ade00f
JB
4443struct get_key_cookie {
4444 struct sk_buff *msg;
4445 int error;
b9454e83 4446 int idx;
41ade00f
JB
4447};
4448
4449static void get_key_callback(void *c, struct key_params *params)
4450{
b9454e83 4451 struct nlattr *key;
41ade00f
JB
4452 struct get_key_cookie *cookie = c;
4453
9360ffd1
DM
4454 if ((params->key &&
4455 nla_put(cookie->msg, NL80211_ATTR_KEY_DATA,
4456 params->key_len, params->key)) ||
4457 (params->seq &&
4458 nla_put(cookie->msg, NL80211_ATTR_KEY_SEQ,
4459 params->seq_len, params->seq)) ||
4460 (params->cipher &&
4461 nla_put_u32(cookie->msg, NL80211_ATTR_KEY_CIPHER,
4462 params->cipher)))
4463 goto nla_put_failure;
41ade00f 4464
ae0be8de 4465 key = nla_nest_start_noflag(cookie->msg, NL80211_ATTR_KEY);
b9454e83
JB
4466 if (!key)
4467 goto nla_put_failure;
4468
9360ffd1
DM
4469 if ((params->key &&
4470 nla_put(cookie->msg, NL80211_KEY_DATA,
4471 params->key_len, params->key)) ||
4472 (params->seq &&
4473 nla_put(cookie->msg, NL80211_KEY_SEQ,
4474 params->seq_len, params->seq)) ||
4475 (params->cipher &&
4476 nla_put_u32(cookie->msg, NL80211_KEY_CIPHER,
4477 params->cipher)))
4478 goto nla_put_failure;
b9454e83 4479
efdfce72 4480 if (nla_put_u8(cookie->msg, NL80211_KEY_IDX, cookie->idx))
9360ffd1 4481 goto nla_put_failure;
b9454e83
JB
4482
4483 nla_nest_end(cookie->msg, key);
4484
41ade00f
JB
4485 return;
4486 nla_put_failure:
4487 cookie->error = 1;
4488}
4489
4490static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
4491{
4c476991 4492 struct cfg80211_registered_device *rdev = info->user_ptr[0];
41ade00f 4493 int err;
4c476991 4494 struct net_device *dev = info->user_ptr[1];
41ade00f 4495 u8 key_idx = 0;
e31b8213
JB
4496 const u8 *mac_addr = NULL;
4497 bool pairwise;
41ade00f
JB
4498 struct get_key_cookie cookie = {
4499 .error = 0,
4500 };
4501 void *hdr;
4502 struct sk_buff *msg;
155d7c73 4503 bool bigtk_support = false;
e7a7b84e
VJ
4504 int link_id = nl80211_link_id_or_invalid(info->attrs);
4505 struct wireless_dev *wdev = dev->ieee80211_ptr;
155d7c73
JB
4506
4507 if (wiphy_ext_feature_isset(&rdev->wiphy,
4508 NL80211_EXT_FEATURE_BEACON_PROTECTION))
4509 bigtk_support = true;
4510
e7a7b84e
VJ
4511 if ((wdev->iftype == NL80211_IFTYPE_STATION ||
4512 wdev->iftype == NL80211_IFTYPE_P2P_CLIENT) &&
155d7c73
JB
4513 wiphy_ext_feature_isset(&rdev->wiphy,
4514 NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT))
4515 bigtk_support = true;
41ade00f 4516
56be393f 4517 if (info->attrs[NL80211_ATTR_KEY_IDX]) {
41ade00f 4518 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
155d7c73
JB
4519
4520 if (key_idx >= 6 && key_idx <= 7 && !bigtk_support) {
4521 GENL_SET_ERR_MSG(info, "BIGTK not supported");
56be393f 4522 return -EINVAL;
155d7c73 4523 }
56be393f 4524 }
41ade00f 4525
41ade00f
JB
4526 if (info->attrs[NL80211_ATTR_MAC])
4527 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
4528
e31b8213
JB
4529 pairwise = !!mac_addr;
4530 if (info->attrs[NL80211_ATTR_KEY_TYPE]) {
4531 u32 kt = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]);
7a087e74 4532
e31b8213
JB
4533 if (kt != NL80211_KEYTYPE_GROUP &&
4534 kt != NL80211_KEYTYPE_PAIRWISE)
4535 return -EINVAL;
4536 pairwise = kt == NL80211_KEYTYPE_PAIRWISE;
4537 }
4538
4c476991
JB
4539 if (!rdev->ops->get_key)
4540 return -EOPNOTSUPP;
41ade00f 4541
0fa7b391
JB
4542 if (!pairwise && mac_addr && !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
4543 return -ENOENT;
4544
fd2120ca 4545 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4c476991
JB
4546 if (!msg)
4547 return -ENOMEM;
41ade00f 4548
15e47304 4549 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
41ade00f 4550 NL80211_CMD_NEW_KEY);
cb35fba3 4551 if (!hdr)
9fe271af 4552 goto nla_put_failure;
41ade00f
JB
4553
4554 cookie.msg = msg;
b9454e83 4555 cookie.idx = key_idx;
41ade00f 4556
9360ffd1
DM
4557 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
4558 nla_put_u8(msg, NL80211_ATTR_KEY_IDX, key_idx))
4559 goto nla_put_failure;
4560 if (mac_addr &&
4561 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr))
4562 goto nla_put_failure;
41ade00f 4563
e7a7b84e
VJ
4564 err = nl80211_validate_key_link_id(info, wdev, link_id, pairwise);
4565 if (err)
4566 goto free_msg;
4567
4568 err = rdev_get_key(rdev, dev, link_id, key_idx, pairwise, mac_addr,
4569 &cookie, get_key_callback);
41ade00f
JB
4570
4571 if (err)
6c95e2a2 4572 goto free_msg;
41ade00f
JB
4573
4574 if (cookie.error)
4575 goto nla_put_failure;
4576
4577 genlmsg_end(msg, hdr);
4c476991 4578 return genlmsg_reply(msg, info);
41ade00f
JB
4579
4580 nla_put_failure:
4581 err = -ENOBUFS;
6c95e2a2 4582 free_msg:
41ade00f 4583 nlmsg_free(msg);
41ade00f
JB
4584 return err;
4585}
4586
4587static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
4588{
4c476991 4589 struct cfg80211_registered_device *rdev = info->user_ptr[0];
b9454e83 4590 struct key_parse key;
41ade00f 4591 int err;
4c476991 4592 struct net_device *dev = info->user_ptr[1];
e7a7b84e
VJ
4593 int link_id = nl80211_link_id_or_invalid(info->attrs);
4594 struct wireless_dev *wdev = dev->ieee80211_ptr;
41ade00f 4595
b9454e83
JB
4596 err = nl80211_parse_key(info, &key);
4597 if (err)
4598 return err;
41ade00f 4599
b9454e83 4600 if (key.idx < 0)
41ade00f
JB
4601 return -EINVAL;
4602
6cdd3979
AW
4603 /* Only support setting default key and
4604 * Extended Key ID action NL80211_KEY_SET_TX.
4605 */
56be393f 4606 if (!key.def && !key.defmgmt && !key.defbeacon &&
6cdd3979 4607 !(key.p.mode == NL80211_KEY_SET_TX))
41ade00f
JB
4608 return -EINVAL;
4609
dbd2fd65 4610 if (key.def) {
076fc877
JB
4611 if (!rdev->ops->set_default_key)
4612 return -EOPNOTSUPP;
41ade00f 4613
e7a7b84e
VJ
4614 err = nl80211_key_allowed(wdev);
4615 if (err)
076fc877 4616 return err;
e7a7b84e
VJ
4617
4618 err = nl80211_validate_key_link_id(info, wdev, link_id, false);
dbd2fd65 4619 if (err)
076fc877 4620 return err;
dbd2fd65 4621
e7a7b84e
VJ
4622 err = rdev_set_default_key(rdev, dev, link_id, key.idx,
4623 key.def_uni, key.def_multi);
dbd2fd65
JB
4624
4625 if (err)
076fc877 4626 return err;
fffd0934 4627
3d23e349 4628#ifdef CONFIG_CFG80211_WEXT
e7a7b84e 4629 wdev->wext.default_key = key.idx;
dbd2fd65 4630#endif
076fc877 4631 return 0;
6cdd3979 4632 } else if (key.defmgmt) {
076fc877
JB
4633 if (key.def_uni || !key.def_multi)
4634 return -EINVAL;
dbd2fd65 4635
076fc877
JB
4636 if (!rdev->ops->set_default_mgmt_key)
4637 return -EOPNOTSUPP;
dbd2fd65 4638
e7a7b84e
VJ
4639 err = nl80211_key_allowed(wdev);
4640 if (err)
076fc877 4641 return err;
e7a7b84e
VJ
4642
4643 err = nl80211_validate_key_link_id(info, wdev, link_id, false);
dbd2fd65 4644 if (err)
076fc877 4645 return err;
dbd2fd65 4646
e7a7b84e 4647 err = rdev_set_default_mgmt_key(rdev, dev, link_id, key.idx);
dbd2fd65 4648 if (err)
076fc877 4649 return err;
dbd2fd65
JB
4650
4651#ifdef CONFIG_CFG80211_WEXT
e7a7b84e 4652 wdev->wext.default_mgmt_key = key.idx;
08645126 4653#endif
076fc877 4654 return 0;
56be393f 4655 } else if (key.defbeacon) {
076fc877
JB
4656 if (key.def_uni || !key.def_multi)
4657 return -EINVAL;
56be393f 4658
076fc877
JB
4659 if (!rdev->ops->set_default_beacon_key)
4660 return -EOPNOTSUPP;
56be393f 4661
e7a7b84e 4662 err = nl80211_key_allowed(wdev);
56be393f 4663 if (err)
076fc877 4664 return err;
56be393f 4665
e7a7b84e
VJ
4666 err = nl80211_validate_key_link_id(info, wdev, link_id, false);
4667 if (err)
076fc877 4668 return err;
e7a7b84e 4669
076fc877 4670 return rdev_set_default_beacon_key(rdev, dev, link_id, key.idx);
6cdd3979
AW
4671 } else if (key.p.mode == NL80211_KEY_SET_TX &&
4672 wiphy_ext_feature_isset(&rdev->wiphy,
4673 NL80211_EXT_FEATURE_EXT_KEY_ID)) {
4674 u8 *mac_addr = NULL;
4675
4676 if (info->attrs[NL80211_ATTR_MAC])
4677 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
4678
076fc877
JB
4679 if (!mac_addr || key.idx < 0 || key.idx > 1)
4680 return -EINVAL;
dbd2fd65 4681
e7a7b84e
VJ
4682 err = nl80211_validate_key_link_id(info, wdev, link_id, true);
4683 if (err)
076fc877 4684 return err;
e7a7b84e 4685
076fc877
JB
4686 return rdev_add_key(rdev, dev, link_id, key.idx,
4687 NL80211_KEYTYPE_PAIRWISE,
4688 mac_addr, &key.p);
6cdd3979 4689 }
41ade00f 4690
076fc877 4691 return -EINVAL;
41ade00f
JB
4692}
4693
4694static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
4695{
4c476991 4696 struct cfg80211_registered_device *rdev = info->user_ptr[0];
fffd0934 4697 int err;
4c476991 4698 struct net_device *dev = info->user_ptr[1];
b9454e83 4699 struct key_parse key;
e31b8213 4700 const u8 *mac_addr = NULL;
e7a7b84e
VJ
4701 int link_id = nl80211_link_id_or_invalid(info->attrs);
4702 struct wireless_dev *wdev = dev->ieee80211_ptr;
41ade00f 4703
b9454e83
JB
4704 err = nl80211_parse_key(info, &key);
4705 if (err)
4706 return err;
41ade00f 4707
f8af764b
JM
4708 if (!key.p.key) {
4709 GENL_SET_ERR_MSG(info, "no key");
41ade00f 4710 return -EINVAL;
f8af764b 4711 }
41ade00f 4712
41ade00f
JB
4713 if (info->attrs[NL80211_ATTR_MAC])
4714 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
4715
e31b8213
JB
4716 if (key.type == -1) {
4717 if (mac_addr)
4718 key.type = NL80211_KEYTYPE_PAIRWISE;
4719 else
4720 key.type = NL80211_KEYTYPE_GROUP;
4721 }
4722
4723 /* for now */
4724 if (key.type != NL80211_KEYTYPE_PAIRWISE &&
f8af764b
JM
4725 key.type != NL80211_KEYTYPE_GROUP) {
4726 GENL_SET_ERR_MSG(info, "key type not pairwise or group");
e31b8213 4727 return -EINVAL;
f8af764b 4728 }
e31b8213 4729
14f34e36
GG
4730 if (key.type == NL80211_KEYTYPE_GROUP &&
4731 info->attrs[NL80211_ATTR_VLAN_ID])
4732 key.p.vlan_id = nla_get_u16(info->attrs[NL80211_ATTR_VLAN_ID]);
4733
4c476991
JB
4734 if (!rdev->ops->add_key)
4735 return -EOPNOTSUPP;
25e47c18 4736
e31b8213
JB
4737 if (cfg80211_validate_key_settings(rdev, &key.p, key.idx,
4738 key.type == NL80211_KEYTYPE_PAIRWISE,
f8af764b
JM
4739 mac_addr)) {
4740 GENL_SET_ERR_MSG(info, "key setting validation failed");
4c476991 4741 return -EINVAL;
f8af764b 4742 }
41ade00f 4743
e7a7b84e 4744 err = nl80211_key_allowed(wdev);
f8af764b
JM
4745 if (err)
4746 GENL_SET_ERR_MSG(info, "key not allowed");
e7a7b84e
VJ
4747
4748 if (!err)
4749 err = nl80211_validate_key_link_id(info, wdev, link_id,
4750 key.type == NL80211_KEYTYPE_PAIRWISE);
4751
f8af764b 4752 if (!err) {
e7a7b84e 4753 err = rdev_add_key(rdev, dev, link_id, key.idx,
e35e4d28
HG
4754 key.type == NL80211_KEYTYPE_PAIRWISE,
4755 mac_addr, &key.p);
f8af764b
JM
4756 if (err)
4757 GENL_SET_ERR_MSG(info, "key addition failed");
4758 }
41ade00f 4759
41ade00f
JB
4760 return err;
4761}
4762
4763static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
4764{
4c476991 4765 struct cfg80211_registered_device *rdev = info->user_ptr[0];
41ade00f 4766 int err;
4c476991 4767 struct net_device *dev = info->user_ptr[1];
41ade00f 4768 u8 *mac_addr = NULL;
b9454e83 4769 struct key_parse key;
e7a7b84e
VJ
4770 int link_id = nl80211_link_id_or_invalid(info->attrs);
4771 struct wireless_dev *wdev = dev->ieee80211_ptr;
41ade00f 4772
b9454e83
JB
4773 err = nl80211_parse_key(info, &key);
4774 if (err)
4775 return err;
41ade00f
JB
4776
4777 if (info->attrs[NL80211_ATTR_MAC])
4778 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
4779
e31b8213
JB
4780 if (key.type == -1) {
4781 if (mac_addr)
4782 key.type = NL80211_KEYTYPE_PAIRWISE;
4783 else
4784 key.type = NL80211_KEYTYPE_GROUP;
4785 }
4786
4787 /* for now */
4788 if (key.type != NL80211_KEYTYPE_PAIRWISE &&
4789 key.type != NL80211_KEYTYPE_GROUP)
4790 return -EINVAL;
4791
2d946308
AT
4792 if (!cfg80211_valid_key_idx(rdev, key.idx,
4793 key.type == NL80211_KEYTYPE_PAIRWISE))
4794 return -EINVAL;
4795
4c476991
JB
4796 if (!rdev->ops->del_key)
4797 return -EOPNOTSUPP;
41ade00f 4798
e7a7b84e 4799 err = nl80211_key_allowed(wdev);
e31b8213 4800
0fa7b391 4801 if (key.type == NL80211_KEYTYPE_GROUP && mac_addr &&
e31b8213
JB
4802 !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
4803 err = -ENOENT;
4804
fffd0934 4805 if (!err)
e7a7b84e
VJ
4806 err = nl80211_validate_key_link_id(info, wdev, link_id,
4807 key.type == NL80211_KEYTYPE_PAIRWISE);
4808
4809 if (!err)
4810 err = rdev_del_key(rdev, dev, link_id, key.idx,
e35e4d28
HG
4811 key.type == NL80211_KEYTYPE_PAIRWISE,
4812 mac_addr);
41ade00f 4813
3d23e349 4814#ifdef CONFIG_CFG80211_WEXT
08645126 4815 if (!err) {
e7a7b84e
VJ
4816 if (key.idx == wdev->wext.default_key)
4817 wdev->wext.default_key = -1;
4818 else if (key.idx == wdev->wext.default_mgmt_key)
4819 wdev->wext.default_mgmt_key = -1;
08645126
JB
4820 }
4821#endif
4822
41ade00f
JB
4823 return err;
4824}
4825
77765eaf
VT
4826/* This function returns an error or the number of nested attributes */
4827static int validate_acl_mac_addrs(struct nlattr *nl_attr)
4828{
4829 struct nlattr *attr;
4830 int n_entries = 0, tmp;
4831
4832 nla_for_each_nested(attr, nl_attr, tmp) {
4833 if (nla_len(attr) != ETH_ALEN)
4834 return -EINVAL;
4835
4836 n_entries++;
4837 }
4838
4839 return n_entries;
4840}
4841
4842/*
4843 * This function parses ACL information and allocates memory for ACL data.
4844 * On successful return, the calling function is responsible to free the
4845 * ACL buffer returned by this function.
4846 */
4847static struct cfg80211_acl_data *parse_acl_data(struct wiphy *wiphy,
4848 struct genl_info *info)
4849{
4850 enum nl80211_acl_policy acl_policy;
4851 struct nlattr *attr;
4852 struct cfg80211_acl_data *acl;
4853 int i = 0, n_entries, tmp;
4854
4855 if (!wiphy->max_acl_mac_addrs)
4856 return ERR_PTR(-EOPNOTSUPP);
4857
4858 if (!info->attrs[NL80211_ATTR_ACL_POLICY])
4859 return ERR_PTR(-EINVAL);
4860
4861 acl_policy = nla_get_u32(info->attrs[NL80211_ATTR_ACL_POLICY]);
4862 if (acl_policy != NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED &&
4863 acl_policy != NL80211_ACL_POLICY_DENY_UNLESS_LISTED)
4864 return ERR_PTR(-EINVAL);
4865
4866 if (!info->attrs[NL80211_ATTR_MAC_ADDRS])
4867 return ERR_PTR(-EINVAL);
4868
4869 n_entries = validate_acl_mac_addrs(info->attrs[NL80211_ATTR_MAC_ADDRS]);
4870 if (n_entries < 0)
4871 return ERR_PTR(n_entries);
4872
4873 if (n_entries > wiphy->max_acl_mac_addrs)
f6289e5d 4874 return ERR_PTR(-EOPNOTSUPP);
77765eaf 4875
391d132c 4876 acl = kzalloc(struct_size(acl, mac_addrs, n_entries), GFP_KERNEL);
77765eaf
VT
4877 if (!acl)
4878 return ERR_PTR(-ENOMEM);
93ca8244 4879 acl->n_acl_entries = n_entries;
77765eaf
VT
4880
4881 nla_for_each_nested(attr, info->attrs[NL80211_ATTR_MAC_ADDRS], tmp) {
4882 memcpy(acl->mac_addrs[i].addr, nla_data(attr), ETH_ALEN);
4883 i++;
4884 }
77765eaf
VT
4885 acl->acl_policy = acl_policy;
4886
4887 return acl;
4888}
4889
4890static int nl80211_set_mac_acl(struct sk_buff *skb, struct genl_info *info)
4891{
4892 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4893 struct net_device *dev = info->user_ptr[1];
4894 struct cfg80211_acl_data *acl;
4895 int err;
4896
4897 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
4898 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
4899 return -EOPNOTSUPP;
4900
7b0a0e3c 4901 if (!dev->ieee80211_ptr->links[0].ap.beacon_interval)
77765eaf
VT
4902 return -EINVAL;
4903
4904 acl = parse_acl_data(&rdev->wiphy, info);
4905 if (IS_ERR(acl))
4906 return PTR_ERR(acl);
4907
4908 err = rdev_set_mac_acl(rdev, dev, acl);
4909
4910 kfree(acl);
4911
4912 return err;
4913}
4914
a7c7fbff
PK
4915static u32 rateset_to_mask(struct ieee80211_supported_band *sband,
4916 u8 *rates, u8 rates_len)
4917{
4918 u8 i;
4919 u32 mask = 0;
4920
4921 for (i = 0; i < rates_len; i++) {
4922 int rate = (rates[i] & 0x7f) * 5;
4923 int ridx;
4924
4925 for (ridx = 0; ridx < sband->n_bitrates; ridx++) {
4926 struct ieee80211_rate *srate =
4927 &sband->bitrates[ridx];
4928 if (rate == srate->bitrate) {
4929 mask |= 1 << ridx;
4930 break;
4931 }
4932 }
4933 if (ridx == sband->n_bitrates)
4934 return 0; /* rate not found */
4935 }
4936
4937 return mask;
4938}
4939
4940static bool ht_rateset_to_mask(struct ieee80211_supported_band *sband,
4941 u8 *rates, u8 rates_len,
4942 u8 mcs[IEEE80211_HT_MCS_MASK_LEN])
4943{
4944 u8 i;
4945
4946 memset(mcs, 0, IEEE80211_HT_MCS_MASK_LEN);
4947
4948 for (i = 0; i < rates_len; i++) {
4949 int ridx, rbit;
4950
4951 ridx = rates[i] / 8;
4952 rbit = BIT(rates[i] % 8);
4953
4954 /* check validity */
4955 if ((ridx < 0) || (ridx >= IEEE80211_HT_MCS_MASK_LEN))
4956 return false;
4957
4958 /* check availability */
30fe6d50 4959 ridx = array_index_nospec(ridx, IEEE80211_HT_MCS_MASK_LEN);
a7c7fbff
PK
4960 if (sband->ht_cap.mcs.rx_mask[ridx] & rbit)
4961 mcs[ridx] |= rbit;
4962 else
4963 return false;
4964 }
4965
4966 return true;
4967}
4968
4969static u16 vht_mcs_map_to_mcs_mask(u8 vht_mcs_map)
4970{
4971 u16 mcs_mask = 0;
4972
4973 switch (vht_mcs_map) {
4974 case IEEE80211_VHT_MCS_NOT_SUPPORTED:
4975 break;
4976 case IEEE80211_VHT_MCS_SUPPORT_0_7:
4977 mcs_mask = 0x00FF;
4978 break;
4979 case IEEE80211_VHT_MCS_SUPPORT_0_8:
4980 mcs_mask = 0x01FF;
4981 break;
4982 case IEEE80211_VHT_MCS_SUPPORT_0_9:
4983 mcs_mask = 0x03FF;
4984 break;
4985 default:
4986 break;
4987 }
4988
4989 return mcs_mask;
4990}
4991
4992static void vht_build_mcs_mask(u16 vht_mcs_map,
4993 u16 vht_mcs_mask[NL80211_VHT_NSS_MAX])
4994{
4995 u8 nss;
4996
4997 for (nss = 0; nss < NL80211_VHT_NSS_MAX; nss++) {
4998 vht_mcs_mask[nss] = vht_mcs_map_to_mcs_mask(vht_mcs_map & 0x03);
4999 vht_mcs_map >>= 2;
5000 }
5001}
5002
5003static bool vht_set_mcs_mask(struct ieee80211_supported_band *sband,
5004 struct nl80211_txrate_vht *txrate,
5005 u16 mcs[NL80211_VHT_NSS_MAX])
5006{
5007 u16 tx_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map);
5008 u16 tx_mcs_mask[NL80211_VHT_NSS_MAX] = {};
5009 u8 i;
5010
5011 if (!sband->vht_cap.vht_supported)
5012 return false;
5013
5014 memset(mcs, 0, sizeof(u16) * NL80211_VHT_NSS_MAX);
5015
5016 /* Build vht_mcs_mask from VHT capabilities */
5017 vht_build_mcs_mask(tx_mcs_map, tx_mcs_mask);
5018
5019 for (i = 0; i < NL80211_VHT_NSS_MAX; i++) {
5020 if ((tx_mcs_mask[i] & txrate->mcs[i]) == txrate->mcs[i])
5021 mcs[i] = txrate->mcs[i];
5022 else
5023 return false;
5024 }
5025
5026 return true;
5027}
5028
eb89a6a6
MH
5029static u16 he_mcs_map_to_mcs_mask(u8 he_mcs_map)
5030{
5031 switch (he_mcs_map) {
5032 case IEEE80211_HE_MCS_NOT_SUPPORTED:
5033 return 0;
5034 case IEEE80211_HE_MCS_SUPPORT_0_7:
5035 return 0x00FF;
5036 case IEEE80211_HE_MCS_SUPPORT_0_9:
5037 return 0x03FF;
5038 case IEEE80211_HE_MCS_SUPPORT_0_11:
5039 return 0xFFF;
5040 default:
5041 break;
5042 }
5043 return 0;
5044}
5045
5046static void he_build_mcs_mask(u16 he_mcs_map,
5047 u16 he_mcs_mask[NL80211_HE_NSS_MAX])
5048{
5049 u8 nss;
5050
5051 for (nss = 0; nss < NL80211_HE_NSS_MAX; nss++) {
5052 he_mcs_mask[nss] = he_mcs_map_to_mcs_mask(he_mcs_map & 0x03);
5053 he_mcs_map >>= 2;
5054 }
5055}
5056
7b0a0e3c 5057static u16 he_get_txmcsmap(struct genl_info *info, unsigned int link_id,
eb89a6a6
MH
5058 const struct ieee80211_sta_he_cap *he_cap)
5059{
5060 struct net_device *dev = info->user_ptr[1];
5061 struct wireless_dev *wdev = dev->ieee80211_ptr;
7b0a0e3c
JB
5062 struct cfg80211_chan_def *chandef;
5063 __le16 tx_mcs;
eb89a6a6 5064
7b0a0e3c
JB
5065 chandef = wdev_chandef(wdev, link_id);
5066 if (!chandef) {
5067 /*
5068 * This is probably broken, but we never maintained
5069 * a chandef in these cases, so it always was.
5070 */
5071 return le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_80);
5072 }
5073
5074 switch (chandef->width) {
eb89a6a6
MH
5075 case NL80211_CHAN_WIDTH_80P80:
5076 tx_mcs = he_cap->he_mcs_nss_supp.tx_mcs_80p80;
5077 break;
5078 case NL80211_CHAN_WIDTH_160:
5079 tx_mcs = he_cap->he_mcs_nss_supp.tx_mcs_160;
5080 break;
5081 default:
5082 tx_mcs = he_cap->he_mcs_nss_supp.tx_mcs_80;
5083 break;
5084 }
7b0a0e3c 5085
eb89a6a6
MH
5086 return le16_to_cpu(tx_mcs);
5087}
5088
5089static bool he_set_mcs_mask(struct genl_info *info,
5090 struct wireless_dev *wdev,
5091 struct ieee80211_supported_band *sband,
5092 struct nl80211_txrate_he *txrate,
7b0a0e3c
JB
5093 u16 mcs[NL80211_HE_NSS_MAX],
5094 unsigned int link_id)
eb89a6a6
MH
5095{
5096 const struct ieee80211_sta_he_cap *he_cap;
5097 u16 tx_mcs_mask[NL80211_HE_NSS_MAX] = {};
5098 u16 tx_mcs_map = 0;
5099 u8 i;
5100
5101 he_cap = ieee80211_get_he_iftype_cap(sband, wdev->iftype);
5102 if (!he_cap)
5103 return false;
5104
5105 memset(mcs, 0, sizeof(u16) * NL80211_HE_NSS_MAX);
5106
7b0a0e3c 5107 tx_mcs_map = he_get_txmcsmap(info, link_id, he_cap);
eb89a6a6
MH
5108
5109 /* Build he_mcs_mask from HE capabilities */
5110 he_build_mcs_mask(tx_mcs_map, tx_mcs_mask);
5111
5112 for (i = 0; i < NL80211_HE_NSS_MAX; i++) {
5113 if ((tx_mcs_mask[i] & txrate->mcs[i]) == txrate->mcs[i])
5114 mcs[i] = txrate->mcs[i];
5115 else
5116 return false;
5117 }
5118
5119 return true;
5120}
5121
a7c7fbff 5122static int nl80211_parse_tx_bitrate_mask(struct genl_info *info,
9a5f6488
TC
5123 struct nlattr *attrs[],
5124 enum nl80211_attrs attr,
eb89a6a6 5125 struct cfg80211_bitrate_mask *mask,
857b34c4 5126 struct net_device *dev,
7b0a0e3c
JB
5127 bool default_all_enabled,
5128 unsigned int link_id)
a7c7fbff
PK
5129{
5130 struct nlattr *tb[NL80211_TXRATE_MAX + 1];
5131 struct cfg80211_registered_device *rdev = info->user_ptr[0];
eb89a6a6 5132 struct wireless_dev *wdev = dev->ieee80211_ptr;
a7c7fbff
PK
5133 int rem, i;
5134 struct nlattr *tx_rates;
5135 struct ieee80211_supported_band *sband;
eb89a6a6 5136 u16 vht_tx_mcs_map, he_tx_mcs_map;
a7c7fbff
PK
5137
5138 memset(mask, 0, sizeof(*mask));
5139 /* Default to all rates enabled */
5140 for (i = 0; i < NUM_NL80211_BANDS; i++) {
eb89a6a6
MH
5141 const struct ieee80211_sta_he_cap *he_cap;
5142
857b34c4
RM
5143 if (!default_all_enabled)
5144 break;
5145
a7c7fbff
PK
5146 sband = rdev->wiphy.bands[i];
5147
5148 if (!sband)
5149 continue;
5150
5151 mask->control[i].legacy = (1 << sband->n_bitrates) - 1;
5152 memcpy(mask->control[i].ht_mcs,
5153 sband->ht_cap.mcs.rx_mask,
5154 sizeof(mask->control[i].ht_mcs));
5155
9df66d5b
PKS
5156 if (sband->vht_cap.vht_supported) {
5157 vht_tx_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map);
5158 vht_build_mcs_mask(vht_tx_mcs_map, mask->control[i].vht_mcs);
5159 }
eb89a6a6
MH
5160
5161 he_cap = ieee80211_get_he_iftype_cap(sband, wdev->iftype);
5162 if (!he_cap)
5163 continue;
5164
7b0a0e3c 5165 he_tx_mcs_map = he_get_txmcsmap(info, link_id, he_cap);
eb89a6a6
MH
5166 he_build_mcs_mask(he_tx_mcs_map, mask->control[i].he_mcs);
5167
5168 mask->control[i].he_gi = 0xFF;
5169 mask->control[i].he_ltf = 0xFF;
a7c7fbff
PK
5170 }
5171
5172 /* if no rates are given set it back to the defaults */
9a5f6488 5173 if (!attrs[attr])
a7c7fbff
PK
5174 goto out;
5175
5176 /* The nested attribute uses enum nl80211_band as the index. This maps
5177 * directly to the enum nl80211_band values used in cfg80211.
5178 */
5179 BUILD_BUG_ON(NL80211_MAX_SUPP_HT_RATES > IEEE80211_HT_MCS_MASK_LEN * 8);
9a5f6488 5180 nla_for_each_nested(tx_rates, attrs[attr], rem) {
a7c7fbff
PK
5181 enum nl80211_band band = nla_type(tx_rates);
5182 int err;
5183
5184 if (band < 0 || band >= NUM_NL80211_BANDS)
5185 return -EINVAL;
5186 sband = rdev->wiphy.bands[band];
5187 if (sband == NULL)
5188 return -EINVAL;
8cb08174
JB
5189 err = nla_parse_nested_deprecated(tb, NL80211_TXRATE_MAX,
5190 tx_rates,
5191 nl80211_txattr_policy,
5192 info->extack);
a7c7fbff
PK
5193 if (err)
5194 return err;
5195 if (tb[NL80211_TXRATE_LEGACY]) {
5196 mask->control[band].legacy = rateset_to_mask(
5197 sband,
5198 nla_data(tb[NL80211_TXRATE_LEGACY]),
5199 nla_len(tb[NL80211_TXRATE_LEGACY]));
5200 if ((mask->control[band].legacy == 0) &&
5201 nla_len(tb[NL80211_TXRATE_LEGACY]))
5202 return -EINVAL;
5203 }
5204 if (tb[NL80211_TXRATE_HT]) {
5205 if (!ht_rateset_to_mask(
5206 sband,
5207 nla_data(tb[NL80211_TXRATE_HT]),
5208 nla_len(tb[NL80211_TXRATE_HT]),
5209 mask->control[band].ht_mcs))
5210 return -EINVAL;
5211 }
c4a30446 5212
a7c7fbff
PK
5213 if (tb[NL80211_TXRATE_VHT]) {
5214 if (!vht_set_mcs_mask(
5215 sband,
5216 nla_data(tb[NL80211_TXRATE_VHT]),
5217 mask->control[band].vht_mcs))
5218 return -EINVAL;
5219 }
c4a30446 5220
a7c7fbff
PK
5221 if (tb[NL80211_TXRATE_GI]) {
5222 mask->control[band].gi =
5223 nla_get_u8(tb[NL80211_TXRATE_GI]);
5224 if (mask->control[band].gi > NL80211_TXRATE_FORCE_LGI)
5225 return -EINVAL;
5226 }
eb89a6a6
MH
5227 if (tb[NL80211_TXRATE_HE] &&
5228 !he_set_mcs_mask(info, wdev, sband,
5229 nla_data(tb[NL80211_TXRATE_HE]),
7b0a0e3c
JB
5230 mask->control[band].he_mcs,
5231 link_id))
eb89a6a6 5232 return -EINVAL;
c4a30446 5233
eb89a6a6
MH
5234 if (tb[NL80211_TXRATE_HE_GI])
5235 mask->control[band].he_gi =
5236 nla_get_u8(tb[NL80211_TXRATE_HE_GI]);
5237 if (tb[NL80211_TXRATE_HE_LTF])
5238 mask->control[band].he_ltf =
5239 nla_get_u8(tb[NL80211_TXRATE_HE_LTF]);
a7c7fbff
PK
5240
5241 if (mask->control[band].legacy == 0) {
eb89a6a6 5242 /* don't allow empty legacy rates if HT, VHT or HE
a7c7fbff
PK
5243 * are not even supported.
5244 */
5245 if (!(rdev->wiphy.bands[band]->ht_cap.ht_supported ||
eb89a6a6
MH
5246 rdev->wiphy.bands[band]->vht_cap.vht_supported ||
5247 ieee80211_get_he_iftype_cap(sband, wdev->iftype)))
a7c7fbff
PK
5248 return -EINVAL;
5249
5250 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++)
5251 if (mask->control[band].ht_mcs[i])
5252 goto out;
5253
5254 for (i = 0; i < NL80211_VHT_NSS_MAX; i++)
5255 if (mask->control[band].vht_mcs[i])
5256 goto out;
5257
eb89a6a6
MH
5258 for (i = 0; i < NL80211_HE_NSS_MAX; i++)
5259 if (mask->control[band].he_mcs[i])
5260 goto out;
5261
a7c7fbff
PK
5262 /* legacy and mcs rates may not be both empty */
5263 return -EINVAL;
5264 }
5265 }
5266
5267out:
5268 return 0;
5269}
5270
8564e382
JB
5271static int validate_beacon_tx_rate(struct cfg80211_registered_device *rdev,
5272 enum nl80211_band band,
5273 struct cfg80211_bitrate_mask *beacon_rate)
a7c7fbff 5274{
c4a30446 5275 u32 count_ht, count_vht, count_he, i;
8564e382 5276 u32 rate = beacon_rate->control[band].legacy;
a7c7fbff
PK
5277
5278 /* Allow only one rate */
5279 if (hweight32(rate) > 1)
5280 return -EINVAL;
5281
5282 count_ht = 0;
5283 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
8564e382 5284 if (hweight8(beacon_rate->control[band].ht_mcs[i]) > 1) {
a7c7fbff 5285 return -EINVAL;
8564e382 5286 } else if (beacon_rate->control[band].ht_mcs[i]) {
a7c7fbff
PK
5287 count_ht++;
5288 if (count_ht > 1)
5289 return -EINVAL;
5290 }
5291 if (count_ht && rate)
5292 return -EINVAL;
5293 }
5294
5295 count_vht = 0;
5296 for (i = 0; i < NL80211_VHT_NSS_MAX; i++) {
8564e382 5297 if (hweight16(beacon_rate->control[band].vht_mcs[i]) > 1) {
a7c7fbff 5298 return -EINVAL;
8564e382 5299 } else if (beacon_rate->control[band].vht_mcs[i]) {
a7c7fbff
PK
5300 count_vht++;
5301 if (count_vht > 1)
5302 return -EINVAL;
5303 }
5304 if (count_vht && rate)
5305 return -EINVAL;
5306 }
5307
c4a30446
RM
5308 count_he = 0;
5309 for (i = 0; i < NL80211_HE_NSS_MAX; i++) {
5310 if (hweight16(beacon_rate->control[band].he_mcs[i]) > 1) {
5311 return -EINVAL;
5312 } else if (beacon_rate->control[band].he_mcs[i]) {
5313 count_he++;
5314 if (count_he > 1)
5315 return -EINVAL;
5316 }
5317 if (count_he && rate)
5318 return -EINVAL;
5319 }
5320
5321 if ((count_ht && count_vht && count_he) ||
5322 (!rate && !count_ht && !count_vht && !count_he))
a7c7fbff
PK
5323 return -EINVAL;
5324
8564e382
JB
5325 if (rate &&
5326 !wiphy_ext_feature_isset(&rdev->wiphy,
5327 NL80211_EXT_FEATURE_BEACON_RATE_LEGACY))
5328 return -EINVAL;
5329 if (count_ht &&
5330 !wiphy_ext_feature_isset(&rdev->wiphy,
5331 NL80211_EXT_FEATURE_BEACON_RATE_HT))
5332 return -EINVAL;
5333 if (count_vht &&
5334 !wiphy_ext_feature_isset(&rdev->wiphy,
5335 NL80211_EXT_FEATURE_BEACON_RATE_VHT))
5336 return -EINVAL;
c4a30446
RM
5337 if (count_he &&
5338 !wiphy_ext_feature_isset(&rdev->wiphy,
5339 NL80211_EXT_FEATURE_BEACON_RATE_HE))
5340 return -EINVAL;
8564e382 5341
a7c7fbff
PK
5342 return 0;
5343}
5344
dc1e3cb8
JC
5345static int nl80211_parse_mbssid_config(struct wiphy *wiphy,
5346 struct net_device *dev,
5347 struct nlattr *attrs,
5348 struct cfg80211_mbssid_config *config,
5349 u8 num_elems)
5350{
5351 struct nlattr *tb[NL80211_MBSSID_CONFIG_ATTR_MAX + 1];
5352
5353 if (!wiphy->mbssid_max_interfaces)
5354 return -EOPNOTSUPP;
5355
5356 if (nla_parse_nested(tb, NL80211_MBSSID_CONFIG_ATTR_MAX, attrs, NULL,
5357 NULL) ||
5358 !tb[NL80211_MBSSID_CONFIG_ATTR_INDEX])
5359 return -EINVAL;
5360
5361 config->ema = nla_get_flag(tb[NL80211_MBSSID_CONFIG_ATTR_EMA]);
5362 if (config->ema) {
5363 if (!wiphy->ema_max_profile_periodicity)
5364 return -EOPNOTSUPP;
5365
5366 if (num_elems > wiphy->ema_max_profile_periodicity)
5367 return -EINVAL;
5368 }
5369
5370 config->index = nla_get_u8(tb[NL80211_MBSSID_CONFIG_ATTR_INDEX]);
5371 if (config->index >= wiphy->mbssid_max_interfaces ||
5372 (!config->index && !num_elems))
5373 return -EINVAL;
5374
5375 if (tb[NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX]) {
5376 u32 tx_ifindex =
5377 nla_get_u32(tb[NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX]);
5378
5379 if ((!config->index && tx_ifindex != dev->ifindex) ||
5380 (config->index && tx_ifindex == dev->ifindex))
5381 return -EINVAL;
5382
5383 if (tx_ifindex != dev->ifindex) {
5384 struct net_device *tx_netdev =
5385 dev_get_by_index(wiphy_net(wiphy), tx_ifindex);
5386
5387 if (!tx_netdev || !tx_netdev->ieee80211_ptr ||
5388 tx_netdev->ieee80211_ptr->wiphy != wiphy ||
5389 tx_netdev->ieee80211_ptr->iftype !=
5390 NL80211_IFTYPE_AP) {
5391 dev_put(tx_netdev);
5392 return -EINVAL;
5393 }
5394
5395 config->tx_wdev = tx_netdev->ieee80211_ptr;
5396 } else {
5397 config->tx_wdev = dev->ieee80211_ptr;
5398 }
5399 } else if (!config->index) {
5400 config->tx_wdev = dev->ieee80211_ptr;
5401 } else {
5402 return -EINVAL;
5403 }
5404
5405 return 0;
5406}
5407
5408static struct cfg80211_mbssid_elems *
5409nl80211_parse_mbssid_elems(struct wiphy *wiphy, struct nlattr *attrs)
5410{
5411 struct nlattr *nl_elems;
5412 struct cfg80211_mbssid_elems *elems;
5413 int rem_elems;
5414 u8 i = 0, num_elems = 0;
5415
5416 if (!wiphy->mbssid_max_interfaces)
5417 return ERR_PTR(-EINVAL);
5418
6311071a
KY
5419 nla_for_each_nested(nl_elems, attrs, rem_elems) {
5420 if (num_elems >= 255)
5421 return ERR_PTR(-EINVAL);
dc1e3cb8 5422 num_elems++;
6311071a 5423 }
dc1e3cb8
JC
5424
5425 elems = kzalloc(struct_size(elems, elem, num_elems), GFP_KERNEL);
5426 if (!elems)
5427 return ERR_PTR(-ENOMEM);
c14679d7 5428 elems->cnt = num_elems;
dc1e3cb8
JC
5429
5430 nla_for_each_nested(nl_elems, attrs, rem_elems) {
5431 elems->elem[i].data = nla_data(nl_elems);
5432 elems->elem[i].len = nla_len(nl_elems);
5433 i++;
5434 }
dc1e3cb8
JC
5435 return elems;
5436}
5437
dbbb27e1
AD
5438static struct cfg80211_rnr_elems *
5439nl80211_parse_rnr_elems(struct wiphy *wiphy, struct nlattr *attrs,
5440 struct netlink_ext_ack *extack)
5441{
5442 struct nlattr *nl_elems;
5443 struct cfg80211_rnr_elems *elems;
5444 int rem_elems;
5445 u8 i = 0, num_elems = 0;
5446
5447 nla_for_each_nested(nl_elems, attrs, rem_elems) {
5448 int ret;
5449
5450 ret = validate_ie_attr(nl_elems, extack);
5451 if (ret)
5452 return ERR_PTR(ret);
5453
5454 num_elems++;
5455 }
5456
5457 elems = kzalloc(struct_size(elems, elem, num_elems), GFP_KERNEL);
5458 if (!elems)
5459 return ERR_PTR(-ENOMEM);
7b6d7087 5460 elems->cnt = num_elems;
dbbb27e1
AD
5461
5462 nla_for_each_nested(nl_elems, attrs, rem_elems) {
5463 elems->elem[i].data = nla_data(nl_elems);
5464 elems->elem[i].len = nla_len(nl_elems);
5465 i++;
5466 }
dbbb27e1
AD
5467 return elems;
5468}
5469
3d48cb74
RS
5470static int nl80211_parse_he_bss_color(struct nlattr *attrs,
5471 struct cfg80211_he_bss_color *he_bss_color)
5472{
5473 struct nlattr *tb[NL80211_HE_BSS_COLOR_ATTR_MAX + 1];
5474 int err;
5475
5476 err = nla_parse_nested(tb, NL80211_HE_BSS_COLOR_ATTR_MAX, attrs,
5477 he_bss_color_policy, NULL);
5478 if (err)
5479 return err;
5480
5481 if (!tb[NL80211_HE_BSS_COLOR_ATTR_COLOR])
5482 return -EINVAL;
5483
5484 he_bss_color->color =
5485 nla_get_u8(tb[NL80211_HE_BSS_COLOR_ATTR_COLOR]);
5486 he_bss_color->enabled =
5487 !nla_get_flag(tb[NL80211_HE_BSS_COLOR_ATTR_DISABLED]);
5488 he_bss_color->partial =
5489 nla_get_flag(tb[NL80211_HE_BSS_COLOR_ATTR_PARTIAL]);
5490
5491 return 0;
5492}
5493
81e54d08
PKC
5494static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev,
5495 struct nlattr *attrs[],
dbbb27e1
AD
5496 struct cfg80211_beacon_data *bcn,
5497 struct netlink_ext_ack *extack)
ed1b6cc7 5498{
8860020e 5499 bool haveinfo = false;
81e54d08 5500 int err;
ed1b6cc7 5501
8860020e 5502 memset(bcn, 0, sizeof(*bcn));
ed1b6cc7 5503
7b0a0e3c
JB
5504 bcn->link_id = nl80211_link_id(attrs);
5505
a1193be8
SW
5506 if (attrs[NL80211_ATTR_BEACON_HEAD]) {
5507 bcn->head = nla_data(attrs[NL80211_ATTR_BEACON_HEAD]);
5508 bcn->head_len = nla_len(attrs[NL80211_ATTR_BEACON_HEAD]);
8860020e
JB
5509 if (!bcn->head_len)
5510 return -EINVAL;
5511 haveinfo = true;
ed1b6cc7
JB
5512 }
5513
a1193be8
SW
5514 if (attrs[NL80211_ATTR_BEACON_TAIL]) {
5515 bcn->tail = nla_data(attrs[NL80211_ATTR_BEACON_TAIL]);
5516 bcn->tail_len = nla_len(attrs[NL80211_ATTR_BEACON_TAIL]);
8860020e 5517 haveinfo = true;
ed1b6cc7
JB
5518 }
5519
4c476991
JB
5520 if (!haveinfo)
5521 return -EINVAL;
3b85875a 5522
a1193be8
SW
5523 if (attrs[NL80211_ATTR_IE]) {
5524 bcn->beacon_ies = nla_data(attrs[NL80211_ATTR_IE]);
5525 bcn->beacon_ies_len = nla_len(attrs[NL80211_ATTR_IE]);
9946ecfb
JM
5526 }
5527
a1193be8 5528 if (attrs[NL80211_ATTR_IE_PROBE_RESP]) {
8860020e 5529 bcn->proberesp_ies =
a1193be8 5530 nla_data(attrs[NL80211_ATTR_IE_PROBE_RESP]);
8860020e 5531 bcn->proberesp_ies_len =
a1193be8 5532 nla_len(attrs[NL80211_ATTR_IE_PROBE_RESP]);
9946ecfb
JM
5533 }
5534
a1193be8 5535 if (attrs[NL80211_ATTR_IE_ASSOC_RESP]) {
8860020e 5536 bcn->assocresp_ies =
a1193be8 5537 nla_data(attrs[NL80211_ATTR_IE_ASSOC_RESP]);
8860020e 5538 bcn->assocresp_ies_len =
a1193be8 5539 nla_len(attrs[NL80211_ATTR_IE_ASSOC_RESP]);
9946ecfb
JM
5540 }
5541
a1193be8
SW
5542 if (attrs[NL80211_ATTR_PROBE_RESP]) {
5543 bcn->probe_resp = nla_data(attrs[NL80211_ATTR_PROBE_RESP]);
5544 bcn->probe_resp_len = nla_len(attrs[NL80211_ATTR_PROBE_RESP]);
00f740e1
AN
5545 }
5546
81e54d08
PKC
5547 if (attrs[NL80211_ATTR_FTM_RESPONDER]) {
5548 struct nlattr *tb[NL80211_FTM_RESP_ATTR_MAX + 1];
5549
8cb08174
JB
5550 err = nla_parse_nested_deprecated(tb,
5551 NL80211_FTM_RESP_ATTR_MAX,
5552 attrs[NL80211_ATTR_FTM_RESPONDER],
5553 NULL, NULL);
81e54d08
PKC
5554 if (err)
5555 return err;
5556
5557 if (tb[NL80211_FTM_RESP_ATTR_ENABLED] &&
5558 wiphy_ext_feature_isset(&rdev->wiphy,
5559 NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER))
5560 bcn->ftm_responder = 1;
5561 else
5562 return -EOPNOTSUPP;
5563
5564 if (tb[NL80211_FTM_RESP_ATTR_LCI]) {
5565 bcn->lci = nla_data(tb[NL80211_FTM_RESP_ATTR_LCI]);
5566 bcn->lci_len = nla_len(tb[NL80211_FTM_RESP_ATTR_LCI]);
5567 }
5568
5569 if (tb[NL80211_FTM_RESP_ATTR_CIVICLOC]) {
5570 bcn->civicloc = nla_data(tb[NL80211_FTM_RESP_ATTR_CIVICLOC]);
5571 bcn->civicloc_len = nla_len(tb[NL80211_FTM_RESP_ATTR_CIVICLOC]);
5572 }
5573 } else {
5574 bcn->ftm_responder = -1;
5575 }
5576
3d48cb74
RS
5577 if (attrs[NL80211_ATTR_HE_BSS_COLOR]) {
5578 err = nl80211_parse_he_bss_color(attrs[NL80211_ATTR_HE_BSS_COLOR],
5579 &bcn->he_bss_color);
5580 if (err)
5581 return err;
5582 bcn->he_bss_color_valid = true;
5583 }
5584
dc1e3cb8
JC
5585 if (attrs[NL80211_ATTR_MBSSID_ELEMS]) {
5586 struct cfg80211_mbssid_elems *mbssid =
5587 nl80211_parse_mbssid_elems(&rdev->wiphy,
5588 attrs[NL80211_ATTR_MBSSID_ELEMS]);
5589
5590 if (IS_ERR(mbssid))
5591 return PTR_ERR(mbssid);
5592
5593 bcn->mbssid_ies = mbssid;
dbbb27e1
AD
5594
5595 if (bcn->mbssid_ies && attrs[NL80211_ATTR_EMA_RNR_ELEMS]) {
5596 struct cfg80211_rnr_elems *rnr =
5597 nl80211_parse_rnr_elems(&rdev->wiphy,
5598 attrs[NL80211_ATTR_EMA_RNR_ELEMS],
5599 extack);
5600
5601 if (IS_ERR(rnr))
5602 return PTR_ERR(rnr);
5603
5604 if (rnr && rnr->cnt < bcn->mbssid_ies->cnt)
5605 return -EINVAL;
5606
5607 bcn->rnr_ies = rnr;
5608 }
dc1e3cb8
JC
5609 }
5610
8860020e
JB
5611 return 0;
5612}
5613
796e90f4
JC
5614static int nl80211_parse_he_obss_pd(struct nlattr *attrs,
5615 struct ieee80211_he_obss_pd *he_obss_pd)
5616{
5617 struct nlattr *tb[NL80211_HE_OBSS_PD_ATTR_MAX + 1];
5618 int err;
5619
5620 err = nla_parse_nested(tb, NL80211_HE_OBSS_PD_ATTR_MAX, attrs,
5621 he_obss_pd_policy, NULL);
5622 if (err)
5623 return err;
5624
f5bec330
RM
5625 if (!tb[NL80211_HE_OBSS_PD_ATTR_SR_CTRL])
5626 return -EINVAL;
5627
5628 he_obss_pd->sr_ctrl = nla_get_u8(tb[NL80211_HE_OBSS_PD_ATTR_SR_CTRL]);
5629
6c8b6e4a
RM
5630 if (tb[NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET])
5631 he_obss_pd->min_offset =
5632 nla_get_u8(tb[NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET]);
5633 if (tb[NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET])
5634 he_obss_pd->max_offset =
5635 nla_get_u8(tb[NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET]);
f5bec330
RM
5636 if (tb[NL80211_HE_OBSS_PD_ATTR_NON_SRG_MAX_OFFSET])
5637 he_obss_pd->non_srg_max_offset =
5638 nla_get_u8(tb[NL80211_HE_OBSS_PD_ATTR_NON_SRG_MAX_OFFSET]);
6c8b6e4a
RM
5639
5640 if (he_obss_pd->min_offset > he_obss_pd->max_offset)
796e90f4
JC
5641 return -EINVAL;
5642
f5bec330
RM
5643 if (tb[NL80211_HE_OBSS_PD_ATTR_BSS_COLOR_BITMAP])
5644 memcpy(he_obss_pd->bss_color_bitmap,
5645 nla_data(tb[NL80211_HE_OBSS_PD_ATTR_BSS_COLOR_BITMAP]),
5646 sizeof(he_obss_pd->bss_color_bitmap));
5647
5648 if (tb[NL80211_HE_OBSS_PD_ATTR_PARTIAL_BSSID_BITMAP])
5649 memcpy(he_obss_pd->partial_bssid_bitmap,
5650 nla_data(tb[NL80211_HE_OBSS_PD_ATTR_PARTIAL_BSSID_BITMAP]),
5651 sizeof(he_obss_pd->partial_bssid_bitmap));
5652
796e90f4
JC
5653 he_obss_pd->enable = true;
5654
5655 return 0;
5656}
5657
291c49de
AD
5658static int nl80211_parse_fils_discovery(struct cfg80211_registered_device *rdev,
5659 struct nlattr *attrs,
bb55441c 5660 struct cfg80211_fils_discovery *fd)
291c49de
AD
5661{
5662 struct nlattr *tb[NL80211_FILS_DISCOVERY_ATTR_MAX + 1];
5663 int ret;
291c49de
AD
5664
5665 if (!wiphy_ext_feature_isset(&rdev->wiphy,
5666 NL80211_EXT_FEATURE_FILS_DISCOVERY))
5667 return -EINVAL;
5668
5669 ret = nla_parse_nested(tb, NL80211_FILS_DISCOVERY_ATTR_MAX, attrs,
5670 NULL, NULL);
5671 if (ret)
5672 return ret;
5673
0cfaec25
AD
5674 if (!tb[NL80211_FILS_DISCOVERY_ATTR_INT_MIN] &&
5675 !tb[NL80211_FILS_DISCOVERY_ATTR_INT_MAX] &&
5676 !tb[NL80211_FILS_DISCOVERY_ATTR_TMPL]) {
5677 fd->update = true;
5678 return 0;
5679 }
5680
291c49de
AD
5681 if (!tb[NL80211_FILS_DISCOVERY_ATTR_INT_MIN] ||
5682 !tb[NL80211_FILS_DISCOVERY_ATTR_INT_MAX] ||
5683 !tb[NL80211_FILS_DISCOVERY_ATTR_TMPL])
5684 return -EINVAL;
5685
5686 fd->tmpl_len = nla_len(tb[NL80211_FILS_DISCOVERY_ATTR_TMPL]);
5687 fd->tmpl = nla_data(tb[NL80211_FILS_DISCOVERY_ATTR_TMPL]);
5688 fd->min_interval = nla_get_u32(tb[NL80211_FILS_DISCOVERY_ATTR_INT_MIN]);
5689 fd->max_interval = nla_get_u32(tb[NL80211_FILS_DISCOVERY_ATTR_INT_MAX]);
0cfaec25 5690 fd->update = true;
291c49de
AD
5691 return 0;
5692}
5693
7443dcd1
AD
5694static int
5695nl80211_parse_unsol_bcast_probe_resp(struct cfg80211_registered_device *rdev,
5696 struct nlattr *attrs,
bb55441c 5697 struct cfg80211_unsol_bcast_probe_resp *presp)
7443dcd1
AD
5698{
5699 struct nlattr *tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_MAX + 1];
5700 int ret;
7443dcd1
AD
5701
5702 if (!wiphy_ext_feature_isset(&rdev->wiphy,
5703 NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP))
5704 return -EINVAL;
5705
5706 ret = nla_parse_nested(tb, NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_MAX,
5707 attrs, NULL, NULL);
5708 if (ret)
5709 return ret;
5710
0cfaec25
AD
5711 if (!tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INT] &&
5712 !tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL]) {
5713 presp->update = true;
5714 return 0;
5715 }
5716
7443dcd1
AD
5717 if (!tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INT] ||
5718 !tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL])
5719 return -EINVAL;
5720
5721 presp->tmpl = nla_data(tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL]);
5722 presp->tmpl_len = nla_len(tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL]);
5723 presp->interval = nla_get_u32(tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INT]);
0cfaec25 5724 presp->update = true;
7443dcd1
AD
5725 return 0;
5726}
5727
66cd794e 5728static void nl80211_check_ap_rate_selectors(struct cfg80211_ap_settings *params,
153e2a11 5729 const struct element *rates)
66cd794e
JB
5730{
5731 int i;
5732
5733 if (!rates)
5734 return;
5735
153e2a11
JB
5736 for (i = 0; i < rates->datalen; i++) {
5737 if (rates->data[i] == BSS_MEMBERSHIP_SELECTOR_HT_PHY)
66cd794e 5738 params->ht_required = true;
153e2a11 5739 if (rates->data[i] == BSS_MEMBERSHIP_SELECTOR_VHT_PHY)
66cd794e 5740 params->vht_required = true;
153e2a11 5741 if (rates->data[i] == BSS_MEMBERSHIP_SELECTOR_HE_PHY)
2a392596 5742 params->he_required = true;
153e2a11 5743 if (rates->data[i] == BSS_MEMBERSHIP_SELECTOR_SAE_H2E)
d6587602 5744 params->sae_h2e_required = true;
66cd794e
JB
5745 }
5746}
5747
5748/*
5749 * Since the nl80211 API didn't include, from the beginning, attributes about
5750 * HT/VHT requirements/capabilities, we parse them out of the IEs for the
5751 * benefit of drivers that rebuild IEs in the firmware.
5752 */
8bc65d38 5753static int nl80211_calculate_ap_params(struct cfg80211_ap_settings *params)
66cd794e
JB
5754{
5755 const struct cfg80211_beacon_data *bcn = &params->beacon;
ba83bfb1
IM
5756 size_t ies_len = bcn->tail_len;
5757 const u8 *ies = bcn->tail;
153e2a11
JB
5758 const struct element *rates;
5759 const struct element *cap;
66cd794e 5760
153e2a11 5761 rates = cfg80211_find_elem(WLAN_EID_SUPP_RATES, ies, ies_len);
66cd794e
JB
5762 nl80211_check_ap_rate_selectors(params, rates);
5763
153e2a11 5764 rates = cfg80211_find_elem(WLAN_EID_EXT_SUPP_RATES, ies, ies_len);
66cd794e
JB
5765 nl80211_check_ap_rate_selectors(params, rates);
5766
153e2a11
JB
5767 cap = cfg80211_find_elem(WLAN_EID_HT_CAPABILITY, ies, ies_len);
5768 if (cap && cap->datalen >= sizeof(*params->ht_cap))
5769 params->ht_cap = (void *)cap->data;
5770 cap = cfg80211_find_elem(WLAN_EID_VHT_CAPABILITY, ies, ies_len);
5771 if (cap && cap->datalen >= sizeof(*params->vht_cap))
5772 params->vht_cap = (void *)cap->data;
5773 cap = cfg80211_find_ext_elem(WLAN_EID_EXT_HE_CAPABILITY, ies, ies_len);
5774 if (cap && cap->datalen >= sizeof(*params->he_cap) + 1)
5775 params->he_cap = (void *)(cap->data + 1);
5776 cap = cfg80211_find_ext_elem(WLAN_EID_EXT_HE_OPERATION, ies, ies_len);
5777 if (cap && cap->datalen >= sizeof(*params->he_oper) + 1)
5778 params->he_oper = (void *)(cap->data + 1);
8bc65d38
AD
5779 cap = cfg80211_find_ext_elem(WLAN_EID_EXT_EHT_CAPABILITY, ies, ies_len);
5780 if (cap) {
5781 if (!cap->datalen)
5782 return -EINVAL;
5783 params->eht_cap = (void *)(cap->data + 1);
5784 if (!ieee80211_eht_capa_size_ok((const u8 *)params->he_cap,
5785 (const u8 *)params->eht_cap,
ea5cba26 5786 cap->datalen - 1, true))
8bc65d38
AD
5787 return -EINVAL;
5788 }
5789 cap = cfg80211_find_ext_elem(WLAN_EID_EXT_EHT_OPERATION, ies, ies_len);
5790 if (cap) {
5791 if (!cap->datalen)
5792 return -EINVAL;
5793 params->eht_oper = (void *)(cap->data + 1);
5794 if (!ieee80211_eht_oper_size_ok((const u8 *)params->eht_oper,
5795 cap->datalen - 1))
5796 return -EINVAL;
5797 }
5798 return 0;
66cd794e
JB
5799}
5800
46c1dd0c
FF
5801static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev,
5802 struct cfg80211_ap_settings *params)
5803{
5804 struct wireless_dev *wdev;
46c1dd0c 5805
53873f13 5806 list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
46c1dd0c
FF
5807 if (wdev->iftype != NL80211_IFTYPE_AP &&
5808 wdev->iftype != NL80211_IFTYPE_P2P_GO)
5809 continue;
5810
7b0a0e3c 5811 if (!wdev->u.ap.preset_chandef.chan)
46c1dd0c
FF
5812 continue;
5813
7b0a0e3c
JB
5814 params->chandef = wdev->u.ap.preset_chandef;
5815 return true;
46c1dd0c
FF
5816 }
5817
7b0a0e3c 5818 return false;
46c1dd0c
FF
5819}
5820
e39e5b5e
JM
5821static bool nl80211_valid_auth_type(struct cfg80211_registered_device *rdev,
5822 enum nl80211_auth_type auth_type,
5823 enum nl80211_commands cmd)
5824{
5825 if (auth_type > NL80211_AUTHTYPE_MAX)
5826 return false;
5827
5828 switch (cmd) {
5829 case NL80211_CMD_AUTHENTICATE:
5830 if (!(rdev->wiphy.features & NL80211_FEATURE_SAE) &&
5831 auth_type == NL80211_AUTHTYPE_SAE)
5832 return false;
63181060
JM
5833 if (!wiphy_ext_feature_isset(&rdev->wiphy,
5834 NL80211_EXT_FEATURE_FILS_STA) &&
5835 (auth_type == NL80211_AUTHTYPE_FILS_SK ||
5836 auth_type == NL80211_AUTHTYPE_FILS_SK_PFS ||
5837 auth_type == NL80211_AUTHTYPE_FILS_PK))
5838 return false;
e39e5b5e
JM
5839 return true;
5840 case NL80211_CMD_CONNECT:
10773a7c 5841 if (!(rdev->wiphy.features & NL80211_FEATURE_SAE) &&
26f7044e
CHH
5842 !wiphy_ext_feature_isset(&rdev->wiphy,
5843 NL80211_EXT_FEATURE_SAE_OFFLOAD) &&
10773a7c 5844 auth_type == NL80211_AUTHTYPE_SAE)
a3caf744 5845 return false;
10773a7c 5846
a3caf744
VK
5847 /* FILS with SK PFS or PK not supported yet */
5848 if (auth_type == NL80211_AUTHTYPE_FILS_SK_PFS ||
5849 auth_type == NL80211_AUTHTYPE_FILS_PK)
5850 return false;
5851 if (!wiphy_ext_feature_isset(
5852 &rdev->wiphy,
5853 NL80211_EXT_FEATURE_FILS_SK_OFFLOAD) &&
5854 auth_type == NL80211_AUTHTYPE_FILS_SK)
5855 return false;
5856 return true;
e39e5b5e 5857 case NL80211_CMD_START_AP:
2831a631
CHH
5858 if (!wiphy_ext_feature_isset(&rdev->wiphy,
5859 NL80211_EXT_FEATURE_SAE_OFFLOAD_AP) &&
5860 auth_type == NL80211_AUTHTYPE_SAE)
e39e5b5e 5861 return false;
63181060
JM
5862 /* FILS not supported yet */
5863 if (auth_type == NL80211_AUTHTYPE_FILS_SK ||
5864 auth_type == NL80211_AUTHTYPE_FILS_SK_PFS ||
5865 auth_type == NL80211_AUTHTYPE_FILS_PK)
5866 return false;
e39e5b5e
JM
5867 return true;
5868 default:
5869 return false;
5870 }
5871}
5872
77669c15
5873static void nl80211_send_ap_started(struct wireless_dev *wdev,
5874 unsigned int link_id)
5875{
5876 struct wiphy *wiphy = wdev->wiphy;
5877 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
5878 struct sk_buff *msg;
5879 void *hdr;
5880
5881 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
5882 if (!msg)
5883 return;
5884
5885 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_START_AP);
5886 if (!hdr)
5887 goto out;
5888
5889 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
5890 nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex) ||
5891 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
5892 NL80211_ATTR_PAD) ||
5893 (wdev->u.ap.ssid_len &&
5894 nla_put(msg, NL80211_ATTR_SSID, wdev->u.ap.ssid_len,
5895 wdev->u.ap.ssid)) ||
5896 (wdev->valid_links &&
5897 nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id)))
5898 goto out;
5899
5900 genlmsg_end(msg, hdr);
5901
5902 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(wiphy), msg, 0,
5903 NL80211_MCGRP_MLME, GFP_KERNEL);
5904 return;
5905out:
5906 nlmsg_free(msg);
5907}
5908
5112fa50
AKS
5909static int nl80211_validate_ap_phy_operation(struct cfg80211_ap_settings *params)
5910{
5911 struct ieee80211_channel *channel = params->chandef.chan;
5912
5913 if ((params->he_cap || params->he_oper) &&
5914 (channel->flags & IEEE80211_CHAN_NO_HE))
5915 return -EOPNOTSUPP;
5916
5917 if ((params->eht_cap || params->eht_oper) &&
5918 (channel->flags & IEEE80211_CHAN_NO_EHT))
5919 return -EOPNOTSUPP;
5920
5921 return 0;
5922}
5923
8860020e
JB
5924static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
5925{
5926 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7b0a0e3c 5927 unsigned int link_id = nl80211_link_id(info->attrs);
8860020e
JB
5928 struct net_device *dev = info->user_ptr[1];
5929 struct wireless_dev *wdev = dev->ieee80211_ptr;
9e263e19 5930 struct cfg80211_ap_settings *params;
8860020e
JB
5931 int err;
5932
5933 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
5934 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
5935 return -EOPNOTSUPP;
5936
5937 if (!rdev->ops->start_ap)
5938 return -EOPNOTSUPP;
5939
7b0a0e3c 5940 if (wdev->links[link_id].ap.beacon_interval)
8860020e
JB
5941 return -EALREADY;
5942
8860020e
JB
5943 /* these are required for START_AP */
5944 if (!info->attrs[NL80211_ATTR_BEACON_INTERVAL] ||
5945 !info->attrs[NL80211_ATTR_DTIM_PERIOD] ||
5946 !info->attrs[NL80211_ATTR_BEACON_HEAD])
5947 return -EINVAL;
5948
9e263e19
JB
5949 params = kzalloc(sizeof(*params), GFP_KERNEL);
5950 if (!params)
5951 return -ENOMEM;
5952
dbbb27e1
AD
5953 err = nl80211_parse_beacon(rdev, info->attrs, &params->beacon,
5954 info->extack);
8860020e 5955 if (err)
9e263e19 5956 goto out;
8860020e 5957
9e263e19 5958 params->beacon_interval =
8860020e 5959 nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
9e263e19 5960 params->dtim_period =
8860020e
JB
5961 nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);
5962
0c317a02 5963 err = cfg80211_validate_beacon_int(rdev, dev->ieee80211_ptr->iftype,
9e263e19 5964 params->beacon_interval);
8860020e 5965 if (err)
9e263e19 5966 goto out;
8860020e
JB
5967
5968 /*
5969 * In theory, some of these attributes should be required here
5970 * but since they were not used when the command was originally
5971 * added, keep them optional for old user space programs to let
5972 * them continue to work with drivers that do not need the
5973 * additional information -- drivers must check!
5974 */
5975 if (info->attrs[NL80211_ATTR_SSID]) {
9e263e19
JB
5976 params->ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
5977 params->ssid_len =
8860020e 5978 nla_len(info->attrs[NL80211_ATTR_SSID]);
9e263e19
JB
5979 if (params->ssid_len == 0) {
5980 err = -EINVAL;
5981 goto out;
5982 }
7b0a0e3c
JB
5983
5984 if (wdev->u.ap.ssid_len &&
5985 (wdev->u.ap.ssid_len != params->ssid_len ||
5986 memcmp(wdev->u.ap.ssid, params->ssid, params->ssid_len))) {
5987 /* require identical SSID for MLO */
5988 err = -EINVAL;
5989 goto out;
5990 }
5991 } else if (wdev->valid_links) {
5992 /* require SSID for MLO */
5993 err = -EINVAL;
5994 goto out;
8860020e
JB
5995 }
5996
ab0d76f6 5997 if (info->attrs[NL80211_ATTR_HIDDEN_SSID])
9e263e19 5998 params->hidden_ssid = nla_get_u32(
8860020e 5999 info->attrs[NL80211_ATTR_HIDDEN_SSID]);
8860020e 6000
9e263e19 6001 params->privacy = !!info->attrs[NL80211_ATTR_PRIVACY];
8860020e
JB
6002
6003 if (info->attrs[NL80211_ATTR_AUTH_TYPE]) {
9e263e19 6004 params->auth_type = nla_get_u32(
8860020e 6005 info->attrs[NL80211_ATTR_AUTH_TYPE]);
9e263e19
JB
6006 if (!nl80211_valid_auth_type(rdev, params->auth_type,
6007 NL80211_CMD_START_AP)) {
6008 err = -EINVAL;
6009 goto out;
6010 }
8860020e 6011 } else
9e263e19 6012 params->auth_type = NL80211_AUTHTYPE_AUTOMATIC;
8860020e 6013
9e263e19 6014 err = nl80211_crypto_settings(rdev, info, &params->crypto,
8860020e
JB
6015 NL80211_MAX_NR_CIPHER_SUITES);
6016 if (err)
9e263e19 6017 goto out;
8860020e 6018
1b658f11 6019 if (info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]) {
9e263e19
JB
6020 if (!(rdev->wiphy.features & NL80211_FEATURE_INACTIVITY_TIMER)) {
6021 err = -EOPNOTSUPP;
6022 goto out;
6023 }
6024 params->inactivity_timeout = nla_get_u16(
1b658f11
VT
6025 info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]);
6026 }
6027
53cabad7 6028 if (info->attrs[NL80211_ATTR_P2P_CTWINDOW]) {
9e263e19
JB
6029 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
6030 err = -EINVAL;
6031 goto out;
6032 }
6033 params->p2p_ctwindow =
53cabad7 6034 nla_get_u8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]);
9e263e19
JB
6035 if (params->p2p_ctwindow != 0 &&
6036 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN)) {
6037 err = -EINVAL;
6038 goto out;
6039 }
53cabad7
JB
6040 }
6041
6042 if (info->attrs[NL80211_ATTR_P2P_OPPPS]) {
6043 u8 tmp;
6044
9e263e19
JB
6045 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
6046 err = -EINVAL;
6047 goto out;
6048 }
53cabad7 6049 tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]);
9e263e19
JB
6050 params->p2p_opp_ps = tmp;
6051 if (params->p2p_opp_ps != 0 &&
6052 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS)) {
6053 err = -EINVAL;
6054 goto out;
6055 }
53cabad7
JB
6056 }
6057
aa430da4 6058 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
9e263e19 6059 err = nl80211_parse_chandef(rdev, info, &params->chandef);
683b6d3b 6060 if (err)
9e263e19 6061 goto out;
7b0a0e3c
JB
6062 } else if (wdev->valid_links) {
6063 /* with MLD need to specify the channel configuration */
6064 err = -EINVAL;
6065 goto out;
6066 } else if (wdev->u.ap.preset_chandef.chan) {
6067 params->chandef = wdev->u.ap.preset_chandef;
9e263e19
JB
6068 } else if (!nl80211_get_ap_channel(rdev, params)) {
6069 err = -EINVAL;
6070 goto out;
6071 }
aa430da4 6072
9e263e19
JB
6073 if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &params->chandef,
6074 wdev->iftype)) {
6075 err = -EINVAL;
6076 goto out;
6077 }
aa430da4 6078
a7c7fbff 6079 if (info->attrs[NL80211_ATTR_TX_RATES]) {
9a5f6488
TC
6080 err = nl80211_parse_tx_bitrate_mask(info, info->attrs,
6081 NL80211_ATTR_TX_RATES,
9e263e19 6082 &params->beacon_rate,
7b0a0e3c 6083 dev, false, link_id);
a7c7fbff 6084 if (err)
076fc877 6085 goto out;
a7c7fbff 6086
9e263e19
JB
6087 err = validate_beacon_tx_rate(rdev, params->chandef.chan->band,
6088 &params->beacon_rate);
a7c7fbff 6089 if (err)
076fc877 6090 goto out;
a7c7fbff
PK
6091 }
6092
18998c38 6093 if (info->attrs[NL80211_ATTR_SMPS_MODE]) {
9e263e19 6094 params->smps_mode =
18998c38 6095 nla_get_u8(info->attrs[NL80211_ATTR_SMPS_MODE]);
9e263e19 6096 switch (params->smps_mode) {
18998c38
EP
6097 case NL80211_SMPS_OFF:
6098 break;
6099 case NL80211_SMPS_STATIC:
6100 if (!(rdev->wiphy.features &
9e263e19
JB
6101 NL80211_FEATURE_STATIC_SMPS)) {
6102 err = -EINVAL;
076fc877 6103 goto out;
9e263e19 6104 }
18998c38
EP
6105 break;
6106 case NL80211_SMPS_DYNAMIC:
6107 if (!(rdev->wiphy.features &
9e263e19
JB
6108 NL80211_FEATURE_DYNAMIC_SMPS)) {
6109 err = -EINVAL;
076fc877 6110 goto out;
9e263e19 6111 }
18998c38
EP
6112 break;
6113 default:
9e263e19 6114 err = -EINVAL;
076fc877 6115 goto out;
18998c38
EP
6116 }
6117 } else {
9e263e19 6118 params->smps_mode = NL80211_SMPS_OFF;
18998c38
EP
6119 }
6120
9e263e19
JB
6121 params->pbss = nla_get_flag(info->attrs[NL80211_ATTR_PBSS]);
6122 if (params->pbss && !rdev->wiphy.bands[NL80211_BAND_60GHZ]) {
6123 err = -EOPNOTSUPP;
076fc877 6124 goto out;
9e263e19 6125 }
6e8ef842 6126
4baf6bea 6127 if (info->attrs[NL80211_ATTR_ACL_POLICY]) {
9e263e19
JB
6128 params->acl = parse_acl_data(&rdev->wiphy, info);
6129 if (IS_ERR(params->acl)) {
6130 err = PTR_ERR(params->acl);
05075fe7 6131 params->acl = NULL;
076fc877 6132 goto out;
9e263e19 6133 }
4baf6bea
OO
6134 }
6135
9e263e19 6136 params->twt_responder =
a0de1ca3
JC
6137 nla_get_flag(info->attrs[NL80211_ATTR_TWT_RESPONDER]);
6138
796e90f4
JC
6139 if (info->attrs[NL80211_ATTR_HE_OBSS_PD]) {
6140 err = nl80211_parse_he_obss_pd(
6141 info->attrs[NL80211_ATTR_HE_OBSS_PD],
9e263e19 6142 &params->he_obss_pd);
bc7a39b4 6143 if (err)
076fc877 6144 goto out;
796e90f4
JC
6145 }
6146
291c49de
AD
6147 if (info->attrs[NL80211_ATTR_FILS_DISCOVERY]) {
6148 err = nl80211_parse_fils_discovery(rdev,
6149 info->attrs[NL80211_ATTR_FILS_DISCOVERY],
bb55441c 6150 &params->fils_discovery);
291c49de 6151 if (err)
076fc877 6152 goto out;
291c49de
AD
6153 }
6154
7443dcd1
AD
6155 if (info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP]) {
6156 err = nl80211_parse_unsol_bcast_probe_resp(
6157 rdev, info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP],
bb55441c 6158 &params->unsol_bcast_probe_resp);
7443dcd1 6159 if (err)
076fc877 6160 goto out;
7443dcd1
AD
6161 }
6162
dc1e3cb8
JC
6163 if (info->attrs[NL80211_ATTR_MBSSID_CONFIG]) {
6164 err = nl80211_parse_mbssid_config(&rdev->wiphy, dev,
6165 info->attrs[NL80211_ATTR_MBSSID_CONFIG],
6166 &params->mbssid_config,
6167 params->beacon.mbssid_ies ?
6168 params->beacon.mbssid_ies->cnt :
6169 0);
6170 if (err)
076fc877 6171 goto out;
dc1e3cb8
JC
6172 }
6173
dbbb27e1
AD
6174 if (!params->mbssid_config.ema && params->beacon.rnr_ies) {
6175 err = -EINVAL;
076fc877 6176 goto out;
dbbb27e1
AD
6177 }
6178
8bc65d38
AD
6179 err = nl80211_calculate_ap_params(params);
6180 if (err)
076fc877 6181 goto out;
66cd794e 6182
5112fa50
AKS
6183 err = nl80211_validate_ap_phy_operation(params);
6184 if (err)
7d6904bf 6185 goto out;
5112fa50 6186
47301a74
VJ
6187 if (info->attrs[NL80211_ATTR_AP_SETTINGS_FLAGS])
6188 params->flags = nla_get_u32(
6189 info->attrs[NL80211_ATTR_AP_SETTINGS_FLAGS]);
6190 else if (info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])
6191 params->flags |= NL80211_AP_SETTINGS_EXTERNAL_AUTH_SUPPORT;
fe494370 6192
7b0a0e3c
JB
6193 if (wdev->conn_owner_nlportid &&
6194 info->attrs[NL80211_ATTR_SOCKET_OWNER] &&
6195 wdev->conn_owner_nlportid != info->snd_portid) {
6196 err = -EINVAL;
076fc877 6197 goto out;
7b0a0e3c
JB
6198 }
6199
6200 /* FIXME: validate MLO/link-id against driver capabilities */
6201
9e263e19 6202 err = rdev_start_ap(rdev, dev, params);
46c1dd0c 6203 if (!err) {
7b0a0e3c
JB
6204 wdev->links[link_id].ap.beacon_interval = params->beacon_interval;
6205 wdev->links[link_id].ap.chandef = params->chandef;
6206 wdev->u.ap.ssid_len = params->ssid_len;
6207 memcpy(wdev->u.ap.ssid, params->ssid,
6208 params->ssid_len);
466a3061
DK
6209
6210 if (info->attrs[NL80211_ATTR_SOCKET_OWNER])
6211 wdev->conn_owner_nlportid = info->snd_portid;
77669c15
6212
6213 nl80211_send_ap_started(wdev, link_id);
46c1dd0c 6214 }
9951ebfc 6215out:
9e263e19 6216 kfree(params->acl);
dc1e3cb8
JC
6217 kfree(params->beacon.mbssid_ies);
6218 if (params->mbssid_config.tx_wdev &&
6219 params->mbssid_config.tx_wdev->netdev &&
6220 params->mbssid_config.tx_wdev->netdev != dev)
6221 dev_put(params->mbssid_config.tx_wdev->netdev);
dbbb27e1 6222 kfree(params->beacon.rnr_ies);
9e263e19 6223 kfree(params);
77765eaf 6224
56d1893d 6225 return err;
ed1b6cc7
JB
6226}
6227
8860020e
JB
6228static int nl80211_set_beacon(struct sk_buff *skb, struct genl_info *info)
6229{
6230 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7b0a0e3c 6231 unsigned int link_id = nl80211_link_id(info->attrs);
8860020e
JB
6232 struct net_device *dev = info->user_ptr[1];
6233 struct wireless_dev *wdev = dev->ieee80211_ptr;
bb55441c 6234 struct cfg80211_ap_update *params;
b2d431d4 6235 struct nlattr *attr;
8860020e
JB
6236 int err;
6237
6238 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
6239 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
6240 return -EOPNOTSUPP;
6241
6242 if (!rdev->ops->change_beacon)
6243 return -EOPNOTSUPP;
6244
7b0a0e3c 6245 if (!wdev->links[link_id].ap.beacon_interval)
8860020e
JB
6246 return -EINVAL;
6247
66f85d57
AD
6248 params = kzalloc(sizeof(*params), GFP_KERNEL);
6249 if (!params)
6250 return -ENOMEM;
6251
6252 err = nl80211_parse_beacon(rdev, info->attrs, &params->beacon,
6253 info->extack);
8860020e 6254 if (err)
dc1e3cb8 6255 goto out;
8860020e 6256
b2d431d4
AD
6257 attr = info->attrs[NL80211_ATTR_FILS_DISCOVERY];
6258 if (attr) {
bb55441c
JB
6259 err = nl80211_parse_fils_discovery(rdev, attr,
6260 &params->fils_discovery);
b2d431d4
AD
6261 if (err)
6262 goto out;
6263 }
6264
6265 attr = info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP];
6266 if (attr) {
bb55441c
JB
6267 err = nl80211_parse_unsol_bcast_probe_resp(rdev, attr,
6268 &params->unsol_bcast_probe_resp);
b2d431d4
AD
6269 if (err)
6270 goto out;
6271 }
6272
66f85d57 6273 err = rdev_change_beacon(rdev, dev, params);
c56589ed 6274
dc1e3cb8 6275out:
66f85d57
AD
6276 kfree(params->beacon.mbssid_ies);
6277 kfree(params->beacon.rnr_ies);
6278 kfree(params);
c56589ed 6279 return err;
8860020e
JB
6280}
6281
6282static int nl80211_stop_ap(struct sk_buff *skb, struct genl_info *info)
ed1b6cc7 6283{
4c476991 6284 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7b0a0e3c 6285 unsigned int link_id = nl80211_link_id(info->attrs);
4c476991 6286 struct net_device *dev = info->user_ptr[1];
ed1b6cc7 6287
7b0a0e3c 6288 return cfg80211_stop_ap(rdev, dev, link_id, false);
ed1b6cc7
JB
6289}
6290
5727ef1b
JB
6291static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = {
6292 [NL80211_STA_FLAG_AUTHORIZED] = { .type = NLA_FLAG },
6293 [NL80211_STA_FLAG_SHORT_PREAMBLE] = { .type = NLA_FLAG },
6294 [NL80211_STA_FLAG_WME] = { .type = NLA_FLAG },
0e46724a 6295 [NL80211_STA_FLAG_MFP] = { .type = NLA_FLAG },
b39c48fa 6296 [NL80211_STA_FLAG_AUTHENTICATED] = { .type = NLA_FLAG },
d83023da 6297 [NL80211_STA_FLAG_TDLS_PEER] = { .type = NLA_FLAG },
5727ef1b
JB
6298};
6299
eccb8e8f 6300static int parse_station_flags(struct genl_info *info,
bdd3ae3d 6301 enum nl80211_iftype iftype,
eccb8e8f 6302 struct station_parameters *params)
5727ef1b
JB
6303{
6304 struct nlattr *flags[NL80211_STA_FLAG_MAX + 1];
eccb8e8f 6305 struct nlattr *nla;
5727ef1b
JB
6306 int flag;
6307
eccb8e8f
JB
6308 /*
6309 * Try parsing the new attribute first so userspace
6310 * can specify both for older kernels.
6311 */
6312 nla = info->attrs[NL80211_ATTR_STA_FLAGS2];
6313 if (nla) {
6314 struct nl80211_sta_flag_update *sta_flags;
6315
6316 sta_flags = nla_data(nla);
6317 params->sta_flags_mask = sta_flags->mask;
6318 params->sta_flags_set = sta_flags->set;
77ee7c89 6319 params->sta_flags_set &= params->sta_flags_mask;
eccb8e8f
JB
6320 if ((params->sta_flags_mask |
6321 params->sta_flags_set) & BIT(__NL80211_STA_FLAG_INVALID))
6322 return -EINVAL;
6323 return 0;
6324 }
6325
6326 /* if present, parse the old attribute */
5727ef1b 6327
eccb8e8f 6328 nla = info->attrs[NL80211_ATTR_STA_FLAGS];
5727ef1b
JB
6329 if (!nla)
6330 return 0;
6331
8cb08174 6332 if (nla_parse_nested_deprecated(flags, NL80211_STA_FLAG_MAX, nla, sta_flags_policy, info->extack))
5727ef1b
JB
6333 return -EINVAL;
6334
bdd3ae3d
JB
6335 /*
6336 * Only allow certain flags for interface types so that
6337 * other attributes are silently ignored. Remember that
6338 * this is backward compatibility code with old userspace
6339 * and shouldn't be hit in other cases anyway.
6340 */
6341 switch (iftype) {
6342 case NL80211_IFTYPE_AP:
6343 case NL80211_IFTYPE_AP_VLAN:
6344 case NL80211_IFTYPE_P2P_GO:
6345 params->sta_flags_mask = BIT(NL80211_STA_FLAG_AUTHORIZED) |
6346 BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) |
6347 BIT(NL80211_STA_FLAG_WME) |
6348 BIT(NL80211_STA_FLAG_MFP);
6349 break;
6350 case NL80211_IFTYPE_P2P_CLIENT:
6351 case NL80211_IFTYPE_STATION:
6352 params->sta_flags_mask = BIT(NL80211_STA_FLAG_AUTHORIZED) |
6353 BIT(NL80211_STA_FLAG_TDLS_PEER);
6354 break;
6355 case NL80211_IFTYPE_MESH_POINT:
6356 params->sta_flags_mask = BIT(NL80211_STA_FLAG_AUTHENTICATED) |
6357 BIT(NL80211_STA_FLAG_MFP) |
6358 BIT(NL80211_STA_FLAG_AUTHORIZED);
5cf3006c 6359 break;
bdd3ae3d
JB
6360 default:
6361 return -EINVAL;
6362 }
5727ef1b 6363
3383b5a6
JB
6364 for (flag = 1; flag <= NL80211_STA_FLAG_MAX; flag++) {
6365 if (flags[flag]) {
eccb8e8f 6366 params->sta_flags_set |= (1<<flag);
5727ef1b 6367
3383b5a6
JB
6368 /* no longer support new API additions in old API */
6369 if (flag > NL80211_STA_FLAG_MAX_OLD_API)
6370 return -EINVAL;
6371 }
6372 }
6373
5727ef1b
JB
6374 return 0;
6375}
6376
9bb7e0f2 6377bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, int attr)
c8dcfd8a
FF
6378{
6379 struct nlattr *rate;
8eb41c8d
VK
6380 u32 bitrate;
6381 u16 bitrate_compat;
bbf67e45 6382 enum nl80211_rate_info rate_flg;
c8dcfd8a 6383
ae0be8de 6384 rate = nla_nest_start_noflag(msg, attr);
c8dcfd8a 6385 if (!rate)
db9c64cf 6386 return false;
c8dcfd8a
FF
6387
6388 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
6389 bitrate = cfg80211_calculate_bitrate(info);
8eb41c8d
VK
6390 /* report 16-bit bitrate only if we can */
6391 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
db9c64cf
JB
6392 if (bitrate > 0 &&
6393 nla_put_u32(msg, NL80211_RATE_INFO_BITRATE32, bitrate))
6394 return false;
6395 if (bitrate_compat > 0 &&
6396 nla_put_u16(msg, NL80211_RATE_INFO_BITRATE, bitrate_compat))
6397 return false;
6398
b51f3bee 6399 switch (info->bw) {
2ad66fcb
GI
6400 case RATE_INFO_BW_1:
6401 rate_flg = NL80211_RATE_INFO_1_MHZ_WIDTH;
6402 break;
6403 case RATE_INFO_BW_2:
6404 rate_flg = NL80211_RATE_INFO_2_MHZ_WIDTH;
6405 break;
6406 case RATE_INFO_BW_4:
6407 rate_flg = NL80211_RATE_INFO_4_MHZ_WIDTH;
6408 break;
b51f3bee
JB
6409 case RATE_INFO_BW_5:
6410 rate_flg = NL80211_RATE_INFO_5_MHZ_WIDTH;
6411 break;
2ad66fcb
GI
6412 case RATE_INFO_BW_8:
6413 rate_flg = NL80211_RATE_INFO_8_MHZ_WIDTH;
6414 break;
b51f3bee
JB
6415 case RATE_INFO_BW_10:
6416 rate_flg = NL80211_RATE_INFO_10_MHZ_WIDTH;
6417 break;
2ad66fcb
GI
6418 case RATE_INFO_BW_16:
6419 rate_flg = NL80211_RATE_INFO_16_MHZ_WIDTH;
6420 break;
b51f3bee
JB
6421 default:
6422 WARN_ON(1);
7b506ff6 6423 fallthrough;
b51f3bee
JB
6424 case RATE_INFO_BW_20:
6425 rate_flg = 0;
6426 break;
6427 case RATE_INFO_BW_40:
6428 rate_flg = NL80211_RATE_INFO_40_MHZ_WIDTH;
6429 break;
6430 case RATE_INFO_BW_80:
6431 rate_flg = NL80211_RATE_INFO_80_MHZ_WIDTH;
6432 break;
6433 case RATE_INFO_BW_160:
6434 rate_flg = NL80211_RATE_INFO_160_MHZ_WIDTH;
6435 break;
c4cbaf79
LC
6436 case RATE_INFO_BW_HE_RU:
6437 rate_flg = 0;
6438 WARN_ON(!(info->flags & RATE_INFO_FLAGS_HE_MCS));
cfb14110
VJ
6439 break;
6440 case RATE_INFO_BW_320:
6441 rate_flg = NL80211_RATE_INFO_320_MHZ_WIDTH;
6442 break;
6443 case RATE_INFO_BW_EHT_RU:
6444 rate_flg = 0;
6445 WARN_ON(!(info->flags & RATE_INFO_FLAGS_EHT_MCS));
6446 break;
b51f3bee
JB
6447 }
6448
6449 if (rate_flg && nla_put_flag(msg, rate_flg))
6450 return false;
6451
db9c64cf
JB
6452 if (info->flags & RATE_INFO_FLAGS_MCS) {
6453 if (nla_put_u8(msg, NL80211_RATE_INFO_MCS, info->mcs))
6454 return false;
db9c64cf
JB
6455 if (info->flags & RATE_INFO_FLAGS_SHORT_GI &&
6456 nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI))
6457 return false;
6458 } else if (info->flags & RATE_INFO_FLAGS_VHT_MCS) {
6459 if (nla_put_u8(msg, NL80211_RATE_INFO_VHT_MCS, info->mcs))
6460 return false;
6461 if (nla_put_u8(msg, NL80211_RATE_INFO_VHT_NSS, info->nss))
6462 return false;
db9c64cf
JB
6463 if (info->flags & RATE_INFO_FLAGS_SHORT_GI &&
6464 nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI))
6465 return false;
c4cbaf79
LC
6466 } else if (info->flags & RATE_INFO_FLAGS_HE_MCS) {
6467 if (nla_put_u8(msg, NL80211_RATE_INFO_HE_MCS, info->mcs))
6468 return false;
6469 if (nla_put_u8(msg, NL80211_RATE_INFO_HE_NSS, info->nss))
6470 return false;
6471 if (nla_put_u8(msg, NL80211_RATE_INFO_HE_GI, info->he_gi))
6472 return false;
6473 if (nla_put_u8(msg, NL80211_RATE_INFO_HE_DCM, info->he_dcm))
6474 return false;
6475 if (info->bw == RATE_INFO_BW_HE_RU &&
6476 nla_put_u8(msg, NL80211_RATE_INFO_HE_RU_ALLOC,
6477 info->he_ru_alloc))
6478 return false;
2ad66fcb
GI
6479 } else if (info->flags & RATE_INFO_FLAGS_S1G_MCS) {
6480 if (nla_put_u8(msg, NL80211_RATE_INFO_S1G_MCS, info->mcs))
6481 return false;
6482 if (nla_put_u8(msg, NL80211_RATE_INFO_S1G_NSS, info->nss))
6483 return false;
6484 if (info->flags & RATE_INFO_FLAGS_SHORT_GI &&
6485 nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI))
6486 return false;
cfb14110
VJ
6487 } else if (info->flags & RATE_INFO_FLAGS_EHT_MCS) {
6488 if (nla_put_u8(msg, NL80211_RATE_INFO_EHT_MCS, info->mcs))
6489 return false;
6490 if (nla_put_u8(msg, NL80211_RATE_INFO_EHT_NSS, info->nss))
6491 return false;
6492 if (nla_put_u8(msg, NL80211_RATE_INFO_EHT_GI, info->eht_gi))
6493 return false;
6494 if (info->bw == RATE_INFO_BW_EHT_RU &&
6495 nla_put_u8(msg, NL80211_RATE_INFO_EHT_RU_ALLOC,
6496 info->eht_ru_alloc))
6497 return false;
db9c64cf 6498 }
c8dcfd8a
FF
6499
6500 nla_nest_end(msg, rate);
6501 return true;
c8dcfd8a
FF
6502}
6503
119363c7
FF
6504static bool nl80211_put_signal(struct sk_buff *msg, u8 mask, s8 *signal,
6505 int id)
6506{
6507 void *attr;
6508 int i = 0;
6509
6510 if (!mask)
6511 return true;
6512
ae0be8de 6513 attr = nla_nest_start_noflag(msg, id);
119363c7
FF
6514 if (!attr)
6515 return false;
6516
6517 for (i = 0; i < IEEE80211_MAX_CHAINS; i++) {
6518 if (!(mask & BIT(i)))
6519 continue;
6520
6521 if (nla_put_u8(msg, i, signal[i]))
6522 return false;
6523 }
6524
6525 nla_nest_end(msg, attr);
6526
6527 return true;
6528}
6529
cf5ead82
JB
6530static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
6531 u32 seq, int flags,
66266b3a
JL
6532 struct cfg80211_registered_device *rdev,
6533 struct net_device *dev,
98b62183 6534 const u8 *mac_addr, struct station_info *sinfo)
fd5b74dc
JB
6535{
6536 void *hdr;
f4263c98 6537 struct nlattr *sinfoattr, *bss_param;
fd5b74dc 6538
cf5ead82 6539 hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
f77bf486
AS
6540 if (!hdr) {
6541 cfg80211_sinfo_release_content(sinfo);
fd5b74dc 6542 return -1;
f77bf486 6543 }
fd5b74dc 6544
9360ffd1
DM
6545 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
6546 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr) ||
6547 nla_put_u32(msg, NL80211_ATTR_GENERATION, sinfo->generation))
6548 goto nla_put_failure;
f5ea9120 6549
ae0be8de 6550 sinfoattr = nla_nest_start_noflag(msg, NL80211_ATTR_STA_INFO);
2ec600d6 6551 if (!sinfoattr)
fd5b74dc 6552 goto nla_put_failure;
319090bf
JB
6553
6554#define PUT_SINFO(attr, memb, type) do { \
d686b920 6555 BUILD_BUG_ON(sizeof(type) == sizeof(u64)); \
397c657a 6556 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_ ## attr) && \
319090bf
JB
6557 nla_put_ ## type(msg, NL80211_STA_INFO_ ## attr, \
6558 sinfo->memb)) \
6559 goto nla_put_failure; \
6560 } while (0)
d686b920 6561#define PUT_SINFO_U64(attr, memb) do { \
397c657a 6562 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_ ## attr) && \
d686b920
JB
6563 nla_put_u64_64bit(msg, NL80211_STA_INFO_ ## attr, \
6564 sinfo->memb, NL80211_STA_INFO_PAD)) \
6565 goto nla_put_failure; \
6566 } while (0)
319090bf
JB
6567
6568 PUT_SINFO(CONNECTED_TIME, connected_time, u32);
6569 PUT_SINFO(INACTIVE_TIME, inactive_time, u32);
6c7a0033 6570 PUT_SINFO_U64(ASSOC_AT_BOOTTIME, assoc_at);
319090bf 6571
397c657a
OE
6572 if (sinfo->filled & (BIT_ULL(NL80211_STA_INFO_RX_BYTES) |
6573 BIT_ULL(NL80211_STA_INFO_RX_BYTES64)) &&
9360ffd1 6574 nla_put_u32(msg, NL80211_STA_INFO_RX_BYTES,
42745e03 6575 (u32)sinfo->rx_bytes))
9360ffd1 6576 goto nla_put_failure;
319090bf 6577
397c657a
OE
6578 if (sinfo->filled & (BIT_ULL(NL80211_STA_INFO_TX_BYTES) |
6579 BIT_ULL(NL80211_STA_INFO_TX_BYTES64)) &&
9360ffd1 6580 nla_put_u32(msg, NL80211_STA_INFO_TX_BYTES,
42745e03
VK
6581 (u32)sinfo->tx_bytes))
6582 goto nla_put_failure;
319090bf 6583
d686b920
JB
6584 PUT_SINFO_U64(RX_BYTES64, rx_bytes);
6585 PUT_SINFO_U64(TX_BYTES64, tx_bytes);
319090bf
JB
6586 PUT_SINFO(LLID, llid, u16);
6587 PUT_SINFO(PLID, plid, u16);
6588 PUT_SINFO(PLINK_STATE, plink_state, u8);
d686b920 6589 PUT_SINFO_U64(RX_DURATION, rx_duration);
36647055
THJ
6590 PUT_SINFO_U64(TX_DURATION, tx_duration);
6591
6592 if (wiphy_ext_feature_isset(&rdev->wiphy,
6593 NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))
6594 PUT_SINFO(AIRTIME_WEIGHT, airtime_weight, u16);
319090bf 6595
66266b3a
JL
6596 switch (rdev->wiphy.signal_type) {
6597 case CFG80211_SIGNAL_TYPE_MBM:
319090bf
JB
6598 PUT_SINFO(SIGNAL, signal, u8);
6599 PUT_SINFO(SIGNAL_AVG, signal_avg, u8);
66266b3a
JL
6600 break;
6601 default:
6602 break;
6603 }
397c657a 6604 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL)) {
119363c7
FF
6605 if (!nl80211_put_signal(msg, sinfo->chains,
6606 sinfo->chain_signal,
6607 NL80211_STA_INFO_CHAIN_SIGNAL))
6608 goto nla_put_failure;
6609 }
397c657a 6610 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL_AVG)) {
119363c7
FF
6611 if (!nl80211_put_signal(msg, sinfo->chains,
6612 sinfo->chain_signal_avg,
6613 NL80211_STA_INFO_CHAIN_SIGNAL_AVG))
6614 goto nla_put_failure;
6615 }
397c657a 6616 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_BITRATE)) {
c8dcfd8a
FF
6617 if (!nl80211_put_sta_rate(msg, &sinfo->txrate,
6618 NL80211_STA_INFO_TX_BITRATE))
6619 goto nla_put_failure;
6620 }
397c657a 6621 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_RX_BITRATE)) {
c8dcfd8a
FF
6622 if (!nl80211_put_sta_rate(msg, &sinfo->rxrate,
6623 NL80211_STA_INFO_RX_BITRATE))
420e7fab 6624 goto nla_put_failure;
420e7fab 6625 }
319090bf
JB
6626
6627 PUT_SINFO(RX_PACKETS, rx_packets, u32);
6628 PUT_SINFO(TX_PACKETS, tx_packets, u32);
6629 PUT_SINFO(TX_RETRIES, tx_retries, u32);
6630 PUT_SINFO(TX_FAILED, tx_failed, u32);
6631 PUT_SINFO(EXPECTED_THROUGHPUT, expected_throughput, u32);
ab60633c 6632 PUT_SINFO(AIRTIME_LINK_METRIC, airtime_link_metric, u32);
319090bf
JB
6633 PUT_SINFO(BEACON_LOSS, beacon_loss_count, u32);
6634 PUT_SINFO(LOCAL_PM, local_pm, u32);
6635 PUT_SINFO(PEER_PM, peer_pm, u32);
6636 PUT_SINFO(NONPEER_PM, nonpeer_pm, u32);
dbdaee7a 6637 PUT_SINFO(CONNECTED_TO_GATE, connected_to_gate, u8);
1303a51c 6638 PUT_SINFO(CONNECTED_TO_AS, connected_to_as, u8);
319090bf 6639
397c657a 6640 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_BSS_PARAM)) {
ae0be8de
MK
6641 bss_param = nla_nest_start_noflag(msg,
6642 NL80211_STA_INFO_BSS_PARAM);
f4263c98
PS
6643 if (!bss_param)
6644 goto nla_put_failure;
6645
9360ffd1
DM
6646 if (((sinfo->bss_param.flags & BSS_PARAM_FLAGS_CTS_PROT) &&
6647 nla_put_flag(msg, NL80211_STA_BSS_PARAM_CTS_PROT)) ||
6648 ((sinfo->bss_param.flags & BSS_PARAM_FLAGS_SHORT_PREAMBLE) &&
6649 nla_put_flag(msg, NL80211_STA_BSS_PARAM_SHORT_PREAMBLE)) ||
6650 ((sinfo->bss_param.flags & BSS_PARAM_FLAGS_SHORT_SLOT_TIME) &&
6651 nla_put_flag(msg, NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME)) ||
6652 nla_put_u8(msg, NL80211_STA_BSS_PARAM_DTIM_PERIOD,
6653 sinfo->bss_param.dtim_period) ||
6654 nla_put_u16(msg, NL80211_STA_BSS_PARAM_BEACON_INTERVAL,
6655 sinfo->bss_param.beacon_interval))
6656 goto nla_put_failure;
f4263c98
PS
6657
6658 nla_nest_end(msg, bss_param);
6659 }
397c657a 6660 if ((sinfo->filled & BIT_ULL(NL80211_STA_INFO_STA_FLAGS)) &&
9360ffd1
DM
6661 nla_put(msg, NL80211_STA_INFO_STA_FLAGS,
6662 sizeof(struct nl80211_sta_flag_update),
6663 &sinfo->sta_flags))
6664 goto nla_put_failure;
319090bf 6665
d686b920
JB
6666 PUT_SINFO_U64(T_OFFSET, t_offset);
6667 PUT_SINFO_U64(RX_DROP_MISC, rx_dropped_misc);
6668 PUT_SINFO_U64(BEACON_RX, rx_beacon);
a76b1942 6669 PUT_SINFO(BEACON_SIGNAL_AVG, rx_beacon_signal_avg, u8);
0d4e14a3
AB
6670 PUT_SINFO(RX_MPDUS, rx_mpdu_count, u32);
6671 PUT_SINFO(FCS_ERROR_COUNT, fcs_err_count, u32);
81d5439d 6672 if (wiphy_ext_feature_isset(&rdev->wiphy,
9c06602b
BP
6673 NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT)) {
6674 PUT_SINFO(ACK_SIGNAL, ack_signal, u8);
6675 PUT_SINFO(ACK_SIGNAL_AVG, avg_ack_signal, s8);
6676 }
319090bf
JB
6677
6678#undef PUT_SINFO
d686b920 6679#undef PUT_SINFO_U64
6de39808 6680
8689c051 6681 if (sinfo->pertid) {
6de39808
JB
6682 struct nlattr *tidsattr;
6683 int tid;
6684
ae0be8de
MK
6685 tidsattr = nla_nest_start_noflag(msg,
6686 NL80211_STA_INFO_TID_STATS);
6de39808
JB
6687 if (!tidsattr)
6688 goto nla_put_failure;
6689
6690 for (tid = 0; tid < IEEE80211_NUM_TIDS + 1; tid++) {
6691 struct cfg80211_tid_stats *tidstats;
6692 struct nlattr *tidattr;
6693
6694 tidstats = &sinfo->pertid[tid];
6695
6696 if (!tidstats->filled)
6697 continue;
6698
ae0be8de 6699 tidattr = nla_nest_start_noflag(msg, tid + 1);
6de39808
JB
6700 if (!tidattr)
6701 goto nla_put_failure;
6702
d686b920 6703#define PUT_TIDVAL_U64(attr, memb) do { \
6de39808 6704 if (tidstats->filled & BIT(NL80211_TID_STATS_ ## attr) && \
d686b920
JB
6705 nla_put_u64_64bit(msg, NL80211_TID_STATS_ ## attr, \
6706 tidstats->memb, NL80211_TID_STATS_PAD)) \
6de39808
JB
6707 goto nla_put_failure; \
6708 } while (0)
6709
d686b920
JB
6710 PUT_TIDVAL_U64(RX_MSDU, rx_msdu);
6711 PUT_TIDVAL_U64(TX_MSDU, tx_msdu);
6712 PUT_TIDVAL_U64(TX_MSDU_RETRIES, tx_msdu_retries);
6713 PUT_TIDVAL_U64(TX_MSDU_FAILED, tx_msdu_failed);
6de39808 6714
d686b920 6715#undef PUT_TIDVAL_U64
52539ca8
THJ
6716 if ((tidstats->filled &
6717 BIT(NL80211_TID_STATS_TXQ_STATS)) &&
6718 !nl80211_put_txq_stats(msg, &tidstats->txq_stats,
6719 NL80211_TID_STATS_TXQ_STATS))
6720 goto nla_put_failure;
6721
6de39808
JB
6722 nla_nest_end(msg, tidattr);
6723 }
6724
6725 nla_nest_end(msg, tidsattr);
6726 }
6727
2ec600d6 6728 nla_nest_end(msg, sinfoattr);
fd5b74dc 6729
319090bf 6730 if (sinfo->assoc_req_ies_len &&
9360ffd1
DM
6731 nla_put(msg, NL80211_ATTR_IE, sinfo->assoc_req_ies_len,
6732 sinfo->assoc_req_ies))
6733 goto nla_put_failure;
50d3dfb7 6734
a42e59eb
VJ
6735 if (sinfo->assoc_resp_ies_len &&
6736 nla_put(msg, NL80211_ATTR_RESP_IE, sinfo->assoc_resp_ies_len,
6737 sinfo->assoc_resp_ies))
6738 goto nla_put_failure;
6739
6740 if (sinfo->mlo_params_valid) {
6741 if (nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID,
6742 sinfo->assoc_link_id))
6743 goto nla_put_failure;
6744
6745 if (!is_zero_ether_addr(sinfo->mld_addr) &&
6746 nla_put(msg, NL80211_ATTR_MLD_ADDR, ETH_ALEN,
6747 sinfo->mld_addr))
6748 goto nla_put_failure;
6749 }
6750
7ea3e110 6751 cfg80211_sinfo_release_content(sinfo);
053c095a
JB
6752 genlmsg_end(msg, hdr);
6753 return 0;
fd5b74dc
JB
6754
6755 nla_put_failure:
7ea3e110 6756 cfg80211_sinfo_release_content(sinfo);
bc3ed28c
TG
6757 genlmsg_cancel(msg, hdr);
6758 return -EMSGSIZE;
fd5b74dc
JB
6759}
6760
2ec600d6 6761static int nl80211_dump_station(struct sk_buff *skb,
bba95fef 6762 struct netlink_callback *cb)
2ec600d6 6763{
73887fd9 6764 struct station_info sinfo;
1b8ec87a 6765 struct cfg80211_registered_device *rdev;
97990a06 6766 struct wireless_dev *wdev;
2ec600d6 6767 u8 mac_addr[ETH_ALEN];
97990a06 6768 int sta_idx = cb->args[2];
2ec600d6 6769 int err;
2ec600d6 6770
ce6b6974 6771 err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev, NULL);
67748893 6772 if (err)
a05829a7
JB
6773 return err;
6774 /* nl80211_prepare_wdev_dump acquired it in the successful case */
6775 __acquire(&rdev->wiphy.mtx);
bba95fef 6776
97990a06
JB
6777 if (!wdev->netdev) {
6778 err = -EINVAL;
6779 goto out_err;
6780 }
6781
1b8ec87a 6782 if (!rdev->ops->dump_station) {
eec60b03 6783 err = -EOPNOTSUPP;
bba95fef
JB
6784 goto out_err;
6785 }
6786
bba95fef 6787 while (1) {
73887fd9 6788 memset(&sinfo, 0, sizeof(sinfo));
1b8ec87a 6789 err = rdev_dump_station(rdev, wdev->netdev, sta_idx,
73887fd9 6790 mac_addr, &sinfo);
bba95fef
JB
6791 if (err == -ENOENT)
6792 break;
6793 if (err)
3b85875a 6794 goto out_err;
bba95fef 6795
cf5ead82 6796 if (nl80211_send_station(skb, NL80211_CMD_NEW_STATION,
15e47304 6797 NETLINK_CB(cb->skb).portid,
bba95fef 6798 cb->nlh->nlmsg_seq, NLM_F_MULTI,
1b8ec87a 6799 rdev, wdev->netdev, mac_addr,
73887fd9 6800 &sinfo) < 0)
bba95fef
JB
6801 goto out;
6802
6803 sta_idx++;
6804 }
6805
bba95fef 6806 out:
97990a06 6807 cb->args[2] = sta_idx;
bba95fef 6808 err = skb->len;
bba95fef 6809 out_err:
a05829a7 6810 wiphy_unlock(&rdev->wiphy);
bba95fef
JB
6811
6812 return err;
2ec600d6 6813}
fd5b74dc 6814
5727ef1b
JB
6815static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
6816{
4c476991
JB
6817 struct cfg80211_registered_device *rdev = info->user_ptr[0];
6818 struct net_device *dev = info->user_ptr[1];
73887fd9 6819 struct station_info sinfo;
fd5b74dc
JB
6820 struct sk_buff *msg;
6821 u8 *mac_addr = NULL;
4c476991 6822 int err;
fd5b74dc 6823
73887fd9 6824 memset(&sinfo, 0, sizeof(sinfo));
fd5b74dc 6825
73887fd9
JB
6826 if (!info->attrs[NL80211_ATTR_MAC])
6827 return -EINVAL;
fd5b74dc
JB
6828
6829 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
6830
73887fd9
JB
6831 if (!rdev->ops->get_station)
6832 return -EOPNOTSUPP;
3b85875a 6833
73887fd9 6834 err = rdev_get_station(rdev, dev, mac_addr, &sinfo);
fd5b74dc 6835 if (err)
73887fd9 6836 return err;
2ec600d6 6837
fd2120ca 6838 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
7ea3e110 6839 if (!msg) {
ba8f566a 6840 cfg80211_sinfo_release_content(&sinfo);
73887fd9 6841 return -ENOMEM;
7ea3e110 6842 }
fd5b74dc 6843
cf5ead82
JB
6844 if (nl80211_send_station(msg, NL80211_CMD_NEW_STATION,
6845 info->snd_portid, info->snd_seq, 0,
73887fd9 6846 rdev, dev, mac_addr, &sinfo) < 0) {
4c476991 6847 nlmsg_free(msg);
73887fd9 6848 return -ENOBUFS;
4c476991 6849 }
3b85875a 6850
73887fd9 6851 return genlmsg_reply(msg, info);
5727ef1b
JB
6852}
6853
77ee7c89
JB
6854int cfg80211_check_station_change(struct wiphy *wiphy,
6855 struct station_parameters *params,
6856 enum cfg80211_station_type statype)
6857{
e4208427
AB
6858 if (params->listen_interval != -1 &&
6859 statype != CFG80211_STA_AP_CLIENT_UNASSOC)
77ee7c89 6860 return -EINVAL;
e4208427 6861
17b94247
AB
6862 if (params->support_p2p_ps != -1 &&
6863 statype != CFG80211_STA_AP_CLIENT_UNASSOC)
6864 return -EINVAL;
6865
c72e1140 6866 if (params->aid &&
e4208427
AB
6867 !(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) &&
6868 statype != CFG80211_STA_AP_CLIENT_UNASSOC)
77ee7c89
JB
6869 return -EINVAL;
6870
6871 /* When you run into this, adjust the code below for the new flag */
2518e89d 6872 BUILD_BUG_ON(NL80211_STA_FLAG_MAX != 8);
77ee7c89
JB
6873
6874 switch (statype) {
eef941e6
TP
6875 case CFG80211_STA_MESH_PEER_KERNEL:
6876 case CFG80211_STA_MESH_PEER_USER:
77ee7c89
JB
6877 /*
6878 * No ignoring the TDLS flag here -- the userspace mesh
6879 * code doesn't have the bug of including TDLS in the
6880 * mask everywhere.
6881 */
6882 if (params->sta_flags_mask &
6883 ~(BIT(NL80211_STA_FLAG_AUTHENTICATED) |
6884 BIT(NL80211_STA_FLAG_MFP) |
6885 BIT(NL80211_STA_FLAG_AUTHORIZED)))
6886 return -EINVAL;
6887 break;
6888 case CFG80211_STA_TDLS_PEER_SETUP:
6889 case CFG80211_STA_TDLS_PEER_ACTIVE:
6890 if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))
6891 return -EINVAL;
6892 /* ignore since it can't change */
6893 params->sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
6894 break;
6895 default:
6896 /* disallow mesh-specific things */
6897 if (params->plink_action != NL80211_PLINK_ACTION_NO_ACTION)
6898 return -EINVAL;
6899 if (params->local_pm)
6900 return -EINVAL;
6901 if (params->sta_modify_mask & STATION_PARAM_APPLY_PLINK_STATE)
6902 return -EINVAL;
6903 }
6904
6905 if (statype != CFG80211_STA_TDLS_PEER_SETUP &&
6906 statype != CFG80211_STA_TDLS_PEER_ACTIVE) {
6907 /* TDLS can't be set, ... */
6908 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))
6909 return -EINVAL;
6910 /*
6911 * ... but don't bother the driver with it. This works around
6912 * a hostapd/wpa_supplicant issue -- it always includes the
6913 * TLDS_PEER flag in the mask even for AP mode.
6914 */
6915 params->sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
6916 }
6917
47edb11b
AB
6918 if (statype != CFG80211_STA_TDLS_PEER_SETUP &&
6919 statype != CFG80211_STA_AP_CLIENT_UNASSOC) {
77ee7c89
JB
6920 /* reject other things that can't change */
6921 if (params->sta_modify_mask & STATION_PARAM_APPLY_UAPSD)
6922 return -EINVAL;
6923 if (params->sta_modify_mask & STATION_PARAM_APPLY_CAPABILITY)
6924 return -EINVAL;
b95eb7f0 6925 if (params->link_sta_params.supported_rates)
77ee7c89 6926 return -EINVAL;
b95eb7f0
ST
6927 if (params->ext_capab || params->link_sta_params.ht_capa ||
6928 params->link_sta_params.vht_capa ||
6929 params->link_sta_params.he_capa ||
6930 params->link_sta_params.eht_capa)
77ee7c89 6931 return -EINVAL;
2518e89d
JB
6932 if (params->sta_flags_mask & BIT(NL80211_STA_FLAG_SPP_AMSDU))
6933 return -EINVAL;
77ee7c89
JB
6934 }
6935
47edb11b
AB
6936 if (statype != CFG80211_STA_AP_CLIENT &&
6937 statype != CFG80211_STA_AP_CLIENT_UNASSOC) {
77ee7c89
JB
6938 if (params->vlan)
6939 return -EINVAL;
6940 }
6941
6942 switch (statype) {
6943 case CFG80211_STA_AP_MLME_CLIENT:
6944 /* Use this only for authorizing/unauthorizing a station */
6945 if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)))
6946 return -EOPNOTSUPP;
6947 break;
6948 case CFG80211_STA_AP_CLIENT:
47edb11b 6949 case CFG80211_STA_AP_CLIENT_UNASSOC:
77ee7c89
JB
6950 /* accept only the listed bits */
6951 if (params->sta_flags_mask &
6952 ~(BIT(NL80211_STA_FLAG_AUTHORIZED) |
6953 BIT(NL80211_STA_FLAG_AUTHENTICATED) |
6954 BIT(NL80211_STA_FLAG_ASSOCIATED) |
6955 BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) |
6956 BIT(NL80211_STA_FLAG_WME) |
2518e89d
JB
6957 BIT(NL80211_STA_FLAG_MFP) |
6958 BIT(NL80211_STA_FLAG_SPP_AMSDU)))
77ee7c89
JB
6959 return -EINVAL;
6960
6961 /* but authenticated/associated only if driver handles it */
6962 if (!(wiphy->features & NL80211_FEATURE_FULL_AP_CLIENT_STATE) &&
6963 params->sta_flags_mask &
6964 (BIT(NL80211_STA_FLAG_AUTHENTICATED) |
6965 BIT(NL80211_STA_FLAG_ASSOCIATED)))
6966 return -EINVAL;
6967 break;
6968 case CFG80211_STA_IBSS:
6969 case CFG80211_STA_AP_STA:
6970 /* reject any changes other than AUTHORIZED */
6971 if (params->sta_flags_mask & ~BIT(NL80211_STA_FLAG_AUTHORIZED))
6972 return -EINVAL;
6973 break;
6974 case CFG80211_STA_TDLS_PEER_SETUP:
6975 /* reject any changes other than AUTHORIZED or WME */
6976 if (params->sta_flags_mask & ~(BIT(NL80211_STA_FLAG_AUTHORIZED) |
6977 BIT(NL80211_STA_FLAG_WME)))
6978 return -EINVAL;
6979 /* force (at least) rates when authorizing */
6980 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED) &&
b95eb7f0 6981 !params->link_sta_params.supported_rates)
77ee7c89
JB
6982 return -EINVAL;
6983 break;
6984 case CFG80211_STA_TDLS_PEER_ACTIVE:
6985 /* reject any changes */
6986 return -EINVAL;
eef941e6 6987 case CFG80211_STA_MESH_PEER_KERNEL:
77ee7c89
JB
6988 if (params->sta_modify_mask & STATION_PARAM_APPLY_PLINK_STATE)
6989 return -EINVAL;
6990 break;
eef941e6 6991 case CFG80211_STA_MESH_PEER_USER:
42925040
CYY
6992 if (params->plink_action != NL80211_PLINK_ACTION_NO_ACTION &&
6993 params->plink_action != NL80211_PLINK_ACTION_BLOCK)
77ee7c89
JB
6994 return -EINVAL;
6995 break;
6996 }
6997
06f7c88c
BL
6998 /*
6999 * Older kernel versions ignored this attribute entirely, so don't
7000 * reject attempts to update it but mark it as unused instead so the
7001 * driver won't look at the data.
7002 */
7003 if (statype != CFG80211_STA_AP_CLIENT_UNASSOC &&
7004 statype != CFG80211_STA_TDLS_PEER_SETUP)
b95eb7f0 7005 params->link_sta_params.opmode_notif_used = false;
06f7c88c 7006
77ee7c89
JB
7007 return 0;
7008}
7009EXPORT_SYMBOL(cfg80211_check_station_change);
7010
5727ef1b 7011/*
c258d2de 7012 * Get vlan interface making sure it is running and on the right wiphy.
5727ef1b 7013 */
80b99899
JB
7014static struct net_device *get_vlan(struct genl_info *info,
7015 struct cfg80211_registered_device *rdev)
5727ef1b 7016{
463d0183 7017 struct nlattr *vlanattr = info->attrs[NL80211_ATTR_STA_VLAN];
80b99899
JB
7018 struct net_device *v;
7019 int ret;
7020
7021 if (!vlanattr)
7022 return NULL;
7023
7024 v = dev_get_by_index(genl_info_net(info), nla_get_u32(vlanattr));
7025 if (!v)
7026 return ERR_PTR(-ENODEV);
7027
7028 if (!v->ieee80211_ptr || v->ieee80211_ptr->wiphy != &rdev->wiphy) {
7029 ret = -EINVAL;
7030 goto error;
5727ef1b 7031 }
80b99899 7032
77ee7c89
JB
7033 if (v->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
7034 v->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
7035 v->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
7036 ret = -EINVAL;
7037 goto error;
7038 }
7039
80b99899
JB
7040 if (!netif_running(v)) {
7041 ret = -ENETDOWN;
7042 goto error;
7043 }
7044
7045 return v;
7046 error:
7047 dev_put(v);
7048 return ERR_PTR(ret);
5727ef1b
JB
7049}
7050
ff276691
JB
7051static int nl80211_parse_sta_wme(struct genl_info *info,
7052 struct station_parameters *params)
df881293 7053{
df881293
JM
7054 struct nlattr *tb[NL80211_STA_WME_MAX + 1];
7055 struct nlattr *nla;
7056 int err;
7057
df881293
JM
7058 /* parse WME attributes if present */
7059 if (!info->attrs[NL80211_ATTR_STA_WME])
7060 return 0;
7061
7062 nla = info->attrs[NL80211_ATTR_STA_WME];
8cb08174
JB
7063 err = nla_parse_nested_deprecated(tb, NL80211_STA_WME_MAX, nla,
7064 nl80211_sta_wme_policy,
7065 info->extack);
df881293
JM
7066 if (err)
7067 return err;
7068
7069 if (tb[NL80211_STA_WME_UAPSD_QUEUES])
7070 params->uapsd_queues = nla_get_u8(
7071 tb[NL80211_STA_WME_UAPSD_QUEUES]);
7072 if (params->uapsd_queues & ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK)
7073 return -EINVAL;
7074
7075 if (tb[NL80211_STA_WME_MAX_SP])
7076 params->max_sp = nla_get_u8(tb[NL80211_STA_WME_MAX_SP]);
7077
7078 if (params->max_sp & ~IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK)
7079 return -EINVAL;
7080
7081 params->sta_modify_mask |= STATION_PARAM_APPLY_UAPSD;
7082
7083 return 0;
7084}
7085
c01fc9ad
SD
7086static int nl80211_parse_sta_channel_info(struct genl_info *info,
7087 struct station_parameters *params)
7088{
7089 if (info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]) {
7090 params->supported_channels =
7091 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]);
7092 params->supported_channels_len =
7093 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]);
7094 /*
7095 * Need to include at least one (first channel, number of
cb9abd48
JB
7096 * channels) tuple for each subband (checked in policy),
7097 * and must have proper tuples for the rest of the data as well.
c01fc9ad 7098 */
c01fc9ad
SD
7099 if (params->supported_channels_len % 2)
7100 return -EINVAL;
7101 }
7102
7103 if (info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]) {
7104 params->supported_oper_classes =
7105 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]);
7106 params->supported_oper_classes_len =
7107 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]);
c01fc9ad
SD
7108 }
7109 return 0;
7110}
7111
ff276691
JB
7112static int nl80211_set_station_tdls(struct genl_info *info,
7113 struct station_parameters *params)
7114{
c01fc9ad 7115 int err;
ff276691 7116 /* Dummy STA entry gets updated once the peer capabilities are known */
5e4b6f56
JM
7117 if (info->attrs[NL80211_ATTR_PEER_AID])
7118 params->aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]);
ff276691 7119 if (info->attrs[NL80211_ATTR_HT_CAPABILITY])
b95eb7f0 7120 params->link_sta_params.ht_capa =
ff276691
JB
7121 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
7122 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY])
b95eb7f0 7123 params->link_sta_params.vht_capa =
ff276691 7124 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);
c4cbaf79 7125 if (info->attrs[NL80211_ATTR_HE_CAPABILITY]) {
b95eb7f0 7126 params->link_sta_params.he_capa =
c4cbaf79 7127 nla_data(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
b95eb7f0 7128 params->link_sta_params.he_capa_len =
c4cbaf79 7129 nla_len(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
ea05fd35
IP
7130
7131 if (info->attrs[NL80211_ATTR_EHT_CAPABILITY]) {
b95eb7f0 7132 params->link_sta_params.eht_capa =
ea05fd35 7133 nla_data(info->attrs[NL80211_ATTR_EHT_CAPABILITY]);
b95eb7f0 7134 params->link_sta_params.eht_capa_len =
ea05fd35
IP
7135 nla_len(info->attrs[NL80211_ATTR_EHT_CAPABILITY]);
7136
b95eb7f0
ST
7137 if (!ieee80211_eht_capa_size_ok((const u8 *)params->link_sta_params.he_capa,
7138 (const u8 *)params->link_sta_params.eht_capa,
ea5cba26
JB
7139 params->link_sta_params.eht_capa_len,
7140 false))
ea05fd35
IP
7141 return -EINVAL;
7142 }
c4cbaf79 7143 }
ff276691 7144
c01fc9ad
SD
7145 err = nl80211_parse_sta_channel_info(info, params);
7146 if (err)
7147 return err;
7148
ff276691
JB
7149 return nl80211_parse_sta_wme(info, params);
7150}
7151
e96d1cd2 7152static int nl80211_parse_sta_txpower_setting(struct genl_info *info,
577e5b8c
ST
7153 struct sta_txpwr *txpwr,
7154 bool *txpwr_set)
e96d1cd2
ARN
7155{
7156 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7157 int idx;
7158
7159 if (info->attrs[NL80211_ATTR_STA_TX_POWER_SETTING]) {
7160 if (!rdev->ops->set_tx_power ||
7161 !wiphy_ext_feature_isset(&rdev->wiphy,
7162 NL80211_EXT_FEATURE_STA_TX_PWR))
7163 return -EOPNOTSUPP;
7164
7165 idx = NL80211_ATTR_STA_TX_POWER_SETTING;
577e5b8c 7166 txpwr->type = nla_get_u8(info->attrs[idx]);
e96d1cd2 7167
577e5b8c 7168 if (txpwr->type == NL80211_TX_POWER_LIMITED) {
e96d1cd2
ARN
7169 idx = NL80211_ATTR_STA_TX_POWER;
7170
7171 if (info->attrs[idx])
577e5b8c 7172 txpwr->power = nla_get_s16(info->attrs[idx]);
e96d1cd2
ARN
7173 else
7174 return -EINVAL;
7175 }
577e5b8c
ST
7176
7177 *txpwr_set = true;
7178 } else {
7179 *txpwr_set = false;
e96d1cd2
ARN
7180 }
7181
7182 return 0;
7183}
7184
5727ef1b
JB
7185static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
7186{
4c476991 7187 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4c476991 7188 struct net_device *dev = info->user_ptr[1];
5727ef1b 7189 struct station_parameters params;
77ee7c89
JB
7190 u8 *mac_addr;
7191 int err;
5727ef1b
JB
7192
7193 memset(&params, 0, sizeof(params));
7194
77ee7c89
JB
7195 if (!rdev->ops->change_station)
7196 return -EOPNOTSUPP;
7197
e4208427
AB
7198 /*
7199 * AID and listen_interval properties can be set only for unassociated
7200 * station. Include these parameters here and will check them in
7201 * cfg80211_check_station_change().
7202 */
a9bc31e4
AB
7203 if (info->attrs[NL80211_ATTR_STA_AID])
7204 params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
e4208427 7205
14f34e36
GG
7206 if (info->attrs[NL80211_ATTR_VLAN_ID])
7207 params.vlan_id = nla_get_u16(info->attrs[NL80211_ATTR_VLAN_ID]);
7208
e4208427
AB
7209 if (info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
7210 params.listen_interval =
7211 nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
7212 else
7213 params.listen_interval = -1;
5727ef1b 7214
ab0d76f6
JB
7215 if (info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS])
7216 params.support_p2p_ps =
7217 nla_get_u8(info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]);
7218 else
17b94247 7219 params.support_p2p_ps = -1;
17b94247 7220
5727ef1b
JB
7221 if (!info->attrs[NL80211_ATTR_MAC])
7222 return -EINVAL;
7223
d2bc5249
AO
7224 params.link_sta_params.link_id =
7225 nl80211_link_id_or_invalid(info->attrs);
7226
7227 if (info->attrs[NL80211_ATTR_MLD_ADDR]) {
7228 /* If MLD_ADDR attribute is set then this is an MLD station
7229 * and the MLD_ADDR attribute holds the MLD address and the
7230 * MAC attribute holds for the LINK address.
7231 * In that case, the link_id is also expected to be valid.
7232 */
7233 if (params.link_sta_params.link_id < 0)
7234 return -EINVAL;
7235
7236 mac_addr = nla_data(info->attrs[NL80211_ATTR_MLD_ADDR]);
7237 params.link_sta_params.mld_mac = mac_addr;
7238 params.link_sta_params.link_mac =
7239 nla_data(info->attrs[NL80211_ATTR_MAC]);
7240 if (!is_valid_ether_addr(params.link_sta_params.link_mac))
7241 return -EINVAL;
7242 } else {
7243 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
7244 }
7245
5727ef1b
JB
7246
7247 if (info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]) {
b95eb7f0 7248 params.link_sta_params.supported_rates =
5727ef1b 7249 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
b95eb7f0 7250 params.link_sta_params.supported_rates_len =
5727ef1b
JB
7251 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
7252 }
7253
9d62a986
JM
7254 if (info->attrs[NL80211_ATTR_STA_CAPABILITY]) {
7255 params.capability =
7256 nla_get_u16(info->attrs[NL80211_ATTR_STA_CAPABILITY]);
7257 params.sta_modify_mask |= STATION_PARAM_APPLY_CAPABILITY;
7258 }
7259
7260 if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]) {
7261 params.ext_capab =
7262 nla_data(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]);
7263 params.ext_capab_len =
7264 nla_len(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]);
7265 }
7266
bdd3ae3d 7267 if (parse_station_flags(info, dev->ieee80211_ptr->iftype, &params))
5727ef1b
JB
7268 return -EINVAL;
7269
ab0d76f6 7270 if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION])
2ec600d6 7271 params.plink_action =
f8bacc21 7272 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
2ec600d6 7273
f8bacc21 7274 if (info->attrs[NL80211_ATTR_STA_PLINK_STATE]) {
9c3990aa 7275 params.plink_state =
f8bacc21 7276 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_STATE]);
ab0d76f6 7277 if (info->attrs[NL80211_ATTR_MESH_PEER_AID])
7d27a0ba
MH
7278 params.peer_aid = nla_get_u16(
7279 info->attrs[NL80211_ATTR_MESH_PEER_AID]);
f8bacc21
JB
7280 params.sta_modify_mask |= STATION_PARAM_APPLY_PLINK_STATE;
7281 }
9c3990aa 7282
ab0d76f6
JB
7283 if (info->attrs[NL80211_ATTR_LOCAL_MESH_POWER_MODE])
7284 params.local_pm = nla_get_u32(
3b1c5a53
MP
7285 info->attrs[NL80211_ATTR_LOCAL_MESH_POWER_MODE]);
7286
06f7c88c 7287 if (info->attrs[NL80211_ATTR_OPMODE_NOTIF]) {
b95eb7f0
ST
7288 params.link_sta_params.opmode_notif_used = true;
7289 params.link_sta_params.opmode_notif =
06f7c88c
BL
7290 nla_get_u8(info->attrs[NL80211_ATTR_OPMODE_NOTIF]);
7291 }
7292
43e64bf3 7293 if (info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY])
b95eb7f0 7294 params.link_sta_params.he_6ghz_capa =
fce2ff72 7295 nla_data(info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY]);
43e64bf3 7296
36647055
THJ
7297 if (info->attrs[NL80211_ATTR_AIRTIME_WEIGHT])
7298 params.airtime_weight =
7299 nla_get_u16(info->attrs[NL80211_ATTR_AIRTIME_WEIGHT]);
7300
7301 if (params.airtime_weight &&
7302 !wiphy_ext_feature_isset(&rdev->wiphy,
7303 NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))
7304 return -EOPNOTSUPP;
7305
b95eb7f0
ST
7306 err = nl80211_parse_sta_txpower_setting(info,
7307 &params.link_sta_params.txpwr,
7308 &params.link_sta_params.txpwr_set);
e96d1cd2
ARN
7309 if (err)
7310 return err;
7311
77ee7c89
JB
7312 /* Include parameters for TDLS peer (will check later) */
7313 err = nl80211_set_station_tdls(info, &params);
7314 if (err)
7315 return err;
7316
7317 params.vlan = get_vlan(info, rdev);
7318 if (IS_ERR(params.vlan))
7319 return PTR_ERR(params.vlan);
7320
a97f4424
JB
7321 switch (dev->ieee80211_ptr->iftype) {
7322 case NL80211_IFTYPE_AP:
7323 case NL80211_IFTYPE_AP_VLAN:
074ac8df 7324 case NL80211_IFTYPE_P2P_GO:
074ac8df 7325 case NL80211_IFTYPE_P2P_CLIENT:
a97f4424 7326 case NL80211_IFTYPE_STATION:
267335d6 7327 case NL80211_IFTYPE_ADHOC:
a97f4424 7328 case NL80211_IFTYPE_MESH_POINT:
a97f4424
JB
7329 break;
7330 default:
77ee7c89
JB
7331 err = -EOPNOTSUPP;
7332 goto out_put_vlan;
034d655e
JB
7333 }
7334
77ee7c89 7335 /* driver will call cfg80211_check_station_change() */
e35e4d28 7336 err = rdev_change_station(rdev, dev, mac_addr, &params);
5727ef1b 7337
77ee7c89 7338 out_put_vlan:
1160dfa1 7339 dev_put(params.vlan);
3b85875a 7340
5727ef1b
JB
7341 return err;
7342}
7343
7344static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
7345{
4c476991 7346 struct cfg80211_registered_device *rdev = info->user_ptr[0];
5727ef1b 7347 int err;
4c476991 7348 struct net_device *dev = info->user_ptr[1];
efbfe516 7349 struct wireless_dev *wdev = dev->ieee80211_ptr;
5727ef1b
JB
7350 struct station_parameters params;
7351 u8 *mac_addr = NULL;
bda95eb1
JB
7352 u32 auth_assoc = BIT(NL80211_STA_FLAG_AUTHENTICATED) |
7353 BIT(NL80211_STA_FLAG_ASSOCIATED);
5727ef1b
JB
7354
7355 memset(&params, 0, sizeof(params));
7356
984c311b
JB
7357 if (!rdev->ops->add_station)
7358 return -EOPNOTSUPP;
7359
5727ef1b
JB
7360 if (!info->attrs[NL80211_ATTR_MAC])
7361 return -EINVAL;
7362
5727ef1b
JB
7363 if (!info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
7364 return -EINVAL;
7365
7366 if (!info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES])
7367 return -EINVAL;
7368
5e4b6f56
JM
7369 if (!info->attrs[NL80211_ATTR_STA_AID] &&
7370 !info->attrs[NL80211_ATTR_PEER_AID])
0e956c13
TLSC
7371 return -EINVAL;
7372
b95eb7f0
ST
7373 params.link_sta_params.link_id =
7374 nl80211_link_id_or_invalid(info->attrs);
7375
c0d67012 7376 if (info->attrs[NL80211_ATTR_MLD_ADDR]) {
c0d67012
ST
7377 mac_addr = nla_data(info->attrs[NL80211_ATTR_MLD_ADDR]);
7378 params.link_sta_params.mld_mac = mac_addr;
7379 params.link_sta_params.link_mac =
7380 nla_data(info->attrs[NL80211_ATTR_MAC]);
7381 if (!is_valid_ether_addr(params.link_sta_params.link_mac))
7382 return -EINVAL;
7383 } else {
7384 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
7385 }
7386
b95eb7f0 7387 params.link_sta_params.supported_rates =
5727ef1b 7388 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
b95eb7f0 7389 params.link_sta_params.supported_rates_len =
5727ef1b
JB
7390 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
7391 params.listen_interval =
7392 nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
51b50fbe 7393
14f34e36
GG
7394 if (info->attrs[NL80211_ATTR_VLAN_ID])
7395 params.vlan_id = nla_get_u16(info->attrs[NL80211_ATTR_VLAN_ID]);
7396
17b94247 7397 if (info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]) {
ab0d76f6
JB
7398 params.support_p2p_ps =
7399 nla_get_u8(info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]);
17b94247
AB
7400 } else {
7401 /*
7402 * if not specified, assume it's supported for P2P GO interface,
7403 * and is NOT supported for AP interface
7404 */
7405 params.support_p2p_ps =
7406 dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO;
7407 }
7408
3d124ea2 7409 if (info->attrs[NL80211_ATTR_PEER_AID])
5e4b6f56 7410 params.aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]);
3d124ea2
JM
7411 else
7412 params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
51b50fbe 7413
9d62a986
JM
7414 if (info->attrs[NL80211_ATTR_STA_CAPABILITY]) {
7415 params.capability =
7416 nla_get_u16(info->attrs[NL80211_ATTR_STA_CAPABILITY]);
7417 params.sta_modify_mask |= STATION_PARAM_APPLY_CAPABILITY;
7418 }
7419
7420 if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]) {
7421 params.ext_capab =
7422 nla_data(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]);
7423 params.ext_capab_len =
7424 nla_len(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]);
7425 }
7426
36aedc90 7427 if (info->attrs[NL80211_ATTR_HT_CAPABILITY])
b95eb7f0 7428 params.link_sta_params.ht_capa =
36aedc90 7429 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
5727ef1b 7430
f461be3e 7431 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY])
b95eb7f0 7432 params.link_sta_params.vht_capa =
f461be3e
MP
7433 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);
7434
c4cbaf79 7435 if (info->attrs[NL80211_ATTR_HE_CAPABILITY]) {
b95eb7f0 7436 params.link_sta_params.he_capa =
c4cbaf79 7437 nla_data(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
b95eb7f0 7438 params.link_sta_params.he_capa_len =
c4cbaf79 7439 nla_len(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
ea05fd35
IP
7440
7441 if (info->attrs[NL80211_ATTR_EHT_CAPABILITY]) {
b95eb7f0 7442 params.link_sta_params.eht_capa =
ea05fd35 7443 nla_data(info->attrs[NL80211_ATTR_EHT_CAPABILITY]);
b95eb7f0 7444 params.link_sta_params.eht_capa_len =
ea05fd35
IP
7445 nla_len(info->attrs[NL80211_ATTR_EHT_CAPABILITY]);
7446
b95eb7f0
ST
7447 if (!ieee80211_eht_capa_size_ok((const u8 *)params.link_sta_params.he_capa,
7448 (const u8 *)params.link_sta_params.eht_capa,
ea5cba26
JB
7449 params.link_sta_params.eht_capa_len,
7450 false))
ea05fd35
IP
7451 return -EINVAL;
7452 }
c4cbaf79
LC
7453 }
7454
43e64bf3 7455 if (info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY])
b95eb7f0 7456 params.link_sta_params.he_6ghz_capa =
43e64bf3
RM
7457 nla_data(info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY]);
7458
60f4a7b1 7459 if (info->attrs[NL80211_ATTR_OPMODE_NOTIF]) {
b95eb7f0
ST
7460 params.link_sta_params.opmode_notif_used = true;
7461 params.link_sta_params.opmode_notif =
60f4a7b1
MK
7462 nla_get_u8(info->attrs[NL80211_ATTR_OPMODE_NOTIF]);
7463 }
7464
ab0d76f6 7465 if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION])
96b78dff 7466 params.plink_action =
f8bacc21 7467 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
96b78dff 7468
36647055
THJ
7469 if (info->attrs[NL80211_ATTR_AIRTIME_WEIGHT])
7470 params.airtime_weight =
7471 nla_get_u16(info->attrs[NL80211_ATTR_AIRTIME_WEIGHT]);
7472
7473 if (params.airtime_weight &&
7474 !wiphy_ext_feature_isset(&rdev->wiphy,
7475 NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))
7476 return -EOPNOTSUPP;
7477
b95eb7f0
ST
7478 err = nl80211_parse_sta_txpower_setting(info,
7479 &params.link_sta_params.txpwr,
7480 &params.link_sta_params.txpwr_set);
e96d1cd2
ARN
7481 if (err)
7482 return err;
7483
c01fc9ad
SD
7484 err = nl80211_parse_sta_channel_info(info, &params);
7485 if (err)
7486 return err;
7487
ff276691
JB
7488 err = nl80211_parse_sta_wme(info, &params);
7489 if (err)
7490 return err;
bdd90d5e 7491
bdd3ae3d 7492 if (parse_station_flags(info, dev->ieee80211_ptr->iftype, &params))
5727ef1b
JB
7493 return -EINVAL;
7494
496fcc29
JB
7495 /* HT/VHT requires QoS, but if we don't have that just ignore HT/VHT
7496 * as userspace might just pass through the capabilities from the IEs
7497 * directly, rather than enforcing this restriction and returning an
7498 * error in this case.
7499 */
7500 if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_WME))) {
b95eb7f0
ST
7501 params.link_sta_params.ht_capa = NULL;
7502 params.link_sta_params.vht_capa = NULL;
c4cbaf79 7503
ea05fd35 7504 /* HE and EHT require WME */
b95eb7f0
ST
7505 if (params.link_sta_params.he_capa_len ||
7506 params.link_sta_params.he_6ghz_capa ||
7507 params.link_sta_params.eht_capa_len)
c4cbaf79 7508 return -EINVAL;
496fcc29
JB
7509 }
7510
43e64bf3 7511 /* Ensure that HT/VHT capabilities are not set for 6 GHz HE STA */
b95eb7f0
ST
7512 if (params.link_sta_params.he_6ghz_capa &&
7513 (params.link_sta_params.ht_capa || params.link_sta_params.vht_capa))
43e64bf3
RM
7514 return -EINVAL;
7515
77ee7c89 7516 /* When you run into this, adjust the code below for the new flag */
2518e89d 7517 BUILD_BUG_ON(NL80211_STA_FLAG_MAX != 8);
77ee7c89 7518
bdd90d5e
JB
7519 switch (dev->ieee80211_ptr->iftype) {
7520 case NL80211_IFTYPE_AP:
7521 case NL80211_IFTYPE_AP_VLAN:
7522 case NL80211_IFTYPE_P2P_GO:
984c311b
JB
7523 /* ignore WME attributes if iface/sta is not capable */
7524 if (!(rdev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) ||
7525 !(params.sta_flags_set & BIT(NL80211_STA_FLAG_WME)))
7526 params.sta_modify_mask &= ~STATION_PARAM_APPLY_UAPSD;
c75786c9 7527
bdd90d5e 7528 /* TDLS peers cannot be added */
3d124ea2
JM
7529 if ((params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) ||
7530 info->attrs[NL80211_ATTR_PEER_AID])
4319e193 7531 return -EINVAL;
bdd90d5e
JB
7532 /* but don't bother the driver with it */
7533 params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
3b9ce80c 7534
d582cffb
JB
7535 /* allow authenticated/associated only if driver handles it */
7536 if (!(rdev->wiphy.features &
7537 NL80211_FEATURE_FULL_AP_CLIENT_STATE) &&
bda95eb1 7538 params.sta_flags_mask & auth_assoc)
d582cffb
JB
7539 return -EINVAL;
7540
2518e89d
JB
7541 if (!wiphy_ext_feature_isset(&rdev->wiphy,
7542 NL80211_EXT_FEATURE_SPP_AMSDU_SUPPORT) &&
7543 params.sta_flags_mask & BIT(NL80211_STA_FLAG_SPP_AMSDU))
7544 return -EINVAL;
7545
bda95eb1
JB
7546 /* Older userspace, or userspace wanting to be compatible with
7547 * !NL80211_FEATURE_FULL_AP_CLIENT_STATE, will not set the auth
7548 * and assoc flags in the mask, but assumes the station will be
7549 * added as associated anyway since this was the required driver
7550 * behaviour before NL80211_FEATURE_FULL_AP_CLIENT_STATE was
7551 * introduced.
7552 * In order to not bother drivers with this quirk in the API
7553 * set the flags in both the mask and set for new stations in
7554 * this case.
7555 */
7556 if (!(params.sta_flags_mask & auth_assoc)) {
7557 params.sta_flags_mask |= auth_assoc;
7558 params.sta_flags_set |= auth_assoc;
7559 }
7560
bdd90d5e
JB
7561 /* must be last in here for error handling */
7562 params.vlan = get_vlan(info, rdev);
7563 if (IS_ERR(params.vlan))
7564 return PTR_ERR(params.vlan);
7565 break;
7566 case NL80211_IFTYPE_MESH_POINT:
984c311b
JB
7567 /* ignore uAPSD data */
7568 params.sta_modify_mask &= ~STATION_PARAM_APPLY_UAPSD;
7569
d582cffb
JB
7570 /* associated is disallowed */
7571 if (params.sta_flags_mask & BIT(NL80211_STA_FLAG_ASSOCIATED))
7572 return -EINVAL;
bdd90d5e 7573 /* TDLS peers cannot be added */
3d124ea2
JM
7574 if ((params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) ||
7575 info->attrs[NL80211_ATTR_PEER_AID])
bdd90d5e
JB
7576 return -EINVAL;
7577 break;
7578 case NL80211_IFTYPE_STATION:
93d08f0b 7579 case NL80211_IFTYPE_P2P_CLIENT:
984c311b
JB
7580 /* ignore uAPSD data */
7581 params.sta_modify_mask &= ~STATION_PARAM_APPLY_UAPSD;
7582
77ee7c89
JB
7583 /* these are disallowed */
7584 if (params.sta_flags_mask &
7585 (BIT(NL80211_STA_FLAG_ASSOCIATED) |
7586 BIT(NL80211_STA_FLAG_AUTHENTICATED)))
d582cffb 7587 return -EINVAL;
bdd90d5e
JB
7588 /* Only TDLS peers can be added */
7589 if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))
7590 return -EINVAL;
7591 /* Can only add if TDLS ... */
7592 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS))
7593 return -EOPNOTSUPP;
7594 /* ... with external setup is supported */
7595 if (!(rdev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP))
7596 return -EOPNOTSUPP;
77ee7c89
JB
7597 /*
7598 * Older wpa_supplicant versions always mark the TDLS peer
7599 * as authorized, but it shouldn't yet be.
7600 */
7601 params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_AUTHORIZED);
bdd90d5e
JB
7602 break;
7603 default:
7604 return -EOPNOTSUPP;
c75786c9
EP
7605 }
7606
bdd90d5e 7607 /* be aware of params.vlan when changing code here */
5727ef1b 7608
efbfe516
JB
7609 if (wdev->valid_links) {
7610 if (params.link_sta_params.link_id < 0) {
7611 err = -EINVAL;
7612 goto out;
7613 }
7614 if (!(wdev->valid_links & BIT(params.link_sta_params.link_id))) {
7615 err = -ENOLINK;
7616 goto out;
7617 }
7618 } else {
7619 if (params.link_sta_params.link_id >= 0) {
7620 err = -EINVAL;
7621 goto out;
7622 }
7623 }
e35e4d28 7624 err = rdev_add_station(rdev, dev, mac_addr, &params);
efbfe516 7625out:
1160dfa1 7626 dev_put(params.vlan);
5727ef1b
JB
7627 return err;
7628}
7629
7630static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info)
7631{
4c476991
JB
7632 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7633 struct net_device *dev = info->user_ptr[1];
f6ca96aa 7634 struct wireless_dev *wdev = dev->ieee80211_ptr;
89c771e5 7635 struct station_del_parameters params;
f6ca96aa 7636 int link_id = nl80211_link_id_or_invalid(info->attrs);
89c771e5
JM
7637
7638 memset(&params, 0, sizeof(params));
5727ef1b
JB
7639
7640 if (info->attrs[NL80211_ATTR_MAC])
89c771e5 7641 params.mac = nla_data(info->attrs[NL80211_ATTR_MAC]);
5727ef1b 7642
f6ca96aa 7643 switch (wdev->iftype) {
306b79ea
JB
7644 case NL80211_IFTYPE_AP:
7645 case NL80211_IFTYPE_AP_VLAN:
7646 case NL80211_IFTYPE_MESH_POINT:
7647 case NL80211_IFTYPE_P2P_GO:
7648 /* always accept these */
7649 break;
7650 case NL80211_IFTYPE_ADHOC:
7651 /* conditionally accept */
7652 if (wiphy_ext_feature_isset(&rdev->wiphy,
7653 NL80211_EXT_FEATURE_DEL_IBSS_STA))
7654 break;
edafcf42 7655 return -EINVAL;
306b79ea 7656 default:
4c476991 7657 return -EINVAL;
306b79ea 7658 }
5727ef1b 7659
4c476991
JB
7660 if (!rdev->ops->del_station)
7661 return -EOPNOTSUPP;
3b85875a 7662
98856866
JM
7663 if (info->attrs[NL80211_ATTR_MGMT_SUBTYPE]) {
7664 params.subtype =
7665 nla_get_u8(info->attrs[NL80211_ATTR_MGMT_SUBTYPE]);
7666 if (params.subtype != IEEE80211_STYPE_DISASSOC >> 4 &&
7667 params.subtype != IEEE80211_STYPE_DEAUTH >> 4)
7668 return -EINVAL;
7669 } else {
7670 /* Default to Deauthentication frame */
7671 params.subtype = IEEE80211_STYPE_DEAUTH >> 4;
7672 }
7673
7674 if (info->attrs[NL80211_ATTR_REASON_CODE]) {
7675 params.reason_code =
7676 nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
7677 if (params.reason_code == 0)
7678 return -EINVAL; /* 0 is reserved */
7679 } else {
7680 /* Default to reason code 2 */
7681 params.reason_code = WLAN_REASON_PREV_AUTH_NOT_VALID;
7682 }
7683
f6ca96aa
AKS
7684 /* Link ID not expected in case of non-ML operation */
7685 if (!wdev->valid_links && link_id != -1)
7686 return -EINVAL;
7687
7688 /* If given, a valid link ID should be passed during MLO */
7689 if (wdev->valid_links && link_id >= 0 &&
7690 !(wdev->valid_links & BIT(link_id)))
7691 return -EINVAL;
7692
7693 params.link_id = link_id;
7694
076fc877 7695 return rdev_del_station(rdev, dev, &params);
5727ef1b
JB
7696}
7697
15e47304 7698static int nl80211_send_mpath(struct sk_buff *msg, u32 portid, u32 seq,
2ec600d6
LCC
7699 int flags, struct net_device *dev,
7700 u8 *dst, u8 *next_hop,
7701 struct mpath_info *pinfo)
7702{
7703 void *hdr;
7704 struct nlattr *pinfoattr;
7705
1ef4c850 7706 hdr = nl80211hdr_put(msg, portid, seq, flags, NL80211_CMD_NEW_MPATH);
2ec600d6
LCC
7707 if (!hdr)
7708 return -1;
7709
9360ffd1
DM
7710 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
7711 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, dst) ||
7712 nla_put(msg, NL80211_ATTR_MPATH_NEXT_HOP, ETH_ALEN, next_hop) ||
7713 nla_put_u32(msg, NL80211_ATTR_GENERATION, pinfo->generation))
7714 goto nla_put_failure;
f5ea9120 7715
ae0be8de 7716 pinfoattr = nla_nest_start_noflag(msg, NL80211_ATTR_MPATH_INFO);
2ec600d6
LCC
7717 if (!pinfoattr)
7718 goto nla_put_failure;
9360ffd1
DM
7719 if ((pinfo->filled & MPATH_INFO_FRAME_QLEN) &&
7720 nla_put_u32(msg, NL80211_MPATH_INFO_FRAME_QLEN,
7721 pinfo->frame_qlen))
7722 goto nla_put_failure;
7723 if (((pinfo->filled & MPATH_INFO_SN) &&
7724 nla_put_u32(msg, NL80211_MPATH_INFO_SN, pinfo->sn)) ||
7725 ((pinfo->filled & MPATH_INFO_METRIC) &&
7726 nla_put_u32(msg, NL80211_MPATH_INFO_METRIC,
7727 pinfo->metric)) ||
7728 ((pinfo->filled & MPATH_INFO_EXPTIME) &&
7729 nla_put_u32(msg, NL80211_MPATH_INFO_EXPTIME,
7730 pinfo->exptime)) ||
7731 ((pinfo->filled & MPATH_INFO_FLAGS) &&
7732 nla_put_u8(msg, NL80211_MPATH_INFO_FLAGS,
7733 pinfo->flags)) ||
7734 ((pinfo->filled & MPATH_INFO_DISCOVERY_TIMEOUT) &&
7735 nla_put_u32(msg, NL80211_MPATH_INFO_DISCOVERY_TIMEOUT,
7736 pinfo->discovery_timeout)) ||
7737 ((pinfo->filled & MPATH_INFO_DISCOVERY_RETRIES) &&
7738 nla_put_u8(msg, NL80211_MPATH_INFO_DISCOVERY_RETRIES,
cc241636
JH
7739 pinfo->discovery_retries)) ||
7740 ((pinfo->filled & MPATH_INFO_HOP_COUNT) &&
7741 nla_put_u8(msg, NL80211_MPATH_INFO_HOP_COUNT,
540bbcb9
JH
7742 pinfo->hop_count)) ||
7743 ((pinfo->filled & MPATH_INFO_PATH_CHANGE) &&
7744 nla_put_u32(msg, NL80211_MPATH_INFO_PATH_CHANGE,
7745 pinfo->path_change_count)))
9360ffd1 7746 goto nla_put_failure;
2ec600d6
LCC
7747
7748 nla_nest_end(msg, pinfoattr);
7749
053c095a
JB
7750 genlmsg_end(msg, hdr);
7751 return 0;
2ec600d6
LCC
7752
7753 nla_put_failure:
bc3ed28c
TG
7754 genlmsg_cancel(msg, hdr);
7755 return -EMSGSIZE;
2ec600d6
LCC
7756}
7757
7758static int nl80211_dump_mpath(struct sk_buff *skb,
bba95fef 7759 struct netlink_callback *cb)
2ec600d6 7760{
2ec600d6 7761 struct mpath_info pinfo;
1b8ec87a 7762 struct cfg80211_registered_device *rdev;
97990a06 7763 struct wireless_dev *wdev;
2ec600d6
LCC
7764 u8 dst[ETH_ALEN];
7765 u8 next_hop[ETH_ALEN];
97990a06 7766 int path_idx = cb->args[2];
2ec600d6 7767 int err;
2ec600d6 7768
ce6b6974 7769 err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev, NULL);
67748893 7770 if (err)
a05829a7
JB
7771 return err;
7772 /* nl80211_prepare_wdev_dump acquired it in the successful case */
7773 __acquire(&rdev->wiphy.mtx);
bba95fef 7774
1b8ec87a 7775 if (!rdev->ops->dump_mpath) {
eec60b03 7776 err = -EOPNOTSUPP;
bba95fef
JB
7777 goto out_err;
7778 }
7779
97990a06 7780 if (wdev->iftype != NL80211_IFTYPE_MESH_POINT) {
eec60b03 7781 err = -EOPNOTSUPP;
0448b5fc 7782 goto out_err;
eec60b03
JM
7783 }
7784
bba95fef 7785 while (1) {
1b8ec87a 7786 err = rdev_dump_mpath(rdev, wdev->netdev, path_idx, dst,
97990a06 7787 next_hop, &pinfo);
bba95fef 7788 if (err == -ENOENT)
2ec600d6 7789 break;
bba95fef 7790 if (err)
3b85875a 7791 goto out_err;
2ec600d6 7792
15e47304 7793 if (nl80211_send_mpath(skb, NETLINK_CB(cb->skb).portid,
bba95fef 7794 cb->nlh->nlmsg_seq, NLM_F_MULTI,
97990a06 7795 wdev->netdev, dst, next_hop,
bba95fef
JB
7796 &pinfo) < 0)
7797 goto out;
2ec600d6 7798
bba95fef 7799 path_idx++;
2ec600d6 7800 }
2ec600d6 7801
bba95fef 7802 out:
97990a06 7803 cb->args[2] = path_idx;
bba95fef 7804 err = skb->len;
bba95fef 7805 out_err:
a05829a7 7806 wiphy_unlock(&rdev->wiphy);
bba95fef 7807 return err;
2ec600d6
LCC
7808}
7809
7810static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info)
7811{
4c476991 7812 struct cfg80211_registered_device *rdev = info->user_ptr[0];
2ec600d6 7813 int err;
4c476991 7814 struct net_device *dev = info->user_ptr[1];
2ec600d6
LCC
7815 struct mpath_info pinfo;
7816 struct sk_buff *msg;
7817 u8 *dst = NULL;
7818 u8 next_hop[ETH_ALEN];
7819
7820 memset(&pinfo, 0, sizeof(pinfo));
7821
7822 if (!info->attrs[NL80211_ATTR_MAC])
7823 return -EINVAL;
7824
7825 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
7826
4c476991
JB
7827 if (!rdev->ops->get_mpath)
7828 return -EOPNOTSUPP;
2ec600d6 7829
4c476991
JB
7830 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
7831 return -EOPNOTSUPP;
eec60b03 7832
e35e4d28 7833 err = rdev_get_mpath(rdev, dev, dst, next_hop, &pinfo);
2ec600d6 7834 if (err)
4c476991 7835 return err;
2ec600d6 7836
fd2120ca 7837 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2ec600d6 7838 if (!msg)
4c476991 7839 return -ENOMEM;
2ec600d6 7840
15e47304 7841 if (nl80211_send_mpath(msg, info->snd_portid, info->snd_seq, 0,
4c476991
JB
7842 dev, dst, next_hop, &pinfo) < 0) {
7843 nlmsg_free(msg);
7844 return -ENOBUFS;
7845 }
3b85875a 7846
4c476991 7847 return genlmsg_reply(msg, info);
2ec600d6
LCC
7848}
7849
7850static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info)
7851{
4c476991
JB
7852 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7853 struct net_device *dev = info->user_ptr[1];
2ec600d6
LCC
7854 u8 *dst = NULL;
7855 u8 *next_hop = NULL;
7856
7857 if (!info->attrs[NL80211_ATTR_MAC])
7858 return -EINVAL;
7859
7860 if (!info->attrs[NL80211_ATTR_MPATH_NEXT_HOP])
7861 return -EINVAL;
7862
7863 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
7864 next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);
7865
4c476991
JB
7866 if (!rdev->ops->change_mpath)
7867 return -EOPNOTSUPP;
35a8efe1 7868
4c476991
JB
7869 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
7870 return -EOPNOTSUPP;
2ec600d6 7871
e35e4d28 7872 return rdev_change_mpath(rdev, dev, dst, next_hop);
2ec600d6 7873}
4c476991 7874
2ec600d6
LCC
7875static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info)
7876{
4c476991
JB
7877 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7878 struct net_device *dev = info->user_ptr[1];
2ec600d6
LCC
7879 u8 *dst = NULL;
7880 u8 *next_hop = NULL;
7881
7882 if (!info->attrs[NL80211_ATTR_MAC])
7883 return -EINVAL;
7884
7885 if (!info->attrs[NL80211_ATTR_MPATH_NEXT_HOP])
7886 return -EINVAL;
7887
7888 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
7889 next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);
7890
4c476991
JB
7891 if (!rdev->ops->add_mpath)
7892 return -EOPNOTSUPP;
35a8efe1 7893
4c476991
JB
7894 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
7895 return -EOPNOTSUPP;
2ec600d6 7896
e35e4d28 7897 return rdev_add_mpath(rdev, dev, dst, next_hop);
2ec600d6
LCC
7898}
7899
7900static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info)
7901{
4c476991
JB
7902 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7903 struct net_device *dev = info->user_ptr[1];
2ec600d6
LCC
7904 u8 *dst = NULL;
7905
7906 if (info->attrs[NL80211_ATTR_MAC])
7907 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
7908
4c476991
JB
7909 if (!rdev->ops->del_mpath)
7910 return -EOPNOTSUPP;
3b85875a 7911
b501426c
MP
7912 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
7913 return -EOPNOTSUPP;
7914
e35e4d28 7915 return rdev_del_mpath(rdev, dev, dst);
2ec600d6
LCC
7916}
7917
66be7d2b
HR
7918static int nl80211_get_mpp(struct sk_buff *skb, struct genl_info *info)
7919{
7920 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7921 int err;
7922 struct net_device *dev = info->user_ptr[1];
7923 struct mpath_info pinfo;
7924 struct sk_buff *msg;
7925 u8 *dst = NULL;
7926 u8 mpp[ETH_ALEN];
7927
7928 memset(&pinfo, 0, sizeof(pinfo));
7929
7930 if (!info->attrs[NL80211_ATTR_MAC])
7931 return -EINVAL;
7932
7933 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
7934
7935 if (!rdev->ops->get_mpp)
7936 return -EOPNOTSUPP;
7937
7938 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
7939 return -EOPNOTSUPP;
7940
7941 err = rdev_get_mpp(rdev, dev, dst, mpp, &pinfo);
7942 if (err)
7943 return err;
7944
7945 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
7946 if (!msg)
7947 return -ENOMEM;
7948
7949 if (nl80211_send_mpath(msg, info->snd_portid, info->snd_seq, 0,
7950 dev, dst, mpp, &pinfo) < 0) {
7951 nlmsg_free(msg);
7952 return -ENOBUFS;
7953 }
7954
7955 return genlmsg_reply(msg, info);
7956}
7957
7958static int nl80211_dump_mpp(struct sk_buff *skb,
7959 struct netlink_callback *cb)
7960{
7961 struct mpath_info pinfo;
7962 struct cfg80211_registered_device *rdev;
7963 struct wireless_dev *wdev;
7964 u8 dst[ETH_ALEN];
7965 u8 mpp[ETH_ALEN];
7966 int path_idx = cb->args[2];
7967 int err;
7968
ce6b6974 7969 err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev, NULL);
66be7d2b 7970 if (err)
a05829a7
JB
7971 return err;
7972 /* nl80211_prepare_wdev_dump acquired it in the successful case */
7973 __acquire(&rdev->wiphy.mtx);
66be7d2b
HR
7974
7975 if (!rdev->ops->dump_mpp) {
7976 err = -EOPNOTSUPP;
7977 goto out_err;
7978 }
7979
7980 if (wdev->iftype != NL80211_IFTYPE_MESH_POINT) {
7981 err = -EOPNOTSUPP;
7982 goto out_err;
7983 }
7984
7985 while (1) {
7986 err = rdev_dump_mpp(rdev, wdev->netdev, path_idx, dst,
7987 mpp, &pinfo);
7988 if (err == -ENOENT)
7989 break;
7990 if (err)
7991 goto out_err;
7992
7993 if (nl80211_send_mpath(skb, NETLINK_CB(cb->skb).portid,
7994 cb->nlh->nlmsg_seq, NLM_F_MULTI,
7995 wdev->netdev, dst, mpp,
7996 &pinfo) < 0)
7997 goto out;
7998
7999 path_idx++;
8000 }
8001
8002 out:
8003 cb->args[2] = path_idx;
8004 err = skb->len;
8005 out_err:
a05829a7 8006 wiphy_unlock(&rdev->wiphy);
66be7d2b
HR
8007 return err;
8008}
8009
9f1ba906
JM
8010static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
8011{
4c476991
JB
8012 struct cfg80211_registered_device *rdev = info->user_ptr[0];
8013 struct net_device *dev = info->user_ptr[1];
9f1ba906
JM
8014 struct bss_parameters params;
8015
8016 memset(&params, 0, sizeof(params));
1e0f8cc9 8017 params.link_id = nl80211_link_id_or_invalid(info->attrs);
9f1ba906
JM
8018 /* default to not changing parameters */
8019 params.use_cts_prot = -1;
8020 params.use_short_preamble = -1;
8021 params.use_short_slot_time = -1;
fd8aaaf3 8022 params.ap_isolate = -1;
50b12f59 8023 params.ht_opmode = -1;
53cabad7
JB
8024 params.p2p_ctwindow = -1;
8025 params.p2p_opp_ps = -1;
9f1ba906
JM
8026
8027 if (info->attrs[NL80211_ATTR_BSS_CTS_PROT])
8028 params.use_cts_prot =
8029 nla_get_u8(info->attrs[NL80211_ATTR_BSS_CTS_PROT]);
8030 if (info->attrs[NL80211_ATTR_BSS_SHORT_PREAMBLE])
8031 params.use_short_preamble =
8032 nla_get_u8(info->attrs[NL80211_ATTR_BSS_SHORT_PREAMBLE]);
8033 if (info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME])
8034 params.use_short_slot_time =
8035 nla_get_u8(info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME]);
90c97a04
JM
8036 if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) {
8037 params.basic_rates =
8038 nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
8039 params.basic_rates_len =
8040 nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
8041 }
fd8aaaf3
FF
8042 if (info->attrs[NL80211_ATTR_AP_ISOLATE])
8043 params.ap_isolate = !!nla_get_u8(info->attrs[NL80211_ATTR_AP_ISOLATE]);
50b12f59
HS
8044 if (info->attrs[NL80211_ATTR_BSS_HT_OPMODE])
8045 params.ht_opmode =
8046 nla_get_u16(info->attrs[NL80211_ATTR_BSS_HT_OPMODE]);
9f1ba906 8047
53cabad7
JB
8048 if (info->attrs[NL80211_ATTR_P2P_CTWINDOW]) {
8049 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
8050 return -EINVAL;
8051 params.p2p_ctwindow =
ab0d76f6 8052 nla_get_u8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]);
53cabad7
JB
8053 if (params.p2p_ctwindow != 0 &&
8054 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN))
8055 return -EINVAL;
8056 }
8057
8058 if (info->attrs[NL80211_ATTR_P2P_OPPPS]) {
8059 u8 tmp;
8060
8061 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
8062 return -EINVAL;
8063 tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]);
53cabad7
JB
8064 params.p2p_opp_ps = tmp;
8065 if (params.p2p_opp_ps &&
8066 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS))
8067 return -EINVAL;
8068 }
8069
4c476991
JB
8070 if (!rdev->ops->change_bss)
8071 return -EOPNOTSUPP;
9f1ba906 8072
074ac8df 8073 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
4c476991
JB
8074 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
8075 return -EOPNOTSUPP;
3b85875a 8076
076fc877 8077 return rdev_change_bss(rdev, dev, &params);
9f1ba906
JM
8078}
8079
b2e1b302
LR
8080static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info)
8081{
b2e1b302 8082 char *data = NULL;
05050753 8083 bool is_indoor;
57b5ce07 8084 enum nl80211_user_reg_hint_type user_reg_hint_type;
05050753
I
8085 u32 owner_nlportid;
8086
80778f18
LR
8087 /*
8088 * You should only get this when cfg80211 hasn't yet initialized
8089 * completely when built-in to the kernel right between the time
8090 * window between nl80211_init() and regulatory_init(), if that is
8091 * even possible.
8092 */
458f4f9e 8093 if (unlikely(!rcu_access_pointer(cfg80211_regdomain)))
fe33eb39 8094 return -EINPROGRESS;
80778f18 8095
57b5ce07
LR
8096 if (info->attrs[NL80211_ATTR_USER_REG_HINT_TYPE])
8097 user_reg_hint_type =
8098 nla_get_u32(info->attrs[NL80211_ATTR_USER_REG_HINT_TYPE]);
8099 else
8100 user_reg_hint_type = NL80211_USER_REG_HINT_USER;
8101
8102 switch (user_reg_hint_type) {
8103 case NL80211_USER_REG_HINT_USER:
8104 case NL80211_USER_REG_HINT_CELL_BASE:
52616f2b
IP
8105 if (!info->attrs[NL80211_ATTR_REG_ALPHA2])
8106 return -EINVAL;
8107
8108 data = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]);
8109 return regulatory_hint_user(data, user_reg_hint_type);
8110 case NL80211_USER_REG_HINT_INDOOR:
05050753
I
8111 if (info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
8112 owner_nlportid = info->snd_portid;
8113 is_indoor = !!info->attrs[NL80211_ATTR_REG_INDOOR];
8114 } else {
8115 owner_nlportid = 0;
8116 is_indoor = true;
8117 }
8118
dbda949b
JB
8119 regulatory_hint_indoor(is_indoor, owner_nlportid);
8120 return 0;
57b5ce07
LR
8121 default:
8122 return -EINVAL;
8123 }
b2e1b302
LR
8124}
8125
1ea4ff3e
JB
8126static int nl80211_reload_regdb(struct sk_buff *skb, struct genl_info *info)
8127{
8128 return reg_reload_regdb();
8129}
8130
24bdd9f4 8131static int nl80211_get_mesh_config(struct sk_buff *skb,
29cbe68c 8132 struct genl_info *info)
93da9cc1 8133{
4c476991 8134 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4c476991 8135 struct net_device *dev = info->user_ptr[1];
29cbe68c
JB
8136 struct wireless_dev *wdev = dev->ieee80211_ptr;
8137 struct mesh_config cur_params;
8138 int err = 0;
93da9cc1 8139 void *hdr;
8140 struct nlattr *pinfoattr;
8141 struct sk_buff *msg;
8142
29cbe68c
JB
8143 if (wdev->iftype != NL80211_IFTYPE_MESH_POINT)
8144 return -EOPNOTSUPP;
8145
24bdd9f4 8146 if (!rdev->ops->get_mesh_config)
4c476991 8147 return -EOPNOTSUPP;
f3f92586 8148
29cbe68c 8149 /* If not connected, get default parameters */
7b0a0e3c 8150 if (!wdev->u.mesh.id_len)
29cbe68c
JB
8151 memcpy(&cur_params, &default_mesh_config, sizeof(cur_params));
8152 else
e35e4d28 8153 err = rdev_get_mesh_config(rdev, dev, &cur_params);
29cbe68c 8154
93da9cc1 8155 if (err)
4c476991 8156 return err;
93da9cc1 8157
8158 /* Draw up a netlink message to send back */
fd2120ca 8159 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4c476991
JB
8160 if (!msg)
8161 return -ENOMEM;
15e47304 8162 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
24bdd9f4 8163 NL80211_CMD_GET_MESH_CONFIG);
93da9cc1 8164 if (!hdr)
efe1cf0c 8165 goto out;
ae0be8de 8166 pinfoattr = nla_nest_start_noflag(msg, NL80211_ATTR_MESH_CONFIG);
93da9cc1 8167 if (!pinfoattr)
8168 goto nla_put_failure;
9360ffd1
DM
8169 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
8170 nla_put_u16(msg, NL80211_MESHCONF_RETRY_TIMEOUT,
8171 cur_params.dot11MeshRetryTimeout) ||
8172 nla_put_u16(msg, NL80211_MESHCONF_CONFIRM_TIMEOUT,
8173 cur_params.dot11MeshConfirmTimeout) ||
8174 nla_put_u16(msg, NL80211_MESHCONF_HOLDING_TIMEOUT,
8175 cur_params.dot11MeshHoldingTimeout) ||
8176 nla_put_u16(msg, NL80211_MESHCONF_MAX_PEER_LINKS,
8177 cur_params.dot11MeshMaxPeerLinks) ||
8178 nla_put_u8(msg, NL80211_MESHCONF_MAX_RETRIES,
8179 cur_params.dot11MeshMaxRetries) ||
8180 nla_put_u8(msg, NL80211_MESHCONF_TTL,
8181 cur_params.dot11MeshTTL) ||
8182 nla_put_u8(msg, NL80211_MESHCONF_ELEMENT_TTL,
8183 cur_params.element_ttl) ||
8184 nla_put_u8(msg, NL80211_MESHCONF_AUTO_OPEN_PLINKS,
8185 cur_params.auto_open_plinks) ||
7eab0f64
JL
8186 nla_put_u32(msg, NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR,
8187 cur_params.dot11MeshNbrOffsetMaxNeighbor) ||
9360ffd1
DM
8188 nla_put_u8(msg, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES,
8189 cur_params.dot11MeshHWMPmaxPREQretries) ||
8190 nla_put_u32(msg, NL80211_MESHCONF_PATH_REFRESH_TIME,
8191 cur_params.path_refresh_time) ||
8192 nla_put_u16(msg, NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT,
8193 cur_params.min_discovery_timeout) ||
8194 nla_put_u32(msg, NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT,
8195 cur_params.dot11MeshHWMPactivePathTimeout) ||
8196 nla_put_u16(msg, NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL,
8197 cur_params.dot11MeshHWMPpreqMinInterval) ||
8198 nla_put_u16(msg, NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL,
8199 cur_params.dot11MeshHWMPperrMinInterval) ||
8200 nla_put_u16(msg, NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
8201 cur_params.dot11MeshHWMPnetDiameterTraversalTime) ||
8202 nla_put_u8(msg, NL80211_MESHCONF_HWMP_ROOTMODE,
8203 cur_params.dot11MeshHWMPRootMode) ||
8204 nla_put_u16(msg, NL80211_MESHCONF_HWMP_RANN_INTERVAL,
8205 cur_params.dot11MeshHWMPRannInterval) ||
8206 nla_put_u8(msg, NL80211_MESHCONF_GATE_ANNOUNCEMENTS,
8207 cur_params.dot11MeshGateAnnouncementProtocol) ||
8208 nla_put_u8(msg, NL80211_MESHCONF_FORWARDING,
8209 cur_params.dot11MeshForwarding) ||
335d5349 8210 nla_put_s32(msg, NL80211_MESHCONF_RSSI_THRESHOLD,
70c33eaa
AN
8211 cur_params.rssi_threshold) ||
8212 nla_put_u32(msg, NL80211_MESHCONF_HT_OPMODE,
ac1073a6
CYY
8213 cur_params.ht_opmode) ||
8214 nla_put_u32(msg, NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT,
8215 cur_params.dot11MeshHWMPactivePathToRootTimeout) ||
8216 nla_put_u16(msg, NL80211_MESHCONF_HWMP_ROOT_INTERVAL,
728b19e5
CYY
8217 cur_params.dot11MeshHWMProotInterval) ||
8218 nla_put_u16(msg, NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL,
3b1c5a53
MP
8219 cur_params.dot11MeshHWMPconfirmationInterval) ||
8220 nla_put_u32(msg, NL80211_MESHCONF_POWER_MODE,
8221 cur_params.power_mode) ||
8222 nla_put_u16(msg, NL80211_MESHCONF_AWAKE_WINDOW,
8e7c0538
CT
8223 cur_params.dot11MeshAwakeWindowDuration) ||
8224 nla_put_u32(msg, NL80211_MESHCONF_PLINK_TIMEOUT,
01d66fbd
BC
8225 cur_params.plink_timeout) ||
8226 nla_put_u8(msg, NL80211_MESHCONF_CONNECTED_TO_GATE,
e3718a61
LL
8227 cur_params.dot11MeshConnectedToMeshGate) ||
8228 nla_put_u8(msg, NL80211_MESHCONF_NOLEARN,
184eebe6
MT
8229 cur_params.dot11MeshNolearn) ||
8230 nla_put_u8(msg, NL80211_MESHCONF_CONNECTED_TO_AS,
8231 cur_params.dot11MeshConnectedToAuthServer))
9360ffd1 8232 goto nla_put_failure;
93da9cc1 8233 nla_nest_end(msg, pinfoattr);
8234 genlmsg_end(msg, hdr);
4c476991 8235 return genlmsg_reply(msg, info);
93da9cc1 8236
3b85875a 8237 nla_put_failure:
efe1cf0c 8238 out:
d080e275 8239 nlmsg_free(msg);
4c476991 8240 return -ENOBUFS;
93da9cc1 8241}
8242
ab0d76f6
JB
8243static const struct nla_policy
8244nl80211_meshconf_params_policy[NL80211_MESHCONF_ATTR_MAX+1] = {
8245 [NL80211_MESHCONF_RETRY_TIMEOUT] =
8246 NLA_POLICY_RANGE(NLA_U16, 1, 255),
8247 [NL80211_MESHCONF_CONFIRM_TIMEOUT] =
8248 NLA_POLICY_RANGE(NLA_U16, 1, 255),
8249 [NL80211_MESHCONF_HOLDING_TIMEOUT] =
8250 NLA_POLICY_RANGE(NLA_U16, 1, 255),
8251 [NL80211_MESHCONF_MAX_PEER_LINKS] =
8252 NLA_POLICY_RANGE(NLA_U16, 0, 255),
8253 [NL80211_MESHCONF_MAX_RETRIES] = NLA_POLICY_MAX(NLA_U8, 16),
8254 [NL80211_MESHCONF_TTL] = NLA_POLICY_MIN(NLA_U8, 1),
8255 [NL80211_MESHCONF_ELEMENT_TTL] = NLA_POLICY_MIN(NLA_U8, 1),
8256 [NL80211_MESHCONF_AUTO_OPEN_PLINKS] = NLA_POLICY_MAX(NLA_U8, 1),
8257 [NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR] =
8258 NLA_POLICY_RANGE(NLA_U32, 1, 255),
93da9cc1 8259 [NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES] = { .type = NLA_U8 },
8260 [NL80211_MESHCONF_PATH_REFRESH_TIME] = { .type = NLA_U32 },
ab0d76f6 8261 [NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT] = NLA_POLICY_MIN(NLA_U16, 1),
93da9cc1 8262 [NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT] = { .type = NLA_U32 },
ab0d76f6
JB
8263 [NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL] =
8264 NLA_POLICY_MIN(NLA_U16, 1),
8265 [NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL] =
8266 NLA_POLICY_MIN(NLA_U16, 1),
8267 [NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME] =
8268 NLA_POLICY_MIN(NLA_U16, 1),
8269 [NL80211_MESHCONF_HWMP_ROOTMODE] = NLA_POLICY_MAX(NLA_U8, 4),
8270 [NL80211_MESHCONF_HWMP_RANN_INTERVAL] =
8271 NLA_POLICY_MIN(NLA_U16, 1),
8272 [NL80211_MESHCONF_GATE_ANNOUNCEMENTS] = NLA_POLICY_MAX(NLA_U8, 1),
8273 [NL80211_MESHCONF_FORWARDING] = NLA_POLICY_MAX(NLA_U8, 1),
8274 [NL80211_MESHCONF_RSSI_THRESHOLD] =
8275 NLA_POLICY_RANGE(NLA_S32, -255, 0),
a4f606ea 8276 [NL80211_MESHCONF_HT_OPMODE] = { .type = NLA_U16 },
ac1073a6 8277 [NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT] = { .type = NLA_U32 },
ab0d76f6
JB
8278 [NL80211_MESHCONF_HWMP_ROOT_INTERVAL] =
8279 NLA_POLICY_MIN(NLA_U16, 1),
8280 [NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL] =
8281 NLA_POLICY_MIN(NLA_U16, 1),
8282 [NL80211_MESHCONF_POWER_MODE] =
8283 NLA_POLICY_RANGE(NLA_U32,
8284 NL80211_MESH_POWER_ACTIVE,
8285 NL80211_MESH_POWER_MAX),
3b1c5a53 8286 [NL80211_MESHCONF_AWAKE_WINDOW] = { .type = NLA_U16 },
8e7c0538 8287 [NL80211_MESHCONF_PLINK_TIMEOUT] = { .type = NLA_U32 },
01d66fbd 8288 [NL80211_MESHCONF_CONNECTED_TO_GATE] = NLA_POLICY_RANGE(NLA_U8, 0, 1),
e3718a61 8289 [NL80211_MESHCONF_NOLEARN] = NLA_POLICY_RANGE(NLA_U8, 0, 1),
184eebe6 8290 [NL80211_MESHCONF_CONNECTED_TO_AS] = NLA_POLICY_RANGE(NLA_U8, 0, 1),
93da9cc1 8291};
8292
c80d545d
JC
8293static const struct nla_policy
8294 nl80211_mesh_setup_params_policy[NL80211_MESH_SETUP_ATTR_MAX+1] = {
d299a1f2 8295 [NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC] = { .type = NLA_U8 },
c80d545d
JC
8296 [NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL] = { .type = NLA_U8 },
8297 [NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC] = { .type = NLA_U8 },
15d5dda6 8298 [NL80211_MESH_SETUP_USERSPACE_AUTH] = { .type = NLA_FLAG },
6e16d90b 8299 [NL80211_MESH_SETUP_AUTH_PROTOCOL] = { .type = NLA_U8 },
bb2798d4 8300 [NL80211_MESH_SETUP_USERSPACE_MPM] = { .type = NLA_FLAG },
3d7af878
JB
8301 [NL80211_MESH_SETUP_IE] =
8302 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr,
8303 IEEE80211_MAX_DATA_LEN),
b130e5ce 8304 [NL80211_MESH_SETUP_USERSPACE_AMPE] = { .type = NLA_FLAG },
c80d545d
JC
8305};
8306
24bdd9f4 8307static int nl80211_parse_mesh_config(struct genl_info *info,
bd90fdcc
JB
8308 struct mesh_config *cfg,
8309 u32 *mask_out)
93da9cc1 8310{
93da9cc1 8311 struct nlattr *tb[NL80211_MESHCONF_ATTR_MAX + 1];
bd90fdcc 8312 u32 mask = 0;
9757235f 8313 u16 ht_opmode;
93da9cc1 8314
ab0d76f6
JB
8315#define FILL_IN_MESH_PARAM_IF_SET(tb, cfg, param, mask, attr, fn) \
8316do { \
8317 if (tb[attr]) { \
8318 cfg->param = fn(tb[attr]); \
8319 mask |= BIT((attr) - 1); \
8320 } \
ea54fba2 8321} while (0)
bd90fdcc 8322
24bdd9f4 8323 if (!info->attrs[NL80211_ATTR_MESH_CONFIG])
93da9cc1 8324 return -EINVAL;
8cb08174 8325 if (nla_parse_nested_deprecated(tb, NL80211_MESHCONF_ATTR_MAX, info->attrs[NL80211_ATTR_MESH_CONFIG], nl80211_meshconf_params_policy, info->extack))
93da9cc1 8326 return -EINVAL;
8327
93da9cc1 8328 /* This makes sure that there aren't more than 32 mesh config
8329 * parameters (otherwise our bitfield scheme would not work.) */
8330 BUILD_BUG_ON(NL80211_MESHCONF_ATTR_MAX > 32);
8331
8332 /* Fill in the params struct */
ab0d76f6
JB
8333 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshRetryTimeout, mask,
8334 NL80211_MESHCONF_RETRY_TIMEOUT, nla_get_u16);
8335 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConfirmTimeout, mask,
8336 NL80211_MESHCONF_CONFIRM_TIMEOUT,
8337 nla_get_u16);
8338 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHoldingTimeout, mask,
8339 NL80211_MESHCONF_HOLDING_TIMEOUT,
8340 nla_get_u16);
8341 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxPeerLinks, mask,
8342 NL80211_MESHCONF_MAX_PEER_LINKS,
8343 nla_get_u16);
8344 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxRetries, mask,
8345 NL80211_MESHCONF_MAX_RETRIES, nla_get_u8);
8346 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshTTL, mask,
8347 NL80211_MESHCONF_TTL, nla_get_u8);
8348 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, element_ttl, mask,
8349 NL80211_MESHCONF_ELEMENT_TTL, nla_get_u8);
8350 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, auto_open_plinks, mask,
8351 NL80211_MESHCONF_AUTO_OPEN_PLINKS,
8352 nla_get_u8);
ea54fba2 8353 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshNbrOffsetMaxNeighbor,
ab0d76f6 8354 mask,
a4f606ea 8355 NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR,
ab0d76f6
JB
8356 nla_get_u32);
8357 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPmaxPREQretries, mask,
8358 NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES,
8359 nla_get_u8);
8360 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, path_refresh_time, mask,
8361 NL80211_MESHCONF_PATH_REFRESH_TIME,
8362 nla_get_u32);
8363 if (mask & BIT(NL80211_MESHCONF_PATH_REFRESH_TIME) &&
8364 (cfg->path_refresh_time < 1 || cfg->path_refresh_time > 65535))
8365 return -EINVAL;
8366 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, min_discovery_timeout, mask,
8367 NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT,
8368 nla_get_u16);
ea54fba2 8369 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathTimeout,
ab0d76f6 8370 mask,
a4f606ea 8371 NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT,
ab0d76f6
JB
8372 nla_get_u32);
8373 if (mask & BIT(NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT) &&
8374 (cfg->dot11MeshHWMPactivePathTimeout < 1 ||
8375 cfg->dot11MeshHWMPactivePathTimeout > 65535))
8376 return -EINVAL;
8377 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPpreqMinInterval, mask,
ea54fba2 8378 NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL,
ab0d76f6
JB
8379 nla_get_u16);
8380 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPperrMinInterval, mask,
ea54fba2 8381 NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL,
ab0d76f6 8382 nla_get_u16);
93da9cc1 8383 FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
ab0d76f6 8384 dot11MeshHWMPnetDiameterTraversalTime, mask,
a4f606ea 8385 NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
ab0d76f6
JB
8386 nla_get_u16);
8387 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRootMode, mask,
8388 NL80211_MESHCONF_HWMP_ROOTMODE, nla_get_u8);
8389 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRannInterval, mask,
8390 NL80211_MESHCONF_HWMP_RANN_INTERVAL,
8391 nla_get_u16);
8392 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshGateAnnouncementProtocol,
ea54fba2 8393 mask, NL80211_MESHCONF_GATE_ANNOUNCEMENTS,
ab0d76f6
JB
8394 nla_get_u8);
8395 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshForwarding, mask,
8396 NL80211_MESHCONF_FORWARDING, nla_get_u8);
8397 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, rssi_threshold, mask,
8398 NL80211_MESHCONF_RSSI_THRESHOLD,
8399 nla_get_s32);
01d66fbd
BC
8400 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConnectedToMeshGate, mask,
8401 NL80211_MESHCONF_CONNECTED_TO_GATE,
8402 nla_get_u8);
184eebe6
MT
8403 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConnectedToAuthServer, mask,
8404 NL80211_MESHCONF_CONNECTED_TO_AS,
8405 nla_get_u8);
9757235f
MH
8406 /*
8407 * Check HT operation mode based on
188f60ab 8408 * IEEE 802.11-2016 9.4.2.57 HT Operation element.
9757235f
MH
8409 */
8410 if (tb[NL80211_MESHCONF_HT_OPMODE]) {
8411 ht_opmode = nla_get_u16(tb[NL80211_MESHCONF_HT_OPMODE]);
8412
8413 if (ht_opmode & ~(IEEE80211_HT_OP_MODE_PROTECTION |
8414 IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT |
8415 IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT))
8416 return -EINVAL;
8417
188f60ab
BC
8418 /* NON_HT_STA bit is reserved, but some programs set it */
8419 ht_opmode &= ~IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT;
9757235f 8420
9757235f 8421 cfg->ht_opmode = ht_opmode;
fd551bac 8422 mask |= (1 << (NL80211_MESHCONF_HT_OPMODE - 1));
9757235f 8423 }
728b19e5 8424 FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
ab0d76f6
JB
8425 dot11MeshHWMPactivePathToRootTimeout, mask,
8426 NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT,
8427 nla_get_u32);
8428 if (mask & BIT(NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT) &&
8429 (cfg->dot11MeshHWMPactivePathToRootTimeout < 1 ||
8430 cfg->dot11MeshHWMPactivePathToRootTimeout > 65535))
8431 return -EINVAL;
8432 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMProotInterval, mask,
8433 NL80211_MESHCONF_HWMP_ROOT_INTERVAL,
8434 nla_get_u16);
8435 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPconfirmationInterval,
8436 mask,
728b19e5 8437 NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL,
ab0d76f6
JB
8438 nla_get_u16);
8439 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, power_mode, mask,
8440 NL80211_MESHCONF_POWER_MODE, nla_get_u32);
8441 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshAwakeWindowDuration, mask,
8442 NL80211_MESHCONF_AWAKE_WINDOW, nla_get_u16);
8443 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, plink_timeout, mask,
8444 NL80211_MESHCONF_PLINK_TIMEOUT, nla_get_u32);
e3718a61
LL
8445 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshNolearn, mask,
8446 NL80211_MESHCONF_NOLEARN, nla_get_u8);
bd90fdcc
JB
8447 if (mask_out)
8448 *mask_out = mask;
c80d545d 8449
bd90fdcc
JB
8450 return 0;
8451
8452#undef FILL_IN_MESH_PARAM_IF_SET
8453}
8454
c80d545d
JC
8455static int nl80211_parse_mesh_setup(struct genl_info *info,
8456 struct mesh_setup *setup)
8457{
bb2798d4 8458 struct cfg80211_registered_device *rdev = info->user_ptr[0];
c80d545d
JC
8459 struct nlattr *tb[NL80211_MESH_SETUP_ATTR_MAX + 1];
8460
8461 if (!info->attrs[NL80211_ATTR_MESH_SETUP])
8462 return -EINVAL;
8cb08174 8463 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
8464 return -EINVAL;
8465
d299a1f2
JC
8466 if (tb[NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC])
8467 setup->sync_method =
8468 (nla_get_u8(tb[NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC])) ?
8469 IEEE80211_SYNC_METHOD_VENDOR :
8470 IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET;
8471
c80d545d
JC
8472 if (tb[NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL])
8473 setup->path_sel_proto =
8474 (nla_get_u8(tb[NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL])) ?
8475 IEEE80211_PATH_PROTOCOL_VENDOR :
8476 IEEE80211_PATH_PROTOCOL_HWMP;
8477
8478 if (tb[NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC])
8479 setup->path_metric =
8480 (nla_get_u8(tb[NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC])) ?
8481 IEEE80211_PATH_METRIC_VENDOR :
8482 IEEE80211_PATH_METRIC_AIRTIME;
8483
581a8b0f 8484 if (tb[NL80211_MESH_SETUP_IE]) {
c80d545d 8485 struct nlattr *ieattr =
581a8b0f 8486 tb[NL80211_MESH_SETUP_IE];
581a8b0f
JC
8487 setup->ie = nla_data(ieattr);
8488 setup->ie_len = nla_len(ieattr);
c80d545d 8489 }
bb2798d4
TP
8490 if (tb[NL80211_MESH_SETUP_USERSPACE_MPM] &&
8491 !(rdev->wiphy.features & NL80211_FEATURE_USERSPACE_MPM))
8492 return -EINVAL;
8493 setup->user_mpm = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_MPM]);
b130e5ce
JC
8494 setup->is_authenticated = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AUTH]);
8495 setup->is_secure = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AMPE]);
bb2798d4
TP
8496 if (setup->is_secure)
8497 setup->user_mpm = true;
c80d545d 8498
6e16d90b
CT
8499 if (tb[NL80211_MESH_SETUP_AUTH_PROTOCOL]) {
8500 if (!setup->user_mpm)
8501 return -EINVAL;
8502 setup->auth_id =
8503 nla_get_u8(tb[NL80211_MESH_SETUP_AUTH_PROTOCOL]);
8504 }
8505
c80d545d
JC
8506 return 0;
8507}
8508
24bdd9f4 8509static int nl80211_update_mesh_config(struct sk_buff *skb,
29cbe68c 8510 struct genl_info *info)
bd90fdcc
JB
8511{
8512 struct cfg80211_registered_device *rdev = info->user_ptr[0];
8513 struct net_device *dev = info->user_ptr[1];
29cbe68c 8514 struct wireless_dev *wdev = dev->ieee80211_ptr;
334bf33e 8515 struct mesh_config cfg = {};
bd90fdcc
JB
8516 u32 mask;
8517 int err;
8518
29cbe68c
JB
8519 if (wdev->iftype != NL80211_IFTYPE_MESH_POINT)
8520 return -EOPNOTSUPP;
8521
24bdd9f4 8522 if (!rdev->ops->update_mesh_config)
bd90fdcc
JB
8523 return -EOPNOTSUPP;
8524
24bdd9f4 8525 err = nl80211_parse_mesh_config(info, &cfg, &mask);
bd90fdcc
JB
8526 if (err)
8527 return err;
8528
7b0a0e3c 8529 if (!wdev->u.mesh.id_len)
29cbe68c
JB
8530 err = -ENOLINK;
8531
8532 if (!err)
e35e4d28 8533 err = rdev_update_mesh_config(rdev, dev, mask, &cfg);
29cbe68c 8534
29cbe68c 8535 return err;
93da9cc1 8536}
8537
ad30ca2c
AN
8538static int nl80211_put_regdom(const struct ieee80211_regdomain *regdom,
8539 struct sk_buff *msg)
f130347c 8540{
f130347c
LR
8541 struct nlattr *nl_reg_rules;
8542 unsigned int i;
f130347c 8543
458f4f9e
JB
8544 if (nla_put_string(msg, NL80211_ATTR_REG_ALPHA2, regdom->alpha2) ||
8545 (regdom->dfs_region &&
8546 nla_put_u8(msg, NL80211_ATTR_DFS_REGION, regdom->dfs_region)))
ad30ca2c 8547 goto nla_put_failure;
458f4f9e 8548
ae0be8de 8549 nl_reg_rules = nla_nest_start_noflag(msg, NL80211_ATTR_REG_RULES);
f130347c 8550 if (!nl_reg_rules)
ad30ca2c 8551 goto nla_put_failure;
f130347c 8552
458f4f9e 8553 for (i = 0; i < regdom->n_reg_rules; i++) {
f130347c
LR
8554 struct nlattr *nl_reg_rule;
8555 const struct ieee80211_reg_rule *reg_rule;
8556 const struct ieee80211_freq_range *freq_range;
8557 const struct ieee80211_power_rule *power_rule;
97524820 8558 unsigned int max_bandwidth_khz;
f130347c 8559
458f4f9e 8560 reg_rule = &regdom->reg_rules[i];
f130347c
LR
8561 freq_range = &reg_rule->freq_range;
8562 power_rule = &reg_rule->power_rule;
8563
ae0be8de 8564 nl_reg_rule = nla_nest_start_noflag(msg, i);
f130347c 8565 if (!nl_reg_rule)
ad30ca2c 8566 goto nla_put_failure;
f130347c 8567
97524820
JD
8568 max_bandwidth_khz = freq_range->max_bandwidth_khz;
8569 if (!max_bandwidth_khz)
8570 max_bandwidth_khz = reg_get_max_bandwidth(regdom,
8571 reg_rule);
8572
9360ffd1
DM
8573 if (nla_put_u32(msg, NL80211_ATTR_REG_RULE_FLAGS,
8574 reg_rule->flags) ||
8575 nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_START,
8576 freq_range->start_freq_khz) ||
8577 nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_END,
8578 freq_range->end_freq_khz) ||
8579 nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_MAX_BW,
97524820 8580 max_bandwidth_khz) ||
9360ffd1
DM
8581 nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN,
8582 power_rule->max_antenna_gain) ||
8583 nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_EIRP,
089027e5
JD
8584 power_rule->max_eirp) ||
8585 nla_put_u32(msg, NL80211_ATTR_DFS_CAC_TIME,
8586 reg_rule->dfs_cac_ms))
ad30ca2c 8587 goto nla_put_failure;
f130347c 8588
ddd7f45c
WG
8589 if ((reg_rule->flags & NL80211_RRF_PSD) &&
8590 nla_put_s8(msg, NL80211_ATTR_POWER_RULE_PSD,
8591 reg_rule->psd))
8592 goto nla_put_failure;
8593
f130347c
LR
8594 nla_nest_end(msg, nl_reg_rule);
8595 }
8596
8597 nla_nest_end(msg, nl_reg_rules);
ad30ca2c
AN
8598 return 0;
8599
8600nla_put_failure:
8601 return -EMSGSIZE;
8602}
8603
8604static int nl80211_get_reg_do(struct sk_buff *skb, struct genl_info *info)
8605{
8606 const struct ieee80211_regdomain *regdom = NULL;
8607 struct cfg80211_registered_device *rdev;
8608 struct wiphy *wiphy = NULL;
8609 struct sk_buff *msg;
024fcf5e 8610 int err = -EMSGSIZE;
ad30ca2c
AN
8611 void *hdr;
8612
8613 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
8614 if (!msg)
8615 return -ENOBUFS;
8616
8617 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
8618 NL80211_CMD_GET_REG);
8619 if (!hdr)
8620 goto put_failure;
8621
a05829a7
JB
8622 rtnl_lock();
8623
ad30ca2c 8624 if (info->attrs[NL80211_ATTR_WIPHY]) {
1bdd716c
AN
8625 bool self_managed;
8626
ad30ca2c
AN
8627 rdev = cfg80211_get_dev_from_info(genl_info_net(info), info);
8628 if (IS_ERR(rdev)) {
024fcf5e
JB
8629 err = PTR_ERR(rdev);
8630 goto nla_put_failure;
ad30ca2c
AN
8631 }
8632
8633 wiphy = &rdev->wiphy;
1bdd716c
AN
8634 self_managed = wiphy->regulatory_flags &
8635 REGULATORY_WIPHY_SELF_MANAGED;
024fcf5e
JB
8636
8637 rcu_read_lock();
8638
ad30ca2c
AN
8639 regdom = get_wiphy_regdom(wiphy);
8640
1bdd716c
AN
8641 /* a self-managed-reg device must have a private regdom */
8642 if (WARN_ON(!regdom && self_managed)) {
024fcf5e
JB
8643 err = -EINVAL;
8644 goto nla_put_failure_rcu;
1bdd716c
AN
8645 }
8646
ad30ca2c
AN
8647 if (regdom &&
8648 nla_put_u32(msg, NL80211_ATTR_WIPHY, get_wiphy_idx(wiphy)))
024fcf5e
JB
8649 goto nla_put_failure_rcu;
8650 } else {
8651 rcu_read_lock();
ad30ca2c
AN
8652 }
8653
8654 if (!wiphy && reg_last_request_cell_base() &&
8655 nla_put_u32(msg, NL80211_ATTR_USER_REG_HINT_TYPE,
8656 NL80211_USER_REG_HINT_CELL_BASE))
024fcf5e 8657 goto nla_put_failure_rcu;
ad30ca2c
AN
8658
8659 if (!regdom)
8660 regdom = rcu_dereference(cfg80211_regdomain);
8661
8662 if (nl80211_put_regdom(regdom, msg))
8663 goto nla_put_failure_rcu;
8664
8665 rcu_read_unlock();
f130347c
LR
8666
8667 genlmsg_end(msg, hdr);
a05829a7 8668 rtnl_unlock();
5fe231e8 8669 return genlmsg_reply(msg, info);
f130347c 8670
458f4f9e
JB
8671nla_put_failure_rcu:
8672 rcu_read_unlock();
f130347c 8673nla_put_failure:
a05829a7 8674 rtnl_unlock();
efe1cf0c 8675put_failure:
d080e275 8676 nlmsg_free(msg);
024fcf5e 8677 return err;
f130347c
LR
8678}
8679
ad30ca2c
AN
8680static int nl80211_send_regdom(struct sk_buff *msg, struct netlink_callback *cb,
8681 u32 seq, int flags, struct wiphy *wiphy,
8682 const struct ieee80211_regdomain *regdom)
8683{
8684 void *hdr = nl80211hdr_put(msg, NETLINK_CB(cb->skb).portid, seq, flags,
8685 NL80211_CMD_GET_REG);
8686
8687 if (!hdr)
8688 return -1;
8689
0a833c29 8690 genl_dump_check_consistent(cb, hdr);
ad30ca2c
AN
8691
8692 if (nl80211_put_regdom(regdom, msg))
8693 goto nla_put_failure;
8694
8695 if (!wiphy && reg_last_request_cell_base() &&
8696 nla_put_u32(msg, NL80211_ATTR_USER_REG_HINT_TYPE,
8697 NL80211_USER_REG_HINT_CELL_BASE))
8698 goto nla_put_failure;
8699
8700 if (wiphy &&
8701 nla_put_u32(msg, NL80211_ATTR_WIPHY, get_wiphy_idx(wiphy)))
8702 goto nla_put_failure;
8703
1bdd716c
AN
8704 if (wiphy && wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED &&
8705 nla_put_flag(msg, NL80211_ATTR_WIPHY_SELF_MANAGED_REG))
8706 goto nla_put_failure;
8707
053c095a
JB
8708 genlmsg_end(msg, hdr);
8709 return 0;
ad30ca2c
AN
8710
8711nla_put_failure:
8712 genlmsg_cancel(msg, hdr);
8713 return -EMSGSIZE;
8714}
8715
8716static int nl80211_get_reg_dump(struct sk_buff *skb,
8717 struct netlink_callback *cb)
8718{
8719 const struct ieee80211_regdomain *regdom = NULL;
8720 struct cfg80211_registered_device *rdev;
8721 int err, reg_idx, start = cb->args[2];
8722
024fcf5e 8723 rcu_read_lock();
ad30ca2c
AN
8724
8725 if (cfg80211_regdomain && start == 0) {
8726 err = nl80211_send_regdom(skb, cb, cb->nlh->nlmsg_seq,
8727 NLM_F_MULTI, NULL,
024fcf5e 8728 rcu_dereference(cfg80211_regdomain));
ad30ca2c
AN
8729 if (err < 0)
8730 goto out_err;
8731 }
8732
8733 /* the global regdom is idx 0 */
8734 reg_idx = 1;
024fcf5e 8735 list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) {
ad30ca2c
AN
8736 regdom = get_wiphy_regdom(&rdev->wiphy);
8737 if (!regdom)
8738 continue;
8739
8740 if (++reg_idx <= start)
8741 continue;
8742
8743 err = nl80211_send_regdom(skb, cb, cb->nlh->nlmsg_seq,
8744 NLM_F_MULTI, &rdev->wiphy, regdom);
8745 if (err < 0) {
8746 reg_idx--;
8747 break;
8748 }
8749 }
8750
8751 cb->args[2] = reg_idx;
8752 err = skb->len;
8753out_err:
024fcf5e 8754 rcu_read_unlock();
ad30ca2c
AN
8755 return err;
8756}
8757
b6863036
JB
8758#ifdef CONFIG_CFG80211_CRDA_SUPPORT
8759static const struct nla_policy reg_rule_policy[NL80211_REG_RULE_ATTR_MAX + 1] = {
8760 [NL80211_ATTR_REG_RULE_FLAGS] = { .type = NLA_U32 },
8761 [NL80211_ATTR_FREQ_RANGE_START] = { .type = NLA_U32 },
8762 [NL80211_ATTR_FREQ_RANGE_END] = { .type = NLA_U32 },
8763 [NL80211_ATTR_FREQ_RANGE_MAX_BW] = { .type = NLA_U32 },
8764 [NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN] = { .type = NLA_U32 },
8765 [NL80211_ATTR_POWER_RULE_MAX_EIRP] = { .type = NLA_U32 },
8766 [NL80211_ATTR_DFS_CAC_TIME] = { .type = NLA_U32 },
8767};
8768
8769static int parse_reg_rule(struct nlattr *tb[],
8770 struct ieee80211_reg_rule *reg_rule)
8771{
8772 struct ieee80211_freq_range *freq_range = &reg_rule->freq_range;
8773 struct ieee80211_power_rule *power_rule = &reg_rule->power_rule;
8774
8775 if (!tb[NL80211_ATTR_REG_RULE_FLAGS])
8776 return -EINVAL;
8777 if (!tb[NL80211_ATTR_FREQ_RANGE_START])
8778 return -EINVAL;
8779 if (!tb[NL80211_ATTR_FREQ_RANGE_END])
8780 return -EINVAL;
8781 if (!tb[NL80211_ATTR_FREQ_RANGE_MAX_BW])
8782 return -EINVAL;
8783 if (!tb[NL80211_ATTR_POWER_RULE_MAX_EIRP])
8784 return -EINVAL;
8785
8786 reg_rule->flags = nla_get_u32(tb[NL80211_ATTR_REG_RULE_FLAGS]);
8787
8788 freq_range->start_freq_khz =
8789 nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]);
8790 freq_range->end_freq_khz =
8791 nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]);
8792 freq_range->max_bandwidth_khz =
8793 nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]);
8794
8795 power_rule->max_eirp =
8796 nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_EIRP]);
8797
8798 if (tb[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN])
8799 power_rule->max_antenna_gain =
8800 nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN]);
8801
8802 if (tb[NL80211_ATTR_DFS_CAC_TIME])
8803 reg_rule->dfs_cac_ms =
8804 nla_get_u32(tb[NL80211_ATTR_DFS_CAC_TIME]);
8805
8806 return 0;
8807}
8808
b2e1b302
LR
8809static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
8810{
8811 struct nlattr *tb[NL80211_REG_RULE_ATTR_MAX + 1];
8812 struct nlattr *nl_reg_rule;
ea372c54
JB
8813 char *alpha2;
8814 int rem_reg_rules, r;
391d132c 8815 u32 num_rules = 0, rule_idx = 0;
4c7d3982 8816 enum nl80211_dfs_regions dfs_region = NL80211_DFS_UNSET;
ea372c54 8817 struct ieee80211_regdomain *rd;
b2e1b302
LR
8818
8819 if (!info->attrs[NL80211_ATTR_REG_ALPHA2])
8820 return -EINVAL;
8821
8822 if (!info->attrs[NL80211_ATTR_REG_RULES])
8823 return -EINVAL;
8824
8825 alpha2 = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]);
8826
8b60b078
LR
8827 if (info->attrs[NL80211_ATTR_DFS_REGION])
8828 dfs_region = nla_get_u8(info->attrs[NL80211_ATTR_DFS_REGION]);
8829
b2e1b302 8830 nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES],
1a919318 8831 rem_reg_rules) {
b2e1b302
LR
8832 num_rules++;
8833 if (num_rules > NL80211_MAX_SUPP_REG_RULES)
4776c6e7 8834 return -EINVAL;
b2e1b302
LR
8835 }
8836
a05829a7
JB
8837 rtnl_lock();
8838 if (!reg_is_valid_request(alpha2)) {
8839 r = -EINVAL;
8840 goto out;
8841 }
e438768f 8842
391d132c 8843 rd = kzalloc(struct_size(rd, reg_rules, num_rules), GFP_KERNEL);
a05829a7
JB
8844 if (!rd) {
8845 r = -ENOMEM;
8846 goto out;
8847 }
b2e1b302
LR
8848
8849 rd->n_reg_rules = num_rules;
8850 rd->alpha2[0] = alpha2[0];
8851 rd->alpha2[1] = alpha2[1];
8852
8b60b078
LR
8853 /*
8854 * Disable DFS master mode if the DFS region was
8855 * not supported or known on this kernel.
8856 */
8857 if (reg_supported_dfs_region(dfs_region))
8858 rd->dfs_region = dfs_region;
8859
b2e1b302 8860 nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES],
1a919318 8861 rem_reg_rules) {
8cb08174
JB
8862 r = nla_parse_nested_deprecated(tb, NL80211_REG_RULE_ATTR_MAX,
8863 nl_reg_rule, reg_rule_policy,
8864 info->extack);
ae811e21
JB
8865 if (r)
8866 goto bad_reg;
b2e1b302
LR
8867 r = parse_reg_rule(tb, &rd->reg_rules[rule_idx]);
8868 if (r)
8869 goto bad_reg;
8870
8871 rule_idx++;
8872
d0e18f83
LR
8873 if (rule_idx > NL80211_MAX_SUPP_REG_RULES) {
8874 r = -EINVAL;
b2e1b302 8875 goto bad_reg;
d0e18f83 8876 }
b2e1b302
LR
8877 }
8878
a05829a7 8879 r = set_regdom(rd, REGD_SOURCE_CRDA);
06627990 8880 /* set_regdom takes ownership of rd */
a05829a7 8881 rd = NULL;
d2372b31 8882 bad_reg:
b2e1b302 8883 kfree(rd);
a05829a7
JB
8884 out:
8885 rtnl_unlock();
d0e18f83 8886 return r;
b2e1b302 8887}
b6863036 8888#endif /* CONFIG_CFG80211_CRDA_SUPPORT */
b2e1b302 8889
83f5e2cf
JB
8890static int validate_scan_freqs(struct nlattr *freqs)
8891{
8892 struct nlattr *attr1, *attr2;
8893 int n_channels = 0, tmp1, tmp2;
8894
d7f13f74
SD
8895 nla_for_each_nested(attr1, freqs, tmp1)
8896 if (nla_len(attr1) != sizeof(u32))
8897 return 0;
8898
83f5e2cf
JB
8899 nla_for_each_nested(attr1, freqs, tmp1) {
8900 n_channels++;
8901 /*
8902 * Some hardware has a limited channel list for
8903 * scanning, and it is pretty much nonsensical
8904 * to scan for a channel twice, so disallow that
8905 * and don't require drivers to check that the
8906 * channel list they get isn't longer than what
8907 * they can scan, as long as they can scan all
8908 * the channels they registered at once.
8909 */
8910 nla_for_each_nested(attr2, freqs, tmp2)
8911 if (attr1 != attr2 &&
8912 nla_get_u32(attr1) == nla_get_u32(attr2))
8913 return 0;
8914 }
8915
8916 return n_channels;
8917}
8918
57fbcce3 8919static bool is_band_valid(struct wiphy *wiphy, enum nl80211_band b)
38de03d2 8920{
57fbcce3 8921 return b < NUM_NL80211_BANDS && wiphy->bands[b];
38de03d2
AS
8922}
8923
8924static int parse_bss_select(struct nlattr *nla, struct wiphy *wiphy,
8925 struct cfg80211_bss_selection *bss_select)
8926{
8927 struct nlattr *attr[NL80211_BSS_SELECT_ATTR_MAX + 1];
8928 struct nlattr *nest;
8929 int err;
8930 bool found = false;
8931 int i;
8932
8933 /* only process one nested attribute */
8934 nest = nla_data(nla);
8935 if (!nla_ok(nest, nla_len(nest)))
8936 return -EINVAL;
8937
8cb08174
JB
8938 err = nla_parse_nested_deprecated(attr, NL80211_BSS_SELECT_ATTR_MAX,
8939 nest, nl80211_bss_select_policy,
8940 NULL);
38de03d2
AS
8941 if (err)
8942 return err;
8943
8944 /* only one attribute may be given */
8945 for (i = 0; i <= NL80211_BSS_SELECT_ATTR_MAX; i++) {
8946 if (attr[i]) {
8947 if (found)
8948 return -EINVAL;
8949 found = true;
8950 }
8951 }
8952
8953 bss_select->behaviour = __NL80211_BSS_SELECT_ATTR_INVALID;
8954
8955 if (attr[NL80211_BSS_SELECT_ATTR_RSSI])
8956 bss_select->behaviour = NL80211_BSS_SELECT_ATTR_RSSI;
8957
8958 if (attr[NL80211_BSS_SELECT_ATTR_BAND_PREF]) {
8959 bss_select->behaviour = NL80211_BSS_SELECT_ATTR_BAND_PREF;
8960 bss_select->param.band_pref =
8961 nla_get_u32(attr[NL80211_BSS_SELECT_ATTR_BAND_PREF]);
8962 if (!is_band_valid(wiphy, bss_select->param.band_pref))
8963 return -EINVAL;
8964 }
8965
8966 if (attr[NL80211_BSS_SELECT_ATTR_RSSI_ADJUST]) {
8967 struct nl80211_bss_select_rssi_adjust *adj_param;
8968
8969 adj_param = nla_data(attr[NL80211_BSS_SELECT_ATTR_RSSI_ADJUST]);
8970 bss_select->behaviour = NL80211_BSS_SELECT_ATTR_RSSI_ADJUST;
8971 bss_select->param.adjust.band = adj_param->band;
8972 bss_select->param.adjust.delta = adj_param->delta;
8973 if (!is_band_valid(wiphy, bss_select->param.adjust.band))
8974 return -EINVAL;
8975 }
8976
8977 /* user-space did not provide behaviour attribute */
8978 if (bss_select->behaviour == __NL80211_BSS_SELECT_ATTR_INVALID)
8979 return -EINVAL;
8980
8981 if (!(wiphy->bss_select_support & BIT(bss_select->behaviour)))
8982 return -EINVAL;
8983
8984 return 0;
8985}
8986
9bb7e0f2
JB
8987int nl80211_parse_random_mac(struct nlattr **attrs,
8988 u8 *mac_addr, u8 *mac_addr_mask)
ad2b26ab
JB
8989{
8990 int i;
8991
8992 if (!attrs[NL80211_ATTR_MAC] && !attrs[NL80211_ATTR_MAC_MASK]) {
d2beae10
JP
8993 eth_zero_addr(mac_addr);
8994 eth_zero_addr(mac_addr_mask);
ad2b26ab
JB
8995 mac_addr[0] = 0x2;
8996 mac_addr_mask[0] = 0x3;
8997
8998 return 0;
8999 }
9000
9001 /* need both or none */
9002 if (!attrs[NL80211_ATTR_MAC] || !attrs[NL80211_ATTR_MAC_MASK])
9003 return -EINVAL;
9004
9005 memcpy(mac_addr, nla_data(attrs[NL80211_ATTR_MAC]), ETH_ALEN);
9006 memcpy(mac_addr_mask, nla_data(attrs[NL80211_ATTR_MAC_MASK]), ETH_ALEN);
9007
9008 /* don't allow or configure an mcast address */
9009 if (!is_multicast_ether_addr(mac_addr_mask) ||
9010 is_multicast_ether_addr(mac_addr))
9011 return -EINVAL;
9012
9013 /*
9014 * allow users to pass a MAC address that has bits set outside
9015 * of the mask, but don't bother drivers with having to deal
9016 * with such bits
9017 */
9018 for (i = 0; i < ETH_ALEN; i++)
9019 mac_addr[i] &= mac_addr_mask[i];
9020
9021 return 0;
9022}
9023
7b0a0e3c
JB
9024static bool cfg80211_off_channel_oper_allowed(struct wireless_dev *wdev,
9025 struct ieee80211_channel *chan)
34373d12 9026{
7b0a0e3c
JB
9027 unsigned int link_id;
9028 bool all_ok = true;
9029
076fc877 9030 lockdep_assert_wiphy(wdev->wiphy);
34373d12
VT
9031
9032 if (!cfg80211_beaconing_iface_active(wdev))
9033 return true;
9034
7b0a0e3c
JB
9035 /*
9036 * FIXME: check if we have a free HW resource/link for chan
9037 *
9038 * This, as well as the FIXME below, requires knowing the link
9039 * capabilities of the hardware.
9040 */
9041
9042 /* we cannot leave radar channels */
9043 for_each_valid_link(wdev, link_id) {
9044 struct cfg80211_chan_def *chandef;
9045
9046 chandef = wdev_chandef(wdev, link_id);
f624bb6f 9047 if (!chandef || !chandef->chan)
7b0a0e3c
JB
9048 continue;
9049
9050 /*
9051 * FIXME: don't require all_ok, but rather check only the
9052 * correct HW resource/link onto which 'chan' falls,
9053 * as only that link leaves the channel for doing
9054 * the off-channel operation.
9055 */
9056
9057 if (chandef->chan->flags & IEEE80211_CHAN_RADAR)
9058 all_ok = false;
9059 }
9060
9061 if (all_ok)
34373d12
VT
9062 return true;
9063
9064 return regulatory_pre_cac_allowed(wdev->wiphy);
9065}
9066
db0a4ad8
JB
9067static bool nl80211_check_scan_feat(struct wiphy *wiphy, u32 flags, u32 flag,
9068 enum nl80211_ext_feature_index feat)
9069{
9070 if (!(flags & flag))
9071 return true;
9072 if (wiphy_ext_feature_isset(wiphy, feat))
9073 return true;
9074 return false;
9075}
9076
2d23d073
RZ
9077static int
9078nl80211_check_scan_flags(struct wiphy *wiphy, struct wireless_dev *wdev,
9079 void *request, struct nlattr **attrs,
9080 bool is_sched_scan)
9081{
9082 u8 *mac_addr, *mac_addr_mask;
9083 u32 *flags;
9084 enum nl80211_feature_flags randomness_flag;
9085
9086 if (!attrs[NL80211_ATTR_SCAN_FLAGS])
9087 return 0;
9088
9089 if (is_sched_scan) {
9090 struct cfg80211_sched_scan_request *req = request;
9091
9092 randomness_flag = wdev ?
9093 NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR :
9094 NL80211_FEATURE_ND_RANDOM_MAC_ADDR;
9095 flags = &req->flags;
9096 mac_addr = req->mac_addr;
9097 mac_addr_mask = req->mac_addr_mask;
9098 } else {
9099 struct cfg80211_scan_request *req = request;
9100
9101 randomness_flag = NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
9102 flags = &req->flags;
9103 mac_addr = req->mac_addr;
9104 mac_addr_mask = req->mac_addr_mask;
9105 }
9106
9107 *flags = nla_get_u32(attrs[NL80211_ATTR_SCAN_FLAGS]);
9108
5037a009
SD
9109 if (((*flags & NL80211_SCAN_FLAG_LOW_PRIORITY) &&
9110 !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) ||
db0a4ad8
JB
9111 !nl80211_check_scan_feat(wiphy, *flags,
9112 NL80211_SCAN_FLAG_LOW_SPAN,
9113 NL80211_EXT_FEATURE_LOW_SPAN_SCAN) ||
9114 !nl80211_check_scan_feat(wiphy, *flags,
9115 NL80211_SCAN_FLAG_LOW_POWER,
9116 NL80211_EXT_FEATURE_LOW_POWER_SCAN) ||
9117 !nl80211_check_scan_feat(wiphy, *flags,
9118 NL80211_SCAN_FLAG_HIGH_ACCURACY,
9119 NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN) ||
9120 !nl80211_check_scan_feat(wiphy, *flags,
9121 NL80211_SCAN_FLAG_FILS_MAX_CHANNEL_TIME,
9122 NL80211_EXT_FEATURE_FILS_MAX_CHANNEL_TIME) ||
9123 !nl80211_check_scan_feat(wiphy, *flags,
9124 NL80211_SCAN_FLAG_ACCEPT_BCAST_PROBE_RESP,
9125 NL80211_EXT_FEATURE_ACCEPT_BCAST_PROBE_RESP) ||
9126 !nl80211_check_scan_feat(wiphy, *flags,
9127 NL80211_SCAN_FLAG_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION,
9128 NL80211_EXT_FEATURE_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION) ||
9129 !nl80211_check_scan_feat(wiphy, *flags,
9130 NL80211_SCAN_FLAG_OCE_PROBE_REQ_HIGH_TX_RATE,
2e076f19
JB
9131 NL80211_EXT_FEATURE_OCE_PROBE_REQ_HIGH_TX_RATE) ||
9132 !nl80211_check_scan_feat(wiphy, *flags,
9133 NL80211_SCAN_FLAG_RANDOM_SN,
9134 NL80211_EXT_FEATURE_SCAN_RANDOM_SN) ||
9135 !nl80211_check_scan_feat(wiphy, *flags,
9136 NL80211_SCAN_FLAG_MIN_PREQ_CONTENT,
9137 NL80211_EXT_FEATURE_SCAN_MIN_PREQ_CONTENT))
2d23d073
RZ
9138 return -EOPNOTSUPP;
9139
9140 if (*flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
9141 int err;
9142
9143 if (!(wiphy->features & randomness_flag) ||
7b0a0e3c 9144 (wdev && wdev->connected))
2d23d073
RZ
9145 return -EOPNOTSUPP;
9146
9147 err = nl80211_parse_random_mac(attrs, mac_addr, mac_addr_mask);
9148 if (err)
9149 return err;
9150 }
9151
2d23d073
RZ
9152 return 0;
9153}
9154
2a519311
JB
9155static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
9156{
4c476991 9157 struct cfg80211_registered_device *rdev = info->user_ptr[0];
fd014284 9158 struct wireless_dev *wdev = info->user_ptr[1];
2a519311 9159 struct cfg80211_scan_request *request;
2032f3b2
TP
9160 struct nlattr *scan_freqs = NULL;
9161 bool scan_freqs_khz = false;
2a519311
JB
9162 struct nlattr *attr;
9163 struct wiphy *wiphy;
83f5e2cf 9164 int err, tmp, n_ssids = 0, n_channels, i;
14e05beb 9165 size_t ie_len, size;
838c7b8f 9166 size_t ssids_offset, ie_offset;
2a519311 9167
79c97e97 9168 wiphy = &rdev->wiphy;
2a519311 9169
cb3b7d87
AB
9170 if (wdev->iftype == NL80211_IFTYPE_NAN)
9171 return -EOPNOTSUPP;
9172
4c476991
JB
9173 if (!rdev->ops->scan)
9174 return -EOPNOTSUPP;
2a519311 9175
83286856
CJ
9176 if (rdev->scan_req || rdev->scan_msg)
9177 return -EBUSY;
2a519311 9178
2032f3b2
TP
9179 if (info->attrs[NL80211_ATTR_SCAN_FREQ_KHZ]) {
9180 if (!wiphy_ext_feature_isset(wiphy,
9181 NL80211_EXT_FEATURE_SCAN_FREQ_KHZ))
9182 return -EOPNOTSUPP;
9183 scan_freqs = info->attrs[NL80211_ATTR_SCAN_FREQ_KHZ];
9184 scan_freqs_khz = true;
9185 } else if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES])
9186 scan_freqs = info->attrs[NL80211_ATTR_SCAN_FREQUENCIES];
9187
9188 if (scan_freqs) {
9189 n_channels = validate_scan_freqs(scan_freqs);
83286856
CJ
9190 if (!n_channels)
9191 return -EINVAL;
2a519311 9192 } else {
bdfbec2d 9193 n_channels = ieee80211_get_num_supported_channels(wiphy);
2a519311
JB
9194 }
9195
9196 if (info->attrs[NL80211_ATTR_SCAN_SSIDS])
9197 nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp)
9198 n_ssids++;
9199
83286856
CJ
9200 if (n_ssids > wiphy->max_scan_ssids)
9201 return -EINVAL;
2a519311 9202
70692ad2
JM
9203 if (info->attrs[NL80211_ATTR_IE])
9204 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
9205 else
9206 ie_len = 0;
9207
83286856
CJ
9208 if (ie_len > wiphy->max_scan_ie_len)
9209 return -EINVAL;
18a83659 9210
14e05beb 9211 size = struct_size(request, channels, n_channels);
838c7b8f 9212 ssids_offset = size;
14e05beb 9213 size = size_add(size, array_size(sizeof(*request->ssids), n_ssids));
838c7b8f 9214 ie_offset = size;
14e05beb
JK
9215 size = size_add(size, ie_len);
9216 request = kzalloc(size, GFP_KERNEL);
83286856
CJ
9217 if (!request)
9218 return -ENOMEM;
838c7b8f 9219 request->n_channels = n_channels;
2a519311 9220
2a519311 9221 if (n_ssids)
838c7b8f 9222 request->ssids = (void *)request + ssids_offset;
2a519311 9223 request->n_ssids = n_ssids;
838c7b8f
KC
9224 if (ie_len)
9225 request->ie = (void *)request + ie_offset;
2a519311 9226
584991dc 9227 i = 0;
2032f3b2 9228 if (scan_freqs) {
2a519311 9229 /* user specified, bail out if channel not found */
2032f3b2 9230 nla_for_each_nested(attr, scan_freqs, tmp) {
584991dc 9231 struct ieee80211_channel *chan;
2032f3b2 9232 int freq = nla_get_u32(attr);
584991dc 9233
2032f3b2
TP
9234 if (!scan_freqs_khz)
9235 freq = MHZ_TO_KHZ(freq);
584991dc 9236
2032f3b2 9237 chan = ieee80211_get_channel_khz(wiphy, freq);
584991dc 9238 if (!chan) {
2a519311
JB
9239 err = -EINVAL;
9240 goto out_free;
9241 }
584991dc
JB
9242
9243 /* ignore disabled channels */
9244 if (chan->flags & IEEE80211_CHAN_DISABLED)
9245 continue;
9246
9247 request->channels[i] = chan;
2a519311
JB
9248 i++;
9249 }
9250 } else {
57fbcce3 9251 enum nl80211_band band;
34850ab2 9252
2a519311 9253 /* all channels */
57fbcce3 9254 for (band = 0; band < NUM_NL80211_BANDS; band++) {
2a519311 9255 int j;
7a087e74 9256
2a519311
JB
9257 if (!wiphy->bands[band])
9258 continue;
9259 for (j = 0; j < wiphy->bands[band]->n_channels; j++) {
584991dc
JB
9260 struct ieee80211_channel *chan;
9261
9262 chan = &wiphy->bands[band]->channels[j];
9263
9264 if (chan->flags & IEEE80211_CHAN_DISABLED)
9265 continue;
9266
9267 request->channels[i] = chan;
2a519311
JB
9268 i++;
9269 }
9270 }
9271 }
9272
584991dc
JB
9273 if (!i) {
9274 err = -EINVAL;
9275 goto out_free;
9276 }
9277
9278 request->n_channels = i;
9279
7b0a0e3c
JB
9280 for (i = 0; i < request->n_channels; i++) {
9281 struct ieee80211_channel *chan = request->channels[i];
34373d12 9282
7b0a0e3c
JB
9283 /* if we can go off-channel to the target channel we're good */
9284 if (cfg80211_off_channel_oper_allowed(wdev, chan))
9285 continue;
34373d12 9286
7b0a0e3c 9287 if (!cfg80211_wdev_on_sub_chan(wdev, chan, true)) {
34373d12
VT
9288 err = -EBUSY;
9289 goto out_free;
9290 }
9291 }
34373d12 9292
2a519311 9293 i = 0;
13874e4b 9294 if (n_ssids) {
2a519311 9295 nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) {
57a27e1d 9296 if (nla_len(attr) > IEEE80211_MAX_SSID_LEN) {
2a519311
JB
9297 err = -EINVAL;
9298 goto out_free;
9299 }
57a27e1d 9300 request->ssids[i].ssid_len = nla_len(attr);
2a519311 9301 memcpy(request->ssids[i].ssid, nla_data(attr), nla_len(attr));
2a519311
JB
9302 i++;
9303 }
9304 }
9305
70692ad2
JM
9306 if (info->attrs[NL80211_ATTR_IE]) {
9307 request->ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
de95a54b
JB
9308 memcpy((void *)request->ie,
9309 nla_data(info->attrs[NL80211_ATTR_IE]),
70692ad2
JM
9310 request->ie_len);
9311 }
9312
57fbcce3 9313 for (i = 0; i < NUM_NL80211_BANDS; i++)
a401d2bb
JB
9314 if (wiphy->bands[i])
9315 request->rates[i] =
9316 (1 << wiphy->bands[i]->n_bitrates) - 1;
34850ab2
JB
9317
9318 if (info->attrs[NL80211_ATTR_SCAN_SUPP_RATES]) {
9319 nla_for_each_nested(attr,
9320 info->attrs[NL80211_ATTR_SCAN_SUPP_RATES],
9321 tmp) {
57fbcce3 9322 enum nl80211_band band = nla_type(attr);
34850ab2 9323
57fbcce3 9324 if (band < 0 || band >= NUM_NL80211_BANDS) {
34850ab2
JB
9325 err = -EINVAL;
9326 goto out_free;
9327 }
1b09cd82
FF
9328
9329 if (!wiphy->bands[band])
9330 continue;
9331
34850ab2
JB
9332 err = ieee80211_get_ratemask(wiphy->bands[band],
9333 nla_data(attr),
9334 nla_len(attr),
9335 &request->rates[band]);
9336 if (err)
9337 goto out_free;
9338 }
9339 }
9340
1d76250b 9341 if (info->attrs[NL80211_ATTR_MEASUREMENT_DURATION]) {
1d76250b
AS
9342 request->duration =
9343 nla_get_u16(info->attrs[NL80211_ATTR_MEASUREMENT_DURATION]);
9344 request->duration_mandatory =
9345 nla_get_flag(info->attrs[NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY]);
9346 }
9347
2d23d073
RZ
9348 err = nl80211_check_scan_flags(wiphy, wdev, request, info->attrs,
9349 false);
9350 if (err)
9351 goto out_free;
ed473771 9352
e9f935e3
RM
9353 request->no_cck =
9354 nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]);
9355
2fa436b3
VK
9356 /* Initial implementation used NL80211_ATTR_MAC to set the specific
9357 * BSSID to scan for. This was problematic because that same attribute
9358 * was already used for another purpose (local random MAC address). The
9359 * NL80211_ATTR_BSSID attribute was added to fix this. For backwards
9360 * compatibility with older userspace components, also use the
9361 * NL80211_ATTR_MAC value here if it can be determined to be used for
9362 * the specific BSSID use case instead of the random MAC address
9363 * (NL80211_ATTR_SCAN_FLAGS is used to enable random MAC address use).
9364 */
9365 if (info->attrs[NL80211_ATTR_BSSID])
9366 memcpy(request->bssid,
9367 nla_data(info->attrs[NL80211_ATTR_BSSID]), ETH_ALEN);
9368 else if (!(request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) &&
9369 info->attrs[NL80211_ATTR_MAC])
818965d3
JM
9370 memcpy(request->bssid, nla_data(info->attrs[NL80211_ATTR_MAC]),
9371 ETH_ALEN);
9372 else
9373 eth_broadcast_addr(request->bssid);
9374
6285ee30 9375 request->tsf_report_link_id = nl80211_link_id_or_invalid(info->attrs);
fd014284 9376 request->wdev = wdev;
79c97e97 9377 request->wiphy = &rdev->wiphy;
15d6030b 9378 request->scan_start = jiffies;
2a519311 9379
79c97e97 9380 rdev->scan_req = request;
c8cb5b85 9381 err = cfg80211_scan(rdev);
2a519311 9382
504776be
CJ
9383 if (err)
9384 goto out_free;
9385
9386 nl80211_send_scan_start(rdev, wdev);
1160dfa1 9387 dev_hold(wdev->netdev);
504776be
CJ
9388
9389 return 0;
9390
2a519311 9391 out_free:
504776be
CJ
9392 rdev->scan_req = NULL;
9393 kfree(request);
3b85875a 9394
2a519311
JB
9395 return err;
9396}
9397
91d3ab46
VK
9398static int nl80211_abort_scan(struct sk_buff *skb, struct genl_info *info)
9399{
9400 struct cfg80211_registered_device *rdev = info->user_ptr[0];
9401 struct wireless_dev *wdev = info->user_ptr[1];
9402
9403 if (!rdev->ops->abort_scan)
9404 return -EOPNOTSUPP;
9405
9406 if (rdev->scan_msg)
9407 return 0;
9408
9409 if (!rdev->scan_req)
9410 return -ENOENT;
9411
9412 rdev_abort_scan(rdev, wdev);
9413 return 0;
9414}
9415
3b06d277
AS
9416static int
9417nl80211_parse_sched_scan_plans(struct wiphy *wiphy, int n_plans,
9418 struct cfg80211_sched_scan_request *request,
9419 struct nlattr **attrs)
9420{
9421 int tmp, err, i = 0;
9422 struct nlattr *attr;
9423
9424 if (!attrs[NL80211_ATTR_SCHED_SCAN_PLANS]) {
9425 u32 interval;
9426
9427 /*
9428 * If scan plans are not specified,
5a88de53 9429 * %NL80211_ATTR_SCHED_SCAN_INTERVAL will be specified. In this
3b06d277
AS
9430 * case one scan plan will be set with the specified scan
9431 * interval and infinite number of iterations.
9432 */
3b06d277
AS
9433 interval = nla_get_u32(attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL]);
9434 if (!interval)
9435 return -EINVAL;
9436
9437 request->scan_plans[0].interval =
9438 DIV_ROUND_UP(interval, MSEC_PER_SEC);
9439 if (!request->scan_plans[0].interval)
9440 return -EINVAL;
9441
9442 if (request->scan_plans[0].interval >
9443 wiphy->max_sched_scan_plan_interval)
9444 request->scan_plans[0].interval =
9445 wiphy->max_sched_scan_plan_interval;
9446
9447 return 0;
9448 }
9449
9450 nla_for_each_nested(attr, attrs[NL80211_ATTR_SCHED_SCAN_PLANS], tmp) {
9451 struct nlattr *plan[NL80211_SCHED_SCAN_PLAN_MAX + 1];
9452
9453 if (WARN_ON(i >= n_plans))
9454 return -EINVAL;
9455
8cb08174
JB
9456 err = nla_parse_nested_deprecated(plan,
9457 NL80211_SCHED_SCAN_PLAN_MAX,
9458 attr, nl80211_plan_policy,
9459 NULL);
3b06d277
AS
9460 if (err)
9461 return err;
9462
9463 if (!plan[NL80211_SCHED_SCAN_PLAN_INTERVAL])
9464 return -EINVAL;
9465
9466 request->scan_plans[i].interval =
9467 nla_get_u32(plan[NL80211_SCHED_SCAN_PLAN_INTERVAL]);
9468 if (!request->scan_plans[i].interval ||
9469 request->scan_plans[i].interval >
9470 wiphy->max_sched_scan_plan_interval)
9471 return -EINVAL;
9472
9473 if (plan[NL80211_SCHED_SCAN_PLAN_ITERATIONS]) {
9474 request->scan_plans[i].iterations =
9475 nla_get_u32(plan[NL80211_SCHED_SCAN_PLAN_ITERATIONS]);
9476 if (!request->scan_plans[i].iterations ||
9477 (request->scan_plans[i].iterations >
9478 wiphy->max_sched_scan_plan_iterations))
9479 return -EINVAL;
9480 } else if (i < n_plans - 1) {
9481 /*
9482 * All scan plans but the last one must specify
9483 * a finite number of iterations
9484 */
9485 return -EINVAL;
9486 }
9487
9488 i++;
9489 }
9490
9491 /*
9492 * The last scan plan must not specify the number of
9493 * iterations, it is supposed to run infinitely
9494 */
9495 if (request->scan_plans[n_plans - 1].iterations)
9496 return -EINVAL;
9497
9498 return 0;
9499}
9500
256da02d 9501static struct cfg80211_sched_scan_request *
ad2b26ab 9502nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev,
aad1e812 9503 struct nlattr **attrs, int max_match_sets)
807f8a8c
LC
9504{
9505 struct cfg80211_sched_scan_request *request;
807f8a8c 9506 struct nlattr *attr;
3b06d277 9507 int err, tmp, n_ssids = 0, n_match_sets = 0, n_channels, i, n_plans = 0;
57fbcce3 9508 enum nl80211_band band;
14e05beb 9509 size_t ie_len, size;
a1f1c21c 9510 struct nlattr *tb[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1];
ea73cbce 9511 s32 default_match_rssi = NL80211_SCAN_RSSI_THOLD_OFF;
807f8a8c 9512
256da02d 9513 if (attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
807f8a8c 9514 n_channels = validate_scan_freqs(
256da02d 9515 attrs[NL80211_ATTR_SCAN_FREQUENCIES]);
807f8a8c 9516 if (!n_channels)
256da02d 9517 return ERR_PTR(-EINVAL);
807f8a8c 9518 } else {
bdfbec2d 9519 n_channels = ieee80211_get_num_supported_channels(wiphy);
807f8a8c
LC
9520 }
9521
256da02d
LC
9522 if (attrs[NL80211_ATTR_SCAN_SSIDS])
9523 nla_for_each_nested(attr, attrs[NL80211_ATTR_SCAN_SSIDS],
807f8a8c
LC
9524 tmp)
9525 n_ssids++;
9526
93b6aa69 9527 if (n_ssids > wiphy->max_sched_scan_ssids)
256da02d 9528 return ERR_PTR(-EINVAL);
807f8a8c 9529
ea73cbce
JB
9530 /*
9531 * First, count the number of 'real' matchsets. Due to an issue with
9532 * the old implementation, matchsets containing only the RSSI attribute
9533 * (NL80211_SCHED_SCAN_MATCH_ATTR_RSSI) are considered as the 'default'
9534 * RSSI for all matchsets, rather than their own matchset for reporting
9535 * all APs with a strong RSSI. This is needed to be compatible with
9536 * older userspace that treated a matchset with only the RSSI as the
9537 * global RSSI for all other matchsets - if there are other matchsets.
9538 */
256da02d 9539 if (attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) {
a1f1c21c 9540 nla_for_each_nested(attr,
256da02d 9541 attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
ea73cbce
JB
9542 tmp) {
9543 struct nlattr *rssi;
9544
8cb08174
JB
9545 err = nla_parse_nested_deprecated(tb,
9546 NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
9547 attr,
9548 nl80211_match_policy,
9549 NULL);
ea73cbce 9550 if (err)
256da02d 9551 return ERR_PTR(err);
3007e352
AVS
9552
9553 /* SSID and BSSID are mutually exclusive */
9554 if (tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID] &&
9555 tb[NL80211_SCHED_SCAN_MATCH_ATTR_BSSID])
9556 return ERR_PTR(-EINVAL);
9557
ea73cbce 9558 /* add other standalone attributes here */
3007e352
AVS
9559 if (tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID] ||
9560 tb[NL80211_SCHED_SCAN_MATCH_ATTR_BSSID]) {
ea73cbce
JB
9561 n_match_sets++;
9562 continue;
9563 }
9564 rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI];
9565 if (rssi)
9566 default_match_rssi = nla_get_s32(rssi);
9567 }
9568 }
9569
9570 /* However, if there's no other matchset, add the RSSI one */
9571 if (!n_match_sets && default_match_rssi != NL80211_SCAN_RSSI_THOLD_OFF)
9572 n_match_sets = 1;
a1f1c21c 9573
aad1e812 9574 if (n_match_sets > max_match_sets)
256da02d 9575 return ERR_PTR(-EINVAL);
a1f1c21c 9576
256da02d
LC
9577 if (attrs[NL80211_ATTR_IE])
9578 ie_len = nla_len(attrs[NL80211_ATTR_IE]);
807f8a8c
LC
9579 else
9580 ie_len = 0;
9581
5a865bad 9582 if (ie_len > wiphy->max_sched_scan_ie_len)
256da02d 9583 return ERR_PTR(-EINVAL);
c10841ca 9584
3b06d277
AS
9585 if (attrs[NL80211_ATTR_SCHED_SCAN_PLANS]) {
9586 /*
9587 * NL80211_ATTR_SCHED_SCAN_INTERVAL must not be specified since
9588 * each scan plan already specifies its own interval
9589 */
9590 if (attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL])
9591 return ERR_PTR(-EINVAL);
9592
9593 nla_for_each_nested(attr,
9594 attrs[NL80211_ATTR_SCHED_SCAN_PLANS], tmp)
9595 n_plans++;
9596 } else {
9597 /*
9598 * The scan interval attribute is kept for backward
9599 * compatibility. If no scan plans are specified and sched scan
9600 * interval is specified, one scan plan will be set with this
9601 * scan interval and infinite number of iterations.
9602 */
9603 if (!attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL])
9604 return ERR_PTR(-EINVAL);
9605
9606 n_plans = 1;
9607 }
9608
9609 if (!n_plans || n_plans > wiphy->max_sched_scan_plans)
9610 return ERR_PTR(-EINVAL);
9611
bf95ecdb 9612 if (!wiphy_ext_feature_isset(
9613 wiphy, NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI) &&
9614 (attrs[NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI] ||
9615 attrs[NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST]))
9616 return ERR_PTR(-EINVAL);
9617
14e05beb
JK
9618 size = struct_size(request, channels, n_channels);
9619 size = size_add(size, array_size(sizeof(*request->ssids), n_ssids));
9620 size = size_add(size, array_size(sizeof(*request->match_sets),
9621 n_match_sets));
9622 size = size_add(size, array_size(sizeof(*request->scan_plans),
9623 n_plans));
9624 size = size_add(size, ie_len);
9625 request = kzalloc(size, GFP_KERNEL);
256da02d
LC
9626 if (!request)
9627 return ERR_PTR(-ENOMEM);
807f8a8c
LC
9628
9629 if (n_ssids)
9630 request->ssids = (void *)&request->channels[n_channels];
9631 request->n_ssids = n_ssids;
9632 if (ie_len) {
13874e4b 9633 if (n_ssids)
807f8a8c
LC
9634 request->ie = (void *)(request->ssids + n_ssids);
9635 else
9636 request->ie = (void *)(request->channels + n_channels);
9637 }
9638
a1f1c21c
LC
9639 if (n_match_sets) {
9640 if (request->ie)
9641 request->match_sets = (void *)(request->ie + ie_len);
13874e4b 9642 else if (n_ssids)
a1f1c21c
LC
9643 request->match_sets =
9644 (void *)(request->ssids + n_ssids);
9645 else
9646 request->match_sets =
9647 (void *)(request->channels + n_channels);
9648 }
9649 request->n_match_sets = n_match_sets;
9650
3b06d277
AS
9651 if (n_match_sets)
9652 request->scan_plans = (void *)(request->match_sets +
9653 n_match_sets);
9654 else if (request->ie)
9655 request->scan_plans = (void *)(request->ie + ie_len);
9656 else if (n_ssids)
9657 request->scan_plans = (void *)(request->ssids + n_ssids);
9658 else
9659 request->scan_plans = (void *)(request->channels + n_channels);
9660
9661 request->n_scan_plans = n_plans;
9662
807f8a8c 9663 i = 0;
256da02d 9664 if (attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
807f8a8c
LC
9665 /* user specified, bail out if channel not found */
9666 nla_for_each_nested(attr,
256da02d 9667 attrs[NL80211_ATTR_SCAN_FREQUENCIES],
807f8a8c
LC
9668 tmp) {
9669 struct ieee80211_channel *chan;
9670
9671 chan = ieee80211_get_channel(wiphy, nla_get_u32(attr));
9672
9673 if (!chan) {
9674 err = -EINVAL;
9675 goto out_free;
9676 }
9677
9678 /* ignore disabled channels */
9679 if (chan->flags & IEEE80211_CHAN_DISABLED)
9680 continue;
9681
9682 request->channels[i] = chan;
9683 i++;
9684 }
9685 } else {
9686 /* all channels */
57fbcce3 9687 for (band = 0; band < NUM_NL80211_BANDS; band++) {
807f8a8c 9688 int j;
7a087e74 9689
807f8a8c
LC
9690 if (!wiphy->bands[band])
9691 continue;
9692 for (j = 0; j < wiphy->bands[band]->n_channels; j++) {
9693 struct ieee80211_channel *chan;
9694
9695 chan = &wiphy->bands[band]->channels[j];
9696
9697 if (chan->flags & IEEE80211_CHAN_DISABLED)
9698 continue;
9699
9700 request->channels[i] = chan;
9701 i++;
9702 }
9703 }
9704 }
9705
9706 if (!i) {
9707 err = -EINVAL;
9708 goto out_free;
9709 }
9710
9711 request->n_channels = i;
9712
9713 i = 0;
13874e4b 9714 if (n_ssids) {
256da02d 9715 nla_for_each_nested(attr, attrs[NL80211_ATTR_SCAN_SSIDS],
807f8a8c 9716 tmp) {
57a27e1d 9717 if (nla_len(attr) > IEEE80211_MAX_SSID_LEN) {
807f8a8c
LC
9718 err = -EINVAL;
9719 goto out_free;
9720 }
57a27e1d 9721 request->ssids[i].ssid_len = nla_len(attr);
807f8a8c
LC
9722 memcpy(request->ssids[i].ssid, nla_data(attr),
9723 nla_len(attr));
807f8a8c
LC
9724 i++;
9725 }
9726 }
9727
a1f1c21c 9728 i = 0;
256da02d 9729 if (attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) {
a1f1c21c 9730 nla_for_each_nested(attr,
256da02d 9731 attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
a1f1c21c 9732 tmp) {
3007e352 9733 struct nlattr *ssid, *bssid, *rssi;
a1f1c21c 9734
8cb08174
JB
9735 err = nla_parse_nested_deprecated(tb,
9736 NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
9737 attr,
9738 nl80211_match_policy,
9739 NULL);
ae811e21
JB
9740 if (err)
9741 goto out_free;
4a4ab0d7 9742 ssid = tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID];
3007e352 9743 bssid = tb[NL80211_SCHED_SCAN_MATCH_ATTR_BSSID];
d39f3b4f
JB
9744
9745 if (!ssid && !bssid) {
9746 i++;
9747 continue;
9748 }
9749
9750 if (WARN_ON(i >= n_match_sets)) {
9751 /* this indicates a programming error,
9752 * the loop above should have verified
9753 * things properly
9754 */
9755 err = -EINVAL;
9756 goto out_free;
9757 }
9758
9759 if (ssid) {
d39f3b4f
JB
9760 memcpy(request->match_sets[i].ssid.ssid,
9761 nla_data(ssid), nla_len(ssid));
9762 request->match_sets[i].ssid.ssid_len =
9763 nla_len(ssid);
9764 }
cb9abd48 9765 if (bssid)
d39f3b4f
JB
9766 memcpy(request->match_sets[i].bssid,
9767 nla_data(bssid), ETH_ALEN);
3007e352 9768
d39f3b4f
JB
9769 /* special attribute - old implementation w/a */
9770 request->match_sets[i].rssi_thold = default_match_rssi;
9771 rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI];
9772 if (rssi)
ea73cbce 9773 request->match_sets[i].rssi_thold =
d39f3b4f 9774 nla_get_s32(rssi);
a1f1c21c
LC
9775 i++;
9776 }
ea73cbce
JB
9777
9778 /* there was no other matchset, so the RSSI one is alone */
f89f46cf 9779 if (i == 0 && n_match_sets)
ea73cbce
JB
9780 request->match_sets[0].rssi_thold = default_match_rssi;
9781
9782 request->min_rssi_thold = INT_MAX;
9783 for (i = 0; i < n_match_sets; i++)
9784 request->min_rssi_thold =
9785 min(request->match_sets[i].rssi_thold,
9786 request->min_rssi_thold);
9787 } else {
9788 request->min_rssi_thold = NL80211_SCAN_RSSI_THOLD_OFF;
a1f1c21c
LC
9789 }
9790
9900e484
JB
9791 if (ie_len) {
9792 request->ie_len = ie_len;
807f8a8c 9793 memcpy((void *)request->ie,
256da02d 9794 nla_data(attrs[NL80211_ATTR_IE]),
807f8a8c
LC
9795 request->ie_len);
9796 }
9797
2d23d073
RZ
9798 err = nl80211_check_scan_flags(wiphy, wdev, request, attrs, true);
9799 if (err)
9800 goto out_free;
ed473771 9801
9c748934
LC
9802 if (attrs[NL80211_ATTR_SCHED_SCAN_DELAY])
9803 request->delay =
9804 nla_get_u32(attrs[NL80211_ATTR_SCHED_SCAN_DELAY]);
9805
bf95ecdb 9806 if (attrs[NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI]) {
9807 request->relative_rssi = nla_get_s8(
9808 attrs[NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI]);
9809 request->relative_rssi_set = true;
9810 }
9811
9812 if (request->relative_rssi_set &&
9813 attrs[NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST]) {
9814 struct nl80211_bss_select_rssi_adjust *rssi_adjust;
9815
9816 rssi_adjust = nla_data(
9817 attrs[NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST]);
9818 request->rssi_adjust.band = rssi_adjust->band;
9819 request->rssi_adjust.delta = rssi_adjust->delta;
9820 if (!is_band_valid(wiphy, request->rssi_adjust.band)) {
9821 err = -EINVAL;
9822 goto out_free;
9823 }
9824 }
9825
3b06d277
AS
9826 err = nl80211_parse_sched_scan_plans(wiphy, n_plans, request, attrs);
9827 if (err)
9828 goto out_free;
9829
15d6030b 9830 request->scan_start = jiffies;
807f8a8c 9831
256da02d 9832 return request;
807f8a8c
LC
9833
9834out_free:
9835 kfree(request);
256da02d
LC
9836 return ERR_PTR(err);
9837}
9838
9839static int nl80211_start_sched_scan(struct sk_buff *skb,
9840 struct genl_info *info)
9841{
9842 struct cfg80211_registered_device *rdev = info->user_ptr[0];
9843 struct net_device *dev = info->user_ptr[1];
ad2b26ab 9844 struct wireless_dev *wdev = dev->ieee80211_ptr;
31a60ed1 9845 struct cfg80211_sched_scan_request *sched_scan_req;
ca986ad9 9846 bool want_multi;
256da02d
LC
9847 int err;
9848
ca986ad9 9849 if (!rdev->wiphy.max_sched_scan_reqs || !rdev->ops->sched_scan_start)
256da02d
LC
9850 return -EOPNOTSUPP;
9851
ca986ad9
AVS
9852 want_multi = info->attrs[NL80211_ATTR_SCHED_SCAN_MULTI];
9853 err = cfg80211_sched_scan_req_possible(rdev, want_multi);
9854 if (err)
9855 return err;
256da02d 9856
31a60ed1 9857 sched_scan_req = nl80211_parse_sched_scan(&rdev->wiphy, wdev,
aad1e812
AVS
9858 info->attrs,
9859 rdev->wiphy.max_match_sets);
31a60ed1
JR
9860
9861 err = PTR_ERR_OR_ZERO(sched_scan_req);
256da02d
LC
9862 if (err)
9863 goto out_err;
9864
ca986ad9
AVS
9865 /* leave request id zero for legacy request
9866 * or if driver does not support multi-scheduled scan
9867 */
2fd351a8
DK
9868 if (want_multi && rdev->wiphy.max_sched_scan_reqs > 1)
9869 sched_scan_req->reqid = cfg80211_assign_cookie(rdev);
ca986ad9 9870
31a60ed1 9871 err = rdev_sched_scan_start(rdev, dev, sched_scan_req);
256da02d
LC
9872 if (err)
9873 goto out_free;
9874
31a60ed1
JR
9875 sched_scan_req->dev = dev;
9876 sched_scan_req->wiphy = &rdev->wiphy;
9877
93a1e86c
JR
9878 if (info->attrs[NL80211_ATTR_SOCKET_OWNER])
9879 sched_scan_req->owner_nlportid = info->snd_portid;
9880
ca986ad9 9881 cfg80211_add_sched_scan_req(rdev, sched_scan_req);
256da02d 9882
96b08fd6 9883 nl80211_send_sched_scan(sched_scan_req, NL80211_CMD_START_SCHED_SCAN);
256da02d
LC
9884 return 0;
9885
9886out_free:
31a60ed1 9887 kfree(sched_scan_req);
256da02d 9888out_err:
807f8a8c
LC
9889 return err;
9890}
9891
9892static int nl80211_stop_sched_scan(struct sk_buff *skb,
9893 struct genl_info *info)
9894{
ca986ad9 9895 struct cfg80211_sched_scan_request *req;
807f8a8c 9896 struct cfg80211_registered_device *rdev = info->user_ptr[0];
ca986ad9 9897 u64 cookie;
807f8a8c 9898
ca986ad9 9899 if (!rdev->wiphy.max_sched_scan_reqs || !rdev->ops->sched_scan_stop)
807f8a8c
LC
9900 return -EOPNOTSUPP;
9901
ca986ad9
AVS
9902 if (info->attrs[NL80211_ATTR_COOKIE]) {
9903 cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);
9904 return __cfg80211_stop_sched_scan(rdev, cookie, false);
9905 }
9906
9907 req = list_first_or_null_rcu(&rdev->sched_scan_req_list,
9908 struct cfg80211_sched_scan_request,
9909 list);
9910 if (!req || req->reqid ||
9911 (req->owner_nlportid &&
9912 req->owner_nlportid != info->snd_portid))
9913 return -ENOENT;
9914
9915 return cfg80211_stop_sched_scan_req(rdev, req, false);
807f8a8c
LC
9916}
9917
04f39047
SW
9918static int nl80211_start_radar_detection(struct sk_buff *skb,
9919 struct genl_info *info)
9920{
9921 struct cfg80211_registered_device *rdev = info->user_ptr[0];
9922 struct net_device *dev = info->user_ptr[1];
9923 struct wireless_dev *wdev = dev->ieee80211_ptr;
13cf6dec 9924 struct wiphy *wiphy = wdev->wiphy;
04f39047 9925 struct cfg80211_chan_def chandef;
55f7435c 9926 enum nl80211_dfs_regions dfs_region;
31559f35 9927 unsigned int cac_time_ms;
84158164
LB
9928 int err = -EINVAL;
9929
9930 flush_delayed_work(&rdev->dfs_update_channels_wk);
9931
9932 wiphy_lock(wiphy);
04f39047 9933
13cf6dec 9934 dfs_region = reg_get_dfs_region(wiphy);
55f7435c 9935 if (dfs_region == NL80211_DFS_UNSET)
84158164 9936 goto unlock;
55f7435c 9937
04f39047
SW
9938 err = nl80211_parse_chandef(rdev, info, &chandef);
9939 if (err)
84158164 9940 goto unlock;
04f39047 9941
13cf6dec 9942 err = cfg80211_chandef_dfs_required(wiphy, &chandef, wdev->iftype);
04f39047 9943 if (err < 0)
84158164 9944 goto unlock;
04f39047 9945
84158164
LB
9946 if (err == 0) {
9947 err = -EINVAL;
9948 goto unlock;
9949 }
04f39047 9950
84158164
LB
9951 if (!cfg80211_chandef_dfs_usable(wiphy, &chandef)) {
9952 err = -EINVAL;
9953 goto unlock;
9954 }
04f39047 9955
a95bfb87
LB
9956 if (nla_get_flag(info->attrs[NL80211_ATTR_RADAR_BACKGROUND])) {
9957 err = cfg80211_start_background_radar_detection(rdev, wdev,
9958 &chandef);
84158164
LB
9959 goto unlock;
9960 }
bc2dfc02 9961
84158164
LB
9962 if (netif_carrier_ok(dev)) {
9963 err = -EBUSY;
9964 goto unlock;
9965 }
bc2dfc02 9966
84158164
LB
9967 if (wdev->cac_started) {
9968 err = -EBUSY;
9969 goto unlock;
9970 }
bc2dfc02 9971
13cf6dec 9972 /* CAC start is offloaded to HW and can't be started manually */
84158164
LB
9973 if (wiphy_ext_feature_isset(wiphy, NL80211_EXT_FEATURE_DFS_OFFLOAD)) {
9974 err = -EOPNOTSUPP;
9975 goto unlock;
9976 }
13cf6dec 9977
84158164
LB
9978 if (!rdev->ops->start_radar_detection) {
9979 err = -EOPNOTSUPP;
9980 goto unlock;
9981 }
04f39047 9982
31559f35
JD
9983 cac_time_ms = cfg80211_chandef_dfs_cac_time(&rdev->wiphy, &chandef);
9984 if (WARN_ON(!cac_time_ms))
9985 cac_time_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
9986
a1056b1b 9987 err = rdev_start_radar_detection(rdev, dev, &chandef, cac_time_ms);
04f39047 9988 if (!err) {
7b0a0e3c 9989 wdev->links[0].ap.chandef = chandef;
04f39047
SW
9990 wdev->cac_started = true;
9991 wdev->cac_start_time = jiffies;
31559f35 9992 wdev->cac_time_ms = cac_time_ms;
04f39047 9993 }
84158164
LB
9994unlock:
9995 wiphy_unlock(wiphy);
9996
04f39047
SW
9997 return err;
9998}
9999
30c63115
S
10000static int nl80211_notify_radar_detection(struct sk_buff *skb,
10001 struct genl_info *info)
10002{
10003 struct cfg80211_registered_device *rdev = info->user_ptr[0];
10004 struct net_device *dev = info->user_ptr[1];
10005 struct wireless_dev *wdev = dev->ieee80211_ptr;
10006 struct wiphy *wiphy = wdev->wiphy;
10007 struct cfg80211_chan_def chandef;
10008 enum nl80211_dfs_regions dfs_region;
10009 int err;
10010
10011 dfs_region = reg_get_dfs_region(wiphy);
10012 if (dfs_region == NL80211_DFS_UNSET) {
10013 GENL_SET_ERR_MSG(info,
10014 "DFS Region is not set. Unexpected Radar indication");
10015 return -EINVAL;
10016 }
10017
10018 err = nl80211_parse_chandef(rdev, info, &chandef);
10019 if (err) {
10020 GENL_SET_ERR_MSG(info, "Unable to extract chandef info");
10021 return err;
10022 }
10023
10024 err = cfg80211_chandef_dfs_required(wiphy, &chandef, wdev->iftype);
10025 if (err < 0) {
10026 GENL_SET_ERR_MSG(info, "chandef is invalid");
10027 return err;
10028 }
10029
10030 if (err == 0) {
10031 GENL_SET_ERR_MSG(info,
10032 "Unexpected Radar indication for chandef/iftype");
10033 return -EINVAL;
10034 }
10035
10036 /* Do not process this notification if radar is already detected
10037 * by kernel on this channel, and return success.
10038 */
10039 if (chandef.chan->dfs_state == NL80211_DFS_UNAVAILABLE)
10040 return 0;
10041
10042 cfg80211_set_dfs_state(wiphy, &chandef, NL80211_DFS_UNAVAILABLE);
10043
10044 cfg80211_sched_dfs_chan_update(rdev);
10045
a680fe46 10046 rdev->radar_chandef = chandef;
30c63115
S
10047
10048 /* Propagate this notification to other radios as well */
10049 queue_work(cfg80211_wq, &rdev->propagate_radar_detect_wk);
10050
10051 return 0;
10052}
10053
81830c8f
JB
10054static int nl80211_parse_counter_offsets(struct cfg80211_registered_device *rdev,
10055 const u8 *data, size_t datalen,
10056 int first_count, struct nlattr *attr,
10057 const u16 **offsets, unsigned int *n_offsets)
10058{
10059 int i;
10060
10061 *n_offsets = 0;
10062
10063 if (!attr)
10064 return 0;
10065
10066 if (!nla_len(attr) || (nla_len(attr) % sizeof(u16)))
10067 return -EINVAL;
10068
10069 *n_offsets = nla_len(attr) / sizeof(u16);
10070 if (rdev->wiphy.max_num_csa_counters &&
10071 (*n_offsets > rdev->wiphy.max_num_csa_counters))
10072 return -EINVAL;
10073
10074 *offsets = nla_data(attr);
10075
10076 /* sanity checks - counters should fit and be the same */
10077 for (i = 0; i < *n_offsets; i++) {
10078 u16 offset = (*offsets)[i];
10079
10080 if (offset >= datalen)
10081 return -EINVAL;
10082
10083 if (first_count != -1 && data[offset] != first_count)
10084 return -EINVAL;
10085 }
10086
10087 return 0;
10088}
10089
16ef1fe2
SW
10090static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
10091{
10092 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7b0a0e3c 10093 unsigned int link_id = nl80211_link_id(info->attrs);
16ef1fe2
SW
10094 struct net_device *dev = info->user_ptr[1];
10095 struct wireless_dev *wdev = dev->ieee80211_ptr;
10096 struct cfg80211_csa_settings params;
a05829a7 10097 struct nlattr **csa_attrs = NULL;
16ef1fe2 10098 int err;
ee4bc9e7 10099 bool need_new_beacon = false;
8d9de16f 10100 bool need_handle_dfs_flag = true;
252e07ca 10101 u32 cs_count;
16ef1fe2
SW
10102
10103 if (!rdev->ops->channel_switch ||
10104 !(rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH))
10105 return -EOPNOTSUPP;
10106
ee4bc9e7
SW
10107 switch (dev->ieee80211_ptr->iftype) {
10108 case NL80211_IFTYPE_AP:
10109 case NL80211_IFTYPE_P2P_GO:
10110 need_new_beacon = true;
8d9de16f
BB
10111 /* For all modes except AP the handle_dfs flag needs to be
10112 * supplied to tell the kernel that userspace will handle radar
10113 * events when they happen. Otherwise a switch to a channel
10114 * requiring DFS will be rejected.
10115 */
10116 need_handle_dfs_flag = false;
ee4bc9e7
SW
10117
10118 /* useless if AP is not running */
7b0a0e3c 10119 if (!wdev->links[link_id].ap.beacon_interval)
1ff79dfa 10120 return -ENOTCONN;
ee4bc9e7
SW
10121 break;
10122 case NL80211_IFTYPE_ADHOC:
7b0a0e3c 10123 if (!wdev->u.ibss.ssid_len)
1ff79dfa
JB
10124 return -ENOTCONN;
10125 break;
c6da674a 10126 case NL80211_IFTYPE_MESH_POINT:
7b0a0e3c 10127 if (!wdev->u.mesh.id_len)
1ff79dfa 10128 return -ENOTCONN;
ee4bc9e7
SW
10129 break;
10130 default:
16ef1fe2 10131 return -EOPNOTSUPP;
ee4bc9e7 10132 }
16ef1fe2
SW
10133
10134 memset(&params, 0, sizeof(params));
c177db2d 10135 params.beacon_csa.ftm_responder = -1;
16ef1fe2
SW
10136
10137 if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] ||
10138 !info->attrs[NL80211_ATTR_CH_SWITCH_COUNT])
10139 return -EINVAL;
10140
10141 /* only important for AP, IBSS and mesh create IEs internally */
d0a361a5 10142 if (need_new_beacon && !info->attrs[NL80211_ATTR_CSA_IES])
16ef1fe2
SW
10143 return -EINVAL;
10144
252e07ca
LC
10145 /* Even though the attribute is u32, the specification says
10146 * u8, so let's make sure we don't overflow.
10147 */
10148 cs_count = nla_get_u32(info->attrs[NL80211_ATTR_CH_SWITCH_COUNT]);
10149 if (cs_count > 255)
10150 return -EINVAL;
10151
10152 params.count = cs_count;
16ef1fe2 10153
ee4bc9e7
SW
10154 if (!need_new_beacon)
10155 goto skip_beacons;
10156
dbbb27e1
AD
10157 err = nl80211_parse_beacon(rdev, info->attrs, &params.beacon_after,
10158 info->extack);
16ef1fe2 10159 if (err)
dc1e3cb8 10160 goto free;
16ef1fe2 10161
a05829a7
JB
10162 csa_attrs = kcalloc(NL80211_ATTR_MAX + 1, sizeof(*csa_attrs),
10163 GFP_KERNEL);
dc1e3cb8
JC
10164 if (!csa_attrs) {
10165 err = -ENOMEM;
10166 goto free;
10167 }
a05829a7 10168
8cb08174
JB
10169 err = nla_parse_nested_deprecated(csa_attrs, NL80211_ATTR_MAX,
10170 info->attrs[NL80211_ATTR_CSA_IES],
10171 nl80211_policy, info->extack);
16ef1fe2 10172 if (err)
a05829a7 10173 goto free;
16ef1fe2 10174
dbbb27e1
AD
10175 err = nl80211_parse_beacon(rdev, csa_attrs, &params.beacon_csa,
10176 info->extack);
16ef1fe2 10177 if (err)
a05829a7 10178 goto free;
16ef1fe2 10179
a05829a7
JB
10180 if (!csa_attrs[NL80211_ATTR_CNTDWN_OFFS_BEACON]) {
10181 err = -EINVAL;
10182 goto free;
10183 }
16ef1fe2 10184
81830c8f
JB
10185 err = nl80211_parse_counter_offsets(rdev, params.beacon_csa.tail,
10186 params.beacon_csa.tail_len,
10187 params.count,
10188 csa_attrs[NL80211_ATTR_CNTDWN_OFFS_BEACON],
10189 &params.counter_offsets_beacon,
10190 &params.n_counter_offsets_beacon);
10191 if (err)
a05829a7 10192 goto free;
16ef1fe2 10193
81830c8f
JB
10194 err = nl80211_parse_counter_offsets(rdev, params.beacon_csa.probe_resp,
10195 params.beacon_csa.probe_resp_len,
10196 params.count,
10197 csa_attrs[NL80211_ATTR_CNTDWN_OFFS_PRESP],
10198 &params.counter_offsets_presp,
10199 &params.n_counter_offsets_presp);
10200 if (err)
a05829a7 10201 goto free;
16ef1fe2 10202
ee4bc9e7 10203skip_beacons:
16ef1fe2
SW
10204 err = nl80211_parse_chandef(rdev, info, &params.chandef);
10205 if (err)
a05829a7 10206 goto free;
16ef1fe2 10207
923b352f 10208 if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &params.chandef,
a05829a7
JB
10209 wdev->iftype)) {
10210 err = -EINVAL;
10211 goto free;
10212 }
16ef1fe2 10213
2beb6dab
LC
10214 err = cfg80211_chandef_dfs_required(wdev->wiphy,
10215 &params.chandef,
10216 wdev->iftype);
10217 if (err < 0)
a05829a7 10218 goto free;
2beb6dab 10219
8d9de16f 10220 if (err > 0) {
2beb6dab 10221 params.radar_required = true;
8d9de16f
BB
10222 if (need_handle_dfs_flag &&
10223 !nla_get_flag(info->attrs[NL80211_ATTR_HANDLE_DFS])) {
a05829a7
JB
10224 err = -EINVAL;
10225 goto free;
8d9de16f
BB
10226 }
10227 }
16ef1fe2 10228
16ef1fe2
SW
10229 if (info->attrs[NL80211_ATTR_CH_SWITCH_BLOCK_TX])
10230 params.block_tx = true;
10231
4ace04c0 10232 params.link_id = link_id;
c56589ed 10233 err = rdev_channel_switch(rdev, dev, &params);
c56589ed 10234
a05829a7 10235free:
dc1e3cb8
JC
10236 kfree(params.beacon_after.mbssid_ies);
10237 kfree(params.beacon_csa.mbssid_ies);
dbbb27e1
AD
10238 kfree(params.beacon_after.rnr_ies);
10239 kfree(params.beacon_csa.rnr_ies);
a05829a7 10240 kfree(csa_attrs);
c56589ed 10241 return err;
16ef1fe2
SW
10242}
10243
9720bb3a
JB
10244static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
10245 u32 seq, int flags,
2a519311 10246 struct cfg80211_registered_device *rdev,
48ab905d
JB
10247 struct wireless_dev *wdev,
10248 struct cfg80211_internal_bss *intbss)
2a519311 10249{
48ab905d 10250 struct cfg80211_bss *res = &intbss->pub;
9caf0364 10251 const struct cfg80211_bss_ies *ies;
7b0a0e3c 10252 unsigned int link_id;
2a519311
JB
10253 void *hdr;
10254 struct nlattr *bss;
48ab905d 10255
076fc877 10256 lockdep_assert_wiphy(wdev->wiphy);
2a519311 10257
15e47304 10258 hdr = nl80211hdr_put(msg, NETLINK_CB(cb->skb).portid, seq, flags,
2a519311
JB
10259 NL80211_CMD_NEW_SCAN_RESULTS);
10260 if (!hdr)
10261 return -1;
10262
0a833c29 10263 genl_dump_check_consistent(cb, hdr);
9720bb3a 10264
97990a06
JB
10265 if (nla_put_u32(msg, NL80211_ATTR_GENERATION, rdev->bss_generation))
10266 goto nla_put_failure;
10267 if (wdev->netdev &&
9360ffd1
DM
10268 nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex))
10269 goto nla_put_failure;
2dad624e
ND
10270 if (nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
10271 NL80211_ATTR_PAD))
97990a06 10272 goto nla_put_failure;
2a519311 10273
ae0be8de 10274 bss = nla_nest_start_noflag(msg, NL80211_ATTR_BSS);
2a519311
JB
10275 if (!bss)
10276 goto nla_put_failure;
9360ffd1 10277 if ((!is_zero_ether_addr(res->bssid) &&
9caf0364 10278 nla_put(msg, NL80211_BSS_BSSID, ETH_ALEN, res->bssid)))
9360ffd1 10279 goto nla_put_failure;
9caf0364
JB
10280
10281 rcu_read_lock();
0e227084
JB
10282 /* indicate whether we have probe response data or not */
10283 if (rcu_access_pointer(res->proberesp_ies) &&
10284 nla_put_flag(msg, NL80211_BSS_PRESP_DATA))
10285 goto fail_unlock_rcu;
10286
10287 /* this pointer prefers to be pointed to probe response data
10288 * but is always valid
10289 */
9caf0364 10290 ies = rcu_dereference(res->ies);
8cef2c9d 10291 if (ies) {
2dad624e
ND
10292 if (nla_put_u64_64bit(msg, NL80211_BSS_TSF, ies->tsf,
10293 NL80211_BSS_PAD))
8cef2c9d 10294 goto fail_unlock_rcu;
8cef2c9d
JB
10295 if (ies->len && nla_put(msg, NL80211_BSS_INFORMATION_ELEMENTS,
10296 ies->len, ies->data))
10297 goto fail_unlock_rcu;
9caf0364 10298 }
0e227084
JB
10299
10300 /* and this pointer is always (unless driver didn't know) beacon data */
9caf0364 10301 ies = rcu_dereference(res->beacon_ies);
0e227084 10302 if (ies && ies->from_beacon) {
2dad624e
ND
10303 if (nla_put_u64_64bit(msg, NL80211_BSS_BEACON_TSF, ies->tsf,
10304 NL80211_BSS_PAD))
8cef2c9d
JB
10305 goto fail_unlock_rcu;
10306 if (ies->len && nla_put(msg, NL80211_BSS_BEACON_IES,
10307 ies->len, ies->data))
10308 goto fail_unlock_rcu;
9caf0364
JB
10309 }
10310 rcu_read_unlock();
10311
9360ffd1
DM
10312 if (res->beacon_interval &&
10313 nla_put_u16(msg, NL80211_BSS_BEACON_INTERVAL, res->beacon_interval))
10314 goto nla_put_failure;
10315 if (nla_put_u16(msg, NL80211_BSS_CAPABILITY, res->capability) ||
10316 nla_put_u32(msg, NL80211_BSS_FREQUENCY, res->channel->center_freq) ||
942ba88b
TP
10317 nla_put_u32(msg, NL80211_BSS_FREQUENCY_OFFSET,
10318 res->channel->freq_offset) ||
9360ffd1
DM
10319 nla_put_u32(msg, NL80211_BSS_SEEN_MS_AGO,
10320 jiffies_to_msecs(jiffies - intbss->ts)))
10321 goto nla_put_failure;
2a519311 10322
1d76250b
AS
10323 if (intbss->parent_tsf &&
10324 (nla_put_u64_64bit(msg, NL80211_BSS_PARENT_TSF,
10325 intbss->parent_tsf, NL80211_BSS_PAD) ||
10326 nla_put(msg, NL80211_BSS_PARENT_BSSID, ETH_ALEN,
10327 intbss->parent_bssid)))
10328 goto nla_put_failure;
10329
6e19bc4b 10330 if (intbss->ts_boottime &&
2dad624e
ND
10331 nla_put_u64_64bit(msg, NL80211_BSS_LAST_SEEN_BOOTTIME,
10332 intbss->ts_boottime, NL80211_BSS_PAD))
6e19bc4b
DS
10333 goto nla_put_failure;
10334
983dafaa
SD
10335 if (!nl80211_put_signal(msg, intbss->pub.chains,
10336 intbss->pub.chain_signal,
10337 NL80211_BSS_CHAIN_SIGNAL))
10338 goto nla_put_failure;
10339
77965c97 10340 switch (rdev->wiphy.signal_type) {
2a519311 10341 case CFG80211_SIGNAL_TYPE_MBM:
9360ffd1
DM
10342 if (nla_put_u32(msg, NL80211_BSS_SIGNAL_MBM, res->signal))
10343 goto nla_put_failure;
2a519311
JB
10344 break;
10345 case CFG80211_SIGNAL_TYPE_UNSPEC:
9360ffd1
DM
10346 if (nla_put_u8(msg, NL80211_BSS_SIGNAL_UNSPEC, res->signal))
10347 goto nla_put_failure;
2a519311
JB
10348 break;
10349 default:
10350 break;
10351 }
10352
48ab905d 10353 switch (wdev->iftype) {
074ac8df 10354 case NL80211_IFTYPE_P2P_CLIENT:
48ab905d 10355 case NL80211_IFTYPE_STATION:
7b0a0e3c
JB
10356 for_each_valid_link(wdev, link_id) {
10357 if (intbss == wdev->links[link_id].client.current_bss &&
dd374f84
JB
10358 (nla_put_u32(msg, NL80211_BSS_STATUS,
10359 NL80211_BSS_STATUS_ASSOCIATED) ||
10360 (wdev->valid_links &&
6522047c
JB
10361 (nla_put_u8(msg, NL80211_BSS_MLO_LINK_ID,
10362 link_id) ||
10363 nla_put(msg, NL80211_BSS_MLD_ADDR, ETH_ALEN,
10364 wdev->u.client.connected_addr)))))
7b0a0e3c
JB
10365 goto nla_put_failure;
10366 }
48ab905d
JB
10367 break;
10368 case NL80211_IFTYPE_ADHOC:
7b0a0e3c 10369 if (intbss == wdev->u.ibss.current_bss &&
9360ffd1
DM
10370 nla_put_u32(msg, NL80211_BSS_STATUS,
10371 NL80211_BSS_STATUS_IBSS_JOINED))
10372 goto nla_put_failure;
48ab905d
JB
10373 break;
10374 default:
10375 break;
10376 }
10377
d02a12b8
JB
10378 if (nla_put_u32(msg, NL80211_BSS_USE_FOR, res->use_for))
10379 goto nla_put_failure;
10380
10381 if (res->cannot_use_reasons &&
10382 nla_put_u64_64bit(msg, NL80211_BSS_CANNOT_USE_REASONS,
10383 res->cannot_use_reasons,
10384 NL80211_BSS_PAD))
10385 goto nla_put_failure;
10386
2a519311
JB
10387 nla_nest_end(msg, bss);
10388
053c095a
JB
10389 genlmsg_end(msg, hdr);
10390 return 0;
2a519311 10391
8cef2c9d
JB
10392 fail_unlock_rcu:
10393 rcu_read_unlock();
2a519311
JB
10394 nla_put_failure:
10395 genlmsg_cancel(msg, hdr);
10396 return -EMSGSIZE;
10397}
10398
97990a06 10399static int nl80211_dump_scan(struct sk_buff *skb, struct netlink_callback *cb)
2a519311 10400{
48ab905d 10401 struct cfg80211_registered_device *rdev;
2a519311 10402 struct cfg80211_internal_bss *scan;
48ab905d 10403 struct wireless_dev *wdev;
d02a12b8 10404 struct nlattr **attrbuf;
97990a06 10405 int start = cb->args[2], idx = 0;
d02a12b8 10406 bool dump_include_use_data;
2a519311
JB
10407 int err;
10408
d02a12b8
JB
10409 attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf), GFP_KERNEL);
10410 if (!attrbuf)
10411 return -ENOMEM;
10412
10413 err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev, attrbuf);
10414 if (err) {
10415 kfree(attrbuf);
67748893 10416 return err;
d02a12b8 10417 }
a05829a7
JB
10418 /* nl80211_prepare_wdev_dump acquired it in the successful case */
10419 __acquire(&rdev->wiphy.mtx);
2a519311 10420
d02a12b8
JB
10421 dump_include_use_data =
10422 attrbuf[NL80211_ATTR_BSS_DUMP_INCLUDE_USE_DATA];
10423 kfree(attrbuf);
10424
48ab905d 10425 spin_lock_bh(&rdev->bss_lock);
d1e23c94
DK
10426
10427 /*
10428 * dump_scan will be called multiple times to break up the scan results
10429 * into multiple messages. It is unlikely that any more bss-es will be
10430 * expired after the first call, so only call only call this on the
10431 * first dump_scan invocation.
10432 */
10433 if (start == 0)
10434 cfg80211_bss_expire(rdev);
48ab905d 10435
9720bb3a
JB
10436 cb->seq = rdev->bss_generation;
10437
48ab905d 10438 list_for_each_entry(scan, &rdev->bss_list, list) {
2a519311
JB
10439 if (++idx <= start)
10440 continue;
d02a12b8
JB
10441 if (!dump_include_use_data &&
10442 !(scan->pub.use_for & NL80211_BSS_USE_FOR_NORMAL))
10443 continue;
9720bb3a 10444 if (nl80211_send_bss(skb, cb,
2a519311 10445 cb->nlh->nlmsg_seq, NLM_F_MULTI,
48ab905d 10446 rdev, wdev, scan) < 0) {
2a519311 10447 idx--;
67748893 10448 break;
2a519311
JB
10449 }
10450 }
10451
48ab905d 10452 spin_unlock_bh(&rdev->bss_lock);
2a519311 10453
97990a06 10454 cb->args[2] = idx;
a05829a7 10455 wiphy_unlock(&rdev->wiphy);
2a519311 10456
67748893 10457 return skb->len;
2a519311
JB
10458}
10459
15e47304 10460static int nl80211_send_survey(struct sk_buff *msg, u32 portid, u32 seq,
11f78ac3
JB
10461 int flags, struct net_device *dev,
10462 bool allow_radio_stats,
10463 struct survey_info *survey)
61fa713c
HS
10464{
10465 void *hdr;
10466 struct nlattr *infoattr;
10467
11f78ac3
JB
10468 /* skip radio stats if userspace didn't request them */
10469 if (!survey->channel && !allow_radio_stats)
10470 return 0;
10471
15e47304 10472 hdr = nl80211hdr_put(msg, portid, seq, flags,
61fa713c
HS
10473 NL80211_CMD_NEW_SURVEY_RESULTS);
10474 if (!hdr)
10475 return -ENOMEM;
10476
9360ffd1
DM
10477 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
10478 goto nla_put_failure;
61fa713c 10479
ae0be8de 10480 infoattr = nla_nest_start_noflag(msg, NL80211_ATTR_SURVEY_INFO);
61fa713c
HS
10481 if (!infoattr)
10482 goto nla_put_failure;
10483
11f78ac3
JB
10484 if (survey->channel &&
10485 nla_put_u32(msg, NL80211_SURVEY_INFO_FREQUENCY,
9360ffd1
DM
10486 survey->channel->center_freq))
10487 goto nla_put_failure;
58ef7c1b
TP
10488
10489 if (survey->channel && survey->channel->freq_offset &&
10490 nla_put_u32(msg, NL80211_SURVEY_INFO_FREQUENCY_OFFSET,
10491 survey->channel->freq_offset))
10492 goto nla_put_failure;
9360ffd1
DM
10493
10494 if ((survey->filled & SURVEY_INFO_NOISE_DBM) &&
10495 nla_put_u8(msg, NL80211_SURVEY_INFO_NOISE, survey->noise))
10496 goto nla_put_failure;
10497 if ((survey->filled & SURVEY_INFO_IN_USE) &&
10498 nla_put_flag(msg, NL80211_SURVEY_INFO_IN_USE))
10499 goto nla_put_failure;
4ed20beb 10500 if ((survey->filled & SURVEY_INFO_TIME) &&
2dad624e
ND
10501 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME,
10502 survey->time, NL80211_SURVEY_INFO_PAD))
9360ffd1 10503 goto nla_put_failure;
4ed20beb 10504 if ((survey->filled & SURVEY_INFO_TIME_BUSY) &&
2dad624e
ND
10505 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_BUSY,
10506 survey->time_busy, NL80211_SURVEY_INFO_PAD))
9360ffd1 10507 goto nla_put_failure;
4ed20beb 10508 if ((survey->filled & SURVEY_INFO_TIME_EXT_BUSY) &&
2dad624e
ND
10509 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_EXT_BUSY,
10510 survey->time_ext_busy, NL80211_SURVEY_INFO_PAD))
9360ffd1 10511 goto nla_put_failure;
4ed20beb 10512 if ((survey->filled & SURVEY_INFO_TIME_RX) &&
2dad624e
ND
10513 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_RX,
10514 survey->time_rx, NL80211_SURVEY_INFO_PAD))
9360ffd1 10515 goto nla_put_failure;
4ed20beb 10516 if ((survey->filled & SURVEY_INFO_TIME_TX) &&
2dad624e
ND
10517 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_TX,
10518 survey->time_tx, NL80211_SURVEY_INFO_PAD))
9360ffd1 10519 goto nla_put_failure;
052536ab 10520 if ((survey->filled & SURVEY_INFO_TIME_SCAN) &&
2dad624e
ND
10521 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_SCAN,
10522 survey->time_scan, NL80211_SURVEY_INFO_PAD))
052536ab 10523 goto nla_put_failure;
c8cd6e7f
FF
10524 if ((survey->filled & SURVEY_INFO_TIME_BSS_RX) &&
10525 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_BSS_RX,
10526 survey->time_bss_rx, NL80211_SURVEY_INFO_PAD))
10527 goto nla_put_failure;
61fa713c
HS
10528
10529 nla_nest_end(msg, infoattr);
10530
053c095a
JB
10531 genlmsg_end(msg, hdr);
10532 return 0;
61fa713c
HS
10533
10534 nla_put_failure:
10535 genlmsg_cancel(msg, hdr);
10536 return -EMSGSIZE;
10537}
10538
11f78ac3 10539static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb)
61fa713c 10540{
50508d94 10541 struct nlattr **attrbuf;
61fa713c 10542 struct survey_info survey;
1b8ec87a 10543 struct cfg80211_registered_device *rdev;
97990a06
JB
10544 struct wireless_dev *wdev;
10545 int survey_idx = cb->args[2];
61fa713c 10546 int res;
11f78ac3 10547 bool radio_stats;
61fa713c 10548
50508d94
JB
10549 attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf), GFP_KERNEL);
10550 if (!attrbuf)
10551 return -ENOMEM;
10552
ce6b6974 10553 res = nl80211_prepare_wdev_dump(cb, &rdev, &wdev, attrbuf);
a05829a7
JB
10554 if (res) {
10555 kfree(attrbuf);
10556 return res;
10557 }
10558 /* nl80211_prepare_wdev_dump acquired it in the successful case */
10559 __acquire(&rdev->wiphy.mtx);
61fa713c 10560
11f78ac3 10561 /* prepare_wdev_dump parsed the attributes */
c90c39da 10562 radio_stats = attrbuf[NL80211_ATTR_SURVEY_RADIO_STATS];
11f78ac3 10563
97990a06
JB
10564 if (!wdev->netdev) {
10565 res = -EINVAL;
10566 goto out_err;
10567 }
10568
1b8ec87a 10569 if (!rdev->ops->dump_survey) {
61fa713c
HS
10570 res = -EOPNOTSUPP;
10571 goto out_err;
10572 }
10573
10574 while (1) {
1b8ec87a 10575 res = rdev_dump_survey(rdev, wdev->netdev, survey_idx, &survey);
61fa713c
HS
10576 if (res == -ENOENT)
10577 break;
10578 if (res)
10579 goto out_err;
10580
11f78ac3
JB
10581 /* don't send disabled channels, but do send non-channel data */
10582 if (survey.channel &&
10583 survey.channel->flags & IEEE80211_CHAN_DISABLED) {
180cdc79
LR
10584 survey_idx++;
10585 continue;
10586 }
10587
61fa713c 10588 if (nl80211_send_survey(skb,
15e47304 10589 NETLINK_CB(cb->skb).portid,
61fa713c 10590 cb->nlh->nlmsg_seq, NLM_F_MULTI,
11f78ac3 10591 wdev->netdev, radio_stats, &survey) < 0)
61fa713c
HS
10592 goto out;
10593 survey_idx++;
10594 }
10595
10596 out:
97990a06 10597 cb->args[2] = survey_idx;
61fa713c
HS
10598 res = skb->len;
10599 out_err:
50508d94 10600 kfree(attrbuf);
a05829a7 10601 wiphy_unlock(&rdev->wiphy);
61fa713c
HS
10602 return res;
10603}
10604
636a5d36
JM
10605static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
10606{
4c476991
JB
10607 struct cfg80211_registered_device *rdev = info->user_ptr[0];
10608 struct net_device *dev = info->user_ptr[1];
19957bb3 10609 struct ieee80211_channel *chan;
325839da
JB
10610 const u8 *bssid, *ssid;
10611 int err, ssid_len;
19957bb3 10612 enum nl80211_auth_type auth_type;
fffd0934 10613 struct key_parse key;
d5cdfacb 10614 bool local_state_change;
325839da 10615 struct cfg80211_auth_request req = {};
942ba88b 10616 u32 freq;
636a5d36 10617
f4a11bb0
JB
10618 if (!info->attrs[NL80211_ATTR_MAC])
10619 return -EINVAL;
10620
1778092e
JM
10621 if (!info->attrs[NL80211_ATTR_AUTH_TYPE])
10622 return -EINVAL;
10623
19957bb3
JB
10624 if (!info->attrs[NL80211_ATTR_SSID])
10625 return -EINVAL;
10626
10627 if (!info->attrs[NL80211_ATTR_WIPHY_FREQ])
10628 return -EINVAL;
10629
fffd0934
JB
10630 err = nl80211_parse_key(info, &key);
10631 if (err)
10632 return err;
10633
10634 if (key.idx >= 0) {
e31b8213
JB
10635 if (key.type != -1 && key.type != NL80211_KEYTYPE_GROUP)
10636 return -EINVAL;
fffd0934
JB
10637 if (!key.p.key || !key.p.key_len)
10638 return -EINVAL;
10639 if ((key.p.cipher != WLAN_CIPHER_SUITE_WEP40 ||
10640 key.p.key_len != WLAN_KEY_LEN_WEP40) &&
10641 (key.p.cipher != WLAN_CIPHER_SUITE_WEP104 ||
10642 key.p.key_len != WLAN_KEY_LEN_WEP104))
10643 return -EINVAL;
b6b5555b 10644 if (key.idx > 3)
fffd0934
JB
10645 return -EINVAL;
10646 } else {
10647 key.p.key_len = 0;
10648 key.p.key = NULL;
10649 }
10650
afea0b7a
JB
10651 if (key.idx >= 0) {
10652 int i;
10653 bool ok = false;
7a087e74 10654
afea0b7a
JB
10655 for (i = 0; i < rdev->wiphy.n_cipher_suites; i++) {
10656 if (key.p.cipher == rdev->wiphy.cipher_suites[i]) {
10657 ok = true;
10658 break;
10659 }
10660 }
4c476991
JB
10661 if (!ok)
10662 return -EINVAL;
afea0b7a
JB
10663 }
10664
4c476991
JB
10665 if (!rdev->ops->auth)
10666 return -EOPNOTSUPP;
636a5d36 10667
074ac8df 10668 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
10669 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
10670 return -EOPNOTSUPP;
eec60b03 10671
19957bb3 10672 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
942ba88b
TP
10673 freq = MHZ_TO_KHZ(nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
10674 if (info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET])
10675 freq +=
10676 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET]);
10677
10678 chan = nl80211_get_valid_chan(&rdev->wiphy, freq);
664834de 10679 if (!chan)
4c476991 10680 return -EINVAL;
636a5d36 10681
19957bb3
JB
10682 ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
10683 ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
636a5d36
JM
10684
10685 if (info->attrs[NL80211_ATTR_IE]) {
325839da
JB
10686 req.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
10687 req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
636a5d36
JM
10688 }
10689
19957bb3 10690 auth_type = nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
e39e5b5e 10691 if (!nl80211_valid_auth_type(rdev, auth_type, NL80211_CMD_AUTHENTICATE))
4c476991 10692 return -EINVAL;
636a5d36 10693
63181060
JM
10694 if ((auth_type == NL80211_AUTHTYPE_SAE ||
10695 auth_type == NL80211_AUTHTYPE_FILS_SK ||
10696 auth_type == NL80211_AUTHTYPE_FILS_SK_PFS ||
10697 auth_type == NL80211_AUTHTYPE_FILS_PK) &&
11b6b5a4 10698 !info->attrs[NL80211_ATTR_AUTH_DATA])
e39e5b5e
JM
10699 return -EINVAL;
10700
11b6b5a4 10701 if (info->attrs[NL80211_ATTR_AUTH_DATA]) {
63181060
JM
10702 if (auth_type != NL80211_AUTHTYPE_SAE &&
10703 auth_type != NL80211_AUTHTYPE_FILS_SK &&
10704 auth_type != NL80211_AUTHTYPE_FILS_SK_PFS &&
10705 auth_type != NL80211_AUTHTYPE_FILS_PK)
e39e5b5e 10706 return -EINVAL;
325839da
JB
10707 req.auth_data = nla_data(info->attrs[NL80211_ATTR_AUTH_DATA]);
10708 req.auth_data_len = nla_len(info->attrs[NL80211_ATTR_AUTH_DATA]);
e39e5b5e
JM
10709 }
10710
d5cdfacb
JM
10711 local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
10712
95de817b
JB
10713 /*
10714 * Since we no longer track auth state, ignore
10715 * requests to only change local state.
10716 */
10717 if (local_state_change)
10718 return 0;
10719
325839da
JB
10720 req.auth_type = auth_type;
10721 req.key = key.p.key;
10722 req.key_len = key.p.key_len;
10723 req.key_idx = key.idx;
d648c230
JB
10724 req.link_id = nl80211_link_id_or_invalid(info->attrs);
10725 if (req.link_id >= 0) {
45aaf17c
JB
10726 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_MLO))
10727 return -EINVAL;
d648c230
JB
10728 if (!info->attrs[NL80211_ATTR_MLD_ADDR])
10729 return -EINVAL;
10730 req.ap_mld_addr = nla_data(info->attrs[NL80211_ATTR_MLD_ADDR]);
727073ca
JB
10731 if (!is_valid_ether_addr(req.ap_mld_addr))
10732 return -EINVAL;
d648c230 10733 }
325839da
JB
10734
10735 req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
10736 IEEE80211_BSS_TYPE_ESS,
10737 IEEE80211_PRIVACY_ANY);
10738 if (!req.bss)
10739 return -ENOENT;
10740
325839da 10741 err = cfg80211_mlme_auth(rdev, dev, &req);
325839da
JB
10742
10743 cfg80211_put_bss(&rdev->wiphy, req.bss);
10744
91bf9b26 10745 return err;
636a5d36
JM
10746}
10747
64bf3d4b
DK
10748static int validate_pae_over_nl80211(struct cfg80211_registered_device *rdev,
10749 struct genl_info *info)
10750{
10751 if (!info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
10752 GENL_SET_ERR_MSG(info, "SOCKET_OWNER not set");
10753 return -EINVAL;
10754 }
10755
10756 if (!rdev->ops->tx_control_port ||
10757 !wiphy_ext_feature_isset(&rdev->wiphy,
10758 NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211))
10759 return -EOPNOTSUPP;
10760
10761 return 0;
10762}
10763
c0692b8f
JB
10764static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev,
10765 struct genl_info *info,
3dc27d25
JB
10766 struct cfg80211_crypto_settings *settings,
10767 int cipher_limit)
b23aa676 10768{
c0b2bbd8
JB
10769 memset(settings, 0, sizeof(*settings));
10770
b23aa676
SO
10771 settings->control_port = info->attrs[NL80211_ATTR_CONTROL_PORT];
10772
c0692b8f
JB
10773 if (info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]) {
10774 u16 proto;
7a087e74 10775
c0692b8f
JB
10776 proto = nla_get_u16(
10777 info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]);
10778 settings->control_port_ethertype = cpu_to_be16(proto);
10779 if (!(rdev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) &&
10780 proto != ETH_P_PAE)
10781 return -EINVAL;
10782 if (info->attrs[NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT])
10783 settings->control_port_no_encrypt = true;
10784 } else
10785 settings->control_port_ethertype = cpu_to_be16(ETH_P_PAE);
10786
64bf3d4b
DK
10787 if (info->attrs[NL80211_ATTR_CONTROL_PORT_OVER_NL80211]) {
10788 int r = validate_pae_over_nl80211(rdev, info);
10789
10790 if (r < 0)
10791 return r;
10792
10793 settings->control_port_over_nl80211 = true;
7f3f96ce
MT
10794
10795 if (info->attrs[NL80211_ATTR_CONTROL_PORT_NO_PREAUTH])
10796 settings->control_port_no_preauth = true;
64bf3d4b
DK
10797 }
10798
b23aa676
SO
10799 if (info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE]) {
10800 void *data;
10801 int len, i;
10802
10803 data = nla_data(info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE]);
10804 len = nla_len(info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE]);
10805 settings->n_ciphers_pairwise = len / sizeof(u32);
10806
10807 if (len % sizeof(u32))
10808 return -EINVAL;
10809
3dc27d25 10810 if (settings->n_ciphers_pairwise > cipher_limit)
b23aa676
SO
10811 return -EINVAL;
10812
10813 memcpy(settings->ciphers_pairwise, data, len);
10814
10815 for (i = 0; i < settings->n_ciphers_pairwise; i++)
38ba3c57
JM
10816 if (!cfg80211_supported_cipher_suite(
10817 &rdev->wiphy,
b23aa676
SO
10818 settings->ciphers_pairwise[i]))
10819 return -EINVAL;
10820 }
10821
10822 if (info->attrs[NL80211_ATTR_CIPHER_SUITE_GROUP]) {
10823 settings->cipher_group =
10824 nla_get_u32(info->attrs[NL80211_ATTR_CIPHER_SUITE_GROUP]);
38ba3c57
JM
10825 if (!cfg80211_supported_cipher_suite(&rdev->wiphy,
10826 settings->cipher_group))
b23aa676
SO
10827 return -EINVAL;
10828 }
10829
57d1b463 10830 if (info->attrs[NL80211_ATTR_WPA_VERSIONS])
b23aa676
SO
10831 settings->wpa_versions =
10832 nla_get_u32(info->attrs[NL80211_ATTR_WPA_VERSIONS]);
b23aa676
SO
10833
10834 if (info->attrs[NL80211_ATTR_AKM_SUITES]) {
10835 void *data;
6d30240e 10836 int len;
b23aa676
SO
10837
10838 data = nla_data(info->attrs[NL80211_ATTR_AKM_SUITES]);
10839 len = nla_len(info->attrs[NL80211_ATTR_AKM_SUITES]);
10840 settings->n_akm_suites = len / sizeof(u32);
10841
10842 if (len % sizeof(u32))
10843 return -EINVAL;
10844
ecad3b0b 10845 if (settings->n_akm_suites > rdev->wiphy.max_num_akm_suites)
1b9ca027
JM
10846 return -EINVAL;
10847
b23aa676 10848 memcpy(settings->akm_suites, data, len);
b23aa676
SO
10849 }
10850
91b5ab62
EP
10851 if (info->attrs[NL80211_ATTR_PMK]) {
10852 if (nla_len(info->attrs[NL80211_ATTR_PMK]) != WLAN_PMK_LEN)
10853 return -EINVAL;
10854 if (!wiphy_ext_feature_isset(&rdev->wiphy,
f9662274
CHH
10855 NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK) &&
10856 !wiphy_ext_feature_isset(&rdev->wiphy,
10857 NL80211_EXT_FEATURE_4WAY_HANDSHAKE_AP_PSK))
91b5ab62
EP
10858 return -EINVAL;
10859 settings->psk = nla_data(info->attrs[NL80211_ATTR_PMK]);
10860 }
10861
26f7044e
CHH
10862 if (info->attrs[NL80211_ATTR_SAE_PASSWORD]) {
10863 if (!wiphy_ext_feature_isset(&rdev->wiphy,
2831a631
CHH
10864 NL80211_EXT_FEATURE_SAE_OFFLOAD) &&
10865 !wiphy_ext_feature_isset(&rdev->wiphy,
10866 NL80211_EXT_FEATURE_SAE_OFFLOAD_AP))
26f7044e
CHH
10867 return -EINVAL;
10868 settings->sae_pwd =
10869 nla_data(info->attrs[NL80211_ATTR_SAE_PASSWORD]);
10870 settings->sae_pwd_len =
10871 nla_len(info->attrs[NL80211_ATTR_SAE_PASSWORD]);
10872 }
10873
9f0ffa41
RD
10874 if (info->attrs[NL80211_ATTR_SAE_PWE])
10875 settings->sae_pwe =
10876 nla_get_u8(info->attrs[NL80211_ATTR_SAE_PWE]);
10877 else
10878 settings->sae_pwe = NL80211_SAE_PWE_UNSPECIFIED;
10879
b23aa676
SO
10880 return 0;
10881}
10882
9ecff10e
JB
10883static struct cfg80211_bss *nl80211_assoc_bss(struct cfg80211_registered_device *rdev,
10884 const u8 *ssid, int ssid_len,
d02a12b8
JB
10885 struct nlattr **attrs,
10886 int assoc_link_id, int link_id)
9ecff10e
JB
10887{
10888 struct ieee80211_channel *chan;
10889 struct cfg80211_bss *bss;
10890 const u8 *bssid;
d02a12b8 10891 u32 freq, use_for = 0;
9ecff10e
JB
10892
10893 if (!attrs[NL80211_ATTR_MAC] || !attrs[NL80211_ATTR_WIPHY_FREQ])
10894 return ERR_PTR(-EINVAL);
10895
10896 bssid = nla_data(attrs[NL80211_ATTR_MAC]);
10897
10898 freq = MHZ_TO_KHZ(nla_get_u32(attrs[NL80211_ATTR_WIPHY_FREQ]));
10899 if (attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET])
10900 freq += nla_get_u32(attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET]);
10901
10902 chan = nl80211_get_valid_chan(&rdev->wiphy, freq);
10903 if (!chan)
10904 return ERR_PTR(-EINVAL);
10905
d02a12b8
JB
10906 if (assoc_link_id >= 0)
10907 use_for = NL80211_BSS_USE_FOR_MLD_LINK;
10908 if (assoc_link_id == link_id)
10909 use_for |= NL80211_BSS_USE_FOR_NORMAL;
10910
10911 bss = __cfg80211_get_bss(&rdev->wiphy, chan, bssid,
10912 ssid, ssid_len,
10913 IEEE80211_BSS_TYPE_ESS,
10914 IEEE80211_PRIVACY_ANY,
10915 use_for);
9ecff10e
JB
10916 if (!bss)
10917 return ERR_PTR(-ENOENT);
10918
9ecff10e
JB
10919 return bss;
10920}
10921
636a5d36
JM
10922static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
10923{
4c476991
JB
10924 struct cfg80211_registered_device *rdev = info->user_ptr[0];
10925 struct net_device *dev = info->user_ptr[1];
f62fab73 10926 struct cfg80211_assoc_request req = {};
d648c230 10927 struct nlattr **attrs = NULL;
96c06950 10928 const u8 *ap_addr, *ssid;
d648c230 10929 unsigned int link_id;
0f759448 10930 int err, ssid_len;
636a5d36 10931
bad29297
AZ
10932 if (dev->ieee80211_ptr->conn_owner_nlportid &&
10933 dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)
10934 return -EPERM;
10935
9ecff10e 10936 if (!info->attrs[NL80211_ATTR_SSID])
f4a11bb0
JB
10937 return -EINVAL;
10938
4c476991
JB
10939 if (!rdev->ops->assoc)
10940 return -EOPNOTSUPP;
636a5d36 10941
074ac8df 10942 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
10943 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
10944 return -EOPNOTSUPP;
eec60b03 10945
19957bb3
JB
10946 ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
10947 ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
636a5d36
JM
10948
10949 if (info->attrs[NL80211_ATTR_IE]) {
f62fab73
JB
10950 req.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
10951 req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
df35f316
JB
10952
10953 if (cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE,
10954 req.ie, req.ie_len)) {
a7b2cc59
BB
10955 NL_SET_ERR_MSG_ATTR(info->extack,
10956 info->attrs[NL80211_ATTR_IE],
10957 "non-inheritance makes no sense");
df35f316
JB
10958 return -EINVAL;
10959 }
636a5d36
JM
10960 }
10961
dc6382ce 10962 if (info->attrs[NL80211_ATTR_USE_MFP]) {
4f5dadce 10963 enum nl80211_mfp mfp =
dc6382ce 10964 nla_get_u32(info->attrs[NL80211_ATTR_USE_MFP]);
4f5dadce 10965 if (mfp == NL80211_MFP_REQUIRED)
f62fab73 10966 req.use_mfp = true;
4c476991
JB
10967 else if (mfp != NL80211_MFP_NO)
10968 return -EINVAL;
dc6382ce
JM
10969 }
10970
3e5d7649 10971 if (info->attrs[NL80211_ATTR_PREV_BSSID])
f62fab73 10972 req.prev_bssid = nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]);
3e5d7649 10973
7e7c8926 10974 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HT]))
f62fab73 10975 req.flags |= ASSOC_REQ_DISABLE_HT;
7e7c8926
BG
10976
10977 if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
f62fab73
JB
10978 memcpy(&req.ht_capa_mask,
10979 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]),
10980 sizeof(req.ht_capa_mask));
7e7c8926
BG
10981
10982 if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
f62fab73 10983 if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
7e7c8926 10984 return -EINVAL;
f62fab73
JB
10985 memcpy(&req.ht_capa,
10986 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]),
10987 sizeof(req.ht_capa));
7e7c8926
BG
10988 }
10989
ee2aca34 10990 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_VHT]))
f62fab73 10991 req.flags |= ASSOC_REQ_DISABLE_VHT;
ee2aca34 10992
b6db0f89
BG
10993 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HE]))
10994 req.flags |= ASSOC_REQ_DISABLE_HE;
10995
36f84235
MS
10996 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_EHT]))
10997 req.flags |= ASSOC_REQ_DISABLE_EHT;
10998
ee2aca34 10999 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK])
f62fab73
JB
11000 memcpy(&req.vht_capa_mask,
11001 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]),
11002 sizeof(req.vht_capa_mask));
ee2aca34
JB
11003
11004 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY]) {
f62fab73 11005 if (!info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK])
ee2aca34 11006 return -EINVAL;
f62fab73
JB
11007 memcpy(&req.vht_capa,
11008 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]),
11009 sizeof(req.vht_capa));
ee2aca34
JB
11010 }
11011
bab5ab7d 11012 if (nla_get_flag(info->attrs[NL80211_ATTR_USE_RRM])) {
0c9ca11b
BL
11013 if (!((rdev->wiphy.features &
11014 NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES) &&
11015 (rdev->wiphy.features & NL80211_FEATURE_QUIET)) &&
11016 !wiphy_ext_feature_isset(&rdev->wiphy,
11017 NL80211_EXT_FEATURE_RRM))
bab5ab7d
AK
11018 return -EINVAL;
11019 req.flags |= ASSOC_REQ_USE_RRM;
11020 }
11021
348bd456
JM
11022 if (info->attrs[NL80211_ATTR_FILS_KEK]) {
11023 req.fils_kek = nla_data(info->attrs[NL80211_ATTR_FILS_KEK]);
11024 req.fils_kek_len = nla_len(info->attrs[NL80211_ATTR_FILS_KEK]);
11025 if (!info->attrs[NL80211_ATTR_FILS_NONCES])
11026 return -EINVAL;
11027 req.fils_nonces =
11028 nla_data(info->attrs[NL80211_ATTR_FILS_NONCES]);
11029 }
11030
d2b7588a
TP
11031 if (info->attrs[NL80211_ATTR_S1G_CAPABILITY_MASK]) {
11032 if (!info->attrs[NL80211_ATTR_S1G_CAPABILITY])
11033 return -EINVAL;
11034 memcpy(&req.s1g_capa_mask,
11035 nla_data(info->attrs[NL80211_ATTR_S1G_CAPABILITY_MASK]),
11036 sizeof(req.s1g_capa_mask));
11037 }
11038
11039 if (info->attrs[NL80211_ATTR_S1G_CAPABILITY]) {
11040 if (!info->attrs[NL80211_ATTR_S1G_CAPABILITY_MASK])
11041 return -EINVAL;
11042 memcpy(&req.s1g_capa,
11043 nla_data(info->attrs[NL80211_ATTR_S1G_CAPABILITY]),
11044 sizeof(req.s1g_capa));
11045 }
11046
2518e89d
JB
11047 if (nla_get_flag(info->attrs[NL80211_ATTR_ASSOC_SPP_AMSDU])) {
11048 if (!wiphy_ext_feature_isset(&rdev->wiphy,
11049 NL80211_EXT_FEATURE_SPP_AMSDU_SUPPORT)) {
11050 GENL_SET_ERR_MSG(info, "SPP A-MSDUs not supported");
11051 return -EINVAL;
11052 }
11053 req.flags |= ASSOC_REQ_SPP_AMSDU;
11054 }
11055
d648c230
JB
11056 req.link_id = nl80211_link_id_or_invalid(info->attrs);
11057
11058 if (info->attrs[NL80211_ATTR_MLO_LINKS]) {
11059 unsigned int attrsize = NUM_NL80211_ATTR * sizeof(*attrs);
11060 struct nlattr *link;
11061 int rem = 0;
11062
11063 if (req.link_id < 0)
11064 return -EINVAL;
11065
11066 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_MLO))
11067 return -EINVAL;
11068
11069 if (info->attrs[NL80211_ATTR_MAC] ||
11070 info->attrs[NL80211_ATTR_WIPHY_FREQ] ||
11071 !info->attrs[NL80211_ATTR_MLD_ADDR])
11072 return -EINVAL;
11073
11074 req.ap_mld_addr = nla_data(info->attrs[NL80211_ATTR_MLD_ADDR]);
96c06950 11075 ap_addr = req.ap_mld_addr;
d648c230
JB
11076
11077 attrs = kzalloc(attrsize, GFP_KERNEL);
11078 if (!attrs)
11079 return -ENOMEM;
11080
11081 nla_for_each_nested(link,
11082 info->attrs[NL80211_ATTR_MLO_LINKS],
11083 rem) {
11084 memset(attrs, 0, attrsize);
11085
11086 nla_parse_nested(attrs, NL80211_ATTR_MAX,
11087 link, NULL, NULL);
11088
11089 if (!attrs[NL80211_ATTR_MLO_LINK_ID]) {
11090 err = -EINVAL;
a7b2cc59 11091 NL_SET_BAD_ATTR(info->extack, link);
d648c230
JB
11092 goto free;
11093 }
11094
11095 link_id = nla_get_u8(attrs[NL80211_ATTR_MLO_LINK_ID]);
11096 /* cannot use the same link ID again */
11097 if (req.links[link_id].bss) {
11098 err = -EINVAL;
a7b2cc59 11099 NL_SET_BAD_ATTR(info->extack, link);
d648c230
JB
11100 goto free;
11101 }
11102 req.links[link_id].bss =
d02a12b8
JB
11103 nl80211_assoc_bss(rdev, ssid, ssid_len, attrs,
11104 req.link_id, link_id);
d648c230
JB
11105 if (IS_ERR(req.links[link_id].bss)) {
11106 err = PTR_ERR(req.links[link_id].bss);
9b6bf4d6 11107 req.links[link_id].bss = NULL;
a7b2cc59
BB
11108 NL_SET_ERR_MSG_ATTR(info->extack,
11109 link, "Error fetching BSS for link");
d648c230
JB
11110 goto free;
11111 }
11112
11113 if (attrs[NL80211_ATTR_IE]) {
11114 req.links[link_id].elems =
11115 nla_data(attrs[NL80211_ATTR_IE]);
11116 req.links[link_id].elems_len =
11117 nla_len(attrs[NL80211_ATTR_IE]);
df35f316
JB
11118
11119 if (cfg80211_find_elem(WLAN_EID_FRAGMENT,
11120 req.links[link_id].elems,
11121 req.links[link_id].elems_len)) {
a7b2cc59
BB
11122 NL_SET_ERR_MSG_ATTR(info->extack,
11123 attrs[NL80211_ATTR_IE],
11124 "cannot deal with fragmentation");
df35f316
JB
11125 err = -EINVAL;
11126 goto free;
11127 }
11128
11129 if (cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE,
11130 req.links[link_id].elems,
11131 req.links[link_id].elems_len)) {
a7b2cc59
BB
11132 NL_SET_ERR_MSG_ATTR(info->extack,
11133 attrs[NL80211_ATTR_IE],
11134 "cannot deal with non-inheritance");
df35f316
JB
11135 err = -EINVAL;
11136 goto free;
11137 }
d648c230 11138 }
6cf963ed
IP
11139
11140 req.links[link_id].disabled =
11141 nla_get_flag(attrs[NL80211_ATTR_MLO_LINK_DISABLED]);
d648c230
JB
11142 }
11143
11144 if (!req.links[req.link_id].bss) {
11145 err = -EINVAL;
11146 goto free;
11147 }
11148
34d76a14
JB
11149 if (req.links[req.link_id].elems_len) {
11150 GENL_SET_ERR_MSG(info,
11151 "cannot have per-link elems on assoc link");
11152 err = -EINVAL;
11153 goto free;
11154 }
11155
6cf963ed
IP
11156 if (req.links[req.link_id].disabled) {
11157 GENL_SET_ERR_MSG(info,
11158 "cannot have assoc link disabled");
11159 err = -EINVAL;
11160 goto free;
11161 }
11162
d648c230
JB
11163 kfree(attrs);
11164 attrs = NULL;
11165 } else {
11166 if (req.link_id >= 0)
11167 return -EINVAL;
11168
d02a12b8
JB
11169 req.bss = nl80211_assoc_bss(rdev, ssid, ssid_len, info->attrs,
11170 -1, -1);
d648c230
JB
11171 if (IS_ERR(req.bss))
11172 return PTR_ERR(req.bss);
96c06950 11173 ap_addr = req.bss->bssid;
d648c230 11174 }
0f759448 11175
f62fab73 11176 err = nl80211_crypto_settings(rdev, info, &req.crypto, 1);
91bf9b26 11177 if (!err) {
a7b2cc59
BB
11178 struct nlattr *link;
11179 int rem = 0;
11180
ccb964b4
JB
11181 err = cfg80211_mlme_assoc(rdev, dev, &req,
11182 info->extack);
bd2522b1
AZ
11183
11184 if (!err && info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
11185 dev->ieee80211_ptr->conn_owner_nlportid =
11186 info->snd_portid;
11187 memcpy(dev->ieee80211_ptr->disconnect_bssid,
96c06950 11188 ap_addr, ETH_ALEN);
bd2522b1 11189 }
a7b2cc59
BB
11190
11191 /* Report error from first problematic link */
11192 if (info->attrs[NL80211_ATTR_MLO_LINKS]) {
11193 nla_for_each_nested(link,
11194 info->attrs[NL80211_ATTR_MLO_LINKS],
11195 rem) {
11196 struct nlattr *link_id_attr =
11197 nla_find_nested(link, NL80211_ATTR_MLO_LINK_ID);
11198
11199 if (!link_id_attr)
11200 continue;
11201
11202 link_id = nla_get_u8(link_id_attr);
11203
11204 if (link_id == req.link_id)
11205 continue;
11206
11207 if (!req.links[link_id].error ||
11208 WARN_ON(req.links[link_id].error > 0))
11209 continue;
11210
11211 WARN_ON(err >= 0);
11212
11213 NL_SET_BAD_ATTR(info->extack, link);
11214 err = req.links[link_id].error;
11215 break;
11216 }
11217 }
91bf9b26 11218 }
636a5d36 11219
d648c230
JB
11220free:
11221 for (link_id = 0; link_id < ARRAY_SIZE(req.links); link_id++)
11222 cfg80211_put_bss(&rdev->wiphy, req.links[link_id].bss);
0f759448 11223 cfg80211_put_bss(&rdev->wiphy, req.bss);
d648c230 11224 kfree(attrs);
0f759448 11225
636a5d36
JM
11226 return err;
11227}
11228
11229static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info)
11230{
4c476991
JB
11231 struct cfg80211_registered_device *rdev = info->user_ptr[0];
11232 struct net_device *dev = info->user_ptr[1];
19957bb3 11233 const u8 *ie = NULL, *bssid;
076fc877 11234 int ie_len = 0;
19957bb3 11235 u16 reason_code;
d5cdfacb 11236 bool local_state_change;
636a5d36 11237
bad29297
AZ
11238 if (dev->ieee80211_ptr->conn_owner_nlportid &&
11239 dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)
11240 return -EPERM;
11241
f4a11bb0
JB
11242 if (!info->attrs[NL80211_ATTR_MAC])
11243 return -EINVAL;
11244
11245 if (!info->attrs[NL80211_ATTR_REASON_CODE])
11246 return -EINVAL;
11247
4c476991
JB
11248 if (!rdev->ops->deauth)
11249 return -EOPNOTSUPP;
636a5d36 11250
074ac8df 11251 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
11252 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
11253 return -EOPNOTSUPP;
eec60b03 11254
19957bb3 11255 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
636a5d36 11256
19957bb3
JB
11257 reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
11258 if (reason_code == 0) {
f4a11bb0 11259 /* Reason Code 0 is reserved */
4c476991 11260 return -EINVAL;
255e737e 11261 }
636a5d36
JM
11262
11263 if (info->attrs[NL80211_ATTR_IE]) {
19957bb3
JB
11264 ie = nla_data(info->attrs[NL80211_ATTR_IE]);
11265 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
636a5d36
JM
11266 }
11267
d5cdfacb
JM
11268 local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
11269
076fc877
JB
11270 return cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code,
11271 local_state_change);
636a5d36
JM
11272}
11273
11274static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info)
11275{
4c476991
JB
11276 struct cfg80211_registered_device *rdev = info->user_ptr[0];
11277 struct net_device *dev = info->user_ptr[1];
19957bb3 11278 const u8 *ie = NULL, *bssid;
076fc877 11279 int ie_len = 0;
19957bb3 11280 u16 reason_code;
d5cdfacb 11281 bool local_state_change;
636a5d36 11282
bad29297
AZ
11283 if (dev->ieee80211_ptr->conn_owner_nlportid &&
11284 dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)
11285 return -EPERM;
11286
f4a11bb0
JB
11287 if (!info->attrs[NL80211_ATTR_MAC])
11288 return -EINVAL;
11289
11290 if (!info->attrs[NL80211_ATTR_REASON_CODE])
11291 return -EINVAL;
11292
4c476991
JB
11293 if (!rdev->ops->disassoc)
11294 return -EOPNOTSUPP;
636a5d36 11295
074ac8df 11296 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
11297 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
11298 return -EOPNOTSUPP;
eec60b03 11299
19957bb3 11300 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
636a5d36 11301
19957bb3
JB
11302 reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
11303 if (reason_code == 0) {
f4a11bb0 11304 /* Reason Code 0 is reserved */
4c476991 11305 return -EINVAL;
255e737e 11306 }
636a5d36
JM
11307
11308 if (info->attrs[NL80211_ATTR_IE]) {
19957bb3
JB
11309 ie = nla_data(info->attrs[NL80211_ATTR_IE]);
11310 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
636a5d36
JM
11311 }
11312
d5cdfacb
JM
11313 local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
11314
076fc877
JB
11315 return cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code,
11316 local_state_change);
636a5d36
JM
11317}
11318
dd5b4cc7
FF
11319static bool
11320nl80211_parse_mcast_rate(struct cfg80211_registered_device *rdev,
57fbcce3 11321 int mcast_rate[NUM_NL80211_BANDS],
dd5b4cc7
FF
11322 int rateval)
11323{
11324 struct wiphy *wiphy = &rdev->wiphy;
11325 bool found = false;
11326 int band, i;
11327
57fbcce3 11328 for (band = 0; band < NUM_NL80211_BANDS; band++) {
dd5b4cc7
FF
11329 struct ieee80211_supported_band *sband;
11330
11331 sband = wiphy->bands[band];
11332 if (!sband)
11333 continue;
11334
11335 for (i = 0; i < sband->n_bitrates; i++) {
11336 if (sband->bitrates[i].bitrate == rateval) {
11337 mcast_rate[band] = i + 1;
11338 found = true;
11339 break;
11340 }
11341 }
11342 }
11343
11344 return found;
11345}
11346
04a773ad
JB
11347static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
11348{
4c476991
JB
11349 struct cfg80211_registered_device *rdev = info->user_ptr[0];
11350 struct net_device *dev = info->user_ptr[1];
04a773ad
JB
11351 struct cfg80211_ibss_params ibss;
11352 struct wiphy *wiphy;
fffd0934 11353 struct cfg80211_cached_keys *connkeys = NULL;
04a773ad
JB
11354 int err;
11355
8e30bc55
JB
11356 memset(&ibss, 0, sizeof(ibss));
11357
683b6d3b 11358 if (!info->attrs[NL80211_ATTR_SSID] ||
04a773ad
JB
11359 !nla_len(info->attrs[NL80211_ATTR_SSID]))
11360 return -EINVAL;
11361
8e30bc55
JB
11362 ibss.beacon_interval = 100;
11363
12d20fc9 11364 if (info->attrs[NL80211_ATTR_BEACON_INTERVAL])
8e30bc55
JB
11365 ibss.beacon_interval =
11366 nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
12d20fc9 11367
0c317a02
PK
11368 err = cfg80211_validate_beacon_int(rdev, NL80211_IFTYPE_ADHOC,
11369 ibss.beacon_interval);
12d20fc9
PK
11370 if (err)
11371 return err;
8e30bc55 11372
4c476991
JB
11373 if (!rdev->ops->join_ibss)
11374 return -EOPNOTSUPP;
04a773ad 11375
4c476991
JB
11376 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC)
11377 return -EOPNOTSUPP;
04a773ad 11378
79c97e97 11379 wiphy = &rdev->wiphy;
04a773ad 11380
39193498 11381 if (info->attrs[NL80211_ATTR_MAC]) {
04a773ad 11382 ibss.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
39193498
JB
11383
11384 if (!is_valid_ether_addr(ibss.bssid))
11385 return -EINVAL;
11386 }
04a773ad
JB
11387 ibss.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
11388 ibss.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
11389
11390 if (info->attrs[NL80211_ATTR_IE]) {
11391 ibss.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
11392 ibss.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
11393 }
11394
683b6d3b
JB
11395 err = nl80211_parse_chandef(rdev, info, &ibss.chandef);
11396 if (err)
11397 return err;
04a773ad 11398
174e0cd2
IP
11399 if (!cfg80211_reg_can_beacon(&rdev->wiphy, &ibss.chandef,
11400 NL80211_IFTYPE_ADHOC))
54858ee5
AS
11401 return -EINVAL;
11402
2f301ab2 11403 switch (ibss.chandef.width) {
bf372645
SW
11404 case NL80211_CHAN_WIDTH_5:
11405 case NL80211_CHAN_WIDTH_10:
2f301ab2
SW
11406 case NL80211_CHAN_WIDTH_20_NOHT:
11407 break;
11408 case NL80211_CHAN_WIDTH_20:
11409 case NL80211_CHAN_WIDTH_40:
ffc11991
JD
11410 if (!(rdev->wiphy.features & NL80211_FEATURE_HT_IBSS))
11411 return -EINVAL;
11412 break;
11413 case NL80211_CHAN_WIDTH_80:
11414 case NL80211_CHAN_WIDTH_80P80:
11415 case NL80211_CHAN_WIDTH_160:
11416 if (!(rdev->wiphy.features & NL80211_FEATURE_HT_IBSS))
11417 return -EINVAL;
11418 if (!wiphy_ext_feature_isset(&rdev->wiphy,
11419 NL80211_EXT_FEATURE_VHT_IBSS))
11420 return -EINVAL;
11421 break;
3743bec6
JD
11422 case NL80211_CHAN_WIDTH_320:
11423 return -EINVAL;
2f301ab2 11424 default:
c04d6150 11425 return -EINVAL;
2f301ab2 11426 }
db9c64cf 11427
04a773ad 11428 ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED];
fffd0934
JB
11429 ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY];
11430
fbd2c8dc
TP
11431 if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) {
11432 u8 *rates =
11433 nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
11434 int n_rates =
11435 nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
11436 struct ieee80211_supported_band *sband =
683b6d3b 11437 wiphy->bands[ibss.chandef.chan->band];
fbd2c8dc 11438
34850ab2
JB
11439 err = ieee80211_get_ratemask(sband, rates, n_rates,
11440 &ibss.basic_rates);
11441 if (err)
11442 return err;
fbd2c8dc 11443 }
dd5b4cc7 11444
803768f5
SW
11445 if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
11446 memcpy(&ibss.ht_capa_mask,
11447 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]),
11448 sizeof(ibss.ht_capa_mask));
11449
11450 if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
11451 if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
11452 return -EINVAL;
11453 memcpy(&ibss.ht_capa,
11454 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]),
11455 sizeof(ibss.ht_capa));
11456 }
11457
dd5b4cc7
FF
11458 if (info->attrs[NL80211_ATTR_MCAST_RATE] &&
11459 !nl80211_parse_mcast_rate(rdev, ibss.mcast_rate,
11460 nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE])))
11461 return -EINVAL;
fbd2c8dc 11462
4c476991 11463 if (ibss.privacy && info->attrs[NL80211_ATTR_KEYS]) {
de7044ee
SM
11464 bool no_ht = false;
11465
768075eb 11466 connkeys = nl80211_parse_connkeys(rdev, info, &no_ht);
4c476991
JB
11467 if (IS_ERR(connkeys))
11468 return PTR_ERR(connkeys);
de7044ee 11469
3d9d1d66
JB
11470 if ((ibss.chandef.width != NL80211_CHAN_WIDTH_20_NOHT) &&
11471 no_ht) {
453431a5 11472 kfree_sensitive(connkeys);
de7044ee
SM
11473 return -EINVAL;
11474 }
4c476991 11475 }
04a773ad 11476
267335d6
AQ
11477 ibss.control_port =
11478 nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT]);
11479
c3bfe1f6
DK
11480 if (info->attrs[NL80211_ATTR_CONTROL_PORT_OVER_NL80211]) {
11481 int r = validate_pae_over_nl80211(rdev, info);
11482
d350a0f4 11483 if (r < 0) {
453431a5 11484 kfree_sensitive(connkeys);
c3bfe1f6 11485 return r;
d350a0f4 11486 }
c3bfe1f6
DK
11487
11488 ibss.control_port_over_nl80211 = true;
11489 }
11490
5336fa88
SW
11491 ibss.userspace_handles_dfs =
11492 nla_get_flag(info->attrs[NL80211_ATTR_HANDLE_DFS]);
11493
f8d16d3e 11494 err = __cfg80211_join_ibss(rdev, dev, &ibss, connkeys);
fffd0934 11495 if (err)
453431a5 11496 kfree_sensitive(connkeys);
f8d16d3e
DK
11497 else if (info->attrs[NL80211_ATTR_SOCKET_OWNER])
11498 dev->ieee80211_ptr->conn_owner_nlportid = info->snd_portid;
f8d16d3e 11499
04a773ad
JB
11500 return err;
11501}
11502
11503static int nl80211_leave_ibss(struct sk_buff *skb, struct genl_info *info)
11504{
4c476991
JB
11505 struct cfg80211_registered_device *rdev = info->user_ptr[0];
11506 struct net_device *dev = info->user_ptr[1];
04a773ad 11507
4c476991
JB
11508 if (!rdev->ops->leave_ibss)
11509 return -EOPNOTSUPP;
04a773ad 11510
4c476991
JB
11511 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC)
11512 return -EOPNOTSUPP;
04a773ad 11513
4c476991 11514 return cfg80211_leave_ibss(rdev, dev, false);
04a773ad
JB
11515}
11516
f4e583c8
AQ
11517static int nl80211_set_mcast_rate(struct sk_buff *skb, struct genl_info *info)
11518{
11519 struct cfg80211_registered_device *rdev = info->user_ptr[0];
11520 struct net_device *dev = info->user_ptr[1];
57fbcce3 11521 int mcast_rate[NUM_NL80211_BANDS];
f4e583c8 11522 u32 nla_rate;
f4e583c8
AQ
11523
11524 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC &&
876dc930
BVB
11525 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT &&
11526 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_OCB)
f4e583c8
AQ
11527 return -EOPNOTSUPP;
11528
11529 if (!rdev->ops->set_mcast_rate)
11530 return -EOPNOTSUPP;
11531
11532 memset(mcast_rate, 0, sizeof(mcast_rate));
11533
11534 if (!info->attrs[NL80211_ATTR_MCAST_RATE])
11535 return -EINVAL;
11536
11537 nla_rate = nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE]);
11538 if (!nl80211_parse_mcast_rate(rdev, mcast_rate, nla_rate))
11539 return -EINVAL;
11540
a21cd7d6 11541 return rdev_set_mcast_rate(rdev, dev, mcast_rate);
f4e583c8
AQ
11542}
11543
ad7e718c
JB
11544static struct sk_buff *
11545__cfg80211_alloc_vendor_skb(struct cfg80211_registered_device *rdev,
6c09e791
AK
11546 struct wireless_dev *wdev, int approxlen,
11547 u32 portid, u32 seq, enum nl80211_commands cmd,
567ffc35
JB
11548 enum nl80211_attrs attr,
11549 const struct nl80211_vendor_cmd_info *info,
11550 gfp_t gfp)
ad7e718c
JB
11551{
11552 struct sk_buff *skb;
11553 void *hdr;
11554 struct nlattr *data;
11555
11556 skb = nlmsg_new(approxlen + 100, gfp);
11557 if (!skb)
11558 return NULL;
11559
11560 hdr = nl80211hdr_put(skb, portid, seq, 0, cmd);
11561 if (!hdr) {
11562 kfree_skb(skb);
11563 return NULL;
11564 }
11565
11566 if (nla_put_u32(skb, NL80211_ATTR_WIPHY, rdev->wiphy_idx))
11567 goto nla_put_failure;
567ffc35
JB
11568
11569 if (info) {
11570 if (nla_put_u32(skb, NL80211_ATTR_VENDOR_ID,
11571 info->vendor_id))
11572 goto nla_put_failure;
11573 if (nla_put_u32(skb, NL80211_ATTR_VENDOR_SUBCMD,
11574 info->subcmd))
11575 goto nla_put_failure;
11576 }
11577
6c09e791 11578 if (wdev) {
2dad624e
ND
11579 if (nla_put_u64_64bit(skb, NL80211_ATTR_WDEV,
11580 wdev_id(wdev), NL80211_ATTR_PAD))
6c09e791
AK
11581 goto nla_put_failure;
11582 if (wdev->netdev &&
11583 nla_put_u32(skb, NL80211_ATTR_IFINDEX,
11584 wdev->netdev->ifindex))
11585 goto nla_put_failure;
11586 }
11587
ae0be8de 11588 data = nla_nest_start_noflag(skb, attr);
76e1fb4b
JB
11589 if (!data)
11590 goto nla_put_failure;
ad7e718c
JB
11591
11592 ((void **)skb->cb)[0] = rdev;
11593 ((void **)skb->cb)[1] = hdr;
11594 ((void **)skb->cb)[2] = data;
11595
11596 return skb;
11597
11598 nla_put_failure:
11599 kfree_skb(skb);
11600 return NULL;
11601}
f4e583c8 11602
e03ad6ea 11603struct sk_buff *__cfg80211_alloc_event_skb(struct wiphy *wiphy,
6c09e791 11604 struct wireless_dev *wdev,
e03ad6ea
JB
11605 enum nl80211_commands cmd,
11606 enum nl80211_attrs attr,
55c1fdf0 11607 unsigned int portid,
e03ad6ea
JB
11608 int vendor_event_idx,
11609 int approxlen, gfp_t gfp)
11610{
f26cbf40 11611 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
e03ad6ea
JB
11612 const struct nl80211_vendor_cmd_info *info;
11613
11614 switch (cmd) {
11615 case NL80211_CMD_TESTMODE:
11616 if (WARN_ON(vendor_event_idx != -1))
11617 return NULL;
11618 info = NULL;
11619 break;
11620 case NL80211_CMD_VENDOR:
11621 if (WARN_ON(vendor_event_idx < 0 ||
11622 vendor_event_idx >= wiphy->n_vendor_events))
11623 return NULL;
11624 info = &wiphy->vendor_events[vendor_event_idx];
11625 break;
11626 default:
11627 WARN_ON(1);
11628 return NULL;
11629 }
11630
55c1fdf0 11631 return __cfg80211_alloc_vendor_skb(rdev, wdev, approxlen, portid, 0,
e03ad6ea
JB
11632 cmd, attr, info, gfp);
11633}
11634EXPORT_SYMBOL(__cfg80211_alloc_event_skb);
11635
11636void __cfg80211_send_event_skb(struct sk_buff *skb, gfp_t gfp)
11637{
11638 struct cfg80211_registered_device *rdev = ((void **)skb->cb)[0];
11639 void *hdr = ((void **)skb->cb)[1];
55c1fdf0 11640 struct nlmsghdr *nlhdr = nlmsg_hdr(skb);
e03ad6ea
JB
11641 struct nlattr *data = ((void **)skb->cb)[2];
11642 enum nl80211_multicast_groups mcgrp = NL80211_MCGRP_TESTMODE;
11643
bd8c78e7
JB
11644 /* clear CB data for netlink core to own from now on */
11645 memset(skb->cb, 0, sizeof(skb->cb));
11646
e03ad6ea
JB
11647 nla_nest_end(skb, data);
11648 genlmsg_end(skb, hdr);
11649
55c1fdf0
JB
11650 if (nlhdr->nlmsg_pid) {
11651 genlmsg_unicast(wiphy_net(&rdev->wiphy), skb,
11652 nlhdr->nlmsg_pid);
11653 } else {
11654 if (data->nla_type == NL80211_ATTR_VENDOR_DATA)
11655 mcgrp = NL80211_MCGRP_VENDOR;
e03ad6ea 11656
55c1fdf0
JB
11657 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
11658 skb, 0, mcgrp, gfp);
11659 }
e03ad6ea
JB
11660}
11661EXPORT_SYMBOL(__cfg80211_send_event_skb);
11662
aff89a9b 11663#ifdef CONFIG_NL80211_TESTMODE
aff89a9b
JB
11664static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info)
11665{
4c476991 11666 struct cfg80211_registered_device *rdev = info->user_ptr[0];
a05829a7 11667 struct wireless_dev *wdev;
aff89a9b
JB
11668 int err;
11669
a05829a7
JB
11670 lockdep_assert_held(&rdev->wiphy.mtx);
11671
11672 wdev = __cfg80211_wdev_from_attrs(rdev, genl_info_net(info),
11673 info->attrs);
11674
fc73f11f
DS
11675 if (!rdev->ops->testmode_cmd)
11676 return -EOPNOTSUPP;
11677
11678 if (IS_ERR(wdev)) {
11679 err = PTR_ERR(wdev);
11680 if (err != -EINVAL)
11681 return err;
11682 wdev = NULL;
11683 } else if (wdev->wiphy != &rdev->wiphy) {
11684 return -EINVAL;
11685 }
11686
aff89a9b
JB
11687 if (!info->attrs[NL80211_ATTR_TESTDATA])
11688 return -EINVAL;
11689
ad7e718c 11690 rdev->cur_cmd_info = info;
fc73f11f 11691 err = rdev_testmode_cmd(rdev, wdev,
aff89a9b
JB
11692 nla_data(info->attrs[NL80211_ATTR_TESTDATA]),
11693 nla_len(info->attrs[NL80211_ATTR_TESTDATA]));
ad7e718c 11694 rdev->cur_cmd_info = NULL;
aff89a9b 11695
aff89a9b
JB
11696 return err;
11697}
11698
71063f0e
WYG
11699static int nl80211_testmode_dump(struct sk_buff *skb,
11700 struct netlink_callback *cb)
11701{
00918d33 11702 struct cfg80211_registered_device *rdev;
50508d94 11703 struct nlattr **attrbuf = NULL;
71063f0e
WYG
11704 int err;
11705 long phy_idx;
11706 void *data = NULL;
11707 int data_len = 0;
11708
5fe231e8
JB
11709 rtnl_lock();
11710
71063f0e
WYG
11711 if (cb->args[0]) {
11712 /*
11713 * 0 is a valid index, but not valid for args[0],
11714 * so we need to offset by 1.
11715 */
11716 phy_idx = cb->args[0] - 1;
a4956dca
LC
11717
11718 rdev = cfg80211_rdev_by_wiphy_idx(phy_idx);
11719 if (!rdev) {
11720 err = -ENOENT;
11721 goto out_err;
11722 }
71063f0e 11723 } else {
50508d94
JB
11724 attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf),
11725 GFP_KERNEL);
11726 if (!attrbuf) {
11727 err = -ENOMEM;
11728 goto out_err;
11729 }
c90c39da 11730
8cb08174
JB
11731 err = nlmsg_parse_deprecated(cb->nlh,
11732 GENL_HDRLEN + nl80211_fam.hdrsize,
11733 attrbuf, nl80211_fam.maxattr,
11734 nl80211_policy, NULL);
71063f0e 11735 if (err)
5fe231e8 11736 goto out_err;
00918d33 11737
c90c39da 11738 rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk), attrbuf);
2bd7e35d 11739 if (IS_ERR(rdev)) {
5fe231e8
JB
11740 err = PTR_ERR(rdev);
11741 goto out_err;
00918d33 11742 }
2bd7e35d 11743 phy_idx = rdev->wiphy_idx;
2bd7e35d 11744
c90c39da
JB
11745 if (attrbuf[NL80211_ATTR_TESTDATA])
11746 cb->args[1] = (long)attrbuf[NL80211_ATTR_TESTDATA];
71063f0e
WYG
11747 }
11748
11749 if (cb->args[1]) {
11750 data = nla_data((void *)cb->args[1]);
11751 data_len = nla_len((void *)cb->args[1]);
11752 }
11753
00918d33 11754 if (!rdev->ops->testmode_dump) {
71063f0e
WYG
11755 err = -EOPNOTSUPP;
11756 goto out_err;
11757 }
11758
11759 while (1) {
15e47304 11760 void *hdr = nl80211hdr_put(skb, NETLINK_CB(cb->skb).portid,
71063f0e
WYG
11761 cb->nlh->nlmsg_seq, NLM_F_MULTI,
11762 NL80211_CMD_TESTMODE);
11763 struct nlattr *tmdata;
11764
cb35fba3
DC
11765 if (!hdr)
11766 break;
11767
9360ffd1 11768 if (nla_put_u32(skb, NL80211_ATTR_WIPHY, phy_idx)) {
71063f0e
WYG
11769 genlmsg_cancel(skb, hdr);
11770 break;
11771 }
11772
ae0be8de 11773 tmdata = nla_nest_start_noflag(skb, NL80211_ATTR_TESTDATA);
71063f0e
WYG
11774 if (!tmdata) {
11775 genlmsg_cancel(skb, hdr);
11776 break;
11777 }
e35e4d28 11778 err = rdev_testmode_dump(rdev, skb, cb, data, data_len);
71063f0e
WYG
11779 nla_nest_end(skb, tmdata);
11780
11781 if (err == -ENOBUFS || err == -ENOENT) {
11782 genlmsg_cancel(skb, hdr);
11783 break;
11784 } else if (err) {
11785 genlmsg_cancel(skb, hdr);
11786 goto out_err;
11787 }
11788
11789 genlmsg_end(skb, hdr);
11790 }
11791
11792 err = skb->len;
11793 /* see above */
11794 cb->args[0] = phy_idx + 1;
11795 out_err:
50508d94 11796 kfree(attrbuf);
5fe231e8 11797 rtnl_unlock();
71063f0e
WYG
11798 return err;
11799}
aff89a9b
JB
11800#endif
11801
b23aa676
SO
11802static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
11803{
4c476991
JB
11804 struct cfg80211_registered_device *rdev = info->user_ptr[0];
11805 struct net_device *dev = info->user_ptr[1];
b23aa676
SO
11806 struct cfg80211_connect_params connect;
11807 struct wiphy *wiphy;
fffd0934 11808 struct cfg80211_cached_keys *connkeys = NULL;
942ba88b 11809 u32 freq = 0;
b23aa676
SO
11810 int err;
11811
11812 memset(&connect, 0, sizeof(connect));
11813
b23aa676
SO
11814 if (!info->attrs[NL80211_ATTR_SSID] ||
11815 !nla_len(info->attrs[NL80211_ATTR_SSID]))
11816 return -EINVAL;
11817
11818 if (info->attrs[NL80211_ATTR_AUTH_TYPE]) {
11819 connect.auth_type =
11820 nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
e39e5b5e
JM
11821 if (!nl80211_valid_auth_type(rdev, connect.auth_type,
11822 NL80211_CMD_CONNECT))
b23aa676
SO
11823 return -EINVAL;
11824 } else
11825 connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
11826
11827 connect.privacy = info->attrs[NL80211_ATTR_PRIVACY];
11828
3a00df57
AS
11829 if (info->attrs[NL80211_ATTR_WANT_1X_4WAY_HS] &&
11830 !wiphy_ext_feature_isset(&rdev->wiphy,
11831 NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X))
11832 return -EINVAL;
11833 connect.want_1x = info->attrs[NL80211_ATTR_WANT_1X_4WAY_HS];
11834
c0692b8f 11835 err = nl80211_crypto_settings(rdev, info, &connect.crypto,
3dc27d25 11836 NL80211_MAX_NR_CIPHER_SUITES);
b23aa676
SO
11837 if (err)
11838 return err;
b23aa676 11839
074ac8df 11840 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
11841 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
11842 return -EOPNOTSUPP;
b23aa676 11843
79c97e97 11844 wiphy = &rdev->wiphy;
b23aa676 11845
4486ea98
BS
11846 connect.bg_scan_period = -1;
11847 if (info->attrs[NL80211_ATTR_BG_SCAN_PERIOD] &&
11848 (wiphy->flags & WIPHY_FLAG_SUPPORTS_FW_ROAM)) {
11849 connect.bg_scan_period =
11850 nla_get_u16(info->attrs[NL80211_ATTR_BG_SCAN_PERIOD]);
11851 }
11852
b23aa676
SO
11853 if (info->attrs[NL80211_ATTR_MAC])
11854 connect.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
1df4a510
JM
11855 else if (info->attrs[NL80211_ATTR_MAC_HINT])
11856 connect.bssid_hint =
11857 nla_data(info->attrs[NL80211_ATTR_MAC_HINT]);
b23aa676
SO
11858 connect.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
11859 connect.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
11860
11861 if (info->attrs[NL80211_ATTR_IE]) {
11862 connect.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
11863 connect.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
11864 }
11865
cee00a95
JM
11866 if (info->attrs[NL80211_ATTR_USE_MFP]) {
11867 connect.mfp = nla_get_u32(info->attrs[NL80211_ATTR_USE_MFP]);
65026002
EG
11868 if (connect.mfp == NL80211_MFP_OPTIONAL &&
11869 !wiphy_ext_feature_isset(&rdev->wiphy,
11870 NL80211_EXT_FEATURE_MFP_OPTIONAL))
11871 return -EOPNOTSUPP;
cee00a95
JM
11872 } else {
11873 connect.mfp = NL80211_MFP_NO;
11874 }
11875
ba6fbacf
JM
11876 if (info->attrs[NL80211_ATTR_PREV_BSSID])
11877 connect.prev_bssid =
11878 nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]);
11879
942ba88b
TP
11880 if (info->attrs[NL80211_ATTR_WIPHY_FREQ])
11881 freq = MHZ_TO_KHZ(nla_get_u32(
11882 info->attrs[NL80211_ATTR_WIPHY_FREQ]));
11883 if (info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET])
11884 freq +=
11885 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET]);
11886
11887 if (freq) {
11888 connect.channel = nl80211_get_valid_chan(wiphy, freq);
664834de 11889 if (!connect.channel)
1df4a510
JM
11890 return -EINVAL;
11891 } else if (info->attrs[NL80211_ATTR_WIPHY_FREQ_HINT]) {
942ba88b
TP
11892 freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ_HINT]);
11893 freq = MHZ_TO_KHZ(freq);
11894 connect.channel_hint = nl80211_get_valid_chan(wiphy, freq);
664834de 11895 if (!connect.channel_hint)
4c476991 11896 return -EINVAL;
b23aa676
SO
11897 }
11898
2a38075c
AAL
11899 if (info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]) {
11900 connect.edmg.channels =
11901 nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]);
11902
11903 if (info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG])
11904 connect.edmg.bw_config =
11905 nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG]);
11906 }
11907
fffd0934 11908 if (connect.privacy && info->attrs[NL80211_ATTR_KEYS]) {
768075eb 11909 connkeys = nl80211_parse_connkeys(rdev, info, NULL);
4c476991
JB
11910 if (IS_ERR(connkeys))
11911 return PTR_ERR(connkeys);
fffd0934
JB
11912 }
11913
7e7c8926
BG
11914 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HT]))
11915 connect.flags |= ASSOC_REQ_DISABLE_HT;
11916
11917 if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
11918 memcpy(&connect.ht_capa_mask,
11919 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]),
11920 sizeof(connect.ht_capa_mask));
11921
11922 if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
b4e4f47e 11923 if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]) {
453431a5 11924 kfree_sensitive(connkeys);
7e7c8926 11925 return -EINVAL;
b4e4f47e 11926 }
7e7c8926
BG
11927 memcpy(&connect.ht_capa,
11928 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]),
11929 sizeof(connect.ht_capa));
11930 }
11931
ee2aca34
JB
11932 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_VHT]))
11933 connect.flags |= ASSOC_REQ_DISABLE_VHT;
11934
b6db0f89
BG
11935 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HE]))
11936 connect.flags |= ASSOC_REQ_DISABLE_HE;
11937
36f84235
MS
11938 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_EHT]))
11939 connect.flags |= ASSOC_REQ_DISABLE_EHT;
11940
ee2aca34
JB
11941 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK])
11942 memcpy(&connect.vht_capa_mask,
11943 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]),
11944 sizeof(connect.vht_capa_mask));
11945
11946 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY]) {
11947 if (!info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]) {
453431a5 11948 kfree_sensitive(connkeys);
ee2aca34
JB
11949 return -EINVAL;
11950 }
11951 memcpy(&connect.vht_capa,
11952 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]),
11953 sizeof(connect.vht_capa));
11954 }
11955
bab5ab7d 11956 if (nla_get_flag(info->attrs[NL80211_ATTR_USE_RRM])) {
0c9ca11b
BL
11957 if (!((rdev->wiphy.features &
11958 NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES) &&
11959 (rdev->wiphy.features & NL80211_FEATURE_QUIET)) &&
11960 !wiphy_ext_feature_isset(&rdev->wiphy,
11961 NL80211_EXT_FEATURE_RRM)) {
453431a5 11962 kfree_sensitive(connkeys);
bab5ab7d 11963 return -EINVAL;
707554b4 11964 }
bab5ab7d
AK
11965 connect.flags |= ASSOC_REQ_USE_RRM;
11966 }
11967
34d50519 11968 connect.pbss = nla_get_flag(info->attrs[NL80211_ATTR_PBSS]);
57fbcce3 11969 if (connect.pbss && !rdev->wiphy.bands[NL80211_BAND_60GHZ]) {
453431a5 11970 kfree_sensitive(connkeys);
34d50519
LD
11971 return -EOPNOTSUPP;
11972 }
11973
38de03d2
AS
11974 if (info->attrs[NL80211_ATTR_BSS_SELECT]) {
11975 /* bss selection makes no sense if bssid is set */
11976 if (connect.bssid) {
453431a5 11977 kfree_sensitive(connkeys);
38de03d2
AS
11978 return -EINVAL;
11979 }
11980
11981 err = parse_bss_select(info->attrs[NL80211_ATTR_BSS_SELECT],
11982 wiphy, &connect.bss_select);
11983 if (err) {
453431a5 11984 kfree_sensitive(connkeys);
38de03d2
AS
11985 return err;
11986 }
11987 }
11988
a3caf744
VK
11989 if (wiphy_ext_feature_isset(&rdev->wiphy,
11990 NL80211_EXT_FEATURE_FILS_SK_OFFLOAD) &&
11991 info->attrs[NL80211_ATTR_FILS_ERP_USERNAME] &&
11992 info->attrs[NL80211_ATTR_FILS_ERP_REALM] &&
11993 info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] &&
11994 info->attrs[NL80211_ATTR_FILS_ERP_RRK]) {
11995 connect.fils_erp_username =
11996 nla_data(info->attrs[NL80211_ATTR_FILS_ERP_USERNAME]);
11997 connect.fils_erp_username_len =
11998 nla_len(info->attrs[NL80211_ATTR_FILS_ERP_USERNAME]);
11999 connect.fils_erp_realm =
12000 nla_data(info->attrs[NL80211_ATTR_FILS_ERP_REALM]);
12001 connect.fils_erp_realm_len =
12002 nla_len(info->attrs[NL80211_ATTR_FILS_ERP_REALM]);
12003 connect.fils_erp_next_seq_num =
12004 nla_get_u16(
12005 info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM]);
12006 connect.fils_erp_rrk =
12007 nla_data(info->attrs[NL80211_ATTR_FILS_ERP_RRK]);
12008 connect.fils_erp_rrk_len =
12009 nla_len(info->attrs[NL80211_ATTR_FILS_ERP_RRK]);
12010 } else if (info->attrs[NL80211_ATTR_FILS_ERP_USERNAME] ||
12011 info->attrs[NL80211_ATTR_FILS_ERP_REALM] ||
12012 info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] ||
12013 info->attrs[NL80211_ATTR_FILS_ERP_RRK]) {
453431a5 12014 kfree_sensitive(connkeys);
a3caf744
VK
12015 return -EINVAL;
12016 }
12017
40cbfa90
SD
12018 if (nla_get_flag(info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])) {
12019 if (!info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
453431a5 12020 kfree_sensitive(connkeys);
40cbfa90
SD
12021 GENL_SET_ERR_MSG(info,
12022 "external auth requires connection ownership");
12023 return -EINVAL;
12024 }
12025 connect.flags |= CONNECT_REQ_EXTERNAL_AUTH_SUPPORT;
12026 }
12027
efbabc11
VJ
12028 if (nla_get_flag(info->attrs[NL80211_ATTR_MLO_SUPPORT]))
12029 connect.flags |= CONNECT_REQ_MLO_SUPPORT;
12030
4ce2bd9c
JM
12031 err = cfg80211_connect(rdev, dev, &connect, connkeys,
12032 connect.prev_bssid);
fffd0934 12033 if (err)
453431a5 12034 kfree_sensitive(connkeys);
bd2522b1
AZ
12035
12036 if (!err && info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
12037 dev->ieee80211_ptr->conn_owner_nlportid = info->snd_portid;
12038 if (connect.bssid)
12039 memcpy(dev->ieee80211_ptr->disconnect_bssid,
12040 connect.bssid, ETH_ALEN);
12041 else
3b1648f1 12042 eth_zero_addr(dev->ieee80211_ptr->disconnect_bssid);
bd2522b1
AZ
12043 }
12044
b23aa676
SO
12045 return err;
12046}
12047
088e8df8 12048static int nl80211_update_connect_params(struct sk_buff *skb,
12049 struct genl_info *info)
12050{
12051 struct cfg80211_connect_params connect = {};
12052 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12053 struct net_device *dev = info->user_ptr[1];
12054 struct wireless_dev *wdev = dev->ieee80211_ptr;
7f9a3e15
VK
12055 bool fils_sk_offload;
12056 u32 auth_type;
088e8df8 12057 u32 changed = 0;
088e8df8 12058
12059 if (!rdev->ops->update_connect_params)
12060 return -EOPNOTSUPP;
12061
12062 if (info->attrs[NL80211_ATTR_IE]) {
088e8df8 12063 connect.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
12064 connect.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
12065 changed |= UPDATE_ASSOC_IES;
12066 }
12067
7f9a3e15
VK
12068 fils_sk_offload = wiphy_ext_feature_isset(&rdev->wiphy,
12069 NL80211_EXT_FEATURE_FILS_SK_OFFLOAD);
12070
12071 /*
12072 * when driver supports fils-sk offload all attributes must be
12073 * provided. So the else covers "fils-sk-not-all" and
12074 * "no-fils-sk-any".
12075 */
12076 if (fils_sk_offload &&
12077 info->attrs[NL80211_ATTR_FILS_ERP_USERNAME] &&
12078 info->attrs[NL80211_ATTR_FILS_ERP_REALM] &&
12079 info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] &&
12080 info->attrs[NL80211_ATTR_FILS_ERP_RRK]) {
12081 connect.fils_erp_username =
12082 nla_data(info->attrs[NL80211_ATTR_FILS_ERP_USERNAME]);
12083 connect.fils_erp_username_len =
12084 nla_len(info->attrs[NL80211_ATTR_FILS_ERP_USERNAME]);
12085 connect.fils_erp_realm =
12086 nla_data(info->attrs[NL80211_ATTR_FILS_ERP_REALM]);
12087 connect.fils_erp_realm_len =
12088 nla_len(info->attrs[NL80211_ATTR_FILS_ERP_REALM]);
12089 connect.fils_erp_next_seq_num =
12090 nla_get_u16(
12091 info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM]);
12092 connect.fils_erp_rrk =
12093 nla_data(info->attrs[NL80211_ATTR_FILS_ERP_RRK]);
12094 connect.fils_erp_rrk_len =
12095 nla_len(info->attrs[NL80211_ATTR_FILS_ERP_RRK]);
12096 changed |= UPDATE_FILS_ERP_INFO;
12097 } else if (info->attrs[NL80211_ATTR_FILS_ERP_USERNAME] ||
12098 info->attrs[NL80211_ATTR_FILS_ERP_REALM] ||
12099 info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] ||
12100 info->attrs[NL80211_ATTR_FILS_ERP_RRK]) {
12101 return -EINVAL;
12102 }
12103
12104 if (info->attrs[NL80211_ATTR_AUTH_TYPE]) {
12105 auth_type = nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
12106 if (!nl80211_valid_auth_type(rdev, auth_type,
12107 NL80211_CMD_CONNECT))
12108 return -EINVAL;
12109
12110 if (auth_type == NL80211_AUTHTYPE_FILS_SK &&
12111 fils_sk_offload && !(changed & UPDATE_FILS_ERP_INFO))
12112 return -EINVAL;
12113
12114 connect.auth_type = auth_type;
12115 changed |= UPDATE_AUTH_TYPE;
12116 }
12117
7b0a0e3c 12118 if (!wdev->connected)
076fc877 12119 return -ENOLINK;
088e8df8 12120
076fc877 12121 return rdev_update_connect_params(rdev, dev, &connect, changed);
088e8df8 12122}
12123
b23aa676
SO
12124static int nl80211_disconnect(struct sk_buff *skb, struct genl_info *info)
12125{
4c476991
JB
12126 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12127 struct net_device *dev = info->user_ptr[1];
b23aa676
SO
12128 u16 reason;
12129
bad29297
AZ
12130 if (dev->ieee80211_ptr->conn_owner_nlportid &&
12131 dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)
12132 return -EPERM;
12133
b23aa676
SO
12134 if (!info->attrs[NL80211_ATTR_REASON_CODE])
12135 reason = WLAN_REASON_DEAUTH_LEAVING;
12136 else
12137 reason = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
12138
12139 if (reason == 0)
12140 return -EINVAL;
12141
074ac8df 12142 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
12143 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
12144 return -EOPNOTSUPP;
b23aa676 12145
076fc877 12146 return cfg80211_disconnect(rdev, dev, reason, true);
b23aa676
SO
12147}
12148
463d0183
JB
12149static int nl80211_wiphy_netns(struct sk_buff *skb, struct genl_info *info)
12150{
4c476991 12151 struct cfg80211_registered_device *rdev = info->user_ptr[0];
463d0183
JB
12152 struct net *net;
12153 int err;
463d0183 12154
4b681c82
VK
12155 if (info->attrs[NL80211_ATTR_PID]) {
12156 u32 pid = nla_get_u32(info->attrs[NL80211_ATTR_PID]);
12157
12158 net = get_net_ns_by_pid(pid);
12159 } else if (info->attrs[NL80211_ATTR_NETNS_FD]) {
12160 u32 fd = nla_get_u32(info->attrs[NL80211_ATTR_NETNS_FD]);
463d0183 12161
4b681c82
VK
12162 net = get_net_ns_by_fd(fd);
12163 } else {
12164 return -EINVAL;
12165 }
463d0183 12166
4c476991
JB
12167 if (IS_ERR(net))
12168 return PTR_ERR(net);
463d0183
JB
12169
12170 err = 0;
12171
12172 /* check if anything to do */
4c476991
JB
12173 if (!net_eq(wiphy_net(&rdev->wiphy), net))
12174 err = cfg80211_switch_netns(rdev, net);
463d0183 12175
463d0183 12176 put_net(net);
463d0183
JB
12177 return err;
12178}
12179
aa0887c4 12180static int nl80211_set_pmksa(struct sk_buff *skb, struct genl_info *info)
67fbb16b 12181{
4c476991 12182 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4c476991 12183 struct net_device *dev = info->user_ptr[1];
67fbb16b 12184 struct cfg80211_pmksa pmksa;
aa0887c4 12185 bool ap_pmksa_caching_support = false;
67fbb16b
SO
12186
12187 memset(&pmksa, 0, sizeof(struct cfg80211_pmksa));
12188
aa0887c4
VY
12189 ap_pmksa_caching_support = wiphy_ext_feature_isset(&rdev->wiphy,
12190 NL80211_EXT_FEATURE_AP_PMKSA_CACHING);
12191
67fbb16b
SO
12192 if (!info->attrs[NL80211_ATTR_PMKID])
12193 return -EINVAL;
12194
67fbb16b 12195 pmksa.pmkid = nla_data(info->attrs[NL80211_ATTR_PMKID]);
a3caf744
VK
12196
12197 if (info->attrs[NL80211_ATTR_MAC]) {
12198 pmksa.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
12199 } else if (info->attrs[NL80211_ATTR_SSID] &&
aa0887c4
VY
12200 info->attrs[NL80211_ATTR_FILS_CACHE_ID] &&
12201 info->attrs[NL80211_ATTR_PMK]) {
a3caf744
VK
12202 pmksa.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
12203 pmksa.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
aa0887c4 12204 pmksa.cache_id = nla_data(info->attrs[NL80211_ATTR_FILS_CACHE_ID]);
a3caf744
VK
12205 } else {
12206 return -EINVAL;
12207 }
aa0887c4 12208
a3caf744
VK
12209 if (info->attrs[NL80211_ATTR_PMK]) {
12210 pmksa.pmk = nla_data(info->attrs[NL80211_ATTR_PMK]);
12211 pmksa.pmk_len = nla_len(info->attrs[NL80211_ATTR_PMK]);
12212 }
67fbb16b 12213
7fc82af8
VJ
12214 if (info->attrs[NL80211_ATTR_PMK_LIFETIME])
12215 pmksa.pmk_lifetime =
12216 nla_get_u32(info->attrs[NL80211_ATTR_PMK_LIFETIME]);
12217
12218 if (info->attrs[NL80211_ATTR_PMK_REAUTH_THRESHOLD])
12219 pmksa.pmk_reauth_threshold =
aa0887c4 12220 nla_get_u8(info->attrs[NL80211_ATTR_PMK_REAUTH_THRESHOLD]);
7fc82af8 12221
074ac8df 12222 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
6c900360 12223 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT &&
aa0887c4
VY
12224 !((dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP ||
12225 dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) &&
12226 ap_pmksa_caching_support))
4c476991 12227 return -EOPNOTSUPP;
67fbb16b 12228
aa0887c4
VY
12229 if (!rdev->ops->set_pmksa)
12230 return -EOPNOTSUPP;
12231
12232 return rdev_set_pmksa(rdev, dev, &pmksa);
12233}
12234
12235static int nl80211_del_pmksa(struct sk_buff *skb, struct genl_info *info)
12236{
12237 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12238 struct net_device *dev = info->user_ptr[1];
12239 struct cfg80211_pmksa pmksa;
12240 bool sae_offload_support = false;
12241 bool owe_offload_support = false;
12242 bool ap_pmksa_caching_support = false;
12243
12244 memset(&pmksa, 0, sizeof(struct cfg80211_pmksa));
12245
12246 sae_offload_support = wiphy_ext_feature_isset(&rdev->wiphy,
12247 NL80211_EXT_FEATURE_SAE_OFFLOAD);
12248 owe_offload_support = wiphy_ext_feature_isset(&rdev->wiphy,
12249 NL80211_EXT_FEATURE_OWE_OFFLOAD);
12250 ap_pmksa_caching_support = wiphy_ext_feature_isset(&rdev->wiphy,
12251 NL80211_EXT_FEATURE_AP_PMKSA_CACHING);
12252
12253 if (info->attrs[NL80211_ATTR_PMKID])
12254 pmksa.pmkid = nla_data(info->attrs[NL80211_ATTR_PMKID]);
12255
12256 if (info->attrs[NL80211_ATTR_MAC]) {
12257 pmksa.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
12258 } else if (info->attrs[NL80211_ATTR_SSID]) {
12259 /* SSID based pmksa flush suppported only for FILS,
12260 * OWE/SAE OFFLOAD cases
12261 */
12262 if (info->attrs[NL80211_ATTR_FILS_CACHE_ID] &&
12263 info->attrs[NL80211_ATTR_PMK]) {
12264 pmksa.cache_id = nla_data(info->attrs[NL80211_ATTR_FILS_CACHE_ID]);
12265 } else if (!sae_offload_support && !owe_offload_support) {
12266 return -EINVAL;
12267 }
12268 pmksa.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
12269 pmksa.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
12270 } else {
12271 return -EINVAL;
67fbb16b
SO
12272 }
12273
aa0887c4
VY
12274 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
12275 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT &&
12276 !((dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP ||
12277 dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) &&
12278 ap_pmksa_caching_support))
12279 return -EOPNOTSUPP;
12280
12281 if (!rdev->ops->del_pmksa)
4c476991 12282 return -EOPNOTSUPP;
67fbb16b 12283
aa0887c4 12284 return rdev_del_pmksa(rdev, dev, &pmksa);
67fbb16b
SO
12285}
12286
12287static int nl80211_flush_pmksa(struct sk_buff *skb, struct genl_info *info)
12288{
4c476991
JB
12289 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12290 struct net_device *dev = info->user_ptr[1];
67fbb16b 12291
074ac8df 12292 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
12293 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
12294 return -EOPNOTSUPP;
67fbb16b 12295
4c476991
JB
12296 if (!rdev->ops->flush_pmksa)
12297 return -EOPNOTSUPP;
67fbb16b 12298
e35e4d28 12299 return rdev_flush_pmksa(rdev, dev);
67fbb16b
SO
12300}
12301
109086ce
AN
12302static int nl80211_tdls_mgmt(struct sk_buff *skb, struct genl_info *info)
12303{
12304 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12305 struct net_device *dev = info->user_ptr[1];
12306 u8 action_code, dialog_token;
df942e7b 12307 u32 peer_capability = 0;
109086ce
AN
12308 u16 status_code;
12309 u8 *peer;
c6112046 12310 int link_id;
31fa97c5 12311 bool initiator;
109086ce
AN
12312
12313 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) ||
12314 !rdev->ops->tdls_mgmt)
12315 return -EOPNOTSUPP;
12316
12317 if (!info->attrs[NL80211_ATTR_TDLS_ACTION] ||
12318 !info->attrs[NL80211_ATTR_STATUS_CODE] ||
12319 !info->attrs[NL80211_ATTR_TDLS_DIALOG_TOKEN] ||
12320 !info->attrs[NL80211_ATTR_IE] ||
12321 !info->attrs[NL80211_ATTR_MAC])
12322 return -EINVAL;
12323
12324 peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
12325 action_code = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_ACTION]);
12326 status_code = nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]);
12327 dialog_token = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_DIALOG_TOKEN]);
31fa97c5 12328 initiator = nla_get_flag(info->attrs[NL80211_ATTR_TDLS_INITIATOR]);
df942e7b
SDU
12329 if (info->attrs[NL80211_ATTR_TDLS_PEER_CAPABILITY])
12330 peer_capability =
12331 nla_get_u32(info->attrs[NL80211_ATTR_TDLS_PEER_CAPABILITY]);
c6112046 12332 link_id = nl80211_link_id_or_invalid(info->attrs);
109086ce 12333
c6112046 12334 return rdev_tdls_mgmt(rdev, dev, peer, link_id, action_code,
df942e7b 12335 dialog_token, status_code, peer_capability,
31fa97c5 12336 initiator,
e35e4d28
HG
12337 nla_data(info->attrs[NL80211_ATTR_IE]),
12338 nla_len(info->attrs[NL80211_ATTR_IE]));
109086ce
AN
12339}
12340
12341static int nl80211_tdls_oper(struct sk_buff *skb, struct genl_info *info)
12342{
12343 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12344 struct net_device *dev = info->user_ptr[1];
12345 enum nl80211_tdls_operation operation;
12346 u8 *peer;
12347
12348 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) ||
12349 !rdev->ops->tdls_oper)
12350 return -EOPNOTSUPP;
12351
12352 if (!info->attrs[NL80211_ATTR_TDLS_OPERATION] ||
12353 !info->attrs[NL80211_ATTR_MAC])
12354 return -EINVAL;
12355
12356 operation = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_OPERATION]);
12357 peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
12358
e35e4d28 12359 return rdev_tdls_oper(rdev, dev, peer, operation);
109086ce
AN
12360}
12361
9588bbd5
JM
12362static int nl80211_remain_on_channel(struct sk_buff *skb,
12363 struct genl_info *info)
12364{
4c476991 12365 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7b0a0e3c 12366 unsigned int link_id = nl80211_link_id(info->attrs);
71bbc994 12367 struct wireless_dev *wdev = info->user_ptr[1];
683b6d3b 12368 struct cfg80211_chan_def chandef;
9588bbd5
JM
12369 struct sk_buff *msg;
12370 void *hdr;
12371 u64 cookie;
683b6d3b 12372 u32 duration;
9588bbd5
JM
12373 int err;
12374
12375 if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] ||
12376 !info->attrs[NL80211_ATTR_DURATION])
12377 return -EINVAL;
12378
12379 duration = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]);
12380
ebf348fc
JB
12381 if (!rdev->ops->remain_on_channel ||
12382 !(rdev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL))
12383 return -EOPNOTSUPP;
12384
9588bbd5 12385 /*
ebf348fc
JB
12386 * We should be on that channel for at least a minimum amount of
12387 * time (10ms) but no longer than the driver supports.
9588bbd5 12388 */
ebf348fc 12389 if (duration < NL80211_MIN_REMAIN_ON_CHANNEL_TIME ||
a293911d 12390 duration > rdev->wiphy.max_remain_on_channel_duration)
9588bbd5
JM
12391 return -EINVAL;
12392
683b6d3b
JB
12393 err = nl80211_parse_chandef(rdev, info, &chandef);
12394 if (err)
12395 return err;
9588bbd5 12396
7b0a0e3c
JB
12397 if (!cfg80211_off_channel_oper_allowed(wdev, chandef.chan)) {
12398 const struct cfg80211_chan_def *oper_chandef, *compat_chandef;
12399
12400 oper_chandef = wdev_chandef(wdev, link_id);
12401
12402 if (WARN_ON(!oper_chandef)) {
12403 /* cannot happen since we must beacon to get here */
12404 WARN_ON(1);
7b0a0e3c
JB
12405 return -EBUSY;
12406 }
12407
12408 /* note: returns first one if identical chandefs */
12409 compat_chandef = cfg80211_chandef_compatible(&chandef,
12410 oper_chandef);
12411
076fc877 12412 if (compat_chandef != &chandef)
34373d12 12413 return -EBUSY;
34373d12 12414 }
34373d12 12415
9588bbd5 12416 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4c476991
JB
12417 if (!msg)
12418 return -ENOMEM;
9588bbd5 12419
15e47304 12420 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
9588bbd5 12421 NL80211_CMD_REMAIN_ON_CHANNEL);
cb35fba3
DC
12422 if (!hdr) {
12423 err = -ENOBUFS;
9588bbd5
JM
12424 goto free_msg;
12425 }
12426
683b6d3b
JB
12427 err = rdev_remain_on_channel(rdev, wdev, chandef.chan,
12428 duration, &cookie);
9588bbd5
JM
12429
12430 if (err)
12431 goto free_msg;
12432
2dad624e
ND
12433 if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
12434 NL80211_ATTR_PAD))
9360ffd1 12435 goto nla_put_failure;
9588bbd5
JM
12436
12437 genlmsg_end(msg, hdr);
4c476991
JB
12438
12439 return genlmsg_reply(msg, info);
9588bbd5
JM
12440
12441 nla_put_failure:
12442 err = -ENOBUFS;
12443 free_msg:
12444 nlmsg_free(msg);
9588bbd5
JM
12445 return err;
12446}
12447
12448static int nl80211_cancel_remain_on_channel(struct sk_buff *skb,
12449 struct genl_info *info)
12450{
4c476991 12451 struct cfg80211_registered_device *rdev = info->user_ptr[0];
71bbc994 12452 struct wireless_dev *wdev = info->user_ptr[1];
9588bbd5 12453 u64 cookie;
9588bbd5
JM
12454
12455 if (!info->attrs[NL80211_ATTR_COOKIE])
12456 return -EINVAL;
12457
4c476991
JB
12458 if (!rdev->ops->cancel_remain_on_channel)
12459 return -EOPNOTSUPP;
9588bbd5 12460
9588bbd5
JM
12461 cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);
12462
e35e4d28 12463 return rdev_cancel_remain_on_channel(rdev, wdev, cookie);
9588bbd5
JM
12464}
12465
13ae75b1
JM
12466static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
12467 struct genl_info *info)
12468{
13ae75b1 12469 struct cfg80211_bitrate_mask mask;
7b0a0e3c 12470 unsigned int link_id = nl80211_link_id(info->attrs);
a7c7fbff 12471 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4c476991 12472 struct net_device *dev = info->user_ptr[1];
a7c7fbff 12473 int err;
13ae75b1 12474
4c476991
JB
12475 if (!rdev->ops->set_bitrate_mask)
12476 return -EOPNOTSUPP;
13ae75b1 12477
9a5f6488 12478 err = nl80211_parse_tx_bitrate_mask(info, info->attrs,
eb89a6a6 12479 NL80211_ATTR_TX_RATES, &mask,
7b0a0e3c 12480 dev, true, link_id);
a7c7fbff 12481 if (err)
076fc877 12482 return err;
13ae75b1 12483
076fc877 12484 return rdev_set_bitrate_mask(rdev, dev, link_id, NULL, &mask);
13ae75b1
JM
12485}
12486
2e161f78 12487static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info)
026331c4 12488{
4c476991 12489 struct cfg80211_registered_device *rdev = info->user_ptr[0];
71bbc994 12490 struct wireless_dev *wdev = info->user_ptr[1];
2e161f78 12491 u16 frame_type = IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION;
026331c4
JM
12492
12493 if (!info->attrs[NL80211_ATTR_FRAME_MATCH])
12494 return -EINVAL;
12495
2e161f78
JB
12496 if (info->attrs[NL80211_ATTR_FRAME_TYPE])
12497 frame_type = nla_get_u16(info->attrs[NL80211_ATTR_FRAME_TYPE]);
026331c4 12498
71bbc994
JB
12499 switch (wdev->iftype) {
12500 case NL80211_IFTYPE_STATION:
12501 case NL80211_IFTYPE_ADHOC:
12502 case NL80211_IFTYPE_P2P_CLIENT:
12503 case NL80211_IFTYPE_AP:
12504 case NL80211_IFTYPE_AP_VLAN:
12505 case NL80211_IFTYPE_MESH_POINT:
12506 case NL80211_IFTYPE_P2P_GO:
98104fde 12507 case NL80211_IFTYPE_P2P_DEVICE:
71bbc994 12508 break;
cb3b7d87 12509 case NL80211_IFTYPE_NAN:
9b89495e
VG
12510 if (!wiphy_ext_feature_isset(wdev->wiphy,
12511 NL80211_EXT_FEATURE_SECURE_NAN))
12512 return -EOPNOTSUPP;
12513 break;
71bbc994 12514 default:
4c476991 12515 return -EOPNOTSUPP;
71bbc994 12516 }
026331c4
JM
12517
12518 /* not much point in registering if we can't reply */
4c476991
JB
12519 if (!rdev->ops->mgmt_tx)
12520 return -EOPNOTSUPP;
026331c4 12521
9dba48a6
JB
12522 if (info->attrs[NL80211_ATTR_RECEIVE_MULTICAST] &&
12523 !wiphy_ext_feature_isset(&rdev->wiphy,
12524 NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS)) {
12525 GENL_SET_ERR_MSG(info,
12526 "multicast RX registrations are not supported");
12527 return -EOPNOTSUPP;
12528 }
12529
15e47304 12530 return cfg80211_mlme_register_mgmt(wdev, info->snd_portid, frame_type,
ff74c51e
IP
12531 nla_data(info->attrs[NL80211_ATTR_FRAME_MATCH]),
12532 nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH]),
9dba48a6 12533 info->attrs[NL80211_ATTR_RECEIVE_MULTICAST],
ff74c51e 12534 info->extack);
026331c4
JM
12535}
12536
2e161f78 12537static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
026331c4 12538{
4c476991 12539 struct cfg80211_registered_device *rdev = info->user_ptr[0];
71bbc994 12540 struct wireless_dev *wdev = info->user_ptr[1];
683b6d3b 12541 struct cfg80211_chan_def chandef;
026331c4 12542 int err;
d64d373f 12543 void *hdr = NULL;
026331c4 12544 u64 cookie;
e247bd90 12545 struct sk_buff *msg = NULL;
b176e629
AO
12546 struct cfg80211_mgmt_tx_params params = {
12547 .dont_wait_for_ack =
12548 info->attrs[NL80211_ATTR_DONT_WAIT_FOR_ACK],
12549 };
026331c4 12550
683b6d3b 12551 if (!info->attrs[NL80211_ATTR_FRAME])
026331c4
JM
12552 return -EINVAL;
12553
4c476991
JB
12554 if (!rdev->ops->mgmt_tx)
12555 return -EOPNOTSUPP;
026331c4 12556
71bbc994 12557 switch (wdev->iftype) {
ea141b75
AQ
12558 case NL80211_IFTYPE_P2P_DEVICE:
12559 if (!info->attrs[NL80211_ATTR_WIPHY_FREQ])
12560 return -EINVAL;
d7832c71 12561 break;
71bbc994
JB
12562 case NL80211_IFTYPE_STATION:
12563 case NL80211_IFTYPE_ADHOC:
12564 case NL80211_IFTYPE_P2P_CLIENT:
12565 case NL80211_IFTYPE_AP:
12566 case NL80211_IFTYPE_AP_VLAN:
12567 case NL80211_IFTYPE_MESH_POINT:
12568 case NL80211_IFTYPE_P2P_GO:
12569 break;
cb3b7d87 12570 case NL80211_IFTYPE_NAN:
9b89495e
VG
12571 if (!wiphy_ext_feature_isset(wdev->wiphy,
12572 NL80211_EXT_FEATURE_SECURE_NAN))
12573 return -EOPNOTSUPP;
12574 break;
71bbc994 12575 default:
4c476991 12576 return -EOPNOTSUPP;
71bbc994 12577 }
026331c4 12578
f7ca38df 12579 if (info->attrs[NL80211_ATTR_DURATION]) {
7c4ef712 12580 if (!(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX))
f7ca38df 12581 return -EINVAL;
b176e629 12582 params.wait = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]);
ebf348fc
JB
12583
12584 /*
12585 * We should wait on the channel for at least a minimum amount
12586 * of time (10ms) but no longer than the driver supports.
12587 */
b176e629
AO
12588 if (params.wait < NL80211_MIN_REMAIN_ON_CHANNEL_TIME ||
12589 params.wait > rdev->wiphy.max_remain_on_channel_duration)
ebf348fc 12590 return -EINVAL;
f7ca38df
JB
12591 }
12592
b176e629 12593 params.offchan = info->attrs[NL80211_ATTR_OFFCHANNEL_TX_OK];
f7ca38df 12594
b176e629 12595 if (params.offchan && !(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX))
7c4ef712
JB
12596 return -EINVAL;
12597
b176e629 12598 params.no_cck = nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]);
e9f935e3 12599
ea141b75
AQ
12600 /* get the channel if any has been specified, otherwise pass NULL to
12601 * the driver. The latter will use the current one
12602 */
12603 chandef.chan = NULL;
12604 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
12605 err = nl80211_parse_chandef(rdev, info, &chandef);
12606 if (err)
12607 return err;
12608 }
12609
b176e629 12610 if (!chandef.chan && params.offchan)
ea141b75 12611 return -EINVAL;
026331c4 12612
7b0a0e3c 12613 if (params.offchan &&
076fc877 12614 !cfg80211_off_channel_oper_allowed(wdev, chandef.chan))
34373d12 12615 return -EBUSY;
95f498bb
JB
12616
12617 params.link_id = nl80211_link_id_or_invalid(info->attrs);
12618 /*
12619 * This now races due to the unlock, but we cannot check
12620 * the valid links for the _station_ anyway, so that's up
12621 * to the driver.
12622 */
12623 if (params.link_id >= 0 &&
076fc877 12624 !(wdev->valid_links & BIT(params.link_id)))
95f498bb 12625 return -EINVAL;
34373d12 12626
34d22ce2
AO
12627 params.buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
12628 params.len = nla_len(info->attrs[NL80211_ATTR_FRAME]);
12629
81830c8f
JB
12630 err = nl80211_parse_counter_offsets(rdev, NULL, params.len, -1,
12631 info->attrs[NL80211_ATTR_CSA_C_OFFSETS_TX],
12632 &params.csa_offsets,
12633 &params.n_csa_offsets);
12634 if (err)
12635 return err;
34d22ce2 12636
b176e629 12637 if (!params.dont_wait_for_ack) {
e247bd90
JB
12638 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
12639 if (!msg)
12640 return -ENOMEM;
026331c4 12641
15e47304 12642 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
e247bd90 12643 NL80211_CMD_FRAME);
cb35fba3
DC
12644 if (!hdr) {
12645 err = -ENOBUFS;
e247bd90
JB
12646 goto free_msg;
12647 }
026331c4 12648 }
e247bd90 12649
b176e629
AO
12650 params.chan = chandef.chan;
12651 err = cfg80211_mlme_mgmt_tx(rdev, wdev, &params, &cookie);
026331c4
JM
12652 if (err)
12653 goto free_msg;
12654
e247bd90 12655 if (msg) {
2dad624e
ND
12656 if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
12657 NL80211_ATTR_PAD))
9360ffd1 12658 goto nla_put_failure;
026331c4 12659
e247bd90
JB
12660 genlmsg_end(msg, hdr);
12661 return genlmsg_reply(msg, info);
12662 }
12663
12664 return 0;
026331c4
JM
12665
12666 nla_put_failure:
12667 err = -ENOBUFS;
12668 free_msg:
12669 nlmsg_free(msg);
026331c4
JM
12670 return err;
12671}
12672
f7ca38df
JB
12673static int nl80211_tx_mgmt_cancel_wait(struct sk_buff *skb, struct genl_info *info)
12674{
12675 struct cfg80211_registered_device *rdev = info->user_ptr[0];
71bbc994 12676 struct wireless_dev *wdev = info->user_ptr[1];
f7ca38df
JB
12677 u64 cookie;
12678
12679 if (!info->attrs[NL80211_ATTR_COOKIE])
12680 return -EINVAL;
12681
12682 if (!rdev->ops->mgmt_tx_cancel_wait)
12683 return -EOPNOTSUPP;
12684
71bbc994
JB
12685 switch (wdev->iftype) {
12686 case NL80211_IFTYPE_STATION:
12687 case NL80211_IFTYPE_ADHOC:
12688 case NL80211_IFTYPE_P2P_CLIENT:
12689 case NL80211_IFTYPE_AP:
12690 case NL80211_IFTYPE_AP_VLAN:
12691 case NL80211_IFTYPE_P2P_GO:
98104fde 12692 case NL80211_IFTYPE_P2P_DEVICE:
71bbc994 12693 break;
cb3b7d87 12694 case NL80211_IFTYPE_NAN:
9b89495e
VG
12695 if (!wiphy_ext_feature_isset(wdev->wiphy,
12696 NL80211_EXT_FEATURE_SECURE_NAN))
12697 return -EOPNOTSUPP;
12698 break;
71bbc994 12699 default:
f7ca38df 12700 return -EOPNOTSUPP;
71bbc994 12701 }
f7ca38df
JB
12702
12703 cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);
12704
e35e4d28 12705 return rdev_mgmt_tx_cancel_wait(rdev, wdev, cookie);
f7ca38df
JB
12706}
12707
ffb9eb3d
KV
12708static int nl80211_set_power_save(struct sk_buff *skb, struct genl_info *info)
12709{
4c476991 12710 struct cfg80211_registered_device *rdev = info->user_ptr[0];
ffb9eb3d 12711 struct wireless_dev *wdev;
4c476991 12712 struct net_device *dev = info->user_ptr[1];
ffb9eb3d
KV
12713 u8 ps_state;
12714 bool state;
12715 int err;
12716
4c476991
JB
12717 if (!info->attrs[NL80211_ATTR_PS_STATE])
12718 return -EINVAL;
ffb9eb3d
KV
12719
12720 ps_state = nla_get_u32(info->attrs[NL80211_ATTR_PS_STATE]);
12721
ffb9eb3d
KV
12722 wdev = dev->ieee80211_ptr;
12723
4c476991
JB
12724 if (!rdev->ops->set_power_mgmt)
12725 return -EOPNOTSUPP;
ffb9eb3d
KV
12726
12727 state = (ps_state == NL80211_PS_ENABLED) ? true : false;
12728
12729 if (state == wdev->ps)
4c476991 12730 return 0;
ffb9eb3d 12731
e35e4d28 12732 err = rdev_set_power_mgmt(rdev, dev, state, wdev->ps_timeout);
4c476991
JB
12733 if (!err)
12734 wdev->ps = state;
ffb9eb3d
KV
12735 return err;
12736}
12737
12738static int nl80211_get_power_save(struct sk_buff *skb, struct genl_info *info)
12739{
4c476991 12740 struct cfg80211_registered_device *rdev = info->user_ptr[0];
ffb9eb3d
KV
12741 enum nl80211_ps_state ps_state;
12742 struct wireless_dev *wdev;
4c476991 12743 struct net_device *dev = info->user_ptr[1];
ffb9eb3d
KV
12744 struct sk_buff *msg;
12745 void *hdr;
12746 int err;
12747
ffb9eb3d
KV
12748 wdev = dev->ieee80211_ptr;
12749
4c476991
JB
12750 if (!rdev->ops->set_power_mgmt)
12751 return -EOPNOTSUPP;
ffb9eb3d
KV
12752
12753 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4c476991
JB
12754 if (!msg)
12755 return -ENOMEM;
ffb9eb3d 12756
15e47304 12757 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
ffb9eb3d
KV
12758 NL80211_CMD_GET_POWER_SAVE);
12759 if (!hdr) {
4c476991 12760 err = -ENOBUFS;
ffb9eb3d
KV
12761 goto free_msg;
12762 }
12763
12764 if (wdev->ps)
12765 ps_state = NL80211_PS_ENABLED;
12766 else
12767 ps_state = NL80211_PS_DISABLED;
12768
9360ffd1
DM
12769 if (nla_put_u32(msg, NL80211_ATTR_PS_STATE, ps_state))
12770 goto nla_put_failure;
ffb9eb3d
KV
12771
12772 genlmsg_end(msg, hdr);
4c476991 12773 return genlmsg_reply(msg, info);
ffb9eb3d 12774
4c476991 12775 nla_put_failure:
ffb9eb3d 12776 err = -ENOBUFS;
4c476991 12777 free_msg:
ffb9eb3d 12778 nlmsg_free(msg);
ffb9eb3d
KV
12779 return err;
12780}
12781
94e860f1
JB
12782static const struct nla_policy
12783nl80211_attr_cqm_policy[NL80211_ATTR_CQM_MAX + 1] = {
4a4b8169 12784 [NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_BINARY },
d6dc1a38
JO
12785 [NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U32 },
12786 [NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 },
84f10708
TP
12787 [NL80211_ATTR_CQM_TXE_RATE] = { .type = NLA_U32 },
12788 [NL80211_ATTR_CQM_TXE_PKTS] = { .type = NLA_U32 },
12789 [NL80211_ATTR_CQM_TXE_INTVL] = { .type = NLA_U32 },
bee427b8 12790 [NL80211_ATTR_CQM_RSSI_LEVEL] = { .type = NLA_S32 },
d6dc1a38
JO
12791};
12792
84f10708 12793static int nl80211_set_cqm_txe(struct genl_info *info,
d9d8b019 12794 u32 rate, u32 pkts, u32 intvl)
84f10708
TP
12795{
12796 struct cfg80211_registered_device *rdev = info->user_ptr[0];
84f10708 12797 struct net_device *dev = info->user_ptr[1];
1da5fcc8 12798 struct wireless_dev *wdev = dev->ieee80211_ptr;
84f10708 12799
d9d8b019 12800 if (rate > 100 || intvl > NL80211_CQM_TXE_MAX_INTVL)
84f10708
TP
12801 return -EINVAL;
12802
84f10708
TP
12803 if (!rdev->ops->set_cqm_txe_config)
12804 return -EOPNOTSUPP;
12805
12806 if (wdev->iftype != NL80211_IFTYPE_STATION &&
12807 wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
12808 return -EOPNOTSUPP;
12809
e35e4d28 12810 return rdev_set_cqm_txe_config(rdev, dev, rate, pkts, intvl);
84f10708
TP
12811}
12812
4a4b8169 12813static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev,
37c20b2e
JB
12814 struct net_device *dev,
12815 struct cfg80211_cqm_config *cqm_config)
4a4b8169
AZ
12816{
12817 struct wireless_dev *wdev = dev->ieee80211_ptr;
12818 s32 last, low, high;
12819 u32 hyst;
1222a160 12820 int i, n, low_index;
4a4b8169
AZ
12821 int err;
12822
4a4b8169
AZ
12823 /*
12824 * Obtain current RSSI value if possible, if not and no RSSI threshold
12825 * event has been received yet, we should receive an event after a
12826 * connection is established and enough beacons received to calculate
12827 * the average.
12828 */
37c20b2e 12829 if (!cqm_config->last_rssi_event_value &&
7b0a0e3c 12830 wdev->links[0].client.current_bss &&
4a4b8169 12831 rdev->ops->get_station) {
73887fd9 12832 struct station_info sinfo = {};
4a4b8169
AZ
12833 u8 *mac_addr;
12834
7b0a0e3c 12835 mac_addr = wdev->links[0].client.current_bss->pub.bssid;
4a4b8169 12836
73887fd9
JB
12837 err = rdev_get_station(rdev, dev, mac_addr, &sinfo);
12838 if (err)
4a4b8169
AZ
12839 return err;
12840
df16737d 12841 cfg80211_sinfo_release_content(&sinfo);
397c657a 12842 if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_BEACON_SIGNAL_AVG))
37c20b2e 12843 cqm_config->last_rssi_event_value =
73887fd9 12844 (s8) sinfo.rx_beacon_signal_avg;
4a4b8169
AZ
12845 }
12846
37c20b2e
JB
12847 last = cqm_config->last_rssi_event_value;
12848 hyst = cqm_config->rssi_hyst;
12849 n = cqm_config->n_rssi_thresholds;
4a4b8169 12850
4b2c5a14
MH
12851 for (i = 0; i < n; i++) {
12852 i = array_index_nospec(i, n);
37c20b2e 12853 if (last < cqm_config->rssi_thresholds[i])
4a4b8169 12854 break;
4b2c5a14 12855 }
4a4b8169 12856
1222a160
MH
12857 low_index = i - 1;
12858 if (low_index >= 0) {
12859 low_index = array_index_nospec(low_index, n);
37c20b2e 12860 low = cqm_config->rssi_thresholds[low_index] - hyst;
1222a160
MH
12861 } else {
12862 low = S32_MIN;
12863 }
12864 if (i < n) {
12865 i = array_index_nospec(i, n);
37c20b2e 12866 high = cqm_config->rssi_thresholds[i] + hyst - 1;
1222a160
MH
12867 } else {
12868 high = S32_MAX;
12869 }
4a4b8169
AZ
12870
12871 return rdev_set_cqm_rssi_range_config(rdev, dev, low, high);
12872}
12873
d6dc1a38 12874static int nl80211_set_cqm_rssi(struct genl_info *info,
4a4b8169
AZ
12875 const s32 *thresholds, int n_thresholds,
12876 u32 hysteresis)
d6dc1a38 12877{
4c476991 12878 struct cfg80211_registered_device *rdev = info->user_ptr[0];
37c20b2e 12879 struct cfg80211_cqm_config *cqm_config = NULL, *old;
4c476991 12880 struct net_device *dev = info->user_ptr[1];
1da5fcc8 12881 struct wireless_dev *wdev = dev->ieee80211_ptr;
4a4b8169 12882 s32 prev = S32_MIN;
7d6904bf 12883 int i, err;
d6dc1a38 12884
4a4b8169
AZ
12885 /* Check all values negative and sorted */
12886 for (i = 0; i < n_thresholds; i++) {
12887 if (thresholds[i] > 0 || thresholds[i] <= prev)
12888 return -EINVAL;
d6dc1a38 12889
4a4b8169
AZ
12890 prev = thresholds[i];
12891 }
d6dc1a38 12892
074ac8df 12893 if (wdev->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
12894 wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
12895 return -EOPNOTSUPP;
d6dc1a38 12896
4a4b8169
AZ
12897 if (n_thresholds == 1 && thresholds[0] == 0) /* Disabling */
12898 n_thresholds = 0;
12899
7d6904bf 12900 old = wiphy_dereference(wdev->wiphy, wdev->cqm_config);
4a4b8169 12901
7e7efdda
JB
12902 /* if already disabled just succeed */
12903 if (!n_thresholds && !old)
12904 return 0;
12905
12906 if (n_thresholds > 1) {
12907 if (!wiphy_ext_feature_isset(&rdev->wiphy,
12908 NL80211_EXT_FEATURE_CQM_RSSI_LIST) ||
12909 !rdev->ops->set_cqm_rssi_range_config)
12910 return -EOPNOTSUPP;
12911 } else {
12912 if (!rdev->ops->set_cqm_rssi_config)
12913 return -EOPNOTSUPP;
12914 }
12915
37c20b2e 12916 if (n_thresholds) {
40f231e7
LB
12917 cqm_config = kzalloc(struct_size(cqm_config, rssi_thresholds,
12918 n_thresholds),
12919 GFP_KERNEL);
076fc877
JB
12920 if (!cqm_config)
12921 return -ENOMEM;
4a4b8169
AZ
12922
12923 cqm_config->rssi_hyst = hysteresis;
12924 cqm_config->n_rssi_thresholds = n_thresholds;
12925 memcpy(cqm_config->rssi_thresholds, thresholds,
40f231e7
LB
12926 flex_array_size(cqm_config, rssi_thresholds,
12927 n_thresholds));
7e7efdda
JB
12928 cqm_config->use_range_api = n_thresholds > 1 ||
12929 !rdev->ops->set_cqm_rssi_config;
4a4b8169 12930
37c20b2e 12931 rcu_assign_pointer(wdev->cqm_config, cqm_config);
7e7efdda
JB
12932
12933 if (cqm_config->use_range_api)
12934 err = cfg80211_cqm_rssi_update(rdev, dev, cqm_config);
12935 else
12936 err = rdev_set_cqm_rssi_config(rdev, dev,
12937 thresholds[0],
12938 hysteresis);
37c20b2e
JB
12939 } else {
12940 RCU_INIT_POINTER(wdev->cqm_config, NULL);
7e7efdda
JB
12941 /* if enabled as range also disable via range */
12942 if (old->use_range_api)
12943 err = rdev_set_cqm_rssi_range_config(rdev, dev, 0, 0);
12944 else
12945 err = rdev_set_cqm_rssi_config(rdev, dev, 0, 0);
4a4b8169
AZ
12946 }
12947
37c20b2e
JB
12948 if (err) {
12949 rcu_assign_pointer(wdev->cqm_config, old);
12950 kfree_rcu(cqm_config, rcu_head);
12951 } else {
12952 kfree_rcu(old, rcu_head);
4a4b8169
AZ
12953 }
12954
4a4b8169 12955 return err;
d6dc1a38
JO
12956}
12957
12958static int nl80211_set_cqm(struct sk_buff *skb, struct genl_info *info)
12959{
12960 struct nlattr *attrs[NL80211_ATTR_CQM_MAX + 1];
12961 struct nlattr *cqm;
12962 int err;
12963
12964 cqm = info->attrs[NL80211_ATTR_CQM];
1da5fcc8
JB
12965 if (!cqm)
12966 return -EINVAL;
d6dc1a38 12967
8cb08174
JB
12968 err = nla_parse_nested_deprecated(attrs, NL80211_ATTR_CQM_MAX, cqm,
12969 nl80211_attr_cqm_policy,
12970 info->extack);
d6dc1a38 12971 if (err)
1da5fcc8 12972 return err;
d6dc1a38
JO
12973
12974 if (attrs[NL80211_ATTR_CQM_RSSI_THOLD] &&
12975 attrs[NL80211_ATTR_CQM_RSSI_HYST]) {
4a4b8169
AZ
12976 const s32 *thresholds =
12977 nla_data(attrs[NL80211_ATTR_CQM_RSSI_THOLD]);
12978 int len = nla_len(attrs[NL80211_ATTR_CQM_RSSI_THOLD]);
1da5fcc8 12979 u32 hysteresis = nla_get_u32(attrs[NL80211_ATTR_CQM_RSSI_HYST]);
d6dc1a38 12980
4a4b8169
AZ
12981 if (len % 4)
12982 return -EINVAL;
12983
12984 return nl80211_set_cqm_rssi(info, thresholds, len / 4,
12985 hysteresis);
1da5fcc8
JB
12986 }
12987
12988 if (attrs[NL80211_ATTR_CQM_TXE_RATE] &&
12989 attrs[NL80211_ATTR_CQM_TXE_PKTS] &&
12990 attrs[NL80211_ATTR_CQM_TXE_INTVL]) {
12991 u32 rate = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_RATE]);
12992 u32 pkts = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_PKTS]);
12993 u32 intvl = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_INTVL]);
12994
12995 return nl80211_set_cqm_txe(info, rate, pkts, intvl);
12996 }
12997
12998 return -EINVAL;
d6dc1a38
JO
12999}
13000
6e0bd6c3
RL
13001static int nl80211_join_ocb(struct sk_buff *skb, struct genl_info *info)
13002{
13003 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13004 struct net_device *dev = info->user_ptr[1];
13005 struct ocb_setup setup = {};
13006 int err;
13007
13008 err = nl80211_parse_chandef(rdev, info, &setup.chandef);
13009 if (err)
13010 return err;
13011
13012 return cfg80211_join_ocb(rdev, dev, &setup);
13013}
13014
13015static int nl80211_leave_ocb(struct sk_buff *skb, struct genl_info *info)
13016{
13017 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13018 struct net_device *dev = info->user_ptr[1];
13019
13020 return cfg80211_leave_ocb(rdev, dev);
13021}
13022
29cbe68c
JB
13023static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info)
13024{
13025 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13026 struct net_device *dev = info->user_ptr[1];
13027 struct mesh_config cfg;
c80d545d 13028 struct mesh_setup setup;
29cbe68c
JB
13029 int err;
13030
13031 /* start with default */
13032 memcpy(&cfg, &default_mesh_config, sizeof(cfg));
c80d545d 13033 memcpy(&setup, &default_mesh_setup, sizeof(setup));
29cbe68c 13034
24bdd9f4 13035 if (info->attrs[NL80211_ATTR_MESH_CONFIG]) {
29cbe68c 13036 /* and parse parameters if given */
24bdd9f4 13037 err = nl80211_parse_mesh_config(info, &cfg, NULL);
29cbe68c
JB
13038 if (err)
13039 return err;
13040 }
13041
13042 if (!info->attrs[NL80211_ATTR_MESH_ID] ||
13043 !nla_len(info->attrs[NL80211_ATTR_MESH_ID]))
13044 return -EINVAL;
13045
c80d545d
JC
13046 setup.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]);
13047 setup.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
13048
4bb62344
CYY
13049 if (info->attrs[NL80211_ATTR_MCAST_RATE] &&
13050 !nl80211_parse_mcast_rate(rdev, setup.mcast_rate,
13051 nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE])))
13052 return -EINVAL;
13053
9bdbf04d
MP
13054 if (info->attrs[NL80211_ATTR_BEACON_INTERVAL]) {
13055 setup.beacon_interval =
13056 nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
12d20fc9 13057
0c317a02
PK
13058 err = cfg80211_validate_beacon_int(rdev,
13059 NL80211_IFTYPE_MESH_POINT,
13060 setup.beacon_interval);
12d20fc9
PK
13061 if (err)
13062 return err;
9bdbf04d
MP
13063 }
13064
13065 if (info->attrs[NL80211_ATTR_DTIM_PERIOD]) {
13066 setup.dtim_period =
13067 nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);
13068 if (setup.dtim_period < 1 || setup.dtim_period > 100)
13069 return -EINVAL;
13070 }
13071
c80d545d
JC
13072 if (info->attrs[NL80211_ATTR_MESH_SETUP]) {
13073 /* parse additional setup parameters if given */
13074 err = nl80211_parse_mesh_setup(info, &setup);
13075 if (err)
13076 return err;
13077 }
13078
d37bb18a
TP
13079 if (setup.user_mpm)
13080 cfg.auto_open_plinks = false;
13081
cc1d2806 13082 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
683b6d3b
JB
13083 err = nl80211_parse_chandef(rdev, info, &setup.chandef);
13084 if (err)
13085 return err;
cc1d2806 13086 } else {
188c1b3c 13087 /* __cfg80211_join_mesh() will sort it out */
683b6d3b 13088 setup.chandef.chan = NULL;
cc1d2806
JB
13089 }
13090
ffb3cf30
AN
13091 if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) {
13092 u8 *rates = nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
13093 int n_rates =
13094 nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
13095 struct ieee80211_supported_band *sband;
13096
13097 if (!setup.chandef.chan)
13098 return -EINVAL;
13099
13100 sband = rdev->wiphy.bands[setup.chandef.chan->band];
13101
13102 err = ieee80211_get_ratemask(sband, rates, n_rates,
13103 &setup.basic_rates);
13104 if (err)
13105 return err;
13106 }
13107
8564e382 13108 if (info->attrs[NL80211_ATTR_TX_RATES]) {
9a5f6488
TC
13109 err = nl80211_parse_tx_bitrate_mask(info, info->attrs,
13110 NL80211_ATTR_TX_RATES,
eb89a6a6 13111 &setup.beacon_rate,
7b0a0e3c 13112 dev, false, 0);
8564e382
JB
13113 if (err)
13114 return err;
13115
265698d7
JB
13116 if (!setup.chandef.chan)
13117 return -EINVAL;
13118
8564e382
JB
13119 err = validate_beacon_tx_rate(rdev, setup.chandef.chan->band,
13120 &setup.beacon_rate);
13121 if (err)
13122 return err;
13123 }
13124
d37d49c2
BB
13125 setup.userspace_handles_dfs =
13126 nla_get_flag(info->attrs[NL80211_ATTR_HANDLE_DFS]);
13127
1224f583
DK
13128 if (info->attrs[NL80211_ATTR_CONTROL_PORT_OVER_NL80211]) {
13129 int r = validate_pae_over_nl80211(rdev, info);
13130
13131 if (r < 0)
13132 return r;
13133
13134 setup.control_port_over_nl80211 = true;
13135 }
13136
188c1b3c
DK
13137 err = __cfg80211_join_mesh(rdev, dev, &setup, &cfg);
13138 if (!err && info->attrs[NL80211_ATTR_SOCKET_OWNER])
13139 dev->ieee80211_ptr->conn_owner_nlportid = info->snd_portid;
188c1b3c
DK
13140
13141 return err;
29cbe68c
JB
13142}
13143
13144static int nl80211_leave_mesh(struct sk_buff *skb, struct genl_info *info)
13145{
13146 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13147 struct net_device *dev = info->user_ptr[1];
13148
13149 return cfg80211_leave_mesh(rdev, dev);
13150}
13151
dfb89c56 13152#ifdef CONFIG_PM
bb92d199
AK
13153static int nl80211_send_wowlan_patterns(struct sk_buff *msg,
13154 struct cfg80211_registered_device *rdev)
13155{
6abb9cb9 13156 struct cfg80211_wowlan *wowlan = rdev->wiphy.wowlan_config;
bb92d199
AK
13157 struct nlattr *nl_pats, *nl_pat;
13158 int i, pat_len;
13159
6abb9cb9 13160 if (!wowlan->n_patterns)
bb92d199
AK
13161 return 0;
13162
ae0be8de 13163 nl_pats = nla_nest_start_noflag(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN);
bb92d199
AK
13164 if (!nl_pats)
13165 return -ENOBUFS;
13166
6abb9cb9 13167 for (i = 0; i < wowlan->n_patterns; i++) {
ae0be8de 13168 nl_pat = nla_nest_start_noflag(msg, i + 1);
bb92d199
AK
13169 if (!nl_pat)
13170 return -ENOBUFS;
6abb9cb9 13171 pat_len = wowlan->patterns[i].pattern_len;
50ac6607 13172 if (nla_put(msg, NL80211_PKTPAT_MASK, DIV_ROUND_UP(pat_len, 8),
6abb9cb9 13173 wowlan->patterns[i].mask) ||
50ac6607
AK
13174 nla_put(msg, NL80211_PKTPAT_PATTERN, pat_len,
13175 wowlan->patterns[i].pattern) ||
13176 nla_put_u32(msg, NL80211_PKTPAT_OFFSET,
6abb9cb9 13177 wowlan->patterns[i].pkt_offset))
bb92d199
AK
13178 return -ENOBUFS;
13179 nla_nest_end(msg, nl_pat);
13180 }
13181 nla_nest_end(msg, nl_pats);
13182
13183 return 0;
13184}
13185
2a0e047e
JB
13186static int nl80211_send_wowlan_tcp(struct sk_buff *msg,
13187 struct cfg80211_wowlan_tcp *tcp)
13188{
13189 struct nlattr *nl_tcp;
13190
13191 if (!tcp)
13192 return 0;
13193
ae0be8de
MK
13194 nl_tcp = nla_nest_start_noflag(msg,
13195 NL80211_WOWLAN_TRIG_TCP_CONNECTION);
2a0e047e
JB
13196 if (!nl_tcp)
13197 return -ENOBUFS;
13198
930345ea
JB
13199 if (nla_put_in_addr(msg, NL80211_WOWLAN_TCP_SRC_IPV4, tcp->src) ||
13200 nla_put_in_addr(msg, NL80211_WOWLAN_TCP_DST_IPV4, tcp->dst) ||
2a0e047e
JB
13201 nla_put(msg, NL80211_WOWLAN_TCP_DST_MAC, ETH_ALEN, tcp->dst_mac) ||
13202 nla_put_u16(msg, NL80211_WOWLAN_TCP_SRC_PORT, tcp->src_port) ||
13203 nla_put_u16(msg, NL80211_WOWLAN_TCP_DST_PORT, tcp->dst_port) ||
13204 nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD,
13205 tcp->payload_len, tcp->payload) ||
13206 nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_INTERVAL,
13207 tcp->data_interval) ||
13208 nla_put(msg, NL80211_WOWLAN_TCP_WAKE_PAYLOAD,
13209 tcp->wake_len, tcp->wake_data) ||
13210 nla_put(msg, NL80211_WOWLAN_TCP_WAKE_MASK,
13211 DIV_ROUND_UP(tcp->wake_len, 8), tcp->wake_mask))
13212 return -ENOBUFS;
13213
13214 if (tcp->payload_seq.len &&
13215 nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ,
13216 sizeof(tcp->payload_seq), &tcp->payload_seq))
13217 return -ENOBUFS;
13218
13219 if (tcp->payload_tok.len &&
13220 nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN,
13221 sizeof(tcp->payload_tok) + tcp->tokens_size,
13222 &tcp->payload_tok))
13223 return -ENOBUFS;
13224
e248ad30
JB
13225 nla_nest_end(msg, nl_tcp);
13226
2a0e047e
JB
13227 return 0;
13228}
13229
75453ccb
LC
13230static int nl80211_send_wowlan_nd(struct sk_buff *msg,
13231 struct cfg80211_sched_scan_request *req)
13232{
3b06d277 13233 struct nlattr *nd, *freqs, *matches, *match, *scan_plans, *scan_plan;
75453ccb
LC
13234 int i;
13235
13236 if (!req)
13237 return 0;
13238
ae0be8de 13239 nd = nla_nest_start_noflag(msg, NL80211_WOWLAN_TRIG_NET_DETECT);
75453ccb
LC
13240 if (!nd)
13241 return -ENOBUFS;
13242
3b06d277
AS
13243 if (req->n_scan_plans == 1 &&
13244 nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_INTERVAL,
13245 req->scan_plans[0].interval * 1000))
75453ccb
LC
13246 return -ENOBUFS;
13247
21fea567
LC
13248 if (nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_DELAY, req->delay))
13249 return -ENOBUFS;
13250
bf95ecdb 13251 if (req->relative_rssi_set) {
13252 struct nl80211_bss_select_rssi_adjust rssi_adjust;
13253
13254 if (nla_put_s8(msg, NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI,
13255 req->relative_rssi))
13256 return -ENOBUFS;
13257
13258 rssi_adjust.band = req->rssi_adjust.band;
13259 rssi_adjust.delta = req->rssi_adjust.delta;
13260 if (nla_put(msg, NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST,
13261 sizeof(rssi_adjust), &rssi_adjust))
13262 return -ENOBUFS;
13263 }
13264
ae0be8de 13265 freqs = nla_nest_start_noflag(msg, NL80211_ATTR_SCAN_FREQUENCIES);
75453ccb
LC
13266 if (!freqs)
13267 return -ENOBUFS;
13268
53b18980
JB
13269 for (i = 0; i < req->n_channels; i++) {
13270 if (nla_put_u32(msg, i, req->channels[i]->center_freq))
13271 return -ENOBUFS;
13272 }
75453ccb
LC
13273
13274 nla_nest_end(msg, freqs);
13275
13276 if (req->n_match_sets) {
ae0be8de
MK
13277 matches = nla_nest_start_noflag(msg,
13278 NL80211_ATTR_SCHED_SCAN_MATCH);
76e1fb4b
JB
13279 if (!matches)
13280 return -ENOBUFS;
13281
75453ccb 13282 for (i = 0; i < req->n_match_sets; i++) {
ae0be8de 13283 match = nla_nest_start_noflag(msg, i);
76e1fb4b
JB
13284 if (!match)
13285 return -ENOBUFS;
13286
53b18980
JB
13287 if (nla_put(msg, NL80211_SCHED_SCAN_MATCH_ATTR_SSID,
13288 req->match_sets[i].ssid.ssid_len,
13289 req->match_sets[i].ssid.ssid))
13290 return -ENOBUFS;
75453ccb
LC
13291 nla_nest_end(msg, match);
13292 }
13293 nla_nest_end(msg, matches);
13294 }
13295
ae0be8de 13296 scan_plans = nla_nest_start_noflag(msg, NL80211_ATTR_SCHED_SCAN_PLANS);
3b06d277
AS
13297 if (!scan_plans)
13298 return -ENOBUFS;
13299
13300 for (i = 0; i < req->n_scan_plans; i++) {
ae0be8de 13301 scan_plan = nla_nest_start_noflag(msg, i + 1);
76e1fb4b
JB
13302 if (!scan_plan)
13303 return -ENOBUFS;
13304
67626964 13305 if (nla_put_u32(msg, NL80211_SCHED_SCAN_PLAN_INTERVAL,
3b06d277
AS
13306 req->scan_plans[i].interval) ||
13307 (req->scan_plans[i].iterations &&
13308 nla_put_u32(msg, NL80211_SCHED_SCAN_PLAN_ITERATIONS,
13309 req->scan_plans[i].iterations)))
13310 return -ENOBUFS;
13311 nla_nest_end(msg, scan_plan);
13312 }
13313 nla_nest_end(msg, scan_plans);
13314
75453ccb
LC
13315 nla_nest_end(msg, nd);
13316
13317 return 0;
13318}
13319
ff1b6e69
JB
13320static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info)
13321{
13322 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13323 struct sk_buff *msg;
13324 void *hdr;
2a0e047e 13325 u32 size = NLMSG_DEFAULT_SIZE;
ff1b6e69 13326
964dc9e2 13327 if (!rdev->wiphy.wowlan)
ff1b6e69
JB
13328 return -EOPNOTSUPP;
13329
6abb9cb9 13330 if (rdev->wiphy.wowlan_config && rdev->wiphy.wowlan_config->tcp) {
2a0e047e 13331 /* adjust size to have room for all the data */
6abb9cb9
JB
13332 size += rdev->wiphy.wowlan_config->tcp->tokens_size +
13333 rdev->wiphy.wowlan_config->tcp->payload_len +
13334 rdev->wiphy.wowlan_config->tcp->wake_len +
13335 rdev->wiphy.wowlan_config->tcp->wake_len / 8;
2a0e047e
JB
13336 }
13337
13338 msg = nlmsg_new(size, GFP_KERNEL);
ff1b6e69
JB
13339 if (!msg)
13340 return -ENOMEM;
13341
15e47304 13342 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
ff1b6e69
JB
13343 NL80211_CMD_GET_WOWLAN);
13344 if (!hdr)
13345 goto nla_put_failure;
13346
6abb9cb9 13347 if (rdev->wiphy.wowlan_config) {
ff1b6e69
JB
13348 struct nlattr *nl_wowlan;
13349
ae0be8de
MK
13350 nl_wowlan = nla_nest_start_noflag(msg,
13351 NL80211_ATTR_WOWLAN_TRIGGERS);
ff1b6e69
JB
13352 if (!nl_wowlan)
13353 goto nla_put_failure;
13354
6abb9cb9 13355 if ((rdev->wiphy.wowlan_config->any &&
9360ffd1 13356 nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) ||
6abb9cb9 13357 (rdev->wiphy.wowlan_config->disconnect &&
9360ffd1 13358 nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) ||
6abb9cb9 13359 (rdev->wiphy.wowlan_config->magic_pkt &&
9360ffd1 13360 nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) ||
6abb9cb9 13361 (rdev->wiphy.wowlan_config->gtk_rekey_failure &&
9360ffd1 13362 nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) ||
6abb9cb9 13363 (rdev->wiphy.wowlan_config->eap_identity_req &&
9360ffd1 13364 nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) ||
6abb9cb9 13365 (rdev->wiphy.wowlan_config->four_way_handshake &&
9360ffd1 13366 nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) ||
6abb9cb9 13367 (rdev->wiphy.wowlan_config->rfkill_release &&
9360ffd1
DM
13368 nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE)))
13369 goto nla_put_failure;
2a0e047e 13370
bb92d199
AK
13371 if (nl80211_send_wowlan_patterns(msg, rdev))
13372 goto nla_put_failure;
2a0e047e 13373
6abb9cb9
JB
13374 if (nl80211_send_wowlan_tcp(msg,
13375 rdev->wiphy.wowlan_config->tcp))
2a0e047e 13376 goto nla_put_failure;
75453ccb
LC
13377
13378 if (nl80211_send_wowlan_nd(
13379 msg,
13380 rdev->wiphy.wowlan_config->nd_config))
13381 goto nla_put_failure;
2a0e047e 13382
ff1b6e69
JB
13383 nla_nest_end(msg, nl_wowlan);
13384 }
13385
13386 genlmsg_end(msg, hdr);
13387 return genlmsg_reply(msg, info);
13388
13389nla_put_failure:
13390 nlmsg_free(msg);
13391 return -ENOBUFS;
13392}
13393
2a0e047e
JB
13394static int nl80211_parse_wowlan_tcp(struct cfg80211_registered_device *rdev,
13395 struct nlattr *attr,
13396 struct cfg80211_wowlan *trig)
13397{
13398 struct nlattr *tb[NUM_NL80211_WOWLAN_TCP];
13399 struct cfg80211_wowlan_tcp *cfg;
13400 struct nl80211_wowlan_tcp_data_token *tok = NULL;
13401 struct nl80211_wowlan_tcp_data_seq *seq = NULL;
13402 u32 size;
13403 u32 data_size, wake_size, tokens_size = 0, wake_mask_size;
13404 int err, port;
13405
964dc9e2 13406 if (!rdev->wiphy.wowlan->tcp)
2a0e047e
JB
13407 return -EINVAL;
13408
8cb08174
JB
13409 err = nla_parse_nested_deprecated(tb, MAX_NL80211_WOWLAN_TCP, attr,
13410 nl80211_wowlan_tcp_policy, NULL);
2a0e047e
JB
13411 if (err)
13412 return err;
13413
13414 if (!tb[NL80211_WOWLAN_TCP_SRC_IPV4] ||
13415 !tb[NL80211_WOWLAN_TCP_DST_IPV4] ||
13416 !tb[NL80211_WOWLAN_TCP_DST_MAC] ||
13417 !tb[NL80211_WOWLAN_TCP_DST_PORT] ||
13418 !tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD] ||
13419 !tb[NL80211_WOWLAN_TCP_DATA_INTERVAL] ||
13420 !tb[NL80211_WOWLAN_TCP_WAKE_PAYLOAD] ||
13421 !tb[NL80211_WOWLAN_TCP_WAKE_MASK])
13422 return -EINVAL;
13423
13424 data_size = nla_len(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD]);
964dc9e2 13425 if (data_size > rdev->wiphy.wowlan->tcp->data_payload_max)
2a0e047e
JB
13426 return -EINVAL;
13427
13428 if (nla_get_u32(tb[NL80211_WOWLAN_TCP_DATA_INTERVAL]) >
964dc9e2 13429 rdev->wiphy.wowlan->tcp->data_interval_max ||
723d568a 13430 nla_get_u32(tb[NL80211_WOWLAN_TCP_DATA_INTERVAL]) == 0)
2a0e047e
JB
13431 return -EINVAL;
13432
13433 wake_size = nla_len(tb[NL80211_WOWLAN_TCP_WAKE_PAYLOAD]);
964dc9e2 13434 if (wake_size > rdev->wiphy.wowlan->tcp->wake_payload_max)
2a0e047e
JB
13435 return -EINVAL;
13436
13437 wake_mask_size = nla_len(tb[NL80211_WOWLAN_TCP_WAKE_MASK]);
13438 if (wake_mask_size != DIV_ROUND_UP(wake_size, 8))
13439 return -EINVAL;
13440
13441 if (tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN]) {
13442 u32 tokln = nla_len(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN]);
13443
13444 tok = nla_data(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN]);
13445 tokens_size = tokln - sizeof(*tok);
13446
13447 if (!tok->len || tokens_size % tok->len)
13448 return -EINVAL;
964dc9e2 13449 if (!rdev->wiphy.wowlan->tcp->tok)
2a0e047e 13450 return -EINVAL;
964dc9e2 13451 if (tok->len > rdev->wiphy.wowlan->tcp->tok->max_len)
2a0e047e 13452 return -EINVAL;
964dc9e2 13453 if (tok->len < rdev->wiphy.wowlan->tcp->tok->min_len)
2a0e047e 13454 return -EINVAL;
964dc9e2 13455 if (tokens_size > rdev->wiphy.wowlan->tcp->tok->bufsize)
2a0e047e
JB
13456 return -EINVAL;
13457 if (tok->offset + tok->len > data_size)
13458 return -EINVAL;
13459 }
13460
13461 if (tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ]) {
13462 seq = nla_data(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ]);
964dc9e2 13463 if (!rdev->wiphy.wowlan->tcp->seq)
2a0e047e
JB
13464 return -EINVAL;
13465 if (seq->len == 0 || seq->len > 4)
13466 return -EINVAL;
13467 if (seq->len + seq->offset > data_size)
13468 return -EINVAL;
13469 }
13470
13471 size = sizeof(*cfg);
13472 size += data_size;
13473 size += wake_size + wake_mask_size;
13474 size += tokens_size;
13475
13476 cfg = kzalloc(size, GFP_KERNEL);
13477 if (!cfg)
13478 return -ENOMEM;
67b61f6c
JB
13479 cfg->src = nla_get_in_addr(tb[NL80211_WOWLAN_TCP_SRC_IPV4]);
13480 cfg->dst = nla_get_in_addr(tb[NL80211_WOWLAN_TCP_DST_IPV4]);
2a0e047e
JB
13481 memcpy(cfg->dst_mac, nla_data(tb[NL80211_WOWLAN_TCP_DST_MAC]),
13482 ETH_ALEN);
13483 if (tb[NL80211_WOWLAN_TCP_SRC_PORT])
13484 port = nla_get_u16(tb[NL80211_WOWLAN_TCP_SRC_PORT]);
13485 else
13486 port = 0;
13487#ifdef CONFIG_INET
13488 /* allocate a socket and port for it and use it */
13489 err = __sock_create(wiphy_net(&rdev->wiphy), PF_INET, SOCK_STREAM,
13490 IPPROTO_TCP, &cfg->sock, 1);
13491 if (err) {
13492 kfree(cfg);
13493 return err;
13494 }
13495 if (inet_csk_get_port(cfg->sock->sk, port)) {
13496 sock_release(cfg->sock);
13497 kfree(cfg);
13498 return -EADDRINUSE;
13499 }
13500 cfg->src_port = inet_sk(cfg->sock->sk)->inet_num;
13501#else
13502 if (!port) {
13503 kfree(cfg);
13504 return -EINVAL;
13505 }
13506 cfg->src_port = port;
13507#endif
13508
13509 cfg->dst_port = nla_get_u16(tb[NL80211_WOWLAN_TCP_DST_PORT]);
13510 cfg->payload_len = data_size;
13511 cfg->payload = (u8 *)cfg + sizeof(*cfg) + tokens_size;
13512 memcpy((void *)cfg->payload,
13513 nla_data(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD]),
13514 data_size);
13515 if (seq)
13516 cfg->payload_seq = *seq;
13517 cfg->data_interval = nla_get_u32(tb[NL80211_WOWLAN_TCP_DATA_INTERVAL]);
13518 cfg->wake_len = wake_size;
13519 cfg->wake_data = (u8 *)cfg + sizeof(*cfg) + tokens_size + data_size;
13520 memcpy((void *)cfg->wake_data,
13521 nla_data(tb[NL80211_WOWLAN_TCP_WAKE_PAYLOAD]),
13522 wake_size);
13523 cfg->wake_mask = (u8 *)cfg + sizeof(*cfg) + tokens_size +
13524 data_size + wake_size;
13525 memcpy((void *)cfg->wake_mask,
13526 nla_data(tb[NL80211_WOWLAN_TCP_WAKE_MASK]),
13527 wake_mask_size);
13528 if (tok) {
13529 cfg->tokens_size = tokens_size;
10d5ea5a
KC
13530 cfg->payload_tok = *tok;
13531 memcpy(cfg->payload_tok.token_stream, tok->token_stream,
13532 tokens_size);
2a0e047e
JB
13533 }
13534
13535 trig->tcp = cfg;
13536
13537 return 0;
13538}
13539
8cd4d456
LC
13540static int nl80211_parse_wowlan_nd(struct cfg80211_registered_device *rdev,
13541 const struct wiphy_wowlan_support *wowlan,
13542 struct nlattr *attr,
13543 struct cfg80211_wowlan *trig)
13544{
13545 struct nlattr **tb;
13546 int err;
13547
6396bb22 13548 tb = kcalloc(NUM_NL80211_ATTR, sizeof(*tb), GFP_KERNEL);
8cd4d456
LC
13549 if (!tb)
13550 return -ENOMEM;
13551
13552 if (!(wowlan->flags & WIPHY_WOWLAN_NET_DETECT)) {
13553 err = -EOPNOTSUPP;
13554 goto out;
13555 }
13556
8cb08174
JB
13557 err = nla_parse_nested_deprecated(tb, NL80211_ATTR_MAX, attr,
13558 nl80211_policy, NULL);
8cd4d456
LC
13559 if (err)
13560 goto out;
13561
aad1e812
AVS
13562 trig->nd_config = nl80211_parse_sched_scan(&rdev->wiphy, NULL, tb,
13563 wowlan->max_nd_match_sets);
8cd4d456
LC
13564 err = PTR_ERR_OR_ZERO(trig->nd_config);
13565 if (err)
13566 trig->nd_config = NULL;
13567
13568out:
13569 kfree(tb);
13570 return err;
13571}
13572
ff1b6e69
JB
13573static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
13574{
13575 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13576 struct nlattr *tb[NUM_NL80211_WOWLAN_TRIG];
ff1b6e69 13577 struct cfg80211_wowlan new_triggers = {};
ae33bd81 13578 struct cfg80211_wowlan *ntrig;
964dc9e2 13579 const struct wiphy_wowlan_support *wowlan = rdev->wiphy.wowlan;
ff1b6e69 13580 int err, i;
6abb9cb9 13581 bool prev_enabled = rdev->wiphy.wowlan_config;
98fc4386 13582 bool regular = false;
ff1b6e69 13583
964dc9e2 13584 if (!wowlan)
ff1b6e69
JB
13585 return -EOPNOTSUPP;
13586
ae33bd81
JB
13587 if (!info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS]) {
13588 cfg80211_rdev_free_wowlan(rdev);
6abb9cb9 13589 rdev->wiphy.wowlan_config = NULL;
ae33bd81
JB
13590 goto set_wakeup;
13591 }
ff1b6e69 13592
8cb08174
JB
13593 err = nla_parse_nested_deprecated(tb, MAX_NL80211_WOWLAN_TRIG,
13594 info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS],
13595 nl80211_wowlan_policy, info->extack);
ff1b6e69
JB
13596 if (err)
13597 return err;
13598
13599 if (tb[NL80211_WOWLAN_TRIG_ANY]) {
13600 if (!(wowlan->flags & WIPHY_WOWLAN_ANY))
13601 return -EINVAL;
13602 new_triggers.any = true;
13603 }
13604
13605 if (tb[NL80211_WOWLAN_TRIG_DISCONNECT]) {
13606 if (!(wowlan->flags & WIPHY_WOWLAN_DISCONNECT))
13607 return -EINVAL;
13608 new_triggers.disconnect = true;
98fc4386 13609 regular = true;
ff1b6e69
JB
13610 }
13611
13612 if (tb[NL80211_WOWLAN_TRIG_MAGIC_PKT]) {
13613 if (!(wowlan->flags & WIPHY_WOWLAN_MAGIC_PKT))
13614 return -EINVAL;
13615 new_triggers.magic_pkt = true;
98fc4386 13616 regular = true;
ff1b6e69
JB
13617 }
13618
77dbbb13
JB
13619 if (tb[NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED])
13620 return -EINVAL;
13621
13622 if (tb[NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE]) {
13623 if (!(wowlan->flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE))
13624 return -EINVAL;
13625 new_triggers.gtk_rekey_failure = true;
98fc4386 13626 regular = true;
77dbbb13
JB
13627 }
13628
13629 if (tb[NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST]) {
13630 if (!(wowlan->flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ))
13631 return -EINVAL;
13632 new_triggers.eap_identity_req = true;
98fc4386 13633 regular = true;
77dbbb13
JB
13634 }
13635
13636 if (tb[NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE]) {
13637 if (!(wowlan->flags & WIPHY_WOWLAN_4WAY_HANDSHAKE))
13638 return -EINVAL;
13639 new_triggers.four_way_handshake = true;
98fc4386 13640 regular = true;
77dbbb13
JB
13641 }
13642
13643 if (tb[NL80211_WOWLAN_TRIG_RFKILL_RELEASE]) {
13644 if (!(wowlan->flags & WIPHY_WOWLAN_RFKILL_RELEASE))
13645 return -EINVAL;
13646 new_triggers.rfkill_release = true;
98fc4386 13647 regular = true;
77dbbb13
JB
13648 }
13649
ff1b6e69
JB
13650 if (tb[NL80211_WOWLAN_TRIG_PKT_PATTERN]) {
13651 struct nlattr *pat;
13652 int n_patterns = 0;
bb92d199 13653 int rem, pat_len, mask_len, pkt_offset;
50ac6607 13654 struct nlattr *pat_tb[NUM_NL80211_PKTPAT];
ff1b6e69 13655
98fc4386
JB
13656 regular = true;
13657
ff1b6e69
JB
13658 nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN],
13659 rem)
13660 n_patterns++;
13661 if (n_patterns > wowlan->n_patterns)
13662 return -EINVAL;
13663
13664 new_triggers.patterns = kcalloc(n_patterns,
13665 sizeof(new_triggers.patterns[0]),
13666 GFP_KERNEL);
13667 if (!new_triggers.patterns)
13668 return -ENOMEM;
13669
13670 new_triggers.n_patterns = n_patterns;
13671 i = 0;
13672
13673 nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN],
13674 rem) {
922bd80f
JB
13675 u8 *mask_pat;
13676
8cb08174
JB
13677 err = nla_parse_nested_deprecated(pat_tb,
13678 MAX_NL80211_PKTPAT,
13679 pat,
13680 nl80211_packet_pattern_policy,
13681 info->extack);
95bca62f
JB
13682 if (err)
13683 goto error;
13684
ff1b6e69 13685 err = -EINVAL;
50ac6607
AK
13686 if (!pat_tb[NL80211_PKTPAT_MASK] ||
13687 !pat_tb[NL80211_PKTPAT_PATTERN])
ff1b6e69 13688 goto error;
50ac6607 13689 pat_len = nla_len(pat_tb[NL80211_PKTPAT_PATTERN]);
ff1b6e69 13690 mask_len = DIV_ROUND_UP(pat_len, 8);
50ac6607 13691 if (nla_len(pat_tb[NL80211_PKTPAT_MASK]) != mask_len)
ff1b6e69
JB
13692 goto error;
13693 if (pat_len > wowlan->pattern_max_len ||
13694 pat_len < wowlan->pattern_min_len)
13695 goto error;
13696
50ac6607 13697 if (!pat_tb[NL80211_PKTPAT_OFFSET])
bb92d199
AK
13698 pkt_offset = 0;
13699 else
13700 pkt_offset = nla_get_u32(
50ac6607 13701 pat_tb[NL80211_PKTPAT_OFFSET]);
bb92d199
AK
13702 if (pkt_offset > wowlan->max_pkt_offset)
13703 goto error;
13704 new_triggers.patterns[i].pkt_offset = pkt_offset;
13705
922bd80f
JB
13706 mask_pat = kmalloc(mask_len + pat_len, GFP_KERNEL);
13707 if (!mask_pat) {
ff1b6e69
JB
13708 err = -ENOMEM;
13709 goto error;
13710 }
922bd80f
JB
13711 new_triggers.patterns[i].mask = mask_pat;
13712 memcpy(mask_pat, nla_data(pat_tb[NL80211_PKTPAT_MASK]),
ff1b6e69 13713 mask_len);
922bd80f
JB
13714 mask_pat += mask_len;
13715 new_triggers.patterns[i].pattern = mask_pat;
ff1b6e69 13716 new_triggers.patterns[i].pattern_len = pat_len;
922bd80f 13717 memcpy(mask_pat,
50ac6607 13718 nla_data(pat_tb[NL80211_PKTPAT_PATTERN]),
ff1b6e69
JB
13719 pat_len);
13720 i++;
13721 }
13722 }
13723
2a0e047e 13724 if (tb[NL80211_WOWLAN_TRIG_TCP_CONNECTION]) {
98fc4386 13725 regular = true;
2a0e047e
JB
13726 err = nl80211_parse_wowlan_tcp(
13727 rdev, tb[NL80211_WOWLAN_TRIG_TCP_CONNECTION],
13728 &new_triggers);
13729 if (err)
13730 goto error;
13731 }
13732
8cd4d456 13733 if (tb[NL80211_WOWLAN_TRIG_NET_DETECT]) {
98fc4386 13734 regular = true;
8cd4d456
LC
13735 err = nl80211_parse_wowlan_nd(
13736 rdev, wowlan, tb[NL80211_WOWLAN_TRIG_NET_DETECT],
13737 &new_triggers);
13738 if (err)
13739 goto error;
13740 }
13741
98fc4386
JB
13742 /* The 'any' trigger means the device continues operating more or less
13743 * as in its normal operation mode and wakes up the host on most of the
13744 * normal interrupts (like packet RX, ...)
13745 * It therefore makes little sense to combine with the more constrained
13746 * wakeup trigger modes.
13747 */
13748 if (new_triggers.any && regular) {
13749 err = -EINVAL;
13750 goto error;
13751 }
13752
ae33bd81
JB
13753 ntrig = kmemdup(&new_triggers, sizeof(new_triggers), GFP_KERNEL);
13754 if (!ntrig) {
13755 err = -ENOMEM;
13756 goto error;
ff1b6e69 13757 }
ae33bd81 13758 cfg80211_rdev_free_wowlan(rdev);
6abb9cb9 13759 rdev->wiphy.wowlan_config = ntrig;
ff1b6e69 13760
ae33bd81 13761 set_wakeup:
6abb9cb9
JB
13762 if (rdev->ops->set_wakeup &&
13763 prev_enabled != !!rdev->wiphy.wowlan_config)
13764 rdev_set_wakeup(rdev, rdev->wiphy.wowlan_config);
6d52563f 13765
ff1b6e69
JB
13766 return 0;
13767 error:
13768 for (i = 0; i < new_triggers.n_patterns; i++)
13769 kfree(new_triggers.patterns[i].mask);
13770 kfree(new_triggers.patterns);
2a0e047e
JB
13771 if (new_triggers.tcp && new_triggers.tcp->sock)
13772 sock_release(new_triggers.tcp->sock);
13773 kfree(new_triggers.tcp);
e5dbe070 13774 kfree(new_triggers.nd_config);
ff1b6e69
JB
13775 return err;
13776}
dfb89c56 13777#endif
ff1b6e69 13778
be29b99a
AK
13779static int nl80211_send_coalesce_rules(struct sk_buff *msg,
13780 struct cfg80211_registered_device *rdev)
13781{
13782 struct nlattr *nl_pats, *nl_pat, *nl_rule, *nl_rules;
13783 int i, j, pat_len;
13784 struct cfg80211_coalesce_rules *rule;
13785
13786 if (!rdev->coalesce->n_rules)
13787 return 0;
13788
ae0be8de 13789 nl_rules = nla_nest_start_noflag(msg, NL80211_ATTR_COALESCE_RULE);
be29b99a
AK
13790 if (!nl_rules)
13791 return -ENOBUFS;
13792
13793 for (i = 0; i < rdev->coalesce->n_rules; i++) {
ae0be8de 13794 nl_rule = nla_nest_start_noflag(msg, i + 1);
be29b99a
AK
13795 if (!nl_rule)
13796 return -ENOBUFS;
13797
13798 rule = &rdev->coalesce->rules[i];
13799 if (nla_put_u32(msg, NL80211_ATTR_COALESCE_RULE_DELAY,
13800 rule->delay))
13801 return -ENOBUFS;
13802
13803 if (nla_put_u32(msg, NL80211_ATTR_COALESCE_RULE_CONDITION,
13804 rule->condition))
13805 return -ENOBUFS;
13806
ae0be8de
MK
13807 nl_pats = nla_nest_start_noflag(msg,
13808 NL80211_ATTR_COALESCE_RULE_PKT_PATTERN);
be29b99a
AK
13809 if (!nl_pats)
13810 return -ENOBUFS;
13811
13812 for (j = 0; j < rule->n_patterns; j++) {
ae0be8de 13813 nl_pat = nla_nest_start_noflag(msg, j + 1);
be29b99a
AK
13814 if (!nl_pat)
13815 return -ENOBUFS;
13816 pat_len = rule->patterns[j].pattern_len;
13817 if (nla_put(msg, NL80211_PKTPAT_MASK,
13818 DIV_ROUND_UP(pat_len, 8),
13819 rule->patterns[j].mask) ||
13820 nla_put(msg, NL80211_PKTPAT_PATTERN, pat_len,
13821 rule->patterns[j].pattern) ||
13822 nla_put_u32(msg, NL80211_PKTPAT_OFFSET,
13823 rule->patterns[j].pkt_offset))
13824 return -ENOBUFS;
13825 nla_nest_end(msg, nl_pat);
13826 }
13827 nla_nest_end(msg, nl_pats);
13828 nla_nest_end(msg, nl_rule);
13829 }
13830 nla_nest_end(msg, nl_rules);
13831
13832 return 0;
13833}
13834
13835static int nl80211_get_coalesce(struct sk_buff *skb, struct genl_info *info)
13836{
13837 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13838 struct sk_buff *msg;
13839 void *hdr;
13840
13841 if (!rdev->wiphy.coalesce)
13842 return -EOPNOTSUPP;
13843
13844 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
13845 if (!msg)
13846 return -ENOMEM;
13847
13848 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
13849 NL80211_CMD_GET_COALESCE);
13850 if (!hdr)
13851 goto nla_put_failure;
13852
13853 if (rdev->coalesce && nl80211_send_coalesce_rules(msg, rdev))
13854 goto nla_put_failure;
13855
13856 genlmsg_end(msg, hdr);
13857 return genlmsg_reply(msg, info);
13858
13859nla_put_failure:
13860 nlmsg_free(msg);
13861 return -ENOBUFS;
13862}
13863
13864void cfg80211_rdev_free_coalesce(struct cfg80211_registered_device *rdev)
13865{
13866 struct cfg80211_coalesce *coalesce = rdev->coalesce;
13867 int i, j;
13868 struct cfg80211_coalesce_rules *rule;
13869
13870 if (!coalesce)
13871 return;
13872
13873 for (i = 0; i < coalesce->n_rules; i++) {
13874 rule = &coalesce->rules[i];
13875 for (j = 0; j < rule->n_patterns; j++)
13876 kfree(rule->patterns[j].mask);
13877 kfree(rule->patterns);
13878 }
13879 kfree(coalesce->rules);
13880 kfree(coalesce);
13881 rdev->coalesce = NULL;
13882}
13883
13884static int nl80211_parse_coalesce_rule(struct cfg80211_registered_device *rdev,
13885 struct nlattr *rule,
13886 struct cfg80211_coalesce_rules *new_rule)
13887{
13888 int err, i;
13889 const struct wiphy_coalesce_support *coalesce = rdev->wiphy.coalesce;
13890 struct nlattr *tb[NUM_NL80211_ATTR_COALESCE_RULE], *pat;
13891 int rem, pat_len, mask_len, pkt_offset, n_patterns = 0;
13892 struct nlattr *pat_tb[NUM_NL80211_PKTPAT];
13893
8cb08174
JB
13894 err = nla_parse_nested_deprecated(tb, NL80211_ATTR_COALESCE_RULE_MAX,
13895 rule, nl80211_coalesce_policy, NULL);
be29b99a
AK
13896 if (err)
13897 return err;
13898
13899 if (tb[NL80211_ATTR_COALESCE_RULE_DELAY])
13900 new_rule->delay =
13901 nla_get_u32(tb[NL80211_ATTR_COALESCE_RULE_DELAY]);
13902 if (new_rule->delay > coalesce->max_delay)
13903 return -EINVAL;
13904
13905 if (tb[NL80211_ATTR_COALESCE_RULE_CONDITION])
13906 new_rule->condition =
13907 nla_get_u32(tb[NL80211_ATTR_COALESCE_RULE_CONDITION]);
be29b99a
AK
13908
13909 if (!tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN])
13910 return -EINVAL;
13911
13912 nla_for_each_nested(pat, tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN],
13913 rem)
13914 n_patterns++;
13915 if (n_patterns > coalesce->n_patterns)
13916 return -EINVAL;
13917
13918 new_rule->patterns = kcalloc(n_patterns, sizeof(new_rule->patterns[0]),
13919 GFP_KERNEL);
13920 if (!new_rule->patterns)
13921 return -ENOMEM;
13922
13923 new_rule->n_patterns = n_patterns;
13924 i = 0;
13925
13926 nla_for_each_nested(pat, tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN],
13927 rem) {
922bd80f
JB
13928 u8 *mask_pat;
13929
8cb08174
JB
13930 err = nla_parse_nested_deprecated(pat_tb, MAX_NL80211_PKTPAT,
13931 pat,
13932 nl80211_packet_pattern_policy,
13933 NULL);
95bca62f
JB
13934 if (err)
13935 return err;
13936
be29b99a
AK
13937 if (!pat_tb[NL80211_PKTPAT_MASK] ||
13938 !pat_tb[NL80211_PKTPAT_PATTERN])
13939 return -EINVAL;
13940 pat_len = nla_len(pat_tb[NL80211_PKTPAT_PATTERN]);
13941 mask_len = DIV_ROUND_UP(pat_len, 8);
13942 if (nla_len(pat_tb[NL80211_PKTPAT_MASK]) != mask_len)
13943 return -EINVAL;
13944 if (pat_len > coalesce->pattern_max_len ||
13945 pat_len < coalesce->pattern_min_len)
13946 return -EINVAL;
13947
13948 if (!pat_tb[NL80211_PKTPAT_OFFSET])
13949 pkt_offset = 0;
13950 else
13951 pkt_offset = nla_get_u32(pat_tb[NL80211_PKTPAT_OFFSET]);
13952 if (pkt_offset > coalesce->max_pkt_offset)
13953 return -EINVAL;
13954 new_rule->patterns[i].pkt_offset = pkt_offset;
13955
922bd80f
JB
13956 mask_pat = kmalloc(mask_len + pat_len, GFP_KERNEL);
13957 if (!mask_pat)
be29b99a 13958 return -ENOMEM;
922bd80f
JB
13959
13960 new_rule->patterns[i].mask = mask_pat;
13961 memcpy(mask_pat, nla_data(pat_tb[NL80211_PKTPAT_MASK]),
13962 mask_len);
13963
13964 mask_pat += mask_len;
13965 new_rule->patterns[i].pattern = mask_pat;
be29b99a 13966 new_rule->patterns[i].pattern_len = pat_len;
922bd80f
JB
13967 memcpy(mask_pat, nla_data(pat_tb[NL80211_PKTPAT_PATTERN]),
13968 pat_len);
be29b99a
AK
13969 i++;
13970 }
13971
13972 return 0;
13973}
13974
13975static int nl80211_set_coalesce(struct sk_buff *skb, struct genl_info *info)
13976{
13977 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13978 const struct wiphy_coalesce_support *coalesce = rdev->wiphy.coalesce;
13979 struct cfg80211_coalesce new_coalesce = {};
13980 struct cfg80211_coalesce *n_coalesce;
13981 int err, rem_rule, n_rules = 0, i, j;
13982 struct nlattr *rule;
13983 struct cfg80211_coalesce_rules *tmp_rule;
13984
13985 if (!rdev->wiphy.coalesce || !rdev->ops->set_coalesce)
13986 return -EOPNOTSUPP;
13987
13988 if (!info->attrs[NL80211_ATTR_COALESCE_RULE]) {
13989 cfg80211_rdev_free_coalesce(rdev);
a1056b1b 13990 rdev_set_coalesce(rdev, NULL);
be29b99a
AK
13991 return 0;
13992 }
13993
13994 nla_for_each_nested(rule, info->attrs[NL80211_ATTR_COALESCE_RULE],
13995 rem_rule)
13996 n_rules++;
13997 if (n_rules > coalesce->n_rules)
13998 return -EINVAL;
13999
14000 new_coalesce.rules = kcalloc(n_rules, sizeof(new_coalesce.rules[0]),
14001 GFP_KERNEL);
14002 if (!new_coalesce.rules)
14003 return -ENOMEM;
14004
14005 new_coalesce.n_rules = n_rules;
14006 i = 0;
14007
14008 nla_for_each_nested(rule, info->attrs[NL80211_ATTR_COALESCE_RULE],
14009 rem_rule) {
14010 err = nl80211_parse_coalesce_rule(rdev, rule,
14011 &new_coalesce.rules[i]);
14012 if (err)
14013 goto error;
14014
14015 i++;
14016 }
14017
a1056b1b 14018 err = rdev_set_coalesce(rdev, &new_coalesce);
be29b99a
AK
14019 if (err)
14020 goto error;
14021
14022 n_coalesce = kmemdup(&new_coalesce, sizeof(new_coalesce), GFP_KERNEL);
14023 if (!n_coalesce) {
14024 err = -ENOMEM;
14025 goto error;
14026 }
14027 cfg80211_rdev_free_coalesce(rdev);
14028 rdev->coalesce = n_coalesce;
14029
14030 return 0;
14031error:
14032 for (i = 0; i < new_coalesce.n_rules; i++) {
14033 tmp_rule = &new_coalesce.rules[i];
801ea33a
JB
14034 if (!tmp_rule)
14035 continue;
be29b99a
AK
14036 for (j = 0; j < tmp_rule->n_patterns; j++)
14037 kfree(tmp_rule->patterns[j].mask);
14038 kfree(tmp_rule->patterns);
14039 }
14040 kfree(new_coalesce.rules);
14041
14042 return err;
14043}
14044
e5497d76
JB
14045static int nl80211_set_rekey_data(struct sk_buff *skb, struct genl_info *info)
14046{
14047 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14048 struct net_device *dev = info->user_ptr[1];
14049 struct wireless_dev *wdev = dev->ieee80211_ptr;
14050 struct nlattr *tb[NUM_NL80211_REKEY_DATA];
f495acd8 14051 struct cfg80211_gtk_rekey_data rekey_data = {};
e5497d76
JB
14052 int err;
14053
14054 if (!info->attrs[NL80211_ATTR_REKEY_DATA])
14055 return -EINVAL;
14056
8cb08174
JB
14057 err = nla_parse_nested_deprecated(tb, MAX_NL80211_REKEY_DATA,
14058 info->attrs[NL80211_ATTR_REKEY_DATA],
14059 nl80211_rekey_policy, info->extack);
e5497d76
JB
14060 if (err)
14061 return err;
14062
e785fa0a
VD
14063 if (!tb[NL80211_REKEY_DATA_REPLAY_CTR] || !tb[NL80211_REKEY_DATA_KEK] ||
14064 !tb[NL80211_REKEY_DATA_KCK])
14065 return -EINVAL;
093a48d2
NE
14066 if (nla_len(tb[NL80211_REKEY_DATA_KEK]) != NL80211_KEK_LEN &&
14067 !(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_EXT_KEK_KCK &&
14068 nla_len(tb[NL80211_REKEY_DATA_KEK]) == NL80211_KEK_EXT_LEN))
e5497d76 14069 return -ERANGE;
093a48d2
NE
14070 if (nla_len(tb[NL80211_REKEY_DATA_KCK]) != NL80211_KCK_LEN &&
14071 !(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_EXT_KEK_KCK &&
648fba79
SB
14072 nla_len(tb[NL80211_REKEY_DATA_KCK]) == NL80211_KCK_EXT_LEN) &&
14073 !(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_EXT_KCK_32 &&
14074 nla_len(tb[NL80211_REKEY_DATA_KCK]) == NL80211_KCK_EXT_LEN_32))
e5497d76
JB
14075 return -ERANGE;
14076
78f686ca
JB
14077 rekey_data.kek = nla_data(tb[NL80211_REKEY_DATA_KEK]);
14078 rekey_data.kck = nla_data(tb[NL80211_REKEY_DATA_KCK]);
14079 rekey_data.replay_ctr = nla_data(tb[NL80211_REKEY_DATA_REPLAY_CTR]);
093a48d2
NE
14080 rekey_data.kek_len = nla_len(tb[NL80211_REKEY_DATA_KEK]);
14081 rekey_data.kck_len = nla_len(tb[NL80211_REKEY_DATA_KCK]);
14082 if (tb[NL80211_REKEY_DATA_AKM])
14083 rekey_data.akm = nla_get_u32(tb[NL80211_REKEY_DATA_AKM]);
e5497d76 14084
076fc877
JB
14085 if (!wdev->connected)
14086 return -ENOTCONN;
e5497d76 14087
076fc877
JB
14088 if (!rdev->ops->set_rekey_data)
14089 return -EOPNOTSUPP;
e5497d76 14090
076fc877 14091 return rdev_set_rekey_data(rdev, dev, &rekey_data);
e5497d76
JB
14092}
14093
28946da7
JB
14094static int nl80211_register_unexpected_frame(struct sk_buff *skb,
14095 struct genl_info *info)
14096{
14097 struct net_device *dev = info->user_ptr[1];
14098 struct wireless_dev *wdev = dev->ieee80211_ptr;
14099
14100 if (wdev->iftype != NL80211_IFTYPE_AP &&
14101 wdev->iftype != NL80211_IFTYPE_P2P_GO)
14102 return -EINVAL;
14103
15e47304 14104 if (wdev->ap_unexpected_nlportid)
28946da7
JB
14105 return -EBUSY;
14106
15e47304 14107 wdev->ap_unexpected_nlportid = info->snd_portid;
28946da7
JB
14108 return 0;
14109}
14110
7f6cf311
JB
14111static int nl80211_probe_client(struct sk_buff *skb,
14112 struct genl_info *info)
14113{
14114 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14115 struct net_device *dev = info->user_ptr[1];
14116 struct wireless_dev *wdev = dev->ieee80211_ptr;
14117 struct sk_buff *msg;
14118 void *hdr;
14119 const u8 *addr;
14120 u64 cookie;
14121 int err;
14122
14123 if (wdev->iftype != NL80211_IFTYPE_AP &&
14124 wdev->iftype != NL80211_IFTYPE_P2P_GO)
14125 return -EOPNOTSUPP;
14126
14127 if (!info->attrs[NL80211_ATTR_MAC])
14128 return -EINVAL;
14129
14130 if (!rdev->ops->probe_client)
14131 return -EOPNOTSUPP;
14132
14133 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
14134 if (!msg)
14135 return -ENOMEM;
14136
15e47304 14137 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
7f6cf311 14138 NL80211_CMD_PROBE_CLIENT);
cb35fba3
DC
14139 if (!hdr) {
14140 err = -ENOBUFS;
7f6cf311
JB
14141 goto free_msg;
14142 }
14143
14144 addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
14145
e35e4d28 14146 err = rdev_probe_client(rdev, dev, addr, &cookie);
7f6cf311
JB
14147 if (err)
14148 goto free_msg;
14149
2dad624e
ND
14150 if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
14151 NL80211_ATTR_PAD))
9360ffd1 14152 goto nla_put_failure;
7f6cf311
JB
14153
14154 genlmsg_end(msg, hdr);
14155
14156 return genlmsg_reply(msg, info);
14157
14158 nla_put_failure:
14159 err = -ENOBUFS;
14160 free_msg:
14161 nlmsg_free(msg);
14162 return err;
14163}
14164
5e760230
JB
14165static int nl80211_register_beacons(struct sk_buff *skb, struct genl_info *info)
14166{
14167 struct cfg80211_registered_device *rdev = info->user_ptr[0];
37c73b5f
BG
14168 struct cfg80211_beacon_registration *reg, *nreg;
14169 int rv;
5e760230
JB
14170
14171 if (!(rdev->wiphy.flags & WIPHY_FLAG_REPORTS_OBSS))
14172 return -EOPNOTSUPP;
14173
37c73b5f
BG
14174 nreg = kzalloc(sizeof(*nreg), GFP_KERNEL);
14175 if (!nreg)
14176 return -ENOMEM;
14177
14178 /* First, check if already registered. */
14179 spin_lock_bh(&rdev->beacon_registrations_lock);
14180 list_for_each_entry(reg, &rdev->beacon_registrations, list) {
14181 if (reg->nlportid == info->snd_portid) {
14182 rv = -EALREADY;
14183 goto out_err;
14184 }
14185 }
14186 /* Add it to the list */
14187 nreg->nlportid = info->snd_portid;
14188 list_add(&nreg->list, &rdev->beacon_registrations);
5e760230 14189
37c73b5f 14190 spin_unlock_bh(&rdev->beacon_registrations_lock);
5e760230
JB
14191
14192 return 0;
37c73b5f
BG
14193out_err:
14194 spin_unlock_bh(&rdev->beacon_registrations_lock);
14195 kfree(nreg);
14196 return rv;
5e760230
JB
14197}
14198
98104fde
JB
14199static int nl80211_start_p2p_device(struct sk_buff *skb, struct genl_info *info)
14200{
14201 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14202 struct wireless_dev *wdev = info->user_ptr[1];
14203 int err;
14204
14205 if (!rdev->ops->start_p2p_device)
14206 return -EOPNOTSUPP;
14207
14208 if (wdev->iftype != NL80211_IFTYPE_P2P_DEVICE)
14209 return -EOPNOTSUPP;
14210
73c7da3d 14211 if (wdev_running(wdev))
98104fde
JB
14212 return 0;
14213
358ae888 14214 if (rfkill_blocked(rdev->wiphy.rfkill))
b6a55015 14215 return -ERFKILL;
98104fde 14216
eeb126e9 14217 err = rdev_start_p2p_device(rdev, wdev);
98104fde
JB
14218 if (err)
14219 return err;
14220
73c7da3d 14221 wdev->is_running = true;
98104fde 14222 rdev->opencount++;
98104fde
JB
14223
14224 return 0;
14225}
14226
14227static int nl80211_stop_p2p_device(struct sk_buff *skb, struct genl_info *info)
14228{
14229 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14230 struct wireless_dev *wdev = info->user_ptr[1];
14231
14232 if (wdev->iftype != NL80211_IFTYPE_P2P_DEVICE)
14233 return -EOPNOTSUPP;
14234
14235 if (!rdev->ops->stop_p2p_device)
14236 return -EOPNOTSUPP;
14237
f9f47529 14238 cfg80211_stop_p2p_device(rdev, wdev);
98104fde
JB
14239
14240 return 0;
14241}
14242
cb3b7d87
AB
14243static int nl80211_start_nan(struct sk_buff *skb, struct genl_info *info)
14244{
14245 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14246 struct wireless_dev *wdev = info->user_ptr[1];
14247 struct cfg80211_nan_conf conf = {};
14248 int err;
14249
14250 if (wdev->iftype != NL80211_IFTYPE_NAN)
14251 return -EOPNOTSUPP;
14252
eeb04a96 14253 if (wdev_running(wdev))
cb3b7d87
AB
14254 return -EEXIST;
14255
358ae888 14256 if (rfkill_blocked(rdev->wiphy.rfkill))
cb3b7d87
AB
14257 return -ERFKILL;
14258
14259 if (!info->attrs[NL80211_ATTR_NAN_MASTER_PREF])
14260 return -EINVAL;
14261
cb3b7d87
AB
14262 conf.master_pref =
14263 nla_get_u8(info->attrs[NL80211_ATTR_NAN_MASTER_PREF]);
cb3b7d87 14264
8585989d
LC
14265 if (info->attrs[NL80211_ATTR_BANDS]) {
14266 u32 bands = nla_get_u32(info->attrs[NL80211_ATTR_BANDS]);
14267
14268 if (bands & ~(u32)wdev->wiphy->nan_supported_bands)
14269 return -EOPNOTSUPP;
14270
14271 if (bands && !(bands & BIT(NL80211_BAND_2GHZ)))
14272 return -EINVAL;
14273
14274 conf.bands = bands;
14275 }
cb3b7d87
AB
14276
14277 err = rdev_start_nan(rdev, wdev, &conf);
14278 if (err)
14279 return err;
14280
73c7da3d 14281 wdev->is_running = true;
cb3b7d87
AB
14282 rdev->opencount++;
14283
14284 return 0;
14285}
14286
14287static int nl80211_stop_nan(struct sk_buff *skb, struct genl_info *info)
14288{
14289 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14290 struct wireless_dev *wdev = info->user_ptr[1];
14291
14292 if (wdev->iftype != NL80211_IFTYPE_NAN)
14293 return -EOPNOTSUPP;
14294
14295 cfg80211_stop_nan(rdev, wdev);
14296
14297 return 0;
14298}
14299
a442b761
AB
14300static int validate_nan_filter(struct nlattr *filter_attr)
14301{
14302 struct nlattr *attr;
14303 int len = 0, n_entries = 0, rem;
14304
14305 nla_for_each_nested(attr, filter_attr, rem) {
14306 len += nla_len(attr);
14307 n_entries++;
14308 }
14309
14310 if (len >= U8_MAX)
14311 return -EINVAL;
14312
14313 return n_entries;
14314}
14315
14316static int handle_nan_filter(struct nlattr *attr_filter,
14317 struct cfg80211_nan_func *func,
14318 bool tx)
14319{
14320 struct nlattr *attr;
14321 int n_entries, rem, i;
14322 struct cfg80211_nan_func_filter *filter;
14323
14324 n_entries = validate_nan_filter(attr_filter);
14325 if (n_entries < 0)
14326 return n_entries;
14327
14328 BUILD_BUG_ON(sizeof(*func->rx_filters) != sizeof(*func->tx_filters));
14329
14330 filter = kcalloc(n_entries, sizeof(*func->rx_filters), GFP_KERNEL);
14331 if (!filter)
14332 return -ENOMEM;
14333
14334 i = 0;
14335 nla_for_each_nested(attr, attr_filter, rem) {
b15ca182 14336 filter[i].filter = nla_memdup(attr, GFP_KERNEL);
6ad27f52
JJ
14337 if (!filter[i].filter)
14338 goto err;
14339
a442b761
AB
14340 filter[i].len = nla_len(attr);
14341 i++;
14342 }
14343 if (tx) {
14344 func->num_tx_filters = n_entries;
14345 func->tx_filters = filter;
14346 } else {
14347 func->num_rx_filters = n_entries;
14348 func->rx_filters = filter;
14349 }
14350
14351 return 0;
6ad27f52
JJ
14352
14353err:
14354 i = 0;
14355 nla_for_each_nested(attr, attr_filter, rem) {
14356 kfree(filter[i].filter);
14357 i++;
14358 }
14359 kfree(filter);
14360 return -ENOMEM;
a442b761
AB
14361}
14362
14363static int nl80211_nan_add_func(struct sk_buff *skb,
14364 struct genl_info *info)
14365{
14366 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14367 struct wireless_dev *wdev = info->user_ptr[1];
14368 struct nlattr *tb[NUM_NL80211_NAN_FUNC_ATTR], *func_attr;
14369 struct cfg80211_nan_func *func;
14370 struct sk_buff *msg = NULL;
14371 void *hdr = NULL;
14372 int err = 0;
14373
14374 if (wdev->iftype != NL80211_IFTYPE_NAN)
14375 return -EOPNOTSUPP;
14376
73c7da3d 14377 if (!wdev_running(wdev))
a442b761
AB
14378 return -ENOTCONN;
14379
14380 if (!info->attrs[NL80211_ATTR_NAN_FUNC])
14381 return -EINVAL;
14382
8cb08174
JB
14383 err = nla_parse_nested_deprecated(tb, NL80211_NAN_FUNC_ATTR_MAX,
14384 info->attrs[NL80211_ATTR_NAN_FUNC],
14385 nl80211_nan_func_policy,
14386 info->extack);
a442b761
AB
14387 if (err)
14388 return err;
14389
14390 func = kzalloc(sizeof(*func), GFP_KERNEL);
14391 if (!func)
14392 return -ENOMEM;
14393
b60ad348 14394 func->cookie = cfg80211_assign_cookie(rdev);
a442b761 14395
cb9abd48 14396 if (!tb[NL80211_NAN_FUNC_TYPE]) {
a442b761
AB
14397 err = -EINVAL;
14398 goto out;
14399 }
14400
14401
14402 func->type = nla_get_u8(tb[NL80211_NAN_FUNC_TYPE]);
14403
14404 if (!tb[NL80211_NAN_FUNC_SERVICE_ID]) {
14405 err = -EINVAL;
14406 goto out;
14407 }
14408
14409 memcpy(func->service_id, nla_data(tb[NL80211_NAN_FUNC_SERVICE_ID]),
14410 sizeof(func->service_id));
14411
14412 func->close_range =
14413 nla_get_flag(tb[NL80211_NAN_FUNC_CLOSE_RANGE]);
14414
14415 if (tb[NL80211_NAN_FUNC_SERVICE_INFO]) {
14416 func->serv_spec_info_len =
14417 nla_len(tb[NL80211_NAN_FUNC_SERVICE_INFO]);
14418 func->serv_spec_info =
14419 kmemdup(nla_data(tb[NL80211_NAN_FUNC_SERVICE_INFO]),
14420 func->serv_spec_info_len,
14421 GFP_KERNEL);
14422 if (!func->serv_spec_info) {
14423 err = -ENOMEM;
14424 goto out;
14425 }
14426 }
14427
14428 if (tb[NL80211_NAN_FUNC_TTL])
14429 func->ttl = nla_get_u32(tb[NL80211_NAN_FUNC_TTL]);
14430
14431 switch (func->type) {
14432 case NL80211_NAN_FUNC_PUBLISH:
14433 if (!tb[NL80211_NAN_FUNC_PUBLISH_TYPE]) {
14434 err = -EINVAL;
14435 goto out;
14436 }
14437
14438 func->publish_type =
14439 nla_get_u8(tb[NL80211_NAN_FUNC_PUBLISH_TYPE]);
14440 func->publish_bcast =
14441 nla_get_flag(tb[NL80211_NAN_FUNC_PUBLISH_BCAST]);
14442
14443 if ((!(func->publish_type & NL80211_NAN_SOLICITED_PUBLISH)) &&
14444 func->publish_bcast) {
14445 err = -EINVAL;
14446 goto out;
14447 }
14448 break;
14449 case NL80211_NAN_FUNC_SUBSCRIBE:
14450 func->subscribe_active =
14451 nla_get_flag(tb[NL80211_NAN_FUNC_SUBSCRIBE_ACTIVE]);
14452 break;
14453 case NL80211_NAN_FUNC_FOLLOW_UP:
14454 if (!tb[NL80211_NAN_FUNC_FOLLOW_UP_ID] ||
3ea15452
HC
14455 !tb[NL80211_NAN_FUNC_FOLLOW_UP_REQ_ID] ||
14456 !tb[NL80211_NAN_FUNC_FOLLOW_UP_DEST]) {
a442b761
AB
14457 err = -EINVAL;
14458 goto out;
14459 }
14460
14461 func->followup_id =
14462 nla_get_u8(tb[NL80211_NAN_FUNC_FOLLOW_UP_ID]);
14463 func->followup_reqid =
14464 nla_get_u8(tb[NL80211_NAN_FUNC_FOLLOW_UP_REQ_ID]);
14465 memcpy(func->followup_dest.addr,
14466 nla_data(tb[NL80211_NAN_FUNC_FOLLOW_UP_DEST]),
14467 sizeof(func->followup_dest.addr));
14468 if (func->ttl) {
14469 err = -EINVAL;
14470 goto out;
14471 }
14472 break;
14473 default:
14474 err = -EINVAL;
14475 goto out;
14476 }
14477
14478 if (tb[NL80211_NAN_FUNC_SRF]) {
14479 struct nlattr *srf_tb[NUM_NL80211_NAN_SRF_ATTR];
14480
8cb08174
JB
14481 err = nla_parse_nested_deprecated(srf_tb,
14482 NL80211_NAN_SRF_ATTR_MAX,
14483 tb[NL80211_NAN_FUNC_SRF],
14484 nl80211_nan_srf_policy,
14485 info->extack);
a442b761
AB
14486 if (err)
14487 goto out;
14488
14489 func->srf_include =
14490 nla_get_flag(srf_tb[NL80211_NAN_SRF_INCLUDE]);
14491
14492 if (srf_tb[NL80211_NAN_SRF_BF]) {
14493 if (srf_tb[NL80211_NAN_SRF_MAC_ADDRS] ||
14494 !srf_tb[NL80211_NAN_SRF_BF_IDX]) {
14495 err = -EINVAL;
14496 goto out;
14497 }
14498
14499 func->srf_bf_len =
14500 nla_len(srf_tb[NL80211_NAN_SRF_BF]);
14501 func->srf_bf =
14502 kmemdup(nla_data(srf_tb[NL80211_NAN_SRF_BF]),
14503 func->srf_bf_len, GFP_KERNEL);
14504 if (!func->srf_bf) {
14505 err = -ENOMEM;
14506 goto out;
14507 }
14508
14509 func->srf_bf_idx =
14510 nla_get_u8(srf_tb[NL80211_NAN_SRF_BF_IDX]);
14511 } else {
14512 struct nlattr *attr, *mac_attr =
14513 srf_tb[NL80211_NAN_SRF_MAC_ADDRS];
14514 int n_entries, rem, i = 0;
14515
14516 if (!mac_attr) {
14517 err = -EINVAL;
14518 goto out;
14519 }
14520
14521 n_entries = validate_acl_mac_addrs(mac_attr);
14522 if (n_entries <= 0) {
14523 err = -EINVAL;
14524 goto out;
14525 }
14526
14527 func->srf_num_macs = n_entries;
14528 func->srf_macs =
6396bb22 14529 kcalloc(n_entries, sizeof(*func->srf_macs),
a442b761
AB
14530 GFP_KERNEL);
14531 if (!func->srf_macs) {
14532 err = -ENOMEM;
14533 goto out;
14534 }
14535
14536 nla_for_each_nested(attr, mac_attr, rem)
14537 memcpy(func->srf_macs[i++].addr, nla_data(attr),
14538 sizeof(*func->srf_macs));
14539 }
14540 }
14541
14542 if (tb[NL80211_NAN_FUNC_TX_MATCH_FILTER]) {
14543 err = handle_nan_filter(tb[NL80211_NAN_FUNC_TX_MATCH_FILTER],
14544 func, true);
14545 if (err)
14546 goto out;
14547 }
14548
14549 if (tb[NL80211_NAN_FUNC_RX_MATCH_FILTER]) {
14550 err = handle_nan_filter(tb[NL80211_NAN_FUNC_RX_MATCH_FILTER],
14551 func, false);
14552 if (err)
14553 goto out;
14554 }
14555
14556 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
14557 if (!msg) {
14558 err = -ENOMEM;
14559 goto out;
14560 }
14561
14562 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
14563 NL80211_CMD_ADD_NAN_FUNCTION);
14564 /* This can't really happen - we just allocated 4KB */
14565 if (WARN_ON(!hdr)) {
14566 err = -ENOMEM;
14567 goto out;
14568 }
14569
14570 err = rdev_add_nan_func(rdev, wdev, func);
14571out:
14572 if (err < 0) {
14573 cfg80211_free_nan_func(func);
14574 nlmsg_free(msg);
14575 return err;
14576 }
14577
14578 /* propagate the instance id and cookie to userspace */
14579 if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, func->cookie,
14580 NL80211_ATTR_PAD))
14581 goto nla_put_failure;
14582
ae0be8de 14583 func_attr = nla_nest_start_noflag(msg, NL80211_ATTR_NAN_FUNC);
a442b761
AB
14584 if (!func_attr)
14585 goto nla_put_failure;
14586
14587 if (nla_put_u8(msg, NL80211_NAN_FUNC_INSTANCE_ID,
14588 func->instance_id))
14589 goto nla_put_failure;
14590
14591 nla_nest_end(msg, func_attr);
14592
14593 genlmsg_end(msg, hdr);
14594 return genlmsg_reply(msg, info);
14595
14596nla_put_failure:
14597 nlmsg_free(msg);
14598 return -ENOBUFS;
14599}
14600
14601static int nl80211_nan_del_func(struct sk_buff *skb,
14602 struct genl_info *info)
14603{
14604 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14605 struct wireless_dev *wdev = info->user_ptr[1];
14606 u64 cookie;
14607
14608 if (wdev->iftype != NL80211_IFTYPE_NAN)
14609 return -EOPNOTSUPP;
14610
73c7da3d 14611 if (!wdev_running(wdev))
a442b761
AB
14612 return -ENOTCONN;
14613
14614 if (!info->attrs[NL80211_ATTR_COOKIE])
14615 return -EINVAL;
14616
a442b761
AB
14617 cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);
14618
14619 rdev_del_nan_func(rdev, wdev, cookie);
14620
14621 return 0;
14622}
14623
a5a9dcf2
AB
14624static int nl80211_nan_change_config(struct sk_buff *skb,
14625 struct genl_info *info)
14626{
14627 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14628 struct wireless_dev *wdev = info->user_ptr[1];
14629 struct cfg80211_nan_conf conf = {};
14630 u32 changed = 0;
14631
14632 if (wdev->iftype != NL80211_IFTYPE_NAN)
14633 return -EOPNOTSUPP;
14634
73c7da3d 14635 if (!wdev_running(wdev))
a5a9dcf2
AB
14636 return -ENOTCONN;
14637
14638 if (info->attrs[NL80211_ATTR_NAN_MASTER_PREF]) {
14639 conf.master_pref =
14640 nla_get_u8(info->attrs[NL80211_ATTR_NAN_MASTER_PREF]);
14641 if (conf.master_pref <= 1 || conf.master_pref == 255)
14642 return -EINVAL;
14643
14644 changed |= CFG80211_NAN_CONF_CHANGED_PREF;
14645 }
14646
8585989d
LC
14647 if (info->attrs[NL80211_ATTR_BANDS]) {
14648 u32 bands = nla_get_u32(info->attrs[NL80211_ATTR_BANDS]);
14649
14650 if (bands & ~(u32)wdev->wiphy->nan_supported_bands)
14651 return -EOPNOTSUPP;
14652
14653 if (bands && !(bands & BIT(NL80211_BAND_2GHZ)))
14654 return -EINVAL;
14655
14656 conf.bands = bands;
14657 changed |= CFG80211_NAN_CONF_CHANGED_BANDS;
a5a9dcf2
AB
14658 }
14659
14660 if (!changed)
14661 return -EINVAL;
14662
14663 return rdev_nan_change_conf(rdev, wdev, &conf, changed);
14664}
14665
50bcd31d
AB
14666void cfg80211_nan_match(struct wireless_dev *wdev,
14667 struct cfg80211_nan_match_params *match, gfp_t gfp)
14668{
14669 struct wiphy *wiphy = wdev->wiphy;
14670 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
14671 struct nlattr *match_attr, *local_func_attr, *peer_func_attr;
14672 struct sk_buff *msg;
14673 void *hdr;
14674
14675 if (WARN_ON(!match->inst_id || !match->peer_inst_id || !match->addr))
14676 return;
14677
14678 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
14679 if (!msg)
14680 return;
14681
14682 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NAN_MATCH);
14683 if (!hdr) {
14684 nlmsg_free(msg);
14685 return;
14686 }
14687
14688 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
14689 (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
14690 wdev->netdev->ifindex)) ||
14691 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
14692 NL80211_ATTR_PAD))
14693 goto nla_put_failure;
14694
14695 if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, match->cookie,
14696 NL80211_ATTR_PAD) ||
14697 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, match->addr))
14698 goto nla_put_failure;
14699
ae0be8de 14700 match_attr = nla_nest_start_noflag(msg, NL80211_ATTR_NAN_MATCH);
50bcd31d
AB
14701 if (!match_attr)
14702 goto nla_put_failure;
14703
ae0be8de
MK
14704 local_func_attr = nla_nest_start_noflag(msg,
14705 NL80211_NAN_MATCH_FUNC_LOCAL);
50bcd31d
AB
14706 if (!local_func_attr)
14707 goto nla_put_failure;
14708
14709 if (nla_put_u8(msg, NL80211_NAN_FUNC_INSTANCE_ID, match->inst_id))
14710 goto nla_put_failure;
14711
14712 nla_nest_end(msg, local_func_attr);
14713
ae0be8de
MK
14714 peer_func_attr = nla_nest_start_noflag(msg,
14715 NL80211_NAN_MATCH_FUNC_PEER);
50bcd31d
AB
14716 if (!peer_func_attr)
14717 goto nla_put_failure;
14718
14719 if (nla_put_u8(msg, NL80211_NAN_FUNC_TYPE, match->type) ||
14720 nla_put_u8(msg, NL80211_NAN_FUNC_INSTANCE_ID, match->peer_inst_id))
14721 goto nla_put_failure;
14722
14723 if (match->info && match->info_len &&
14724 nla_put(msg, NL80211_NAN_FUNC_SERVICE_INFO, match->info_len,
14725 match->info))
14726 goto nla_put_failure;
14727
14728 nla_nest_end(msg, peer_func_attr);
14729 nla_nest_end(msg, match_attr);
14730 genlmsg_end(msg, hdr);
14731
14732 if (!wdev->owner_nlportid)
14733 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
14734 msg, 0, NL80211_MCGRP_NAN, gfp);
14735 else
14736 genlmsg_unicast(wiphy_net(&rdev->wiphy), msg,
14737 wdev->owner_nlportid);
14738
14739 return;
14740
14741nla_put_failure:
14742 nlmsg_free(msg);
14743}
14744EXPORT_SYMBOL(cfg80211_nan_match);
14745
368e5a7b
AB
14746void cfg80211_nan_func_terminated(struct wireless_dev *wdev,
14747 u8 inst_id,
14748 enum nl80211_nan_func_term_reason reason,
14749 u64 cookie, gfp_t gfp)
14750{
14751 struct wiphy *wiphy = wdev->wiphy;
14752 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
14753 struct sk_buff *msg;
14754 struct nlattr *func_attr;
14755 void *hdr;
14756
14757 if (WARN_ON(!inst_id))
14758 return;
14759
14760 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
14761 if (!msg)
14762 return;
14763
14764 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_DEL_NAN_FUNCTION);
14765 if (!hdr) {
14766 nlmsg_free(msg);
14767 return;
14768 }
14769
14770 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
14771 (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
14772 wdev->netdev->ifindex)) ||
14773 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
14774 NL80211_ATTR_PAD))
14775 goto nla_put_failure;
14776
14777 if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
14778 NL80211_ATTR_PAD))
14779 goto nla_put_failure;
14780
ae0be8de 14781 func_attr = nla_nest_start_noflag(msg, NL80211_ATTR_NAN_FUNC);
368e5a7b
AB
14782 if (!func_attr)
14783 goto nla_put_failure;
14784
14785 if (nla_put_u8(msg, NL80211_NAN_FUNC_INSTANCE_ID, inst_id) ||
14786 nla_put_u8(msg, NL80211_NAN_FUNC_TERM_REASON, reason))
14787 goto nla_put_failure;
14788
14789 nla_nest_end(msg, func_attr);
14790 genlmsg_end(msg, hdr);
14791
14792 if (!wdev->owner_nlportid)
14793 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
14794 msg, 0, NL80211_MCGRP_NAN, gfp);
14795 else
14796 genlmsg_unicast(wiphy_net(&rdev->wiphy), msg,
14797 wdev->owner_nlportid);
14798
14799 return;
14800
14801nla_put_failure:
14802 nlmsg_free(msg);
14803}
14804EXPORT_SYMBOL(cfg80211_nan_func_terminated);
14805
3713b4e3
JB
14806static int nl80211_get_protocol_features(struct sk_buff *skb,
14807 struct genl_info *info)
14808{
14809 void *hdr;
14810 struct sk_buff *msg;
14811
14812 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
14813 if (!msg)
14814 return -ENOMEM;
14815
14816 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
14817 NL80211_CMD_GET_PROTOCOL_FEATURES);
14818 if (!hdr)
14819 goto nla_put_failure;
14820
14821 if (nla_put_u32(msg, NL80211_ATTR_PROTOCOL_FEATURES,
14822 NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP))
14823 goto nla_put_failure;
14824
14825 genlmsg_end(msg, hdr);
14826 return genlmsg_reply(msg, info);
14827
14828 nla_put_failure:
14829 kfree_skb(msg);
14830 return -ENOBUFS;
14831}
14832
355199e0
JM
14833static int nl80211_update_ft_ies(struct sk_buff *skb, struct genl_info *info)
14834{
14835 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14836 struct cfg80211_update_ft_ies_params ft_params;
14837 struct net_device *dev = info->user_ptr[1];
14838
14839 if (!rdev->ops->update_ft_ies)
14840 return -EOPNOTSUPP;
14841
14842 if (!info->attrs[NL80211_ATTR_MDID] ||
3d7af878 14843 !info->attrs[NL80211_ATTR_IE])
355199e0
JM
14844 return -EINVAL;
14845
14846 memset(&ft_params, 0, sizeof(ft_params));
14847 ft_params.md = nla_get_u16(info->attrs[NL80211_ATTR_MDID]);
14848 ft_params.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
14849 ft_params.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
14850
14851 return rdev_update_ft_ies(rdev, dev, &ft_params);
14852}
14853
5de17984
AS
14854static int nl80211_crit_protocol_start(struct sk_buff *skb,
14855 struct genl_info *info)
14856{
14857 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14858 struct wireless_dev *wdev = info->user_ptr[1];
14859 enum nl80211_crit_proto_id proto = NL80211_CRIT_PROTO_UNSPEC;
14860 u16 duration;
14861 int ret;
14862
14863 if (!rdev->ops->crit_proto_start)
14864 return -EOPNOTSUPP;
14865
14866 if (WARN_ON(!rdev->ops->crit_proto_stop))
14867 return -EINVAL;
14868
14869 if (rdev->crit_proto_nlportid)
14870 return -EBUSY;
14871
14872 /* determine protocol if provided */
14873 if (info->attrs[NL80211_ATTR_CRIT_PROT_ID])
14874 proto = nla_get_u16(info->attrs[NL80211_ATTR_CRIT_PROT_ID]);
14875
14876 if (proto >= NUM_NL80211_CRIT_PROTO)
14877 return -EINVAL;
14878
14879 /* timeout must be provided */
14880 if (!info->attrs[NL80211_ATTR_MAX_CRIT_PROT_DURATION])
14881 return -EINVAL;
14882
14883 duration =
14884 nla_get_u16(info->attrs[NL80211_ATTR_MAX_CRIT_PROT_DURATION]);
14885
5de17984
AS
14886 ret = rdev_crit_proto_start(rdev, wdev, proto, duration);
14887 if (!ret)
14888 rdev->crit_proto_nlportid = info->snd_portid;
14889
14890 return ret;
14891}
14892
14893static int nl80211_crit_protocol_stop(struct sk_buff *skb,
14894 struct genl_info *info)
14895{
14896 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14897 struct wireless_dev *wdev = info->user_ptr[1];
14898
14899 if (!rdev->ops->crit_proto_stop)
14900 return -EOPNOTSUPP;
14901
14902 if (rdev->crit_proto_nlportid) {
14903 rdev->crit_proto_nlportid = 0;
14904 rdev_crit_proto_stop(rdev, wdev);
14905 }
14906 return 0;
14907}
14908
901bb989
JB
14909static int nl80211_vendor_check_policy(const struct wiphy_vendor_command *vcmd,
14910 struct nlattr *attr,
14911 struct netlink_ext_ack *extack)
14912{
14913 if (vcmd->policy == VENDOR_CMD_RAW_DATA) {
14914 if (attr->nla_type & NLA_F_NESTED) {
14915 NL_SET_ERR_MSG_ATTR(extack, attr,
14916 "unexpected nested data");
14917 return -EINVAL;
14918 }
14919
14920 return 0;
14921 }
14922
14923 if (!(attr->nla_type & NLA_F_NESTED)) {
14924 NL_SET_ERR_MSG_ATTR(extack, attr, "expected nested data");
14925 return -EINVAL;
14926 }
14927
32d5109a 14928 return nla_validate_nested(attr, vcmd->maxattr, vcmd->policy, extack);
901bb989
JB
14929}
14930
ad7e718c
JB
14931static int nl80211_vendor_cmd(struct sk_buff *skb, struct genl_info *info)
14932{
14933 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14934 struct wireless_dev *wdev =
a05829a7
JB
14935 __cfg80211_wdev_from_attrs(rdev, genl_info_net(info),
14936 info->attrs);
ad7e718c
JB
14937 int i, err;
14938 u32 vid, subcmd;
14939
14940 if (!rdev->wiphy.vendor_commands)
14941 return -EOPNOTSUPP;
14942
14943 if (IS_ERR(wdev)) {
14944 err = PTR_ERR(wdev);
14945 if (err != -EINVAL)
14946 return err;
14947 wdev = NULL;
14948 } else if (wdev->wiphy != &rdev->wiphy) {
14949 return -EINVAL;
14950 }
14951
14952 if (!info->attrs[NL80211_ATTR_VENDOR_ID] ||
14953 !info->attrs[NL80211_ATTR_VENDOR_SUBCMD])
14954 return -EINVAL;
14955
14956 vid = nla_get_u32(info->attrs[NL80211_ATTR_VENDOR_ID]);
14957 subcmd = nla_get_u32(info->attrs[NL80211_ATTR_VENDOR_SUBCMD]);
14958 for (i = 0; i < rdev->wiphy.n_vendor_commands; i++) {
14959 const struct wiphy_vendor_command *vcmd;
14960 void *data = NULL;
14961 int len = 0;
14962
14963 vcmd = &rdev->wiphy.vendor_commands[i];
14964
14965 if (vcmd->info.vendor_id != vid || vcmd->info.subcmd != subcmd)
14966 continue;
14967
14968 if (vcmd->flags & (WIPHY_VENDOR_CMD_NEED_WDEV |
14969 WIPHY_VENDOR_CMD_NEED_NETDEV)) {
14970 if (!wdev)
14971 return -EINVAL;
14972 if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_NETDEV &&
14973 !wdev->netdev)
14974 return -EINVAL;
14975
14976 if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_RUNNING) {
73c7da3d 14977 if (!wdev_running(wdev))
ad7e718c
JB
14978 return -ENETDOWN;
14979 }
14980 } else {
14981 wdev = NULL;
14982 }
14983
4052d3d2
JS
14984 if (!vcmd->doit)
14985 return -EOPNOTSUPP;
14986
ad7e718c
JB
14987 if (info->attrs[NL80211_ATTR_VENDOR_DATA]) {
14988 data = nla_data(info->attrs[NL80211_ATTR_VENDOR_DATA]);
14989 len = nla_len(info->attrs[NL80211_ATTR_VENDOR_DATA]);
901bb989
JB
14990
14991 err = nl80211_vendor_check_policy(vcmd,
14992 info->attrs[NL80211_ATTR_VENDOR_DATA],
14993 info->extack);
14994 if (err)
14995 return err;
ad7e718c
JB
14996 }
14997
14998 rdev->cur_cmd_info = info;
901bb989 14999 err = vcmd->doit(&rdev->wiphy, wdev, data, len);
ad7e718c
JB
15000 rdev->cur_cmd_info = NULL;
15001 return err;
15002 }
15003
15004 return -EOPNOTSUPP;
15005}
15006
7bdbe400
JB
15007static int nl80211_prepare_vendor_dump(struct sk_buff *skb,
15008 struct netlink_callback *cb,
15009 struct cfg80211_registered_device **rdev,
15010 struct wireless_dev **wdev)
15011{
50508d94 15012 struct nlattr **attrbuf;
7bdbe400
JB
15013 u32 vid, subcmd;
15014 unsigned int i;
15015 int vcmd_idx = -1;
15016 int err;
15017 void *data = NULL;
15018 unsigned int data_len = 0;
15019
7bdbe400
JB
15020 if (cb->args[0]) {
15021 /* subtract the 1 again here */
15022 struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0] - 1);
15023 struct wireless_dev *tmp;
15024
ea90e0dc
JB
15025 if (!wiphy)
15026 return -ENODEV;
7bdbe400
JB
15027 *rdev = wiphy_to_rdev(wiphy);
15028 *wdev = NULL;
15029
15030 if (cb->args[1]) {
53873f13 15031 list_for_each_entry(tmp, &wiphy->wdev_list, list) {
7bdbe400
JB
15032 if (tmp->identifier == cb->args[1] - 1) {
15033 *wdev = tmp;
15034 break;
15035 }
15036 }
15037 }
15038
15039 /* keep rtnl locked in successful case */
15040 return 0;
15041 }
15042
50508d94
JB
15043 attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf), GFP_KERNEL);
15044 if (!attrbuf)
15045 return -ENOMEM;
15046
8cb08174
JB
15047 err = nlmsg_parse_deprecated(cb->nlh,
15048 GENL_HDRLEN + nl80211_fam.hdrsize,
15049 attrbuf, nl80211_fam.maxattr,
15050 nl80211_policy, NULL);
7bdbe400 15051 if (err)
50508d94 15052 goto out;
7bdbe400 15053
c90c39da 15054 if (!attrbuf[NL80211_ATTR_VENDOR_ID] ||
50508d94
JB
15055 !attrbuf[NL80211_ATTR_VENDOR_SUBCMD]) {
15056 err = -EINVAL;
15057 goto out;
15058 }
7bdbe400 15059
a05829a7 15060 *wdev = __cfg80211_wdev_from_attrs(NULL, sock_net(skb->sk), attrbuf);
7bdbe400
JB
15061 if (IS_ERR(*wdev))
15062 *wdev = NULL;
15063
c90c39da 15064 *rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk), attrbuf);
50508d94
JB
15065 if (IS_ERR(*rdev)) {
15066 err = PTR_ERR(*rdev);
15067 goto out;
15068 }
7bdbe400 15069
c90c39da
JB
15070 vid = nla_get_u32(attrbuf[NL80211_ATTR_VENDOR_ID]);
15071 subcmd = nla_get_u32(attrbuf[NL80211_ATTR_VENDOR_SUBCMD]);
7bdbe400
JB
15072
15073 for (i = 0; i < (*rdev)->wiphy.n_vendor_commands; i++) {
15074 const struct wiphy_vendor_command *vcmd;
15075
15076 vcmd = &(*rdev)->wiphy.vendor_commands[i];
15077
15078 if (vcmd->info.vendor_id != vid || vcmd->info.subcmd != subcmd)
15079 continue;
15080
50508d94
JB
15081 if (!vcmd->dumpit) {
15082 err = -EOPNOTSUPP;
15083 goto out;
15084 }
7bdbe400
JB
15085
15086 vcmd_idx = i;
15087 break;
15088 }
15089
50508d94
JB
15090 if (vcmd_idx < 0) {
15091 err = -EOPNOTSUPP;
15092 goto out;
15093 }
7bdbe400 15094
c90c39da
JB
15095 if (attrbuf[NL80211_ATTR_VENDOR_DATA]) {
15096 data = nla_data(attrbuf[NL80211_ATTR_VENDOR_DATA]);
15097 data_len = nla_len(attrbuf[NL80211_ATTR_VENDOR_DATA]);
901bb989
JB
15098
15099 err = nl80211_vendor_check_policy(
15100 &(*rdev)->wiphy.vendor_commands[vcmd_idx],
15101 attrbuf[NL80211_ATTR_VENDOR_DATA],
15102 cb->extack);
15103 if (err)
50508d94 15104 goto out;
7bdbe400
JB
15105 }
15106
15107 /* 0 is the first index - add 1 to parse only once */
15108 cb->args[0] = (*rdev)->wiphy_idx + 1;
15109 /* add 1 to know if it was NULL */
15110 cb->args[1] = *wdev ? (*wdev)->identifier + 1 : 0;
15111 cb->args[2] = vcmd_idx;
15112 cb->args[3] = (unsigned long)data;
15113 cb->args[4] = data_len;
15114
15115 /* keep rtnl locked in successful case */
50508d94
JB
15116 err = 0;
15117out:
15118 kfree(attrbuf);
15119 return err;
7bdbe400
JB
15120}
15121
15122static int nl80211_vendor_cmd_dump(struct sk_buff *skb,
15123 struct netlink_callback *cb)
15124{
15125 struct cfg80211_registered_device *rdev;
15126 struct wireless_dev *wdev;
15127 unsigned int vcmd_idx;
15128 const struct wiphy_vendor_command *vcmd;
15129 void *data;
15130 int data_len;
15131 int err;
15132 struct nlattr *vendor_data;
15133
ea90e0dc 15134 rtnl_lock();
7bdbe400
JB
15135 err = nl80211_prepare_vendor_dump(skb, cb, &rdev, &wdev);
15136 if (err)
ea90e0dc 15137 goto out;
7bdbe400
JB
15138
15139 vcmd_idx = cb->args[2];
15140 data = (void *)cb->args[3];
15141 data_len = cb->args[4];
15142 vcmd = &rdev->wiphy.vendor_commands[vcmd_idx];
15143
15144 if (vcmd->flags & (WIPHY_VENDOR_CMD_NEED_WDEV |
15145 WIPHY_VENDOR_CMD_NEED_NETDEV)) {
ea90e0dc
JB
15146 if (!wdev) {
15147 err = -EINVAL;
15148 goto out;
15149 }
7bdbe400 15150 if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_NETDEV &&
ea90e0dc
JB
15151 !wdev->netdev) {
15152 err = -EINVAL;
15153 goto out;
15154 }
7bdbe400
JB
15155
15156 if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_RUNNING) {
ea90e0dc
JB
15157 if (!wdev_running(wdev)) {
15158 err = -ENETDOWN;
15159 goto out;
15160 }
7bdbe400
JB
15161 }
15162 }
15163
15164 while (1) {
15165 void *hdr = nl80211hdr_put(skb, NETLINK_CB(cb->skb).portid,
15166 cb->nlh->nlmsg_seq, NLM_F_MULTI,
15167 NL80211_CMD_VENDOR);
15168 if (!hdr)
15169 break;
15170
15171 if (nla_put_u32(skb, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
2dad624e
ND
15172 (wdev && nla_put_u64_64bit(skb, NL80211_ATTR_WDEV,
15173 wdev_id(wdev),
15174 NL80211_ATTR_PAD))) {
7bdbe400
JB
15175 genlmsg_cancel(skb, hdr);
15176 break;
15177 }
15178
ae0be8de
MK
15179 vendor_data = nla_nest_start_noflag(skb,
15180 NL80211_ATTR_VENDOR_DATA);
7bdbe400
JB
15181 if (!vendor_data) {
15182 genlmsg_cancel(skb, hdr);
15183 break;
15184 }
15185
15186 err = vcmd->dumpit(&rdev->wiphy, wdev, skb, data, data_len,
15187 (unsigned long *)&cb->args[5]);
15188 nla_nest_end(skb, vendor_data);
15189
15190 if (err == -ENOBUFS || err == -ENOENT) {
15191 genlmsg_cancel(skb, hdr);
15192 break;
9c167b2d 15193 } else if (err <= 0) {
7bdbe400
JB
15194 genlmsg_cancel(skb, hdr);
15195 goto out;
15196 }
15197
15198 genlmsg_end(skb, hdr);
15199 }
15200
15201 err = skb->len;
15202 out:
15203 rtnl_unlock();
15204 return err;
15205}
15206
ad7e718c
JB
15207struct sk_buff *__cfg80211_alloc_reply_skb(struct wiphy *wiphy,
15208 enum nl80211_commands cmd,
15209 enum nl80211_attrs attr,
15210 int approxlen)
15211{
f26cbf40 15212 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
ad7e718c
JB
15213
15214 if (WARN_ON(!rdev->cur_cmd_info))
15215 return NULL;
15216
6c09e791 15217 return __cfg80211_alloc_vendor_skb(rdev, NULL, approxlen,
ad7e718c
JB
15218 rdev->cur_cmd_info->snd_portid,
15219 rdev->cur_cmd_info->snd_seq,
567ffc35 15220 cmd, attr, NULL, GFP_KERNEL);
ad7e718c
JB
15221}
15222EXPORT_SYMBOL(__cfg80211_alloc_reply_skb);
15223
15224int cfg80211_vendor_cmd_reply(struct sk_buff *skb)
15225{
15226 struct cfg80211_registered_device *rdev = ((void **)skb->cb)[0];
15227 void *hdr = ((void **)skb->cb)[1];
15228 struct nlattr *data = ((void **)skb->cb)[2];
15229
bd8c78e7
JB
15230 /* clear CB data for netlink core to own from now on */
15231 memset(skb->cb, 0, sizeof(skb->cb));
15232
ad7e718c
JB
15233 if (WARN_ON(!rdev->cur_cmd_info)) {
15234 kfree_skb(skb);
15235 return -EINVAL;
15236 }
15237
15238 nla_nest_end(skb, data);
15239 genlmsg_end(skb, hdr);
15240 return genlmsg_reply(skb, rdev->cur_cmd_info);
15241}
15242EXPORT_SYMBOL_GPL(cfg80211_vendor_cmd_reply);
15243
55c1fdf0
JB
15244unsigned int cfg80211_vendor_cmd_get_sender(struct wiphy *wiphy)
15245{
15246 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
15247
15248 if (WARN_ON(!rdev->cur_cmd_info))
15249 return 0;
15250
15251 return rdev->cur_cmd_info->snd_portid;
15252}
15253EXPORT_SYMBOL_GPL(cfg80211_vendor_cmd_get_sender);
15254
fa9ffc74
KP
15255static int nl80211_set_qos_map(struct sk_buff *skb,
15256 struct genl_info *info)
15257{
15258 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15259 struct cfg80211_qos_map *qos_map = NULL;
15260 struct net_device *dev = info->user_ptr[1];
15261 u8 *pos, len, num_des, des_len, des;
15262 int ret;
15263
15264 if (!rdev->ops->set_qos_map)
15265 return -EOPNOTSUPP;
15266
15267 if (info->attrs[NL80211_ATTR_QOS_MAP]) {
15268 pos = nla_data(info->attrs[NL80211_ATTR_QOS_MAP]);
15269 len = nla_len(info->attrs[NL80211_ATTR_QOS_MAP]);
15270
c8b82802 15271 if (len % 2)
fa9ffc74
KP
15272 return -EINVAL;
15273
15274 qos_map = kzalloc(sizeof(struct cfg80211_qos_map), GFP_KERNEL);
15275 if (!qos_map)
15276 return -ENOMEM;
15277
15278 num_des = (len - IEEE80211_QOS_MAP_LEN_MIN) >> 1;
15279 if (num_des) {
15280 des_len = num_des *
15281 sizeof(struct cfg80211_dscp_exception);
15282 memcpy(qos_map->dscp_exception, pos, des_len);
15283 qos_map->num_des = num_des;
15284 for (des = 0; des < num_des; des++) {
15285 if (qos_map->dscp_exception[des].up > 7) {
15286 kfree(qos_map);
15287 return -EINVAL;
15288 }
15289 }
15290 pos += des_len;
15291 }
15292 memcpy(qos_map->up, pos, IEEE80211_QOS_MAP_LEN_MIN);
15293 }
15294
fa9ffc74
KP
15295 ret = nl80211_key_allowed(dev->ieee80211_ptr);
15296 if (!ret)
15297 ret = rdev_set_qos_map(rdev, dev, qos_map);
fa9ffc74
KP
15298
15299 kfree(qos_map);
15300 return ret;
15301}
15302
960d01ac
JB
15303static int nl80211_add_tx_ts(struct sk_buff *skb, struct genl_info *info)
15304{
15305 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15306 struct net_device *dev = info->user_ptr[1];
15307 struct wireless_dev *wdev = dev->ieee80211_ptr;
15308 const u8 *peer;
15309 u8 tsid, up;
15310 u16 admitted_time = 0;
960d01ac 15311
723e73ac 15312 if (!(rdev->wiphy.features & NL80211_FEATURE_SUPPORTS_WMM_ADMISSION))
960d01ac
JB
15313 return -EOPNOTSUPP;
15314
15315 if (!info->attrs[NL80211_ATTR_TSID] || !info->attrs[NL80211_ATTR_MAC] ||
15316 !info->attrs[NL80211_ATTR_USER_PRIO])
15317 return -EINVAL;
15318
15319 tsid = nla_get_u8(info->attrs[NL80211_ATTR_TSID]);
960d01ac 15320 up = nla_get_u8(info->attrs[NL80211_ATTR_USER_PRIO]);
960d01ac
JB
15321
15322 /* WMM uses TIDs 0-7 even for TSPEC */
723e73ac 15323 if (tsid >= IEEE80211_FIRST_TSPEC_TSID) {
960d01ac 15324 /* TODO: handle 802.11 TSPEC/admission control
723e73ac
JB
15325 * need more attributes for that (e.g. BA session requirement);
15326 * change the WMM adminssion test above to allow both then
960d01ac
JB
15327 */
15328 return -EINVAL;
15329 }
15330
15331 peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
15332
15333 if (info->attrs[NL80211_ATTR_ADMITTED_TIME]) {
15334 admitted_time =
15335 nla_get_u16(info->attrs[NL80211_ATTR_ADMITTED_TIME]);
15336 if (!admitted_time)
15337 return -EINVAL;
15338 }
15339
960d01ac
JB
15340 switch (wdev->iftype) {
15341 case NL80211_IFTYPE_STATION:
15342 case NL80211_IFTYPE_P2P_CLIENT:
7b0a0e3c 15343 if (wdev->connected)
960d01ac 15344 break;
076fc877 15345 return -ENOTCONN;
960d01ac 15346 default:
076fc877 15347 return -EOPNOTSUPP;
960d01ac
JB
15348 }
15349
076fc877 15350 return rdev_add_tx_ts(rdev, dev, tsid, peer, up, admitted_time);
960d01ac
JB
15351}
15352
15353static int nl80211_del_tx_ts(struct sk_buff *skb, struct genl_info *info)
15354{
15355 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15356 struct net_device *dev = info->user_ptr[1];
960d01ac
JB
15357 const u8 *peer;
15358 u8 tsid;
960d01ac
JB
15359
15360 if (!info->attrs[NL80211_ATTR_TSID] || !info->attrs[NL80211_ATTR_MAC])
15361 return -EINVAL;
15362
15363 tsid = nla_get_u8(info->attrs[NL80211_ATTR_TSID]);
15364 peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
15365
076fc877 15366 return rdev_del_tx_ts(rdev, dev, tsid, peer);
960d01ac
JB
15367}
15368
1057d35e
AN
15369static int nl80211_tdls_channel_switch(struct sk_buff *skb,
15370 struct genl_info *info)
15371{
15372 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15373 struct net_device *dev = info->user_ptr[1];
15374 struct wireless_dev *wdev = dev->ieee80211_ptr;
15375 struct cfg80211_chan_def chandef = {};
15376 const u8 *addr;
15377 u8 oper_class;
15378 int err;
15379
15380 if (!rdev->ops->tdls_channel_switch ||
15381 !(rdev->wiphy.features & NL80211_FEATURE_TDLS_CHANNEL_SWITCH))
15382 return -EOPNOTSUPP;
15383
15384 switch (dev->ieee80211_ptr->iftype) {
15385 case NL80211_IFTYPE_STATION:
15386 case NL80211_IFTYPE_P2P_CLIENT:
15387 break;
15388 default:
15389 return -EOPNOTSUPP;
15390 }
15391
15392 if (!info->attrs[NL80211_ATTR_MAC] ||
15393 !info->attrs[NL80211_ATTR_OPER_CLASS])
15394 return -EINVAL;
15395
15396 err = nl80211_parse_chandef(rdev, info, &chandef);
15397 if (err)
15398 return err;
15399
15400 /*
15401 * Don't allow wide channels on the 2.4Ghz band, as per IEEE802.11-2012
15402 * section 10.22.6.2.1. Disallow 5/10Mhz channels as well for now, the
15403 * specification is not defined for them.
15404 */
57fbcce3 15405 if (chandef.chan->band == NL80211_BAND_2GHZ &&
1057d35e
AN
15406 chandef.width != NL80211_CHAN_WIDTH_20_NOHT &&
15407 chandef.width != NL80211_CHAN_WIDTH_20)
15408 return -EINVAL;
15409
15410 /* we will be active on the TDLS link */
923b352f
AN
15411 if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &chandef,
15412 wdev->iftype))
1057d35e
AN
15413 return -EINVAL;
15414
15415 /* don't allow switching to DFS channels */
15416 if (cfg80211_chandef_dfs_required(wdev->wiphy, &chandef, wdev->iftype))
15417 return -EINVAL;
15418
15419 addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
15420 oper_class = nla_get_u8(info->attrs[NL80211_ATTR_OPER_CLASS]);
15421
076fc877 15422 return rdev_tdls_channel_switch(rdev, dev, addr, oper_class, &chandef);
1057d35e
AN
15423}
15424
15425static int nl80211_tdls_cancel_channel_switch(struct sk_buff *skb,
15426 struct genl_info *info)
15427{
15428 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15429 struct net_device *dev = info->user_ptr[1];
1057d35e
AN
15430 const u8 *addr;
15431
15432 if (!rdev->ops->tdls_channel_switch ||
15433 !rdev->ops->tdls_cancel_channel_switch ||
15434 !(rdev->wiphy.features & NL80211_FEATURE_TDLS_CHANNEL_SWITCH))
15435 return -EOPNOTSUPP;
15436
15437 switch (dev->ieee80211_ptr->iftype) {
15438 case NL80211_IFTYPE_STATION:
15439 case NL80211_IFTYPE_P2P_CLIENT:
15440 break;
15441 default:
15442 return -EOPNOTSUPP;
15443 }
15444
15445 if (!info->attrs[NL80211_ATTR_MAC])
15446 return -EINVAL;
15447
15448 addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
15449
1057d35e 15450 rdev_tdls_cancel_channel_switch(rdev, dev, addr);
1057d35e
AN
15451
15452 return 0;
15453}
15454
ce0ce13a
MB
15455static int nl80211_set_multicast_to_unicast(struct sk_buff *skb,
15456 struct genl_info *info)
15457{
15458 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15459 struct net_device *dev = info->user_ptr[1];
15460 struct wireless_dev *wdev = dev->ieee80211_ptr;
15461 const struct nlattr *nla;
15462 bool enabled;
15463
ce0ce13a
MB
15464 if (!rdev->ops->set_multicast_to_unicast)
15465 return -EOPNOTSUPP;
15466
15467 if (wdev->iftype != NL80211_IFTYPE_AP &&
15468 wdev->iftype != NL80211_IFTYPE_P2P_GO)
15469 return -EOPNOTSUPP;
15470
15471 nla = info->attrs[NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED];
15472 enabled = nla_get_flag(nla);
15473
15474 return rdev_set_multicast_to_unicast(rdev, dev, enabled);
15475}
15476
3a00df57
AS
15477static int nl80211_set_pmk(struct sk_buff *skb, struct genl_info *info)
15478{
15479 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15480 struct net_device *dev = info->user_ptr[1];
15481 struct wireless_dev *wdev = dev->ieee80211_ptr;
15482 struct cfg80211_pmk_conf pmk_conf = {};
3a00df57
AS
15483
15484 if (wdev->iftype != NL80211_IFTYPE_STATION &&
15485 wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
15486 return -EOPNOTSUPP;
15487
15488 if (!wiphy_ext_feature_isset(&rdev->wiphy,
15489 NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X))
15490 return -EOPNOTSUPP;
15491
15492 if (!info->attrs[NL80211_ATTR_MAC] || !info->attrs[NL80211_ATTR_PMK])
15493 return -EINVAL;
15494
076fc877
JB
15495 if (!wdev->connected)
15496 return -ENOTCONN;
3a00df57
AS
15497
15498 pmk_conf.aa = nla_data(info->attrs[NL80211_ATTR_MAC]);
076fc877
JB
15499 if (memcmp(pmk_conf.aa, wdev->u.client.connected_addr, ETH_ALEN))
15500 return -EINVAL;
3a00df57
AS
15501
15502 pmk_conf.pmk = nla_data(info->attrs[NL80211_ATTR_PMK]);
15503 pmk_conf.pmk_len = nla_len(info->attrs[NL80211_ATTR_PMK]);
15504 if (pmk_conf.pmk_len != WLAN_PMK_LEN &&
076fc877
JB
15505 pmk_conf.pmk_len != WLAN_PMK_LEN_SUITE_B_192)
15506 return -EINVAL;
3a00df57 15507
cb9abd48 15508 if (info->attrs[NL80211_ATTR_PMKR0_NAME])
3a00df57
AS
15509 pmk_conf.pmk_r0_name =
15510 nla_data(info->attrs[NL80211_ATTR_PMKR0_NAME]);
3a00df57 15511
076fc877 15512 return rdev_set_pmk(rdev, dev, &pmk_conf);
3a00df57
AS
15513}
15514
15515static int nl80211_del_pmk(struct sk_buff *skb, struct genl_info *info)
15516{
15517 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15518 struct net_device *dev = info->user_ptr[1];
15519 struct wireless_dev *wdev = dev->ieee80211_ptr;
15520 const u8 *aa;
3a00df57
AS
15521
15522 if (wdev->iftype != NL80211_IFTYPE_STATION &&
15523 wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
15524 return -EOPNOTSUPP;
15525
15526 if (!wiphy_ext_feature_isset(&rdev->wiphy,
15527 NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X))
15528 return -EOPNOTSUPP;
15529
15530 if (!info->attrs[NL80211_ATTR_MAC])
15531 return -EINVAL;
15532
3a00df57 15533 aa = nla_data(info->attrs[NL80211_ATTR_MAC]);
076fc877 15534 return rdev_del_pmk(rdev, dev, aa);
3a00df57
AS
15535}
15536
40cbfa90
SD
15537static int nl80211_external_auth(struct sk_buff *skb, struct genl_info *info)
15538{
15539 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15540 struct net_device *dev = info->user_ptr[1];
15541 struct cfg80211_external_auth_params params;
15542
db8d93a7 15543 if (!rdev->ops->external_auth)
40cbfa90
SD
15544 return -EOPNOTSUPP;
15545
fe494370
SD
15546 if (!info->attrs[NL80211_ATTR_SSID] &&
15547 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
15548 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
40cbfa90
SD
15549 return -EINVAL;
15550
15551 if (!info->attrs[NL80211_ATTR_BSSID])
15552 return -EINVAL;
15553
15554 if (!info->attrs[NL80211_ATTR_STATUS_CODE])
15555 return -EINVAL;
15556
15557 memset(&params, 0, sizeof(params));
15558
fe494370
SD
15559 if (info->attrs[NL80211_ATTR_SSID]) {
15560 params.ssid.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
cb9abd48 15561 if (params.ssid.ssid_len == 0)
fe494370
SD
15562 return -EINVAL;
15563 memcpy(params.ssid.ssid,
15564 nla_data(info->attrs[NL80211_ATTR_SSID]),
15565 params.ssid.ssid_len);
15566 }
40cbfa90
SD
15567
15568 memcpy(params.bssid, nla_data(info->attrs[NL80211_ATTR_BSSID]),
15569 ETH_ALEN);
15570
15571 params.status = nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]);
15572
fe494370
SD
15573 if (info->attrs[NL80211_ATTR_PMKID])
15574 params.pmkid = nla_data(info->attrs[NL80211_ATTR_PMKID]);
15575
40cbfa90
SD
15576 return rdev_external_auth(rdev, dev, &params);
15577}
15578
2576a9ac
DK
15579static int nl80211_tx_control_port(struct sk_buff *skb, struct genl_info *info)
15580{
dca9ca2d 15581 bool dont_wait_for_ack = info->attrs[NL80211_ATTR_DONT_WAIT_FOR_ACK];
2576a9ac
DK
15582 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15583 struct net_device *dev = info->user_ptr[1];
15584 struct wireless_dev *wdev = dev->ieee80211_ptr;
15585 const u8 *buf;
15586 size_t len;
15587 u8 *dest;
15588 u16 proto;
15589 bool noencrypt;
dca9ca2d 15590 u64 cookie = 0;
67207bab 15591 int link_id;
2576a9ac
DK
15592 int err;
15593
15594 if (!wiphy_ext_feature_isset(&rdev->wiphy,
15595 NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211))
15596 return -EOPNOTSUPP;
15597
15598 if (!rdev->ops->tx_control_port)
15599 return -EOPNOTSUPP;
15600
15601 if (!info->attrs[NL80211_ATTR_FRAME] ||
15602 !info->attrs[NL80211_ATTR_MAC] ||
15603 !info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]) {
15604 GENL_SET_ERR_MSG(info, "Frame, MAC or ethertype missing");
15605 return -EINVAL;
15606 }
15607
2576a9ac
DK
15608 switch (wdev->iftype) {
15609 case NL80211_IFTYPE_AP:
15610 case NL80211_IFTYPE_P2P_GO:
15611 case NL80211_IFTYPE_MESH_POINT:
15612 break;
15613 case NL80211_IFTYPE_ADHOC:
7b0a0e3c
JB
15614 if (wdev->u.ibss.current_bss)
15615 break;
076fc877 15616 return -ENOTCONN;
2576a9ac
DK
15617 case NL80211_IFTYPE_STATION:
15618 case NL80211_IFTYPE_P2P_CLIENT:
7b0a0e3c 15619 if (wdev->connected)
2576a9ac 15620 break;
076fc877 15621 return -ENOTCONN;
2576a9ac 15622 default:
076fc877 15623 return -EOPNOTSUPP;
2576a9ac
DK
15624 }
15625
2576a9ac
DK
15626 buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
15627 len = nla_len(info->attrs[NL80211_ATTR_FRAME]);
15628 dest = nla_data(info->attrs[NL80211_ATTR_MAC]);
15629 proto = nla_get_u16(info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]);
15630 noencrypt =
15631 nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT]);
15632
67207bab
AO
15633 link_id = nl80211_link_id_or_invalid(info->attrs);
15634
dca9ca2d 15635 err = rdev_tx_control_port(rdev, dev, buf, len,
67207bab 15636 dest, cpu_to_be16(proto), noencrypt, link_id,
dca9ca2d
MT
15637 dont_wait_for_ack ? NULL : &cookie);
15638 if (!err && !dont_wait_for_ack)
15639 nl_set_extack_cookie_u64(info->extack, cookie);
15640 return err;
2576a9ac
DK
15641}
15642
81e54d08
PKC
15643static int nl80211_get_ftm_responder_stats(struct sk_buff *skb,
15644 struct genl_info *info)
15645{
15646 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15647 struct net_device *dev = info->user_ptr[1];
15648 struct wireless_dev *wdev = dev->ieee80211_ptr;
15649 struct cfg80211_ftm_responder_stats ftm_stats = {};
7b0a0e3c 15650 unsigned int link_id = nl80211_link_id(info->attrs);
81e54d08
PKC
15651 struct sk_buff *msg;
15652 void *hdr;
15653 struct nlattr *ftm_stats_attr;
15654 int err;
15655
7b0a0e3c
JB
15656 if (wdev->iftype != NL80211_IFTYPE_AP ||
15657 !wdev->links[link_id].ap.beacon_interval)
81e54d08
PKC
15658 return -EOPNOTSUPP;
15659
15660 err = rdev_get_ftm_responder_stats(rdev, dev, &ftm_stats);
15661 if (err)
15662 return err;
15663
15664 if (!ftm_stats.filled)
15665 return -ENODATA;
15666
15667 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
15668 if (!msg)
15669 return -ENOMEM;
15670
15671 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
15672 NL80211_CMD_GET_FTM_RESPONDER_STATS);
15673 if (!hdr)
1399c59f 15674 goto nla_put_failure;
81e54d08
PKC
15675
15676 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
15677 goto nla_put_failure;
15678
ae0be8de
MK
15679 ftm_stats_attr = nla_nest_start_noflag(msg,
15680 NL80211_ATTR_FTM_RESPONDER_STATS);
81e54d08
PKC
15681 if (!ftm_stats_attr)
15682 goto nla_put_failure;
15683
15684#define SET_FTM(field, name, type) \
15685 do { if ((ftm_stats.filled & BIT(NL80211_FTM_STATS_ ## name)) && \
15686 nla_put_ ## type(msg, NL80211_FTM_STATS_ ## name, \
15687 ftm_stats.field)) \
15688 goto nla_put_failure; } while (0)
15689#define SET_FTM_U64(field, name) \
15690 do { if ((ftm_stats.filled & BIT(NL80211_FTM_STATS_ ## name)) && \
15691 nla_put_u64_64bit(msg, NL80211_FTM_STATS_ ## name, \
15692 ftm_stats.field, NL80211_FTM_STATS_PAD)) \
15693 goto nla_put_failure; } while (0)
15694
15695 SET_FTM(success_num, SUCCESS_NUM, u32);
15696 SET_FTM(partial_num, PARTIAL_NUM, u32);
15697 SET_FTM(failed_num, FAILED_NUM, u32);
15698 SET_FTM(asap_num, ASAP_NUM, u32);
15699 SET_FTM(non_asap_num, NON_ASAP_NUM, u32);
15700 SET_FTM_U64(total_duration_ms, TOTAL_DURATION_MSEC);
15701 SET_FTM(unknown_triggers_num, UNKNOWN_TRIGGERS_NUM, u32);
15702 SET_FTM(reschedule_requests_num, RESCHEDULE_REQUESTS_NUM, u32);
15703 SET_FTM(out_of_window_triggers_num, OUT_OF_WINDOW_TRIGGERS_NUM, u32);
15704#undef SET_FTM
15705
15706 nla_nest_end(msg, ftm_stats_attr);
15707
15708 genlmsg_end(msg, hdr);
15709 return genlmsg_reply(msg, info);
15710
15711nla_put_failure:
15712 nlmsg_free(msg);
15713 return -ENOBUFS;
15714}
15715
cb74e977
SD
15716static int nl80211_update_owe_info(struct sk_buff *skb, struct genl_info *info)
15717{
15718 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15719 struct cfg80211_update_owe_info owe_info;
15720 struct net_device *dev = info->user_ptr[1];
15721
15722 if (!rdev->ops->update_owe_info)
15723 return -EOPNOTSUPP;
15724
15725 if (!info->attrs[NL80211_ATTR_STATUS_CODE] ||
15726 !info->attrs[NL80211_ATTR_MAC])
15727 return -EINVAL;
15728
15729 memset(&owe_info, 0, sizeof(owe_info));
15730 owe_info.status = nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]);
15731 nla_memcpy(owe_info.peer, info->attrs[NL80211_ATTR_MAC], ETH_ALEN);
15732
15733 if (info->attrs[NL80211_ATTR_IE]) {
15734 owe_info.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
15735 owe_info.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
15736 }
15737
15738 return rdev_update_owe_info(rdev, dev, &owe_info);
15739}
15740
5ab92e7f
RM
15741static int nl80211_probe_mesh_link(struct sk_buff *skb, struct genl_info *info)
15742{
15743 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15744 struct net_device *dev = info->user_ptr[1];
15745 struct wireless_dev *wdev = dev->ieee80211_ptr;
15746 struct station_info sinfo = {};
15747 const u8 *buf;
15748 size_t len;
15749 u8 *dest;
15750 int err;
15751
15752 if (!rdev->ops->probe_mesh_link || !rdev->ops->get_station)
15753 return -EOPNOTSUPP;
15754
15755 if (!info->attrs[NL80211_ATTR_MAC] ||
15756 !info->attrs[NL80211_ATTR_FRAME]) {
15757 GENL_SET_ERR_MSG(info, "Frame or MAC missing");
15758 return -EINVAL;
15759 }
15760
15761 if (wdev->iftype != NL80211_IFTYPE_MESH_POINT)
15762 return -EOPNOTSUPP;
15763
15764 dest = nla_data(info->attrs[NL80211_ATTR_MAC]);
15765 buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
15766 len = nla_len(info->attrs[NL80211_ATTR_FRAME]);
15767
15768 if (len < sizeof(struct ethhdr))
15769 return -EINVAL;
15770
15771 if (!ether_addr_equal(buf, dest) || is_multicast_ether_addr(buf) ||
15772 !ether_addr_equal(buf + ETH_ALEN, dev->dev_addr))
15773 return -EINVAL;
15774
15775 err = rdev_get_station(rdev, dev, dest, &sinfo);
15776 if (err)
15777 return err;
15778
2a279b34
FF
15779 cfg80211_sinfo_release_content(&sinfo);
15780
5ab92e7f
RM
15781 return rdev_probe_mesh_link(rdev, dev, dest, buf, len);
15782}
15783
77f576de
T
15784static int parse_tid_conf(struct cfg80211_registered_device *rdev,
15785 struct nlattr *attrs[], struct net_device *dev,
3710a8a6 15786 struct cfg80211_tid_cfg *tid_conf,
7b0a0e3c
JB
15787 struct genl_info *info, const u8 *peer,
15788 unsigned int link_id)
77f576de
T
15789{
15790 struct netlink_ext_ack *extack = info->extack;
3710a8a6 15791 u64 mask;
77f576de
T
15792 int err;
15793
15794 if (!attrs[NL80211_TID_CONFIG_ATTR_TIDS])
15795 return -EINVAL;
15796
15797 tid_conf->config_override =
15798 nla_get_flag(attrs[NL80211_TID_CONFIG_ATTR_OVERRIDE]);
3710a8a6 15799 tid_conf->tids = nla_get_u16(attrs[NL80211_TID_CONFIG_ATTR_TIDS]);
77f576de
T
15800
15801 if (tid_conf->config_override) {
15802 if (rdev->ops->reset_tid_config) {
15803 err = rdev_reset_tid_config(rdev, dev, peer,
3710a8a6 15804 tid_conf->tids);
c0336955 15805 if (err)
77f576de
T
15806 return err;
15807 } else {
15808 return -EINVAL;
15809 }
15810 }
15811
15812 if (attrs[NL80211_TID_CONFIG_ATTR_NOACK]) {
3710a8a6 15813 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_NOACK);
77f576de
T
15814 tid_conf->noack =
15815 nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_NOACK]);
15816 }
15817
6a21d16c
T
15818 if (attrs[NL80211_TID_CONFIG_ATTR_RETRY_SHORT]) {
15819 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_RETRY_SHORT);
15820 tid_conf->retry_short =
15821 nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_RETRY_SHORT]);
15822
15823 if (tid_conf->retry_short > rdev->wiphy.max_data_retry_count)
15824 return -EINVAL;
15825 }
15826
15827 if (attrs[NL80211_TID_CONFIG_ATTR_RETRY_LONG]) {
15828 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_RETRY_LONG);
15829 tid_conf->retry_long =
15830 nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_RETRY_LONG]);
15831
15832 if (tid_conf->retry_long > rdev->wiphy.max_data_retry_count)
15833 return -EINVAL;
15834 }
15835
ade274b2
T
15836 if (attrs[NL80211_TID_CONFIG_ATTR_AMPDU_CTRL]) {
15837 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_AMPDU_CTRL);
15838 tid_conf->ampdu =
15839 nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_AMPDU_CTRL]);
15840 }
15841
04f7d142
T
15842 if (attrs[NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL]) {
15843 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL);
15844 tid_conf->rtscts =
15845 nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL]);
15846 }
15847
33462e68
SM
15848 if (attrs[NL80211_TID_CONFIG_ATTR_AMSDU_CTRL]) {
15849 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_AMSDU_CTRL);
15850 tid_conf->amsdu =
15851 nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_AMSDU_CTRL]);
15852 }
15853
9a5f6488
TC
15854 if (attrs[NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE]) {
15855 u32 idx = NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE, attr;
15856
15857 tid_conf->txrate_type = nla_get_u8(attrs[idx]);
15858
15859 if (tid_conf->txrate_type != NL80211_TX_RATE_AUTOMATIC) {
15860 attr = NL80211_TID_CONFIG_ATTR_TX_RATE;
15861 err = nl80211_parse_tx_bitrate_mask(info, attrs, attr,
857b34c4 15862 &tid_conf->txrate_mask, dev,
7b0a0e3c 15863 true, link_id);
9a5f6488
TC
15864 if (err)
15865 return err;
15866
15867 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_TX_RATE);
15868 }
15869 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE);
15870 }
15871
3710a8a6
JB
15872 if (peer)
15873 mask = rdev->wiphy.tid_config_support.peer;
15874 else
15875 mask = rdev->wiphy.tid_config_support.vif;
15876
15877 if (tid_conf->mask & ~mask) {
15878 NL_SET_ERR_MSG(extack, "unsupported TID configuration");
f6289e5d 15879 return -EOPNOTSUPP;
3710a8a6
JB
15880 }
15881
77f576de
T
15882 return 0;
15883}
15884
15885static int nl80211_set_tid_config(struct sk_buff *skb,
15886 struct genl_info *info)
15887{
15888 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15889 struct nlattr *attrs[NL80211_TID_CONFIG_ATTR_MAX + 1];
7b0a0e3c 15890 unsigned int link_id = nl80211_link_id(info->attrs);
77f576de 15891 struct net_device *dev = info->user_ptr[1];
3710a8a6 15892 struct cfg80211_tid_config *tid_config;
77f576de
T
15893 struct nlattr *tid;
15894 int conf_idx = 0, rem_conf;
15895 int ret = -EINVAL;
15896 u32 num_conf = 0;
15897
15898 if (!info->attrs[NL80211_ATTR_TID_CONFIG])
15899 return -EINVAL;
15900
15901 if (!rdev->ops->set_tid_config)
15902 return -EOPNOTSUPP;
15903
15904 nla_for_each_nested(tid, info->attrs[NL80211_ATTR_TID_CONFIG],
15905 rem_conf)
15906 num_conf++;
15907
15908 tid_config = kzalloc(struct_size(tid_config, tid_conf, num_conf),
15909 GFP_KERNEL);
15910 if (!tid_config)
15911 return -ENOMEM;
15912
15913 tid_config->n_tid_conf = num_conf;
15914
15915 if (info->attrs[NL80211_ATTR_MAC])
15916 tid_config->peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
15917
15918 nla_for_each_nested(tid, info->attrs[NL80211_ATTR_TID_CONFIG],
15919 rem_conf) {
15920 ret = nla_parse_nested(attrs, NL80211_TID_CONFIG_ATTR_MAX,
15921 tid, NULL, NULL);
15922
15923 if (ret)
15924 goto bad_tid_conf;
15925
15926 ret = parse_tid_conf(rdev, attrs, dev,
15927 &tid_config->tid_conf[conf_idx],
7b0a0e3c 15928 info, tid_config->peer, link_id);
77f576de
T
15929 if (ret)
15930 goto bad_tid_conf;
15931
15932 conf_idx++;
15933 }
15934
15935 ret = rdev_set_tid_config(rdev, dev, tid_config);
15936
15937bad_tid_conf:
15938 kfree(tid_config);
15939 return ret;
15940}
15941
0d2ab3ae
JC
15942static int nl80211_color_change(struct sk_buff *skb, struct genl_info *info)
15943{
15944 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15945 struct cfg80211_color_change_settings params = {};
15946 struct net_device *dev = info->user_ptr[1];
15947 struct wireless_dev *wdev = dev->ieee80211_ptr;
15948 struct nlattr **tb;
15949 u16 offset;
15950 int err;
15951
15952 if (!rdev->ops->color_change)
15953 return -EOPNOTSUPP;
15954
15955 if (!wiphy_ext_feature_isset(&rdev->wiphy,
15956 NL80211_EXT_FEATURE_BSS_COLOR))
15957 return -EOPNOTSUPP;
15958
15959 if (wdev->iftype != NL80211_IFTYPE_AP)
15960 return -EOPNOTSUPP;
15961
15962 if (!info->attrs[NL80211_ATTR_COLOR_CHANGE_COUNT] ||
15963 !info->attrs[NL80211_ATTR_COLOR_CHANGE_COLOR] ||
15964 !info->attrs[NL80211_ATTR_COLOR_CHANGE_ELEMS])
15965 return -EINVAL;
15966
15967 params.count = nla_get_u8(info->attrs[NL80211_ATTR_COLOR_CHANGE_COUNT]);
15968 params.color = nla_get_u8(info->attrs[NL80211_ATTR_COLOR_CHANGE_COLOR]);
15969
dbbb27e1
AD
15970 err = nl80211_parse_beacon(rdev, info->attrs, &params.beacon_next,
15971 info->extack);
0d2ab3ae
JC
15972 if (err)
15973 return err;
15974
15975 tb = kcalloc(NL80211_ATTR_MAX + 1, sizeof(*tb), GFP_KERNEL);
15976 if (!tb)
15977 return -ENOMEM;
15978
15979 err = nla_parse_nested(tb, NL80211_ATTR_MAX,
15980 info->attrs[NL80211_ATTR_COLOR_CHANGE_ELEMS],
15981 nl80211_policy, info->extack);
15982 if (err)
15983 goto out;
15984
dbbb27e1
AD
15985 err = nl80211_parse_beacon(rdev, tb, &params.beacon_color_change,
15986 info->extack);
0d2ab3ae
JC
15987 if (err)
15988 goto out;
15989
15990 if (!tb[NL80211_ATTR_CNTDWN_OFFS_BEACON]) {
15991 err = -EINVAL;
15992 goto out;
15993 }
15994
15995 if (nla_len(tb[NL80211_ATTR_CNTDWN_OFFS_BEACON]) != sizeof(u16)) {
15996 err = -EINVAL;
15997 goto out;
15998 }
15999
16000 offset = nla_get_u16(tb[NL80211_ATTR_CNTDWN_OFFS_BEACON]);
16001 if (offset >= params.beacon_color_change.tail_len) {
16002 err = -EINVAL;
16003 goto out;
16004 }
16005
16006 if (params.beacon_color_change.tail[offset] != params.count) {
16007 err = -EINVAL;
16008 goto out;
16009 }
16010
16011 params.counter_offset_beacon = offset;
16012
16013 if (tb[NL80211_ATTR_CNTDWN_OFFS_PRESP]) {
16014 if (nla_len(tb[NL80211_ATTR_CNTDWN_OFFS_PRESP]) !=
16015 sizeof(u16)) {
16016 err = -EINVAL;
16017 goto out;
16018 }
16019
16020 offset = nla_get_u16(tb[NL80211_ATTR_CNTDWN_OFFS_PRESP]);
16021 if (offset >= params.beacon_color_change.probe_resp_len) {
16022 err = -EINVAL;
16023 goto out;
16024 }
16025
16026 if (params.beacon_color_change.probe_resp[offset] !=
16027 params.count) {
16028 err = -EINVAL;
16029 goto out;
16030 }
16031
16032 params.counter_offset_presp = offset;
16033 }
16034
91d2b6ee 16035 params.link_id = nl80211_link_id(info->attrs);
0d2ab3ae 16036 err = rdev_color_change(rdev, dev, &params);
0d2ab3ae
JC
16037
16038out:
dc1e3cb8
JC
16039 kfree(params.beacon_next.mbssid_ies);
16040 kfree(params.beacon_color_change.mbssid_ies);
dbbb27e1
AD
16041 kfree(params.beacon_next.rnr_ies);
16042 kfree(params.beacon_color_change.rnr_ies);
0d2ab3ae
JC
16043 kfree(tb);
16044 return err;
16045}
16046
e306784a
SM
16047static int nl80211_set_fils_aad(struct sk_buff *skb,
16048 struct genl_info *info)
16049{
16050 struct cfg80211_registered_device *rdev = info->user_ptr[0];
16051 struct net_device *dev = info->user_ptr[1];
16052 struct cfg80211_fils_aad fils_aad = {};
16053 u8 *nonces;
16054
16055 if (!info->attrs[NL80211_ATTR_MAC] ||
16056 !info->attrs[NL80211_ATTR_FILS_KEK] ||
16057 !info->attrs[NL80211_ATTR_FILS_NONCES])
16058 return -EINVAL;
16059
16060 fils_aad.macaddr = nla_data(info->attrs[NL80211_ATTR_MAC]);
16061 fils_aad.kek_len = nla_len(info->attrs[NL80211_ATTR_FILS_KEK]);
16062 fils_aad.kek = nla_data(info->attrs[NL80211_ATTR_FILS_KEK]);
16063 nonces = nla_data(info->attrs[NL80211_ATTR_FILS_NONCES]);
16064 fils_aad.snonce = nonces;
16065 fils_aad.anonce = nonces + FILS_NONCE_LEN;
16066
16067 return rdev_set_fils_aad(rdev, dev, &fils_aad);
16068}
16069
7b0a0e3c
JB
16070static int nl80211_add_link(struct sk_buff *skb, struct genl_info *info)
16071{
f2a0290b 16072 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7b0a0e3c
JB
16073 unsigned int link_id = nl80211_link_id(info->attrs);
16074 struct net_device *dev = info->user_ptr[1];
16075 struct wireless_dev *wdev = dev->ieee80211_ptr;
f2a0290b 16076 int ret;
7b0a0e3c
JB
16077
16078 if (!(wdev->wiphy->flags & WIPHY_FLAG_SUPPORTS_MLO))
16079 return -EINVAL;
16080
16081 switch (wdev->iftype) {
16082 case NL80211_IFTYPE_AP:
16083 break;
16084 default:
16085 return -EINVAL;
16086 }
16087
16088 if (!info->attrs[NL80211_ATTR_MAC] ||
16089 !is_valid_ether_addr(nla_data(info->attrs[NL80211_ATTR_MAC])))
16090 return -EINVAL;
16091
7b0a0e3c
JB
16092 wdev->valid_links |= BIT(link_id);
16093 ether_addr_copy(wdev->links[link_id].addr,
16094 nla_data(info->attrs[NL80211_ATTR_MAC]));
f2a0290b
JB
16095
16096 ret = rdev_add_intf_link(rdev, wdev, link_id);
16097 if (ret) {
16098 wdev->valid_links &= ~BIT(link_id);
16099 eth_zero_addr(wdev->links[link_id].addr);
16100 }
7b0a0e3c 16101
f2a0290b 16102 return ret;
7b0a0e3c
JB
16103}
16104
16105static int nl80211_remove_link(struct sk_buff *skb, struct genl_info *info)
16106{
16107 unsigned int link_id = nl80211_link_id(info->attrs);
16108 struct net_device *dev = info->user_ptr[1];
16109 struct wireless_dev *wdev = dev->ieee80211_ptr;
16110
16111 /* cannot remove if there's no link */
16112 if (!info->attrs[NL80211_ATTR_MLO_LINK_ID])
16113 return -EINVAL;
16114
16115 switch (wdev->iftype) {
16116 case NL80211_IFTYPE_AP:
16117 break;
16118 default:
16119 return -EINVAL;
16120 }
16121
cdf0a0a8 16122 cfg80211_remove_link(wdev, link_id);
7b0a0e3c
JB
16123
16124 return 0;
16125}
16126
577e5b8c
ST
16127static int
16128nl80211_add_mod_link_station(struct sk_buff *skb, struct genl_info *info,
16129 bool add)
16130{
16131 struct link_station_parameters params = {};
16132 struct cfg80211_registered_device *rdev = info->user_ptr[0];
16133 struct net_device *dev = info->user_ptr[1];
16134 int err;
16135
16136 if ((add && !rdev->ops->add_link_station) ||
16137 (!add && !rdev->ops->mod_link_station))
16138 return -EOPNOTSUPP;
16139
16140 if (add && !info->attrs[NL80211_ATTR_MAC])
16141 return -EINVAL;
16142
8876c67e 16143 if (!info->attrs[NL80211_ATTR_MLD_ADDR])
577e5b8c
ST
16144 return -EINVAL;
16145
16146 if (add && !info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES])
16147 return -EINVAL;
16148
8876c67e 16149 params.mld_mac = nla_data(info->attrs[NL80211_ATTR_MLD_ADDR]);
577e5b8c
ST
16150
16151 if (info->attrs[NL80211_ATTR_MAC]) {
16152 params.link_mac = nla_data(info->attrs[NL80211_ATTR_MAC]);
16153 if (!is_valid_ether_addr(params.link_mac))
16154 return -EINVAL;
16155 }
16156
16157 if (!info->attrs[NL80211_ATTR_MLO_LINK_ID])
16158 return -EINVAL;
16159
16160 params.link_id = nla_get_u8(info->attrs[NL80211_ATTR_MLO_LINK_ID]);
16161
16162 if (info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]) {
16163 params.supported_rates =
16164 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
16165 params.supported_rates_len =
16166 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
16167 }
16168
16169 if (info->attrs[NL80211_ATTR_HT_CAPABILITY])
16170 params.ht_capa =
16171 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
16172
16173 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY])
16174 params.vht_capa =
16175 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);
16176
16177 if (info->attrs[NL80211_ATTR_HE_CAPABILITY]) {
16178 params.he_capa =
16179 nla_data(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
16180 params.he_capa_len =
16181 nla_len(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
16182
16183 if (info->attrs[NL80211_ATTR_EHT_CAPABILITY]) {
16184 params.eht_capa =
16185 nla_data(info->attrs[NL80211_ATTR_EHT_CAPABILITY]);
16186 params.eht_capa_len =
16187 nla_len(info->attrs[NL80211_ATTR_EHT_CAPABILITY]);
16188
16189 if (!ieee80211_eht_capa_size_ok((const u8 *)params.he_capa,
16190 (const u8 *)params.eht_capa,
ea5cba26
JB
16191 params.eht_capa_len,
16192 false))
577e5b8c
ST
16193 return -EINVAL;
16194 }
16195 }
16196
16197 if (info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY])
16198 params.he_6ghz_capa =
16199 nla_data(info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY]);
16200
16201 if (info->attrs[NL80211_ATTR_OPMODE_NOTIF]) {
16202 params.opmode_notif_used = true;
16203 params.opmode_notif =
16204 nla_get_u8(info->attrs[NL80211_ATTR_OPMODE_NOTIF]);
16205 }
16206
16207 err = nl80211_parse_sta_txpower_setting(info, &params.txpwr,
16208 &params.txpwr_set);
16209 if (err)
16210 return err;
16211
16212 if (add)
076fc877 16213 return rdev_add_link_station(rdev, dev, &params);
858fd188 16214
076fc877 16215 return rdev_mod_link_station(rdev, dev, &params);
577e5b8c
ST
16216}
16217
16218static int
16219nl80211_add_link_station(struct sk_buff *skb, struct genl_info *info)
16220{
16221 return nl80211_add_mod_link_station(skb, info, true);
16222}
16223
16224static int
16225nl80211_modify_link_station(struct sk_buff *skb, struct genl_info *info)
16226{
16227 return nl80211_add_mod_link_station(skb, info, false);
16228}
16229
16230static int
16231nl80211_remove_link_station(struct sk_buff *skb, struct genl_info *info)
16232{
16233 struct link_station_del_parameters params = {};
16234 struct cfg80211_registered_device *rdev = info->user_ptr[0];
16235 struct net_device *dev = info->user_ptr[1];
16236
16237 if (!rdev->ops->del_link_station)
16238 return -EOPNOTSUPP;
16239
16240 if (!info->attrs[NL80211_ATTR_MLD_ADDR] ||
16241 !info->attrs[NL80211_ATTR_MLO_LINK_ID])
16242 return -EINVAL;
16243
16244 params.mld_mac = nla_data(info->attrs[NL80211_ATTR_MLD_ADDR]);
16245 params.link_id = nla_get_u8(info->attrs[NL80211_ATTR_MLO_LINK_ID]);
16246
076fc877 16247 return rdev_del_link_station(rdev, dev, &params);
577e5b8c
ST
16248}
16249
cbbaf2bb
AS
16250static int nl80211_set_hw_timestamp(struct sk_buff *skb,
16251 struct genl_info *info)
16252{
16253 struct cfg80211_registered_device *rdev = info->user_ptr[0];
16254 struct net_device *dev = info->user_ptr[1];
16255 struct cfg80211_set_hw_timestamp hwts = {};
16256
16257 if (!rdev->wiphy.hw_timestamp_max_peers)
16258 return -EOPNOTSUPP;
16259
16260 if (!info->attrs[NL80211_ATTR_MAC] &&
16261 rdev->wiphy.hw_timestamp_max_peers != CFG80211_HW_TIMESTAMP_ALL_PEERS)
16262 return -EOPNOTSUPP;
16263
16264 if (info->attrs[NL80211_ATTR_MAC])
16265 hwts.macaddr = nla_data(info->attrs[NL80211_ATTR_MAC]);
16266
16267 hwts.enable =
16268 nla_get_flag(info->attrs[NL80211_ATTR_HW_TIMESTAMP_ENABLED]);
16269
16270 return rdev_set_hw_timestamp(rdev, dev, &hwts);
16271}
16272
b61e6b41
IP
16273static int
16274nl80211_set_ttlm(struct sk_buff *skb, struct genl_info *info)
16275{
16276 struct cfg80211_ttlm_params params = {};
16277 struct cfg80211_registered_device *rdev = info->user_ptr[0];
16278 struct net_device *dev = info->user_ptr[1];
16279 struct wireless_dev *wdev = dev->ieee80211_ptr;
16280
16281 if (wdev->iftype != NL80211_IFTYPE_STATION &&
16282 wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
16283 return -EOPNOTSUPP;
16284
16285 if (!wdev->connected)
16286 return -ENOLINK;
16287
16288 if (!info->attrs[NL80211_ATTR_MLO_TTLM_DLINK] ||
16289 !info->attrs[NL80211_ATTR_MLO_TTLM_ULINK])
16290 return -EINVAL;
16291
16292 nla_memcpy(params.dlink,
16293 info->attrs[NL80211_ATTR_MLO_TTLM_DLINK],
16294 sizeof(params.dlink));
16295 nla_memcpy(params.ulink,
16296 info->attrs[NL80211_ATTR_MLO_TTLM_ULINK],
16297 sizeof(params.ulink));
16298
16299 return rdev_set_ttlm(rdev, dev, &params);
16300}
16301
4c476991
JB
16302#define NL80211_FLAG_NEED_WIPHY 0x01
16303#define NL80211_FLAG_NEED_NETDEV 0x02
16304#define NL80211_FLAG_NEED_RTNL 0x04
41265714
JB
16305#define NL80211_FLAG_CHECK_NETDEV_UP 0x08
16306#define NL80211_FLAG_NEED_NETDEV_UP (NL80211_FLAG_NEED_NETDEV |\
16307 NL80211_FLAG_CHECK_NETDEV_UP)
1bf614ef 16308#define NL80211_FLAG_NEED_WDEV 0x10
98104fde 16309/* If a netdev is associated, it must be UP, P2P must be started */
1bf614ef
JB
16310#define NL80211_FLAG_NEED_WDEV_UP (NL80211_FLAG_NEED_WDEV |\
16311 NL80211_FLAG_CHECK_NETDEV_UP)
5393b917 16312#define NL80211_FLAG_CLEAR_SKB 0x20
77cbf790 16313#define NL80211_FLAG_NO_WIPHY_MTX 0x40
7b0a0e3c
JB
16314#define NL80211_FLAG_MLO_VALID_LINK_ID 0x80
16315#define NL80211_FLAG_MLO_UNSUPPORTED 0x100
4c476991 16316
2182db91
JB
16317#define INTERNAL_FLAG_SELECTORS(__sel) \
16318 SELECTOR(__sel, NONE, 0) /* must be first */ \
16319 SELECTOR(__sel, WIPHY, \
16320 NL80211_FLAG_NEED_WIPHY) \
16321 SELECTOR(__sel, WDEV, \
16322 NL80211_FLAG_NEED_WDEV) \
16323 SELECTOR(__sel, NETDEV, \
16324 NL80211_FLAG_NEED_NETDEV) \
7b0a0e3c
JB
16325 SELECTOR(__sel, NETDEV_LINK, \
16326 NL80211_FLAG_NEED_NETDEV | \
16327 NL80211_FLAG_MLO_VALID_LINK_ID) \
16328 SELECTOR(__sel, NETDEV_NO_MLO, \
16329 NL80211_FLAG_NEED_NETDEV | \
16330 NL80211_FLAG_MLO_UNSUPPORTED) \
2182db91
JB
16331 SELECTOR(__sel, WIPHY_RTNL, \
16332 NL80211_FLAG_NEED_WIPHY | \
16333 NL80211_FLAG_NEED_RTNL) \
16334 SELECTOR(__sel, WIPHY_RTNL_NOMTX, \
16335 NL80211_FLAG_NEED_WIPHY | \
16336 NL80211_FLAG_NEED_RTNL | \
16337 NL80211_FLAG_NO_WIPHY_MTX) \
16338 SELECTOR(__sel, WDEV_RTNL, \
16339 NL80211_FLAG_NEED_WDEV | \
16340 NL80211_FLAG_NEED_RTNL) \
16341 SELECTOR(__sel, NETDEV_RTNL, \
16342 NL80211_FLAG_NEED_NETDEV | \
16343 NL80211_FLAG_NEED_RTNL) \
16344 SELECTOR(__sel, NETDEV_UP, \
16345 NL80211_FLAG_NEED_NETDEV_UP) \
7b0a0e3c
JB
16346 SELECTOR(__sel, NETDEV_UP_LINK, \
16347 NL80211_FLAG_NEED_NETDEV_UP | \
16348 NL80211_FLAG_MLO_VALID_LINK_ID) \
16349 SELECTOR(__sel, NETDEV_UP_NO_MLO, \
16350 NL80211_FLAG_NEED_NETDEV_UP | \
16351 NL80211_FLAG_MLO_UNSUPPORTED) \
16352 SELECTOR(__sel, NETDEV_UP_NO_MLO_CLEAR, \
16353 NL80211_FLAG_NEED_NETDEV_UP | \
16354 NL80211_FLAG_CLEAR_SKB | \
16355 NL80211_FLAG_MLO_UNSUPPORTED) \
2182db91
JB
16356 SELECTOR(__sel, NETDEV_UP_NOTMX, \
16357 NL80211_FLAG_NEED_NETDEV_UP | \
16358 NL80211_FLAG_NO_WIPHY_MTX) \
7b0a0e3c
JB
16359 SELECTOR(__sel, NETDEV_UP_NOTMX_NOMLO, \
16360 NL80211_FLAG_NEED_NETDEV_UP | \
16361 NL80211_FLAG_NO_WIPHY_MTX | \
16362 NL80211_FLAG_MLO_UNSUPPORTED) \
2182db91
JB
16363 SELECTOR(__sel, NETDEV_UP_CLEAR, \
16364 NL80211_FLAG_NEED_NETDEV_UP | \
16365 NL80211_FLAG_CLEAR_SKB) \
16366 SELECTOR(__sel, WDEV_UP, \
16367 NL80211_FLAG_NEED_WDEV_UP) \
7b0a0e3c
JB
16368 SELECTOR(__sel, WDEV_UP_LINK, \
16369 NL80211_FLAG_NEED_WDEV_UP | \
16370 NL80211_FLAG_MLO_VALID_LINK_ID) \
2182db91
JB
16371 SELECTOR(__sel, WDEV_UP_RTNL, \
16372 NL80211_FLAG_NEED_WDEV_UP | \
16373 NL80211_FLAG_NEED_RTNL) \
16374 SELECTOR(__sel, WIPHY_CLEAR, \
16375 NL80211_FLAG_NEED_WIPHY | \
16376 NL80211_FLAG_CLEAR_SKB)
16377
16378enum nl80211_internal_flags_selector {
16379#define SELECTOR(_, name, value) NL80211_IFL_SEL_##name,
16380 INTERNAL_FLAG_SELECTORS(_)
16381#undef SELECTOR
16382};
16383
16384static u32 nl80211_internal_flags[] = {
16385#define SELECTOR(_, name, value) [NL80211_IFL_SEL_##name] = value,
16386 INTERNAL_FLAG_SELECTORS(_)
16387#undef SELECTOR
16388};
16389
20b0b53a
JK
16390static int nl80211_pre_doit(const struct genl_split_ops *ops,
16391 struct sk_buff *skb,
4c476991
JB
16392 struct genl_info *info)
16393{
a05829a7 16394 struct cfg80211_registered_device *rdev = NULL;
7b0a0e3c
JB
16395 struct wireless_dev *wdev = NULL;
16396 struct net_device *dev = NULL;
2182db91 16397 u32 internal_flags;
7b0a0e3c 16398 int err;
2182db91
JB
16399
16400 if (WARN_ON(ops->internal_flags >= ARRAY_SIZE(nl80211_internal_flags)))
16401 return -EINVAL;
16402
16403 internal_flags = nl80211_internal_flags[ops->internal_flags];
4c476991 16404
a05829a7 16405 rtnl_lock();
2182db91 16406 if (internal_flags & NL80211_FLAG_NEED_WIPHY) {
4f7eff10 16407 rdev = cfg80211_get_dev_from_info(genl_info_net(info), info);
4c476991 16408 if (IS_ERR(rdev)) {
7b0a0e3c
JB
16409 err = PTR_ERR(rdev);
16410 goto out_unlock;
4c476991
JB
16411 }
16412 info->user_ptr[0] = rdev;
2182db91
JB
16413 } else if (internal_flags & NL80211_FLAG_NEED_NETDEV ||
16414 internal_flags & NL80211_FLAG_NEED_WDEV) {
a05829a7 16415 wdev = __cfg80211_wdev_from_attrs(NULL, genl_info_net(info),
89a54e48
JB
16416 info->attrs);
16417 if (IS_ERR(wdev)) {
7b0a0e3c
JB
16418 err = PTR_ERR(wdev);
16419 goto out_unlock;
4c476991 16420 }
89a54e48 16421
89a54e48 16422 dev = wdev->netdev;
7b0a0e3c 16423 dev_hold(dev);
f26cbf40 16424 rdev = wiphy_to_rdev(wdev->wiphy);
89a54e48 16425
2182db91 16426 if (internal_flags & NL80211_FLAG_NEED_NETDEV) {
1bf614ef 16427 if (!dev) {
7b0a0e3c
JB
16428 err = -EINVAL;
16429 goto out_unlock;
1bf614ef
JB
16430 }
16431
16432 info->user_ptr[1] = dev;
16433 } else {
16434 info->user_ptr[1] = wdev;
41265714 16435 }
1bf614ef 16436
2182db91 16437 if (internal_flags & NL80211_FLAG_CHECK_NETDEV_UP &&
73c7da3d 16438 !wdev_running(wdev)) {
7b0a0e3c
JB
16439 err = -ENETDOWN;
16440 goto out_unlock;
73c7da3d 16441 }
1bf614ef 16442
4c476991 16443 info->user_ptr[0] = rdev;
4c476991
JB
16444 }
16445
7b0a0e3c
JB
16446 if (internal_flags & NL80211_FLAG_MLO_VALID_LINK_ID) {
16447 struct nlattr *link_id = info->attrs[NL80211_ATTR_MLO_LINK_ID];
16448
16449 if (!wdev) {
16450 err = -EINVAL;
16451 goto out_unlock;
16452 }
16453
16454 /* MLO -> require valid link ID */
16455 if (wdev->valid_links &&
16456 (!link_id ||
ff3821bc 16457 !(wdev->valid_links & BIT(nla_get_u8(link_id))))) {
7b0a0e3c
JB
16458 err = -EINVAL;
16459 goto out_unlock;
16460 }
16461
16462 /* non-MLO -> no link ID attribute accepted */
16463 if (!wdev->valid_links && link_id) {
16464 err = -EINVAL;
16465 goto out_unlock;
16466 }
16467 }
16468
16469 if (internal_flags & NL80211_FLAG_MLO_UNSUPPORTED) {
16470 if (info->attrs[NL80211_ATTR_MLO_LINK_ID] ||
16471 (wdev && wdev->valid_links)) {
16472 err = -EINVAL;
16473 goto out_unlock;
16474 }
16475 }
16476
2182db91 16477 if (rdev && !(internal_flags & NL80211_FLAG_NO_WIPHY_MTX)) {
a05829a7
JB
16478 wiphy_lock(&rdev->wiphy);
16479 /* we keep the mutex locked until post_doit */
16480 __release(&rdev->wiphy.mtx);
16481 }
2182db91 16482 if (!(internal_flags & NL80211_FLAG_NEED_RTNL))
a05829a7
JB
16483 rtnl_unlock();
16484
4c476991 16485 return 0;
7b0a0e3c
JB
16486out_unlock:
16487 rtnl_unlock();
16488 dev_put(dev);
16489 return err;
4c476991
JB
16490}
16491
20b0b53a
JK
16492static void nl80211_post_doit(const struct genl_split_ops *ops,
16493 struct sk_buff *skb,
4c476991
JB
16494 struct genl_info *info)
16495{
2182db91
JB
16496 u32 internal_flags = nl80211_internal_flags[ops->internal_flags];
16497
1bf614ef 16498 if (info->user_ptr[1]) {
2182db91 16499 if (internal_flags & NL80211_FLAG_NEED_WDEV) {
1bf614ef
JB
16500 struct wireless_dev *wdev = info->user_ptr[1];
16501
1160dfa1 16502 dev_put(wdev->netdev);
1bf614ef
JB
16503 } else {
16504 dev_put(info->user_ptr[1]);
16505 }
16506 }
5393b917 16507
77cbf790 16508 if (info->user_ptr[0] &&
2182db91 16509 !(internal_flags & NL80211_FLAG_NO_WIPHY_MTX)) {
a05829a7
JB
16510 struct cfg80211_registered_device *rdev = info->user_ptr[0];
16511
16512 /* we kept the mutex locked since pre_doit */
16513 __acquire(&rdev->wiphy.mtx);
16514 wiphy_unlock(&rdev->wiphy);
16515 }
16516
2182db91 16517 if (internal_flags & NL80211_FLAG_NEED_RTNL)
4c476991 16518 rtnl_unlock();
5393b917
JB
16519
16520 /* If needed, clear the netlink message payload from the SKB
16521 * as it might contain key data that shouldn't stick around on
16522 * the heap after the SKB is freed. The netlink message header
16523 * is still needed for further processing, so leave it intact.
16524 */
2182db91 16525 if (internal_flags & NL80211_FLAG_CLEAR_SKB) {
5393b917
JB
16526 struct nlmsghdr *nlh = nlmsg_hdr(skb);
16527
16528 memset(nlmsg_data(nlh), 0, nlmsg_len(nlh));
16529 }
4c476991
JB
16530}
16531
6bdb68ce
CH
16532static int nl80211_set_sar_sub_specs(struct cfg80211_registered_device *rdev,
16533 struct cfg80211_sar_specs *sar_specs,
16534 struct nlattr *spec[], int index)
16535{
16536 u32 range_index, i;
16537
16538 if (!sar_specs || !spec)
16539 return -EINVAL;
16540
16541 if (!spec[NL80211_SAR_ATTR_SPECS_POWER] ||
16542 !spec[NL80211_SAR_ATTR_SPECS_RANGE_INDEX])
16543 return -EINVAL;
16544
16545 range_index = nla_get_u32(spec[NL80211_SAR_ATTR_SPECS_RANGE_INDEX]);
16546
16547 /* check if range_index exceeds num_freq_ranges */
16548 if (range_index >= rdev->wiphy.sar_capa->num_freq_ranges)
16549 return -EINVAL;
16550
16551 /* check if range_index duplicates */
16552 for (i = 0; i < index; i++) {
16553 if (sar_specs->sub_specs[i].freq_range_index == range_index)
16554 return -EINVAL;
16555 }
16556
16557 sar_specs->sub_specs[index].power =
16558 nla_get_s32(spec[NL80211_SAR_ATTR_SPECS_POWER]);
16559
16560 sar_specs->sub_specs[index].freq_range_index = range_index;
16561
16562 return 0;
16563}
16564
16565static int nl80211_set_sar_specs(struct sk_buff *skb, struct genl_info *info)
16566{
16567 struct cfg80211_registered_device *rdev = info->user_ptr[0];
16568 struct nlattr *spec[NL80211_SAR_ATTR_SPECS_MAX + 1];
16569 struct nlattr *tb[NL80211_SAR_ATTR_MAX + 1];
16570 struct cfg80211_sar_specs *sar_spec;
16571 enum nl80211_sar_type type;
16572 struct nlattr *spec_list;
16573 u32 specs;
16574 int rem, err;
16575
16576 if (!rdev->wiphy.sar_capa || !rdev->ops->set_sar_specs)
16577 return -EOPNOTSUPP;
16578
16579 if (!info->attrs[NL80211_ATTR_SAR_SPEC])
16580 return -EINVAL;
16581
16582 nla_parse_nested(tb, NL80211_SAR_ATTR_MAX,
16583 info->attrs[NL80211_ATTR_SAR_SPEC],
16584 NULL, NULL);
16585
16586 if (!tb[NL80211_SAR_ATTR_TYPE] || !tb[NL80211_SAR_ATTR_SPECS])
16587 return -EINVAL;
16588
16589 type = nla_get_u32(tb[NL80211_SAR_ATTR_TYPE]);
16590 if (type != rdev->wiphy.sar_capa->type)
16591 return -EINVAL;
16592
16593 specs = 0;
16594 nla_for_each_nested(spec_list, tb[NL80211_SAR_ATTR_SPECS], rem)
16595 specs++;
16596
16597 if (specs > rdev->wiphy.sar_capa->num_freq_ranges)
16598 return -EINVAL;
16599
40f231e7 16600 sar_spec = kzalloc(struct_size(sar_spec, sub_specs, specs), GFP_KERNEL);
6bdb68ce
CH
16601 if (!sar_spec)
16602 return -ENOMEM;
16603
16604 sar_spec->type = type;
16605 specs = 0;
16606 nla_for_each_nested(spec_list, tb[NL80211_SAR_ATTR_SPECS], rem) {
16607 nla_parse_nested(spec, NL80211_SAR_ATTR_SPECS_MAX,
16608 spec_list, NULL, NULL);
16609
16610 switch (type) {
16611 case NL80211_SAR_TYPE_POWER:
16612 if (nl80211_set_sar_sub_specs(rdev, sar_spec,
16613 spec, specs)) {
16614 err = -EINVAL;
16615 goto error;
16616 }
16617 break;
16618 default:
16619 err = -EINVAL;
16620 goto error;
16621 }
16622 specs++;
16623 }
16624
16625 sar_spec->num_sub_specs = specs;
16626
16627 rdev->cur_cmd_info = info;
16628 err = rdev_set_sar_specs(rdev, sar_spec);
16629 rdev->cur_cmd_info = NULL;
16630error:
16631 kfree(sar_spec);
16632 return err;
16633}
16634
2182db91
JB
16635#define SELECTOR(__sel, name, value) \
16636 ((__sel) == (value)) ? NL80211_IFL_SEL_##name :
16637int __missing_selector(void);
16638#define IFLAGS(__val) INTERNAL_FLAG_SELECTORS(__val) __missing_selector()
16639
4534de83 16640static const struct genl_ops nl80211_ops[] = {
55682965
JB
16641 {
16642 .cmd = NL80211_CMD_GET_WIPHY,
ef6243ac 16643 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
55682965
JB
16644 .doit = nl80211_get_wiphy,
16645 .dumpit = nl80211_dump_wiphy,
86e8cf98 16646 .done = nl80211_dump_wiphy_done,
55682965 16647 /* can be retrieved by unprivileged users */
2182db91 16648 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY),
55682965 16649 },
66a9b928
JK
16650};
16651
16652static const struct genl_small_ops nl80211_small_ops[] = {
55682965
JB
16653 {
16654 .cmd = NL80211_CMD_SET_WIPHY,
ef6243ac 16655 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
55682965 16656 .doit = nl80211_set_wiphy,
5617c6cd 16657 .flags = GENL_UNS_ADMIN_PERM,
55682965
JB
16658 },
16659 {
16660 .cmd = NL80211_CMD_GET_INTERFACE,
ef6243ac 16661 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
55682965
JB
16662 .doit = nl80211_get_interface,
16663 .dumpit = nl80211_dump_interface,
55682965 16664 /* can be retrieved by unprivileged users */
2182db91 16665 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV),
55682965
JB
16666 },
16667 {
16668 .cmd = NL80211_CMD_SET_INTERFACE,
ef6243ac 16669 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
55682965 16670 .doit = nl80211_set_interface,
5617c6cd 16671 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
16672 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV |
16673 NL80211_FLAG_NEED_RTNL),
55682965
JB
16674 },
16675 {
16676 .cmd = NL80211_CMD_NEW_INTERFACE,
ef6243ac 16677 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
55682965 16678 .doit = nl80211_new_interface,
5617c6cd 16679 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
16680 .internal_flags =
16681 IFLAGS(NL80211_FLAG_NEED_WIPHY |
16682 NL80211_FLAG_NEED_RTNL |
16683 /* we take the wiphy mutex later ourselves */
16684 NL80211_FLAG_NO_WIPHY_MTX),
55682965
JB
16685 },
16686 {
16687 .cmd = NL80211_CMD_DEL_INTERFACE,
ef6243ac 16688 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
55682965 16689 .doit = nl80211_del_interface,
5617c6cd 16690 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
16691 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV |
16692 NL80211_FLAG_NEED_RTNL),
41ade00f
JB
16693 },
16694 {
16695 .cmd = NL80211_CMD_GET_KEY,
ef6243ac 16696 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
41ade00f 16697 .doit = nl80211_get_key,
5617c6cd 16698 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16699 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
41ade00f
JB
16700 },
16701 {
16702 .cmd = NL80211_CMD_SET_KEY,
ef6243ac 16703 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
41ade00f 16704 .doit = nl80211_set_key,
5617c6cd 16705 .flags = GENL_UNS_ADMIN_PERM,
7b0a0e3c 16706 /* cannot use NL80211_FLAG_MLO_VALID_LINK_ID, depends on key */
2182db91
JB
16707 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
16708 NL80211_FLAG_CLEAR_SKB),
41ade00f
JB
16709 },
16710 {
16711 .cmd = NL80211_CMD_NEW_KEY,
ef6243ac 16712 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
41ade00f 16713 .doit = nl80211_new_key,
5617c6cd 16714 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
16715 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
16716 NL80211_FLAG_CLEAR_SKB),
41ade00f
JB
16717 },
16718 {
16719 .cmd = NL80211_CMD_DEL_KEY,
ef6243ac 16720 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
41ade00f 16721 .doit = nl80211_del_key,
5617c6cd 16722 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16723 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
55682965 16724 },
ed1b6cc7
JB
16725 {
16726 .cmd = NL80211_CMD_SET_BEACON,
ef6243ac 16727 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5617c6cd 16728 .flags = GENL_UNS_ADMIN_PERM,
8860020e 16729 .doit = nl80211_set_beacon,
7b0a0e3c
JB
16730 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
16731 NL80211_FLAG_MLO_VALID_LINK_ID),
ed1b6cc7
JB
16732 },
16733 {
8860020e 16734 .cmd = NL80211_CMD_START_AP,
ef6243ac 16735 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5617c6cd 16736 .flags = GENL_UNS_ADMIN_PERM,
8860020e 16737 .doit = nl80211_start_ap,
7b0a0e3c
JB
16738 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
16739 NL80211_FLAG_MLO_VALID_LINK_ID),
ed1b6cc7
JB
16740 },
16741 {
8860020e 16742 .cmd = NL80211_CMD_STOP_AP,
ef6243ac 16743 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5617c6cd 16744 .flags = GENL_UNS_ADMIN_PERM,
8860020e 16745 .doit = nl80211_stop_ap,
7b0a0e3c
JB
16746 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
16747 NL80211_FLAG_MLO_VALID_LINK_ID),
ed1b6cc7 16748 },
5727ef1b
JB
16749 {
16750 .cmd = NL80211_CMD_GET_STATION,
ef6243ac 16751 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5727ef1b 16752 .doit = nl80211_get_station,
2ec600d6 16753 .dumpit = nl80211_dump_station,
2182db91 16754 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
5727ef1b
JB
16755 },
16756 {
16757 .cmd = NL80211_CMD_SET_STATION,
ef6243ac 16758 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5727ef1b 16759 .doit = nl80211_set_station,
5617c6cd 16760 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16761 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
5727ef1b
JB
16762 },
16763 {
16764 .cmd = NL80211_CMD_NEW_STATION,
ef6243ac 16765 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5727ef1b 16766 .doit = nl80211_new_station,
5617c6cd 16767 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16768 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
5727ef1b
JB
16769 },
16770 {
16771 .cmd = NL80211_CMD_DEL_STATION,
ef6243ac 16772 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5727ef1b 16773 .doit = nl80211_del_station,
5617c6cd 16774 .flags = GENL_UNS_ADMIN_PERM,
f6ca96aa
AKS
16775 /* cannot use NL80211_FLAG_MLO_VALID_LINK_ID, depends on
16776 * whether MAC address is passed or not. If MAC address is
16777 * passed, then even during MLO, link ID is not required.
16778 */
2182db91 16779 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
2ec600d6
LCC
16780 },
16781 {
16782 .cmd = NL80211_CMD_GET_MPATH,
ef6243ac 16783 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2ec600d6
LCC
16784 .doit = nl80211_get_mpath,
16785 .dumpit = nl80211_dump_mpath,
5617c6cd 16786 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16787 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
2ec600d6 16788 },
66be7d2b
HR
16789 {
16790 .cmd = NL80211_CMD_GET_MPP,
ef6243ac 16791 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
66be7d2b
HR
16792 .doit = nl80211_get_mpp,
16793 .dumpit = nl80211_dump_mpp,
5617c6cd 16794 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16795 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
66be7d2b 16796 },
2ec600d6
LCC
16797 {
16798 .cmd = NL80211_CMD_SET_MPATH,
ef6243ac 16799 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2ec600d6 16800 .doit = nl80211_set_mpath,
5617c6cd 16801 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16802 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
2ec600d6
LCC
16803 },
16804 {
16805 .cmd = NL80211_CMD_NEW_MPATH,
ef6243ac 16806 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2ec600d6 16807 .doit = nl80211_new_mpath,
5617c6cd 16808 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16809 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
2ec600d6
LCC
16810 },
16811 {
16812 .cmd = NL80211_CMD_DEL_MPATH,
ef6243ac 16813 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2ec600d6 16814 .doit = nl80211_del_mpath,
5617c6cd 16815 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16816 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
9f1ba906
JM
16817 },
16818 {
16819 .cmd = NL80211_CMD_SET_BSS,
ef6243ac 16820 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9f1ba906 16821 .doit = nl80211_set_bss,
5617c6cd 16822 .flags = GENL_UNS_ADMIN_PERM,
1e0f8cc9
JB
16823 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
16824 NL80211_FLAG_MLO_VALID_LINK_ID),
b2e1b302 16825 },
f130347c
LR
16826 {
16827 .cmd = NL80211_CMD_GET_REG,
ef6243ac 16828 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ad30ca2c
AN
16829 .doit = nl80211_get_reg_do,
16830 .dumpit = nl80211_get_reg_dump,
f130347c
LR
16831 /* can be retrieved by unprivileged users */
16832 },
b6863036 16833#ifdef CONFIG_CFG80211_CRDA_SUPPORT
b2e1b302
LR
16834 {
16835 .cmd = NL80211_CMD_SET_REG,
ef6243ac 16836 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
b2e1b302 16837 .doit = nl80211_set_reg,
b2e1b302
LR
16838 .flags = GENL_ADMIN_PERM,
16839 },
b6863036 16840#endif
b2e1b302
LR
16841 {
16842 .cmd = NL80211_CMD_REQ_SET_REG,
ef6243ac 16843 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
b2e1b302 16844 .doit = nl80211_req_set_reg,
93da9cc1 16845 .flags = GENL_ADMIN_PERM,
16846 },
1ea4ff3e
JB
16847 {
16848 .cmd = NL80211_CMD_RELOAD_REGDB,
ef6243ac 16849 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1ea4ff3e 16850 .doit = nl80211_reload_regdb,
1ea4ff3e
JB
16851 .flags = GENL_ADMIN_PERM,
16852 },
93da9cc1 16853 {
24bdd9f4 16854 .cmd = NL80211_CMD_GET_MESH_CONFIG,
ef6243ac 16855 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
24bdd9f4 16856 .doit = nl80211_get_mesh_config,
93da9cc1 16857 /* can be retrieved by unprivileged users */
2182db91 16858 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
93da9cc1 16859 },
16860 {
24bdd9f4 16861 .cmd = NL80211_CMD_SET_MESH_CONFIG,
ef6243ac 16862 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
24bdd9f4 16863 .doit = nl80211_update_mesh_config,
5617c6cd 16864 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16865 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
9aed3cc1 16866 },
2a519311
JB
16867 {
16868 .cmd = NL80211_CMD_TRIGGER_SCAN,
ef6243ac 16869 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2a519311 16870 .doit = nl80211_trigger_scan,
5617c6cd 16871 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16872 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
2a519311 16873 },
91d3ab46
VK
16874 {
16875 .cmd = NL80211_CMD_ABORT_SCAN,
ef6243ac 16876 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
91d3ab46 16877 .doit = nl80211_abort_scan,
5617c6cd 16878 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16879 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
91d3ab46 16880 },
2a519311
JB
16881 {
16882 .cmd = NL80211_CMD_GET_SCAN,
ef6243ac 16883 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2a519311
JB
16884 .dumpit = nl80211_dump_scan,
16885 },
807f8a8c
LC
16886 {
16887 .cmd = NL80211_CMD_START_SCHED_SCAN,
ef6243ac 16888 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
807f8a8c 16889 .doit = nl80211_start_sched_scan,
5617c6cd 16890 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16891 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
807f8a8c
LC
16892 },
16893 {
16894 .cmd = NL80211_CMD_STOP_SCHED_SCAN,
ef6243ac 16895 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
807f8a8c 16896 .doit = nl80211_stop_sched_scan,
5617c6cd 16897 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16898 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
807f8a8c 16899 },
636a5d36
JM
16900 {
16901 .cmd = NL80211_CMD_AUTHENTICATE,
ef6243ac 16902 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
636a5d36 16903 .doit = nl80211_authenticate,
5617c6cd 16904 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
16905 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
16906 NL80211_FLAG_CLEAR_SKB),
636a5d36
JM
16907 },
16908 {
16909 .cmd = NL80211_CMD_ASSOCIATE,
ef6243ac 16910 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
636a5d36 16911 .doit = nl80211_associate,
5617c6cd 16912 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
16913 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
16914 NL80211_FLAG_CLEAR_SKB),
636a5d36
JM
16915 },
16916 {
16917 .cmd = NL80211_CMD_DEAUTHENTICATE,
ef6243ac 16918 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
636a5d36 16919 .doit = nl80211_deauthenticate,
5617c6cd 16920 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16921 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
636a5d36
JM
16922 },
16923 {
16924 .cmd = NL80211_CMD_DISASSOCIATE,
ef6243ac 16925 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
636a5d36 16926 .doit = nl80211_disassociate,
5617c6cd 16927 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16928 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
636a5d36 16929 },
04a773ad
JB
16930 {
16931 .cmd = NL80211_CMD_JOIN_IBSS,
ef6243ac 16932 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
04a773ad 16933 .doit = nl80211_join_ibss,
5617c6cd 16934 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16935 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
04a773ad
JB
16936 },
16937 {
16938 .cmd = NL80211_CMD_LEAVE_IBSS,
ef6243ac 16939 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
04a773ad 16940 .doit = nl80211_leave_ibss,
5617c6cd 16941 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16942 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
04a773ad 16943 },
aff89a9b
JB
16944#ifdef CONFIG_NL80211_TESTMODE
16945 {
16946 .cmd = NL80211_CMD_TESTMODE,
ef6243ac 16947 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
aff89a9b 16948 .doit = nl80211_testmode_do,
71063f0e 16949 .dumpit = nl80211_testmode_dump,
5617c6cd 16950 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16951 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY),
aff89a9b
JB
16952 },
16953#endif
b23aa676
SO
16954 {
16955 .cmd = NL80211_CMD_CONNECT,
ef6243ac 16956 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
b23aa676 16957 .doit = nl80211_connect,
5617c6cd 16958 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
16959 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
16960 NL80211_FLAG_CLEAR_SKB),
b23aa676 16961 },
088e8df8 16962 {
16963 .cmd = NL80211_CMD_UPDATE_CONNECT_PARAMS,
ef6243ac 16964 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
088e8df8 16965 .doit = nl80211_update_connect_params,
088e8df8 16966 .flags = GENL_ADMIN_PERM,
2182db91
JB
16967 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
16968 NL80211_FLAG_CLEAR_SKB),
088e8df8 16969 },
b23aa676
SO
16970 {
16971 .cmd = NL80211_CMD_DISCONNECT,
ef6243ac 16972 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
b23aa676 16973 .doit = nl80211_disconnect,
5617c6cd 16974 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16975 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
b23aa676 16976 },
463d0183
JB
16977 {
16978 .cmd = NL80211_CMD_SET_WIPHY_NETNS,
ef6243ac 16979 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
463d0183 16980 .doit = nl80211_wiphy_netns,
5617c6cd 16981 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
16982 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY |
16983 NL80211_FLAG_NEED_RTNL |
16984 NL80211_FLAG_NO_WIPHY_MTX),
463d0183 16985 },
61fa713c
HS
16986 {
16987 .cmd = NL80211_CMD_GET_SURVEY,
ef6243ac 16988 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
61fa713c
HS
16989 .dumpit = nl80211_dump_survey,
16990 },
67fbb16b
SO
16991 {
16992 .cmd = NL80211_CMD_SET_PMKSA,
ef6243ac 16993 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
aa0887c4 16994 .doit = nl80211_set_pmksa,
5617c6cd 16995 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
16996 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
16997 NL80211_FLAG_CLEAR_SKB),
67fbb16b
SO
16998 },
16999 {
17000 .cmd = NL80211_CMD_DEL_PMKSA,
ef6243ac 17001 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
aa0887c4 17002 .doit = nl80211_del_pmksa,
5617c6cd 17003 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17004 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
67fbb16b
SO
17005 },
17006 {
17007 .cmd = NL80211_CMD_FLUSH_PMKSA,
ef6243ac 17008 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
67fbb16b 17009 .doit = nl80211_flush_pmksa,
5617c6cd 17010 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17011 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
67fbb16b 17012 },
9588bbd5
JM
17013 {
17014 .cmd = NL80211_CMD_REMAIN_ON_CHANNEL,
ef6243ac 17015 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9588bbd5 17016 .doit = nl80211_remain_on_channel,
5617c6cd 17017 .flags = GENL_UNS_ADMIN_PERM,
7b0a0e3c
JB
17018 /* FIXME: requiring a link ID here is probably not good */
17019 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP |
17020 NL80211_FLAG_MLO_VALID_LINK_ID),
9588bbd5
JM
17021 },
17022 {
17023 .cmd = NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL,
ef6243ac 17024 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9588bbd5 17025 .doit = nl80211_cancel_remain_on_channel,
5617c6cd 17026 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17027 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
9588bbd5 17028 },
13ae75b1
JM
17029 {
17030 .cmd = NL80211_CMD_SET_TX_BITRATE_MASK,
ef6243ac 17031 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
13ae75b1 17032 .doit = nl80211_set_tx_bitrate_mask,
5617c6cd 17033 .flags = GENL_UNS_ADMIN_PERM,
7b0a0e3c
JB
17034 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV |
17035 NL80211_FLAG_MLO_VALID_LINK_ID),
13ae75b1 17036 },
026331c4 17037 {
2e161f78 17038 .cmd = NL80211_CMD_REGISTER_FRAME,
ef6243ac 17039 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2e161f78 17040 .doit = nl80211_register_mgmt,
5617c6cd 17041 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17042 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV),
026331c4
JM
17043 },
17044 {
2e161f78 17045 .cmd = NL80211_CMD_FRAME,
ef6243ac 17046 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2e161f78 17047 .doit = nl80211_tx_mgmt,
5617c6cd 17048 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17049 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
f7ca38df
JB
17050 },
17051 {
17052 .cmd = NL80211_CMD_FRAME_WAIT_CANCEL,
ef6243ac 17053 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
f7ca38df 17054 .doit = nl80211_tx_mgmt_cancel_wait,
5617c6cd 17055 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17056 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
026331c4 17057 },
ffb9eb3d
KV
17058 {
17059 .cmd = NL80211_CMD_SET_POWER_SAVE,
ef6243ac 17060 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ffb9eb3d 17061 .doit = nl80211_set_power_save,
5617c6cd 17062 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17063 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
ffb9eb3d
KV
17064 },
17065 {
17066 .cmd = NL80211_CMD_GET_POWER_SAVE,
ef6243ac 17067 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ffb9eb3d 17068 .doit = nl80211_get_power_save,
ffb9eb3d 17069 /* can be retrieved by unprivileged users */
2182db91 17070 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
ffb9eb3d 17071 },
d6dc1a38
JO
17072 {
17073 .cmd = NL80211_CMD_SET_CQM,
ef6243ac 17074 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
d6dc1a38 17075 .doit = nl80211_set_cqm,
5617c6cd 17076 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17077 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
d6dc1a38 17078 },
f444de05
JB
17079 {
17080 .cmd = NL80211_CMD_SET_CHANNEL,
ef6243ac 17081 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
f444de05 17082 .doit = nl80211_set_channel,
5617c6cd 17083 .flags = GENL_UNS_ADMIN_PERM,
7b0a0e3c
JB
17084 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV |
17085 NL80211_FLAG_MLO_VALID_LINK_ID),
f444de05 17086 },
29cbe68c
JB
17087 {
17088 .cmd = NL80211_CMD_JOIN_MESH,
ef6243ac 17089 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
29cbe68c 17090 .doit = nl80211_join_mesh,
5617c6cd 17091 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17092 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
29cbe68c
JB
17093 },
17094 {
17095 .cmd = NL80211_CMD_LEAVE_MESH,
ef6243ac 17096 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
29cbe68c 17097 .doit = nl80211_leave_mesh,
5617c6cd 17098 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17099 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
29cbe68c 17100 },
6e0bd6c3
RL
17101 {
17102 .cmd = NL80211_CMD_JOIN_OCB,
ef6243ac 17103 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6e0bd6c3 17104 .doit = nl80211_join_ocb,
5617c6cd 17105 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17106 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
6e0bd6c3
RL
17107 },
17108 {
17109 .cmd = NL80211_CMD_LEAVE_OCB,
ef6243ac 17110 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6e0bd6c3 17111 .doit = nl80211_leave_ocb,
5617c6cd 17112 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17113 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
6e0bd6c3 17114 },
dfb89c56 17115#ifdef CONFIG_PM
ff1b6e69
JB
17116 {
17117 .cmd = NL80211_CMD_GET_WOWLAN,
ef6243ac 17118 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ff1b6e69 17119 .doit = nl80211_get_wowlan,
ff1b6e69 17120 /* can be retrieved by unprivileged users */
2182db91 17121 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY),
ff1b6e69
JB
17122 },
17123 {
17124 .cmd = NL80211_CMD_SET_WOWLAN,
ef6243ac 17125 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ff1b6e69 17126 .doit = nl80211_set_wowlan,
5617c6cd 17127 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17128 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY),
ff1b6e69 17129 },
dfb89c56 17130#endif
e5497d76
JB
17131 {
17132 .cmd = NL80211_CMD_SET_REKEY_OFFLOAD,
ef6243ac 17133 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
e5497d76 17134 .doit = nl80211_set_rekey_data,
5617c6cd 17135 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
17136 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
17137 NL80211_FLAG_CLEAR_SKB),
e5497d76 17138 },
109086ce
AN
17139 {
17140 .cmd = NL80211_CMD_TDLS_MGMT,
ef6243ac 17141 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
109086ce 17142 .doit = nl80211_tdls_mgmt,
5617c6cd 17143 .flags = GENL_UNS_ADMIN_PERM,
c6112046
MS
17144 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
17145 NL80211_FLAG_MLO_VALID_LINK_ID),
109086ce
AN
17146 },
17147 {
17148 .cmd = NL80211_CMD_TDLS_OPER,
ef6243ac 17149 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
109086ce 17150 .doit = nl80211_tdls_oper,
5617c6cd 17151 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17152 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
109086ce 17153 },
28946da7
JB
17154 {
17155 .cmd = NL80211_CMD_UNEXPECTED_FRAME,
ef6243ac 17156 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
28946da7 17157 .doit = nl80211_register_unexpected_frame,
5617c6cd 17158 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17159 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
28946da7 17160 },
7f6cf311
JB
17161 {
17162 .cmd = NL80211_CMD_PROBE_CLIENT,
ef6243ac 17163 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
7f6cf311 17164 .doit = nl80211_probe_client,
5617c6cd 17165 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17166 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
7f6cf311 17167 },
5e760230
JB
17168 {
17169 .cmd = NL80211_CMD_REGISTER_BEACONS,
ef6243ac 17170 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5e760230 17171 .doit = nl80211_register_beacons,
5617c6cd 17172 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17173 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY),
5e760230 17174 },
1d9d9213
SW
17175 {
17176 .cmd = NL80211_CMD_SET_NOACK_MAP,
ef6243ac 17177 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1d9d9213 17178 .doit = nl80211_set_noack_map,
5617c6cd 17179 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17180 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
1d9d9213 17181 },
98104fde
JB
17182 {
17183 .cmd = NL80211_CMD_START_P2P_DEVICE,
ef6243ac 17184 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
98104fde 17185 .doit = nl80211_start_p2p_device,
5617c6cd 17186 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
17187 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV |
17188 NL80211_FLAG_NEED_RTNL),
98104fde
JB
17189 },
17190 {
17191 .cmd = NL80211_CMD_STOP_P2P_DEVICE,
ef6243ac 17192 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
98104fde 17193 .doit = nl80211_stop_p2p_device,
5617c6cd 17194 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
17195 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP |
17196 NL80211_FLAG_NEED_RTNL),
cb3b7d87
AB
17197 },
17198 {
17199 .cmd = NL80211_CMD_START_NAN,
ef6243ac 17200 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
cb3b7d87 17201 .doit = nl80211_start_nan,
cb3b7d87 17202 .flags = GENL_ADMIN_PERM,
2182db91
JB
17203 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV |
17204 NL80211_FLAG_NEED_RTNL),
cb3b7d87
AB
17205 },
17206 {
17207 .cmd = NL80211_CMD_STOP_NAN,
ef6243ac 17208 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
cb3b7d87 17209 .doit = nl80211_stop_nan,
cb3b7d87 17210 .flags = GENL_ADMIN_PERM,
2182db91
JB
17211 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP |
17212 NL80211_FLAG_NEED_RTNL),
a442b761
AB
17213 },
17214 {
17215 .cmd = NL80211_CMD_ADD_NAN_FUNCTION,
ef6243ac 17216 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
a442b761 17217 .doit = nl80211_nan_add_func,
a442b761 17218 .flags = GENL_ADMIN_PERM,
2182db91 17219 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
a442b761
AB
17220 },
17221 {
17222 .cmd = NL80211_CMD_DEL_NAN_FUNCTION,
ef6243ac 17223 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
a442b761 17224 .doit = nl80211_nan_del_func,
a442b761 17225 .flags = GENL_ADMIN_PERM,
2182db91 17226 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
a5a9dcf2
AB
17227 },
17228 {
17229 .cmd = NL80211_CMD_CHANGE_NAN_CONFIG,
ef6243ac 17230 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
a5a9dcf2 17231 .doit = nl80211_nan_change_config,
a5a9dcf2 17232 .flags = GENL_ADMIN_PERM,
2182db91 17233 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
98104fde 17234 },
f4e583c8
AQ
17235 {
17236 .cmd = NL80211_CMD_SET_MCAST_RATE,
ef6243ac 17237 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
f4e583c8 17238 .doit = nl80211_set_mcast_rate,
5617c6cd 17239 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17240 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
77765eaf
VT
17241 },
17242 {
17243 .cmd = NL80211_CMD_SET_MAC_ACL,
ef6243ac 17244 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
77765eaf 17245 .doit = nl80211_set_mac_acl,
5617c6cd 17246 .flags = GENL_UNS_ADMIN_PERM,
7b0a0e3c
JB
17247 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV |
17248 NL80211_FLAG_MLO_UNSUPPORTED),
f4e583c8 17249 },
04f39047
SW
17250 {
17251 .cmd = NL80211_CMD_RADAR_DETECT,
ef6243ac 17252 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
04f39047 17253 .doit = nl80211_start_radar_detection,
5617c6cd 17254 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17255 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
7b0a0e3c
JB
17256 NL80211_FLAG_NO_WIPHY_MTX |
17257 NL80211_FLAG_MLO_UNSUPPORTED),
04f39047 17258 },
3713b4e3
JB
17259 {
17260 .cmd = NL80211_CMD_GET_PROTOCOL_FEATURES,
ef6243ac 17261 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
3713b4e3 17262 .doit = nl80211_get_protocol_features,
3713b4e3 17263 },
355199e0
JM
17264 {
17265 .cmd = NL80211_CMD_UPDATE_FT_IES,
ef6243ac 17266 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
355199e0 17267 .doit = nl80211_update_ft_ies,
5617c6cd 17268 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17269 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
355199e0 17270 },
5de17984
AS
17271 {
17272 .cmd = NL80211_CMD_CRIT_PROTOCOL_START,
ef6243ac 17273 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5de17984 17274 .doit = nl80211_crit_protocol_start,
5617c6cd 17275 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17276 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
5de17984
AS
17277 },
17278 {
17279 .cmd = NL80211_CMD_CRIT_PROTOCOL_STOP,
ef6243ac 17280 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5de17984 17281 .doit = nl80211_crit_protocol_stop,
5617c6cd 17282 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17283 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
be29b99a
AK
17284 },
17285 {
17286 .cmd = NL80211_CMD_GET_COALESCE,
ef6243ac 17287 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
be29b99a 17288 .doit = nl80211_get_coalesce,
2182db91 17289 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY),
be29b99a
AK
17290 },
17291 {
17292 .cmd = NL80211_CMD_SET_COALESCE,
ef6243ac 17293 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
be29b99a 17294 .doit = nl80211_set_coalesce,
5617c6cd 17295 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17296 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY),
16ef1fe2
SW
17297 },
17298 {
17299 .cmd = NL80211_CMD_CHANNEL_SWITCH,
ef6243ac 17300 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
16ef1fe2 17301 .doit = nl80211_channel_switch,
5617c6cd 17302 .flags = GENL_UNS_ADMIN_PERM,
7b0a0e3c
JB
17303 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
17304 NL80211_FLAG_MLO_VALID_LINK_ID),
16ef1fe2 17305 },
ad7e718c
JB
17306 {
17307 .cmd = NL80211_CMD_VENDOR,
ef6243ac 17308 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ad7e718c 17309 .doit = nl80211_vendor_cmd,
7bdbe400 17310 .dumpit = nl80211_vendor_cmd_dump,
5617c6cd 17311 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
17312 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY |
17313 NL80211_FLAG_CLEAR_SKB),
ad7e718c 17314 },
fa9ffc74
KP
17315 {
17316 .cmd = NL80211_CMD_SET_QOS_MAP,
ef6243ac 17317 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
fa9ffc74 17318 .doit = nl80211_set_qos_map,
5617c6cd 17319 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17320 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
fa9ffc74 17321 },
960d01ac
JB
17322 {
17323 .cmd = NL80211_CMD_ADD_TX_TS,
ef6243ac 17324 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
960d01ac 17325 .doit = nl80211_add_tx_ts,
5617c6cd 17326 .flags = GENL_UNS_ADMIN_PERM,
7b0a0e3c
JB
17327 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
17328 NL80211_FLAG_MLO_UNSUPPORTED),
960d01ac
JB
17329 },
17330 {
17331 .cmd = NL80211_CMD_DEL_TX_TS,
ef6243ac 17332 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
960d01ac 17333 .doit = nl80211_del_tx_ts,
5617c6cd 17334 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17335 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
960d01ac 17336 },
1057d35e
AN
17337 {
17338 .cmd = NL80211_CMD_TDLS_CHANNEL_SWITCH,
ef6243ac 17339 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1057d35e 17340 .doit = nl80211_tdls_channel_switch,
5617c6cd 17341 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17342 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
1057d35e
AN
17343 },
17344 {
17345 .cmd = NL80211_CMD_TDLS_CANCEL_CHANNEL_SWITCH,
ef6243ac 17346 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1057d35e 17347 .doit = nl80211_tdls_cancel_channel_switch,
5617c6cd 17348 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17349 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
1057d35e 17350 },
ce0ce13a
MB
17351 {
17352 .cmd = NL80211_CMD_SET_MULTICAST_TO_UNICAST,
ef6243ac 17353 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ce0ce13a 17354 .doit = nl80211_set_multicast_to_unicast,
ce0ce13a 17355 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17356 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
ce0ce13a 17357 },
3a00df57
AS
17358 {
17359 .cmd = NL80211_CMD_SET_PMK,
ef6243ac 17360 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
3a00df57 17361 .doit = nl80211_set_pmk,
2182db91
JB
17362 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
17363 NL80211_FLAG_CLEAR_SKB),
3a00df57
AS
17364 },
17365 {
17366 .cmd = NL80211_CMD_DEL_PMK,
ef6243ac 17367 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
3a00df57 17368 .doit = nl80211_del_pmk,
2182db91 17369 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
3a00df57 17370 },
40cbfa90
SD
17371 {
17372 .cmd = NL80211_CMD_EXTERNAL_AUTH,
ef6243ac 17373 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
40cbfa90 17374 .doit = nl80211_external_auth,
40cbfa90 17375 .flags = GENL_ADMIN_PERM,
2182db91 17376 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
40cbfa90 17377 },
2576a9ac
DK
17378 {
17379 .cmd = NL80211_CMD_CONTROL_PORT_FRAME,
ef6243ac 17380 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2576a9ac 17381 .doit = nl80211_tx_control_port,
2576a9ac 17382 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17383 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
2576a9ac 17384 },
81e54d08
PKC
17385 {
17386 .cmd = NL80211_CMD_GET_FTM_RESPONDER_STATS,
ef6243ac 17387 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
81e54d08 17388 .doit = nl80211_get_ftm_responder_stats,
7b0a0e3c
JB
17389 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV |
17390 NL80211_FLAG_MLO_VALID_LINK_ID),
81e54d08 17391 },
9bb7e0f2
JB
17392 {
17393 .cmd = NL80211_CMD_PEER_MEASUREMENT_START,
ef6243ac 17394 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9bb7e0f2 17395 .doit = nl80211_pmsr_start,
9bb7e0f2 17396 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17397 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
9bb7e0f2 17398 },
30c63115
S
17399 {
17400 .cmd = NL80211_CMD_NOTIFY_RADAR,
ef6243ac 17401 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
30c63115 17402 .doit = nl80211_notify_radar_detection,
30c63115 17403 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17404 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
30c63115 17405 },
cb74e977
SD
17406 {
17407 .cmd = NL80211_CMD_UPDATE_OWE_INFO,
17408 .doit = nl80211_update_owe_info,
17409 .flags = GENL_ADMIN_PERM,
2182db91 17410 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
5ab92e7f
RM
17411 },
17412 {
17413 .cmd = NL80211_CMD_PROBE_MESH_LINK,
17414 .doit = nl80211_probe_mesh_link,
17415 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17416 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
cb74e977 17417 },
77f576de
T
17418 {
17419 .cmd = NL80211_CMD_SET_TID_CONFIG,
17420 .doit = nl80211_set_tid_config,
17421 .flags = GENL_UNS_ADMIN_PERM,
7b0a0e3c
JB
17422 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV |
17423 NL80211_FLAG_MLO_VALID_LINK_ID),
77f576de 17424 },
6bdb68ce
CH
17425 {
17426 .cmd = NL80211_CMD_SET_SAR_SPECS,
17427 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
17428 .doit = nl80211_set_sar_specs,
17429 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
17430 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY |
17431 NL80211_FLAG_NEED_RTNL),
6bdb68ce 17432 },
0d2ab3ae
JC
17433 {
17434 .cmd = NL80211_CMD_COLOR_CHANGE_REQUEST,
17435 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
17436 .doit = nl80211_color_change,
17437 .flags = GENL_UNS_ADMIN_PERM,
91d2b6ee
AKS
17438 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
17439 NL80211_FLAG_MLO_VALID_LINK_ID),
0d2ab3ae 17440 },
e306784a
SM
17441 {
17442 .cmd = NL80211_CMD_SET_FILS_AAD,
17443 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
17444 .doit = nl80211_set_fils_aad,
17445 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17446 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
e306784a 17447 },
7b0a0e3c
JB
17448 {
17449 .cmd = NL80211_CMD_ADD_LINK,
17450 .doit = nl80211_add_link,
17451 .flags = GENL_UNS_ADMIN_PERM,
17452 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
17453 },
17454 {
17455 .cmd = NL80211_CMD_REMOVE_LINK,
17456 .doit = nl80211_remove_link,
17457 .flags = GENL_UNS_ADMIN_PERM,
577e5b8c
ST
17458 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
17459 NL80211_FLAG_MLO_VALID_LINK_ID),
17460 },
17461 {
17462 .cmd = NL80211_CMD_ADD_LINK_STA,
17463 .doit = nl80211_add_link_station,
17464 .flags = GENL_UNS_ADMIN_PERM,
17465 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
17466 NL80211_FLAG_MLO_VALID_LINK_ID),
17467 },
17468 {
17469 .cmd = NL80211_CMD_MODIFY_LINK_STA,
17470 .doit = nl80211_modify_link_station,
17471 .flags = GENL_UNS_ADMIN_PERM,
17472 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
17473 NL80211_FLAG_MLO_VALID_LINK_ID),
17474 },
17475 {
17476 .cmd = NL80211_CMD_REMOVE_LINK_STA,
17477 .doit = nl80211_remove_link_station,
17478 .flags = GENL_UNS_ADMIN_PERM,
7b0a0e3c
JB
17479 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
17480 NL80211_FLAG_MLO_VALID_LINK_ID),
17481 },
cbbaf2bb
AS
17482 {
17483 .cmd = NL80211_CMD_SET_HW_TIMESTAMP,
17484 .doit = nl80211_set_hw_timestamp,
17485 .flags = GENL_UNS_ADMIN_PERM,
17486 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
17487 },
b61e6b41
IP
17488 {
17489 .cmd = NL80211_CMD_SET_TID_TO_LINK_MAPPING,
17490 .doit = nl80211_set_ttlm,
17491 .flags = GENL_UNS_ADMIN_PERM,
17492 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
17493 },
55682965 17494};
9588bbd5 17495
56989f6d 17496static struct genl_family nl80211_fam __ro_after_init = {
489111e5
JB
17497 .name = NL80211_GENL_NAME, /* have users key off the name instead */
17498 .hdrsize = 0, /* no private header */
17499 .version = 1, /* no particular meaning now */
17500 .maxattr = NL80211_ATTR_MAX,
3b0f31f2 17501 .policy = nl80211_policy,
489111e5
JB
17502 .netnsok = true,
17503 .pre_doit = nl80211_pre_doit,
17504 .post_doit = nl80211_post_doit,
17505 .module = THIS_MODULE,
17506 .ops = nl80211_ops,
17507 .n_ops = ARRAY_SIZE(nl80211_ops),
66a9b928
JK
17508 .small_ops = nl80211_small_ops,
17509 .n_small_ops = ARRAY_SIZE(nl80211_small_ops),
9c5d03d3 17510 .resv_start_op = NL80211_CMD_REMOVE_LINK_STA + 1,
489111e5
JB
17511 .mcgrps = nl80211_mcgrps,
17512 .n_mcgrps = ARRAY_SIZE(nl80211_mcgrps),
50508d94 17513 .parallel_ops = true,
489111e5
JB
17514};
17515
55682965
JB
17516/* notification functions */
17517
3bb20556
JB
17518void nl80211_notify_wiphy(struct cfg80211_registered_device *rdev,
17519 enum nl80211_commands cmd)
55682965
JB
17520{
17521 struct sk_buff *msg;
86e8cf98 17522 struct nl80211_dump_wiphy_state state = {};
55682965 17523
3bb20556
JB
17524 WARN_ON(cmd != NL80211_CMD_NEW_WIPHY &&
17525 cmd != NL80211_CMD_DEL_WIPHY);
17526
fd2120ca 17527 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
55682965
JB
17528 if (!msg)
17529 return;
17530
3bb20556 17531 if (nl80211_send_wiphy(rdev, cmd, msg, 0, 0, 0, &state) < 0) {
55682965
JB
17532 nlmsg_free(msg);
17533 return;
17534 }
17535
68eb5503 17536 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17537 NL80211_MCGRP_CONFIG, GFP_KERNEL);
55682965
JB
17538}
17539
896ff063
DK
17540void nl80211_notify_iface(struct cfg80211_registered_device *rdev,
17541 struct wireless_dev *wdev,
17542 enum nl80211_commands cmd)
17543{
17544 struct sk_buff *msg;
17545
896ff063
DK
17546 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
17547 if (!msg)
17548 return;
17549
3d1a5bbf 17550 if (nl80211_send_iface(msg, 0, 0, 0, rdev, wdev, cmd) < 0) {
896ff063
DK
17551 nlmsg_free(msg);
17552 return;
17553 }
17554
17555 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
17556 NL80211_MCGRP_CONFIG, GFP_KERNEL);
17557}
17558
362a415d
JB
17559static int nl80211_add_scan_req(struct sk_buff *msg,
17560 struct cfg80211_registered_device *rdev)
17561{
17562 struct cfg80211_scan_request *req = rdev->scan_req;
17563 struct nlattr *nest;
17564 int i;
c8cb5b85 17565 struct cfg80211_scan_info *info;
362a415d
JB
17566
17567 if (WARN_ON(!req))
17568 return 0;
17569
ae0be8de 17570 nest = nla_nest_start_noflag(msg, NL80211_ATTR_SCAN_SSIDS);
362a415d
JB
17571 if (!nest)
17572 goto nla_put_failure;
9360ffd1
DM
17573 for (i = 0; i < req->n_ssids; i++) {
17574 if (nla_put(msg, i, req->ssids[i].ssid_len, req->ssids[i].ssid))
17575 goto nla_put_failure;
17576 }
362a415d
JB
17577 nla_nest_end(msg, nest);
17578
2032f3b2
TP
17579 if (req->flags & NL80211_SCAN_FLAG_FREQ_KHZ) {
17580 nest = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQ_KHZ);
17581 if (!nest)
17582 goto nla_put_failure;
17583 for (i = 0; i < req->n_channels; i++) {
17584 if (nla_put_u32(msg, i,
17585 ieee80211_channel_to_khz(req->channels[i])))
17586 goto nla_put_failure;
17587 }
17588 nla_nest_end(msg, nest);
17589 } else {
17590 nest = nla_nest_start_noflag(msg,
17591 NL80211_ATTR_SCAN_FREQUENCIES);
17592 if (!nest)
9360ffd1 17593 goto nla_put_failure;
2032f3b2
TP
17594 for (i = 0; i < req->n_channels; i++) {
17595 if (nla_put_u32(msg, i, req->channels[i]->center_freq))
17596 goto nla_put_failure;
17597 }
17598 nla_nest_end(msg, nest);
9360ffd1 17599 }
362a415d 17600
9360ffd1
DM
17601 if (req->ie &&
17602 nla_put(msg, NL80211_ATTR_IE, req->ie_len, req->ie))
17603 goto nla_put_failure;
362a415d 17604
ae917c9f
JB
17605 if (req->flags &&
17606 nla_put_u32(msg, NL80211_ATTR_SCAN_FLAGS, req->flags))
17607 goto nla_put_failure;
ed473771 17608
c8cb5b85
TM
17609 info = rdev->int_scan_req ? &rdev->int_scan_req->info :
17610 &rdev->scan_req->info;
17611 if (info->scan_start_tsf &&
1d76250b 17612 (nla_put_u64_64bit(msg, NL80211_ATTR_SCAN_START_TIME_TSF,
c8cb5b85 17613 info->scan_start_tsf, NL80211_BSS_PAD) ||
1d76250b 17614 nla_put(msg, NL80211_ATTR_SCAN_START_TIME_TSF_BSSID, ETH_ALEN,
c8cb5b85 17615 info->tsf_bssid)))
1d76250b
AS
17616 goto nla_put_failure;
17617
362a415d
JB
17618 return 0;
17619 nla_put_failure:
17620 return -ENOBUFS;
17621}
17622
505a2e88 17623static int nl80211_prep_scan_msg(struct sk_buff *msg,
a538e2d5 17624 struct cfg80211_registered_device *rdev,
fd014284 17625 struct wireless_dev *wdev,
15e47304 17626 u32 portid, u32 seq, int flags,
a538e2d5 17627 u32 cmd)
2a519311
JB
17628{
17629 void *hdr;
17630
15e47304 17631 hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
2a519311
JB
17632 if (!hdr)
17633 return -1;
17634
9360ffd1 17635 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
fd014284
JB
17636 (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
17637 wdev->netdev->ifindex)) ||
2dad624e
ND
17638 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
17639 NL80211_ATTR_PAD))
9360ffd1 17640 goto nla_put_failure;
2a519311 17641
362a415d
JB
17642 /* ignore errors and send incomplete event anyway */
17643 nl80211_add_scan_req(msg, rdev);
2a519311 17644
053c095a
JB
17645 genlmsg_end(msg, hdr);
17646 return 0;
2a519311
JB
17647
17648 nla_put_failure:
17649 genlmsg_cancel(msg, hdr);
17650 return -EMSGSIZE;
17651}
17652
807f8a8c 17653static int
505a2e88 17654nl80211_prep_sched_scan_msg(struct sk_buff *msg,
96b08fd6 17655 struct cfg80211_sched_scan_request *req, u32 cmd)
807f8a8c
LC
17656{
17657 void *hdr;
17658
96b08fd6 17659 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
807f8a8c
LC
17660 if (!hdr)
17661 return -1;
17662
96b08fd6
AVS
17663 if (nla_put_u32(msg, NL80211_ATTR_WIPHY,
17664 wiphy_to_rdev(req->wiphy)->wiphy_idx) ||
17665 nla_put_u32(msg, NL80211_ATTR_IFINDEX, req->dev->ifindex) ||
17666 nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, req->reqid,
17667 NL80211_ATTR_PAD))
9360ffd1 17668 goto nla_put_failure;
807f8a8c 17669
053c095a
JB
17670 genlmsg_end(msg, hdr);
17671 return 0;
807f8a8c
LC
17672
17673 nla_put_failure:
17674 genlmsg_cancel(msg, hdr);
17675 return -EMSGSIZE;
17676}
17677
a538e2d5 17678void nl80211_send_scan_start(struct cfg80211_registered_device *rdev,
fd014284 17679 struct wireless_dev *wdev)
a538e2d5
JB
17680{
17681 struct sk_buff *msg;
17682
58050fce 17683 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
a538e2d5
JB
17684 if (!msg)
17685 return;
17686
505a2e88 17687 if (nl80211_prep_scan_msg(msg, rdev, wdev, 0, 0, 0,
a538e2d5
JB
17688 NL80211_CMD_TRIGGER_SCAN) < 0) {
17689 nlmsg_free(msg);
17690 return;
17691 }
17692
68eb5503 17693 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17694 NL80211_MCGRP_SCAN, GFP_KERNEL);
a538e2d5
JB
17695}
17696
f9d15d16
JB
17697struct sk_buff *nl80211_build_scan_msg(struct cfg80211_registered_device *rdev,
17698 struct wireless_dev *wdev, bool aborted)
2a519311
JB
17699{
17700 struct sk_buff *msg;
17701
fd2120ca 17702 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2a519311 17703 if (!msg)
f9d15d16 17704 return NULL;
2a519311 17705
505a2e88 17706 if (nl80211_prep_scan_msg(msg, rdev, wdev, 0, 0, 0,
f9d15d16
JB
17707 aborted ? NL80211_CMD_SCAN_ABORTED :
17708 NL80211_CMD_NEW_SCAN_RESULTS) < 0) {
2a519311 17709 nlmsg_free(msg);
f9d15d16 17710 return NULL;
2a519311
JB
17711 }
17712
f9d15d16 17713 return msg;
2a519311
JB
17714}
17715
505a2e88
AVS
17716/* send message created by nl80211_build_scan_msg() */
17717void nl80211_send_scan_msg(struct cfg80211_registered_device *rdev,
17718 struct sk_buff *msg)
807f8a8c 17719{
807f8a8c
LC
17720 if (!msg)
17721 return;
17722
68eb5503 17723 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17724 NL80211_MCGRP_SCAN, GFP_KERNEL);
807f8a8c
LC
17725}
17726
96b08fd6 17727void nl80211_send_sched_scan(struct cfg80211_sched_scan_request *req, u32 cmd)
807f8a8c
LC
17728{
17729 struct sk_buff *msg;
17730
58050fce 17731 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
807f8a8c
LC
17732 if (!msg)
17733 return;
17734
96b08fd6 17735 if (nl80211_prep_sched_scan_msg(msg, req, cmd) < 0) {
807f8a8c
LC
17736 nlmsg_free(msg);
17737 return;
17738 }
17739
96b08fd6 17740 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(req->wiphy), msg, 0,
2a94fe48 17741 NL80211_MCGRP_SCAN, GFP_KERNEL);
807f8a8c
LC
17742}
17743
b0d7aa59
JD
17744static bool nl80211_reg_change_event_fill(struct sk_buff *msg,
17745 struct regulatory_request *request)
73d54c9e 17746{
73d54c9e 17747 /* Userspace can always count this one always being set */
9360ffd1
DM
17748 if (nla_put_u8(msg, NL80211_ATTR_REG_INITIATOR, request->initiator))
17749 goto nla_put_failure;
17750
17751 if (request->alpha2[0] == '0' && request->alpha2[1] == '0') {
17752 if (nla_put_u8(msg, NL80211_ATTR_REG_TYPE,
17753 NL80211_REGDOM_TYPE_WORLD))
17754 goto nla_put_failure;
17755 } else if (request->alpha2[0] == '9' && request->alpha2[1] == '9') {
17756 if (nla_put_u8(msg, NL80211_ATTR_REG_TYPE,
17757 NL80211_REGDOM_TYPE_CUSTOM_WORLD))
17758 goto nla_put_failure;
17759 } else if ((request->alpha2[0] == '9' && request->alpha2[1] == '8') ||
17760 request->intersect) {
17761 if (nla_put_u8(msg, NL80211_ATTR_REG_TYPE,
17762 NL80211_REGDOM_TYPE_INTERSECTION))
17763 goto nla_put_failure;
17764 } else {
17765 if (nla_put_u8(msg, NL80211_ATTR_REG_TYPE,
17766 NL80211_REGDOM_TYPE_COUNTRY) ||
17767 nla_put_string(msg, NL80211_ATTR_REG_ALPHA2,
17768 request->alpha2))
17769 goto nla_put_failure;
17770 }
17771
ad30ca2c
AN
17772 if (request->wiphy_idx != WIPHY_IDX_INVALID) {
17773 struct wiphy *wiphy = wiphy_idx_to_wiphy(request->wiphy_idx);
17774
17775 if (wiphy &&
17776 nla_put_u32(msg, NL80211_ATTR_WIPHY, request->wiphy_idx))
17777 goto nla_put_failure;
1bdd716c
AN
17778
17779 if (wiphy &&
17780 wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED &&
17781 nla_put_flag(msg, NL80211_ATTR_WIPHY_SELF_MANAGED_REG))
17782 goto nla_put_failure;
ad30ca2c 17783 }
73d54c9e 17784
b0d7aa59
JD
17785 return true;
17786
17787nla_put_failure:
17788 return false;
17789}
17790
17791/*
17792 * This can happen on global regulatory changes or device specific settings
17793 * based on custom regulatory domains.
17794 */
17795void nl80211_common_reg_change_event(enum nl80211_commands cmd_id,
17796 struct regulatory_request *request)
17797{
17798 struct sk_buff *msg;
17799 void *hdr;
17800
17801 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
17802 if (!msg)
17803 return;
17804
17805 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd_id);
24f6d765 17806 if (!hdr)
17807 goto nla_put_failure;
b0d7aa59 17808
24f6d765 17809 if (!nl80211_reg_change_event_fill(msg, request))
b0d7aa59
JD
17810 goto nla_put_failure;
17811
3b7b72ee 17812 genlmsg_end(msg, hdr);
73d54c9e 17813
bc43b28c 17814 rcu_read_lock();
68eb5503 17815 genlmsg_multicast_allns(&nl80211_fam, msg, 0,
2a94fe48 17816 NL80211_MCGRP_REGULATORY, GFP_ATOMIC);
bc43b28c 17817 rcu_read_unlock();
73d54c9e
LR
17818
17819 return;
17820
17821nla_put_failure:
73d54c9e
LR
17822 nlmsg_free(msg);
17823}
17824
ccf7dd94
JB
17825struct nl80211_mlme_event {
17826 enum nl80211_commands cmd;
17827 const u8 *buf;
17828 size_t buf_len;
17829 int uapsd_queues;
17830 const u8 *req_ies;
17831 size_t req_ies_len;
17832 bool reconnect;
17833};
17834
6039f6d2
JM
17835static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev,
17836 struct net_device *netdev,
ccf7dd94
JB
17837 const struct nl80211_mlme_event *event,
17838 gfp_t gfp)
6039f6d2
JM
17839{
17840 struct sk_buff *msg;
17841 void *hdr;
17842
ccf7dd94 17843 msg = nlmsg_new(100 + event->buf_len + event->req_ies_len, gfp);
6039f6d2
JM
17844 if (!msg)
17845 return;
17846
ccf7dd94 17847 hdr = nl80211hdr_put(msg, 0, 0, 0, event->cmd);
6039f6d2
JM
17848 if (!hdr) {
17849 nlmsg_free(msg);
17850 return;
17851 }
17852
9360ffd1
DM
17853 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
17854 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
ccf7dd94
JB
17855 nla_put(msg, NL80211_ATTR_FRAME, event->buf_len, event->buf) ||
17856 (event->req_ies &&
17857 nla_put(msg, NL80211_ATTR_REQ_IE, event->req_ies_len,
17858 event->req_ies)))
9360ffd1 17859 goto nla_put_failure;
6039f6d2 17860
ccf7dd94
JB
17861 if (event->reconnect &&
17862 nla_put_flag(msg, NL80211_ATTR_RECONNECT_REQUESTED))
3bb02143
JB
17863 goto nla_put_failure;
17864
ccf7dd94 17865 if (event->uapsd_queues >= 0) {
b0b6aa2c 17866 struct nlattr *nla_wmm =
ae0be8de 17867 nla_nest_start_noflag(msg, NL80211_ATTR_STA_WME);
b0b6aa2c
EP
17868 if (!nla_wmm)
17869 goto nla_put_failure;
17870
17871 if (nla_put_u8(msg, NL80211_STA_WME_UAPSD_QUEUES,
ccf7dd94 17872 event->uapsd_queues))
b0b6aa2c
EP
17873 goto nla_put_failure;
17874
17875 nla_nest_end(msg, nla_wmm);
17876 }
17877
3b7b72ee 17878 genlmsg_end(msg, hdr);
6039f6d2 17879
68eb5503 17880 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17881 NL80211_MCGRP_MLME, gfp);
6039f6d2
JM
17882 return;
17883
17884 nla_put_failure:
6039f6d2
JM
17885 nlmsg_free(msg);
17886}
17887
17888void nl80211_send_rx_auth(struct cfg80211_registered_device *rdev,
e6d6e342
JB
17889 struct net_device *netdev, const u8 *buf,
17890 size_t len, gfp_t gfp)
6039f6d2 17891{
ccf7dd94
JB
17892 struct nl80211_mlme_event event = {
17893 .cmd = NL80211_CMD_AUTHENTICATE,
17894 .buf = buf,
17895 .buf_len = len,
17896 .uapsd_queues = -1,
17897 };
17898
17899 nl80211_send_mlme_event(rdev, netdev, &event, gfp);
6039f6d2
JM
17900}
17901
17902void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev,
cd47c0f5 17903 struct net_device *netdev,
88f29324 17904 const struct cfg80211_rx_assoc_resp_data *data)
6039f6d2 17905{
ccf7dd94
JB
17906 struct nl80211_mlme_event event = {
17907 .cmd = NL80211_CMD_ASSOCIATE,
17908 .buf = data->buf,
17909 .buf_len = data->len,
17910 .uapsd_queues = data->uapsd_queues,
17911 .req_ies = data->req_ies,
17912 .req_ies_len = data->req_ies_len,
17913 };
17914
17915 nl80211_send_mlme_event(rdev, netdev, &event, GFP_KERNEL);
6039f6d2
JM
17916}
17917
53b46b84 17918void nl80211_send_deauth(struct cfg80211_registered_device *rdev,
e6d6e342 17919 struct net_device *netdev, const u8 *buf,
3bb02143 17920 size_t len, bool reconnect, gfp_t gfp)
6039f6d2 17921{
ccf7dd94
JB
17922 struct nl80211_mlme_event event = {
17923 .cmd = NL80211_CMD_DEAUTHENTICATE,
17924 .buf = buf,
17925 .buf_len = len,
17926 .reconnect = reconnect,
17927 .uapsd_queues = -1,
17928 };
17929
17930 nl80211_send_mlme_event(rdev, netdev, &event, gfp);
6039f6d2
JM
17931}
17932
53b46b84
JM
17933void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,
17934 struct net_device *netdev, const u8 *buf,
3bb02143 17935 size_t len, bool reconnect, gfp_t gfp)
6039f6d2 17936{
ccf7dd94
JB
17937 struct nl80211_mlme_event event = {
17938 .cmd = NL80211_CMD_DISASSOCIATE,
17939 .buf = buf,
17940 .buf_len = len,
17941 .reconnect = reconnect,
17942 .uapsd_queues = -1,
17943 };
17944
17945 nl80211_send_mlme_event(rdev, netdev, &event, gfp);
6039f6d2
JM
17946}
17947
6ff57cf8
JB
17948void cfg80211_rx_unprot_mlme_mgmt(struct net_device *dev, const u8 *buf,
17949 size_t len)
cf4e594e 17950{
947add36
JB
17951 struct wireless_dev *wdev = dev->ieee80211_ptr;
17952 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 17953 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
6ff57cf8 17954 const struct ieee80211_mgmt *mgmt = (void *)buf;
ccf7dd94
JB
17955 struct nl80211_mlme_event event = {
17956 .buf = buf,
17957 .buf_len = len,
17958 .uapsd_queues = -1,
17959 };
947add36 17960
6ff57cf8
JB
17961 if (WARN_ON(len < 2))
17962 return;
cf4e594e 17963
4d797fce 17964 if (ieee80211_is_deauth(mgmt->frame_control)) {
ccf7dd94 17965 event.cmd = NL80211_CMD_UNPROT_DEAUTHENTICATE;
4d797fce 17966 } else if (ieee80211_is_disassoc(mgmt->frame_control)) {
ccf7dd94 17967 event.cmd = NL80211_CMD_UNPROT_DISASSOCIATE;
4d797fce
JM
17968 } else if (ieee80211_is_beacon(mgmt->frame_control)) {
17969 if (wdev->unprot_beacon_reported &&
17970 elapsed_jiffies_msecs(wdev->unprot_beacon_reported) < 10000)
17971 return;
ccf7dd94 17972 event.cmd = NL80211_CMD_UNPROT_BEACON;
4d797fce
JM
17973 wdev->unprot_beacon_reported = jiffies;
17974 } else {
17975 return;
17976 }
947add36 17977
6ff57cf8 17978 trace_cfg80211_rx_unprot_mlme_mgmt(dev, buf, len);
ccf7dd94 17979 nl80211_send_mlme_event(rdev, dev, &event, GFP_ATOMIC);
cf4e594e 17980}
6ff57cf8 17981EXPORT_SYMBOL(cfg80211_rx_unprot_mlme_mgmt);
cf4e594e 17982
1b06bb40
LR
17983static void nl80211_send_mlme_timeout(struct cfg80211_registered_device *rdev,
17984 struct net_device *netdev, int cmd,
e6d6e342 17985 const u8 *addr, gfp_t gfp)
1965c853
JM
17986{
17987 struct sk_buff *msg;
17988 void *hdr;
17989
e6d6e342 17990 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
1965c853
JM
17991 if (!msg)
17992 return;
17993
17994 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
17995 if (!hdr) {
17996 nlmsg_free(msg);
17997 return;
17998 }
17999
9360ffd1
DM
18000 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
18001 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
18002 nla_put_flag(msg, NL80211_ATTR_TIMED_OUT) ||
18003 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr))
18004 goto nla_put_failure;
1965c853 18005
3b7b72ee 18006 genlmsg_end(msg, hdr);
1965c853 18007
68eb5503 18008 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18009 NL80211_MCGRP_MLME, gfp);
1965c853
JM
18010 return;
18011
18012 nla_put_failure:
1965c853
JM
18013 nlmsg_free(msg);
18014}
18015
18016void nl80211_send_auth_timeout(struct cfg80211_registered_device *rdev,
e6d6e342
JB
18017 struct net_device *netdev, const u8 *addr,
18018 gfp_t gfp)
1965c853
JM
18019{
18020 nl80211_send_mlme_timeout(rdev, netdev, NL80211_CMD_AUTHENTICATE,
e6d6e342 18021 addr, gfp);
1965c853
JM
18022}
18023
18024void nl80211_send_assoc_timeout(struct cfg80211_registered_device *rdev,
e6d6e342
JB
18025 struct net_device *netdev, const u8 *addr,
18026 gfp_t gfp)
1965c853 18027{
e6d6e342
JB
18028 nl80211_send_mlme_timeout(rdev, netdev, NL80211_CMD_ASSOCIATE,
18029 addr, gfp);
1965c853
JM
18030}
18031
b23aa676 18032void nl80211_send_connect_result(struct cfg80211_registered_device *rdev,
5349a0f7
VK
18033 struct net_device *netdev,
18034 struct cfg80211_connect_resp_params *cr,
3093ebbe 18035 gfp_t gfp)
b23aa676
SO
18036{
18037 struct sk_buff *msg;
18038 void *hdr;
efbabc11
VJ
18039 unsigned int link;
18040 size_t link_info_size = 0;
18041 const u8 *connected_addr = cr->valid_links ?
18042 cr->ap_mld_addr : cr->links[0].bssid;
18043
18044 if (cr->valid_links) {
18045 for_each_valid_link(cr, link) {
18046 /* Nested attribute header */
18047 link_info_size += NLA_HDRLEN;
18048 /* Link ID */
18049 link_info_size += nla_total_size(sizeof(u8));
18050 link_info_size += cr->links[link].addr ?
18051 nla_total_size(ETH_ALEN) : 0;
18052 link_info_size += (cr->links[link].bssid ||
18053 cr->links[link].bss) ?
18054 nla_total_size(ETH_ALEN) : 0;
53ad07e9 18055 link_info_size += nla_total_size(sizeof(u16));
efbabc11
VJ
18056 }
18057 }
b23aa676 18058
a3caf744 18059 msg = nlmsg_new(100 + cr->req_ie_len + cr->resp_ie_len +
76804d28 18060 cr->fils.kek_len + cr->fils.pmk_len +
efbabc11
VJ
18061 (cr->fils.pmkid ? WLAN_PMKID_LEN : 0) + link_info_size,
18062 gfp);
b23aa676
SO
18063 if (!msg)
18064 return;
18065
18066 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CONNECT);
18067 if (!hdr) {
18068 nlmsg_free(msg);
18069 return;
18070 }
18071
9360ffd1
DM
18072 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
18073 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
efbabc11
VJ
18074 (connected_addr &&
18075 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, connected_addr)) ||
bf1ecd21 18076 nla_put_u16(msg, NL80211_ATTR_STATUS_CODE,
5349a0f7
VK
18077 cr->status < 0 ? WLAN_STATUS_UNSPECIFIED_FAILURE :
18078 cr->status) ||
18079 (cr->status < 0 &&
3093ebbe 18080 (nla_put_flag(msg, NL80211_ATTR_TIMED_OUT) ||
5349a0f7
VK
18081 nla_put_u32(msg, NL80211_ATTR_TIMEOUT_REASON,
18082 cr->timeout_reason))) ||
18083 (cr->req_ie &&
18084 nla_put(msg, NL80211_ATTR_REQ_IE, cr->req_ie_len, cr->req_ie)) ||
18085 (cr->resp_ie &&
18086 nla_put(msg, NL80211_ATTR_RESP_IE, cr->resp_ie_len,
a3caf744 18087 cr->resp_ie)) ||
76804d28 18088 (cr->fils.update_erp_next_seq_num &&
a3caf744 18089 nla_put_u16(msg, NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM,
76804d28 18090 cr->fils.erp_next_seq_num)) ||
a3caf744 18091 (cr->status == WLAN_STATUS_SUCCESS &&
76804d28
AVS
18092 ((cr->fils.kek &&
18093 nla_put(msg, NL80211_ATTR_FILS_KEK, cr->fils.kek_len,
18094 cr->fils.kek)) ||
18095 (cr->fils.pmk &&
18096 nla_put(msg, NL80211_ATTR_PMK, cr->fils.pmk_len, cr->fils.pmk)) ||
18097 (cr->fils.pmkid &&
18098 nla_put(msg, NL80211_ATTR_PMKID, WLAN_PMKID_LEN, cr->fils.pmkid)))))
9360ffd1 18099 goto nla_put_failure;
b23aa676 18100
efbabc11
VJ
18101 if (cr->valid_links) {
18102 int i = 1;
18103 struct nlattr *nested;
18104
18105 nested = nla_nest_start(msg, NL80211_ATTR_MLO_LINKS);
18106 if (!nested)
18107 goto nla_put_failure;
18108
18109 for_each_valid_link(cr, link) {
18110 struct nlattr *nested_mlo_links;
18111 const u8 *bssid = cr->links[link].bss ?
18112 cr->links[link].bss->bssid :
18113 cr->links[link].bssid;
18114
18115 nested_mlo_links = nla_nest_start(msg, i);
18116 if (!nested_mlo_links)
18117 goto nla_put_failure;
18118
18119 if (nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link) ||
18120 (bssid &&
18121 nla_put(msg, NL80211_ATTR_BSSID, ETH_ALEN, bssid)) ||
18122 (cr->links[link].addr &&
18123 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN,
53ad07e9
JB
18124 cr->links[link].addr)) ||
18125 nla_put_u16(msg, NL80211_ATTR_STATUS_CODE,
18126 cr->links[link].status))
efbabc11
VJ
18127 goto nla_put_failure;
18128
18129 nla_nest_end(msg, nested_mlo_links);
18130 i++;
18131 }
18132 nla_nest_end(msg, nested);
18133 }
18134
3b7b72ee 18135 genlmsg_end(msg, hdr);
b23aa676 18136
68eb5503 18137 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18138 NL80211_MCGRP_MLME, gfp);
b23aa676
SO
18139 return;
18140
18141 nla_put_failure:
b23aa676 18142 nlmsg_free(msg);
b23aa676
SO
18143}
18144
18145void nl80211_send_roamed(struct cfg80211_registered_device *rdev,
29ce6ecb
AS
18146 struct net_device *netdev,
18147 struct cfg80211_roam_info *info, gfp_t gfp)
b23aa676
SO
18148{
18149 struct sk_buff *msg;
18150 void *hdr;
efbabc11
VJ
18151 size_t link_info_size = 0;
18152 unsigned int link;
18153 const u8 *connected_addr = info->ap_mld_addr ?
18154 info->ap_mld_addr :
18155 (info->links[0].bss ?
18156 info->links[0].bss->bssid :
18157 info->links[0].bssid);
18158
18159 if (info->valid_links) {
18160 for_each_valid_link(info, link) {
18161 /* Nested attribute header */
18162 link_info_size += NLA_HDRLEN;
18163 /* Link ID */
18164 link_info_size += nla_total_size(sizeof(u8));
18165 link_info_size += info->links[link].addr ?
18166 nla_total_size(ETH_ALEN) : 0;
18167 link_info_size += (info->links[link].bssid ||
18168 info->links[link].bss) ?
18169 nla_total_size(ETH_ALEN) : 0;
18170 }
18171 }
b23aa676 18172
e841b7b1
AVS
18173 msg = nlmsg_new(100 + info->req_ie_len + info->resp_ie_len +
18174 info->fils.kek_len + info->fils.pmk_len +
efbabc11
VJ
18175 (info->fils.pmkid ? WLAN_PMKID_LEN : 0) +
18176 link_info_size, gfp);
b23aa676
SO
18177 if (!msg)
18178 return;
18179
18180 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_ROAM);
18181 if (!hdr) {
18182 nlmsg_free(msg);
18183 return;
18184 }
18185
9360ffd1
DM
18186 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
18187 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
efbabc11 18188 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, connected_addr) ||
29ce6ecb
AS
18189 (info->req_ie &&
18190 nla_put(msg, NL80211_ATTR_REQ_IE, info->req_ie_len,
18191 info->req_ie)) ||
18192 (info->resp_ie &&
18193 nla_put(msg, NL80211_ATTR_RESP_IE, info->resp_ie_len,
e841b7b1
AVS
18194 info->resp_ie)) ||
18195 (info->fils.update_erp_next_seq_num &&
18196 nla_put_u16(msg, NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM,
18197 info->fils.erp_next_seq_num)) ||
18198 (info->fils.kek &&
18199 nla_put(msg, NL80211_ATTR_FILS_KEK, info->fils.kek_len,
18200 info->fils.kek)) ||
18201 (info->fils.pmk &&
18202 nla_put(msg, NL80211_ATTR_PMK, info->fils.pmk_len, info->fils.pmk)) ||
18203 (info->fils.pmkid &&
18204 nla_put(msg, NL80211_ATTR_PMKID, WLAN_PMKID_LEN, info->fils.pmkid)))
9360ffd1 18205 goto nla_put_failure;
b23aa676 18206
efbabc11
VJ
18207 if (info->valid_links) {
18208 int i = 1;
18209 struct nlattr *nested;
18210
18211 nested = nla_nest_start(msg, NL80211_ATTR_MLO_LINKS);
18212 if (!nested)
18213 goto nla_put_failure;
18214
18215 for_each_valid_link(info, link) {
18216 struct nlattr *nested_mlo_links;
18217 const u8 *bssid = info->links[link].bss ?
18218 info->links[link].bss->bssid :
18219 info->links[link].bssid;
18220
18221 nested_mlo_links = nla_nest_start(msg, i);
18222 if (!nested_mlo_links)
18223 goto nla_put_failure;
18224
18225 if (nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link) ||
18226 (bssid &&
18227 nla_put(msg, NL80211_ATTR_BSSID, ETH_ALEN, bssid)) ||
18228 (info->links[link].addr &&
18229 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN,
18230 info->links[link].addr)))
18231 goto nla_put_failure;
18232
18233 nla_nest_end(msg, nested_mlo_links);
18234 i++;
18235 }
18236 nla_nest_end(msg, nested);
18237 }
18238
3b7b72ee 18239 genlmsg_end(msg, hdr);
b23aa676 18240
68eb5503 18241 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18242 NL80211_MCGRP_MLME, gfp);
b23aa676
SO
18243 return;
18244
503c1fb9 18245 nla_put_failure:
503c1fb9
AS
18246 nlmsg_free(msg);
18247}
18248
18249void nl80211_send_port_authorized(struct cfg80211_registered_device *rdev,
e4e7e3af 18250 struct net_device *netdev, const u8 *peer_addr,
0ff57171 18251 const u8 *td_bitmap, u8 td_bitmap_len)
503c1fb9
AS
18252{
18253 struct sk_buff *msg;
18254 void *hdr;
18255
18256 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
18257 if (!msg)
18258 return;
18259
18260 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_PORT_AUTHORIZED);
18261 if (!hdr) {
18262 nlmsg_free(msg);
18263 return;
18264 }
18265
f4d75993
CHH
18266 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
18267 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
e4e7e3af 18268 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, peer_addr))
503c1fb9
AS
18269 goto nla_put_failure;
18270
0ff57171
VY
18271 if ((td_bitmap_len > 0) && td_bitmap)
18272 if (nla_put(msg, NL80211_ATTR_TD_BITMAP,
18273 td_bitmap_len, td_bitmap))
18274 goto nla_put_failure;
18275
503c1fb9
AS
18276 genlmsg_end(msg, hdr);
18277
18278 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
18279 NL80211_MCGRP_MLME, GFP_KERNEL);
18280 return;
18281
b23aa676 18282 nla_put_failure:
b23aa676 18283 nlmsg_free(msg);
b23aa676
SO
18284}
18285
18286void nl80211_send_disconnected(struct cfg80211_registered_device *rdev,
18287 struct net_device *netdev, u16 reason,
667503dd 18288 const u8 *ie, size_t ie_len, bool from_ap)
b23aa676
SO
18289{
18290 struct sk_buff *msg;
18291 void *hdr;
18292
4ef8c1c9 18293 msg = nlmsg_new(100 + ie_len, GFP_KERNEL);
b23aa676
SO
18294 if (!msg)
18295 return;
18296
18297 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_DISCONNECT);
18298 if (!hdr) {
18299 nlmsg_free(msg);
18300 return;
18301 }
18302
9360ffd1
DM
18303 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
18304 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
86b6c465 18305 (reason &&
9360ffd1
DM
18306 nla_put_u16(msg, NL80211_ATTR_REASON_CODE, reason)) ||
18307 (from_ap &&
18308 nla_put_flag(msg, NL80211_ATTR_DISCONNECTED_BY_AP)) ||
18309 (ie && nla_put(msg, NL80211_ATTR_IE, ie_len, ie)))
18310 goto nla_put_failure;
b23aa676 18311
3b7b72ee 18312 genlmsg_end(msg, hdr);
b23aa676 18313
68eb5503 18314 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18315 NL80211_MCGRP_MLME, GFP_KERNEL);
b23aa676
SO
18316 return;
18317
18318 nla_put_failure:
b23aa676 18319 nlmsg_free(msg);
b23aa676
SO
18320}
18321
065563b2
VJ
18322void cfg80211_links_removed(struct net_device *dev, u16 link_mask)
18323{
18324 struct wireless_dev *wdev = dev->ieee80211_ptr;
18325 struct wiphy *wiphy = wdev->wiphy;
18326 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
18327 struct sk_buff *msg;
18328 struct nlattr *links;
18329 void *hdr;
18330
076fc877 18331 lockdep_assert_wiphy(wdev->wiphy);
065563b2
VJ
18332 trace_cfg80211_links_removed(dev, link_mask);
18333
18334 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION &&
18335 wdev->iftype != NL80211_IFTYPE_P2P_CLIENT))
18336 return;
18337
18338 if (WARN_ON(!wdev->valid_links || !link_mask ||
18339 (wdev->valid_links & link_mask) != link_mask ||
18340 wdev->valid_links == link_mask))
18341 return;
18342
18343 cfg80211_wdev_release_link_bsses(wdev, link_mask);
18344 wdev->valid_links &= ~link_mask;
18345
18346 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
18347 if (!msg)
18348 return;
18349
18350 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_LINKS_REMOVED);
18351 if (!hdr) {
18352 nlmsg_free(msg);
18353 return;
18354 }
18355
18356 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
18357 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
18358 goto nla_put_failure;
18359
18360 links = nla_nest_start(msg, NL80211_ATTR_MLO_LINKS);
18361 if (!links)
18362 goto nla_put_failure;
18363
18364 while (link_mask) {
18365 struct nlattr *link;
18366 int link_id = __ffs(link_mask);
18367
18368 link = nla_nest_start(msg, link_id + 1);
18369 if (!link)
18370 goto nla_put_failure;
18371
18372 if (nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id))
18373 goto nla_put_failure;
18374
18375 nla_nest_end(msg, link);
18376 link_mask &= ~(1 << link_id);
18377 }
18378
18379 nla_nest_end(msg, links);
18380
18381 genlmsg_end(msg, hdr);
18382
18383 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
18384 NL80211_MCGRP_MLME, GFP_KERNEL);
18385 return;
18386
18387 nla_put_failure:
18388 nlmsg_free(msg);
18389}
18390EXPORT_SYMBOL(cfg80211_links_removed);
18391
04a773ad
JB
18392void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev,
18393 struct net_device *netdev, const u8 *bssid,
18394 gfp_t gfp)
18395{
18396 struct sk_buff *msg;
18397 void *hdr;
18398
fd2120ca 18399 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
04a773ad
JB
18400 if (!msg)
18401 return;
18402
18403 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_JOIN_IBSS);
18404 if (!hdr) {
18405 nlmsg_free(msg);
18406 return;
18407 }
18408
9360ffd1
DM
18409 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
18410 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
18411 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid))
18412 goto nla_put_failure;
04a773ad 18413
3b7b72ee 18414 genlmsg_end(msg, hdr);
04a773ad 18415
68eb5503 18416 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18417 NL80211_MCGRP_MLME, gfp);
04a773ad
JB
18418 return;
18419
18420 nla_put_failure:
04a773ad
JB
18421 nlmsg_free(msg);
18422}
18423
947add36 18424void cfg80211_notify_new_peer_candidate(struct net_device *dev, const u8 *addr,
ecbc12ad
BC
18425 const u8 *ie, u8 ie_len,
18426 int sig_dbm, gfp_t gfp)
c93b5e71 18427{
947add36 18428 struct wireless_dev *wdev = dev->ieee80211_ptr;
f26cbf40 18429 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
c93b5e71
JC
18430 struct sk_buff *msg;
18431 void *hdr;
18432
947add36
JB
18433 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_MESH_POINT))
18434 return;
18435
18436 trace_cfg80211_notify_new_peer_candidate(dev, addr);
18437
4ef8c1c9 18438 msg = nlmsg_new(100 + ie_len, gfp);
c93b5e71
JC
18439 if (!msg)
18440 return;
18441
18442 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NEW_PEER_CANDIDATE);
18443 if (!hdr) {
18444 nlmsg_free(msg);
18445 return;
18446 }
18447
9360ffd1 18448 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
947add36
JB
18449 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
18450 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
9360ffd1 18451 (ie_len && ie &&
ecbc12ad
BC
18452 nla_put(msg, NL80211_ATTR_IE, ie_len, ie)) ||
18453 (sig_dbm &&
18454 nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)))
9360ffd1 18455 goto nla_put_failure;
c93b5e71 18456
3b7b72ee 18457 genlmsg_end(msg, hdr);
c93b5e71 18458
68eb5503 18459 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18460 NL80211_MCGRP_MLME, gfp);
c93b5e71
JC
18461 return;
18462
18463 nla_put_failure:
c93b5e71
JC
18464 nlmsg_free(msg);
18465}
947add36 18466EXPORT_SYMBOL(cfg80211_notify_new_peer_candidate);
c93b5e71 18467
a3b8b056
JM
18468void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev,
18469 struct net_device *netdev, const u8 *addr,
18470 enum nl80211_key_type key_type, int key_id,
e6d6e342 18471 const u8 *tsc, gfp_t gfp)
a3b8b056
JM
18472{
18473 struct sk_buff *msg;
18474 void *hdr;
18475
e6d6e342 18476 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
a3b8b056
JM
18477 if (!msg)
18478 return;
18479
18480 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_MICHAEL_MIC_FAILURE);
18481 if (!hdr) {
18482 nlmsg_free(msg);
18483 return;
18484 }
18485
9360ffd1
DM
18486 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
18487 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
18488 (addr && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) ||
18489 nla_put_u32(msg, NL80211_ATTR_KEY_TYPE, key_type) ||
18490 (key_id != -1 &&
18491 nla_put_u8(msg, NL80211_ATTR_KEY_IDX, key_id)) ||
18492 (tsc && nla_put(msg, NL80211_ATTR_KEY_SEQ, 6, tsc)))
18493 goto nla_put_failure;
a3b8b056 18494
3b7b72ee 18495 genlmsg_end(msg, hdr);
a3b8b056 18496
68eb5503 18497 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18498 NL80211_MCGRP_MLME, gfp);
a3b8b056
JM
18499 return;
18500
18501 nla_put_failure:
a3b8b056
JM
18502 nlmsg_free(msg);
18503}
18504
6bad8766
LR
18505void nl80211_send_beacon_hint_event(struct wiphy *wiphy,
18506 struct ieee80211_channel *channel_before,
18507 struct ieee80211_channel *channel_after)
18508{
18509 struct sk_buff *msg;
18510 void *hdr;
18511 struct nlattr *nl_freq;
18512
fd2120ca 18513 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
6bad8766
LR
18514 if (!msg)
18515 return;
18516
18517 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_REG_BEACON_HINT);
18518 if (!hdr) {
18519 nlmsg_free(msg);
18520 return;
18521 }
18522
18523 /*
18524 * Since we are applying the beacon hint to a wiphy we know its
18525 * wiphy_idx is valid
18526 */
9360ffd1
DM
18527 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, get_wiphy_idx(wiphy)))
18528 goto nla_put_failure;
6bad8766
LR
18529
18530 /* Before */
ae0be8de 18531 nl_freq = nla_nest_start_noflag(msg, NL80211_ATTR_FREQ_BEFORE);
6bad8766
LR
18532 if (!nl_freq)
18533 goto nla_put_failure;
50f32718
HD
18534
18535 if (nl80211_msg_put_channel(msg, wiphy, channel_before, false))
6bad8766
LR
18536 goto nla_put_failure;
18537 nla_nest_end(msg, nl_freq);
18538
18539 /* After */
ae0be8de 18540 nl_freq = nla_nest_start_noflag(msg, NL80211_ATTR_FREQ_AFTER);
6bad8766
LR
18541 if (!nl_freq)
18542 goto nla_put_failure;
50f32718
HD
18543
18544 if (nl80211_msg_put_channel(msg, wiphy, channel_after, false))
6bad8766
LR
18545 goto nla_put_failure;
18546 nla_nest_end(msg, nl_freq);
18547
3b7b72ee 18548 genlmsg_end(msg, hdr);
6bad8766 18549
463d0183 18550 rcu_read_lock();
68eb5503 18551 genlmsg_multicast_allns(&nl80211_fam, msg, 0,
2a94fe48 18552 NL80211_MCGRP_REGULATORY, GFP_ATOMIC);
463d0183 18553 rcu_read_unlock();
6bad8766
LR
18554
18555 return;
18556
18557nla_put_failure:
6bad8766
LR
18558 nlmsg_free(msg);
18559}
18560
9588bbd5
JM
18561static void nl80211_send_remain_on_chan_event(
18562 int cmd, struct cfg80211_registered_device *rdev,
71bbc994 18563 struct wireless_dev *wdev, u64 cookie,
9588bbd5 18564 struct ieee80211_channel *chan,
9588bbd5
JM
18565 unsigned int duration, gfp_t gfp)
18566{
18567 struct sk_buff *msg;
18568 void *hdr;
18569
18570 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
18571 if (!msg)
18572 return;
18573
18574 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
18575 if (!hdr) {
18576 nlmsg_free(msg);
18577 return;
18578 }
18579
9360ffd1 18580 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
71bbc994
JB
18581 (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
18582 wdev->netdev->ifindex)) ||
2dad624e
ND
18583 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
18584 NL80211_ATTR_PAD) ||
9360ffd1 18585 nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, chan->center_freq) ||
42d97a59
JB
18586 nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
18587 NL80211_CHAN_NO_HT) ||
2dad624e
ND
18588 nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
18589 NL80211_ATTR_PAD))
9360ffd1 18590 goto nla_put_failure;
9588bbd5 18591
9360ffd1
DM
18592 if (cmd == NL80211_CMD_REMAIN_ON_CHANNEL &&
18593 nla_put_u32(msg, NL80211_ATTR_DURATION, duration))
18594 goto nla_put_failure;
9588bbd5 18595
3b7b72ee 18596 genlmsg_end(msg, hdr);
9588bbd5 18597
68eb5503 18598 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18599 NL80211_MCGRP_MLME, gfp);
9588bbd5
JM
18600 return;
18601
18602 nla_put_failure:
9588bbd5
JM
18603 nlmsg_free(msg);
18604}
18605
a083ee8a 18606void cfg80211_assoc_comeback(struct net_device *netdev,
e69dac88 18607 const u8 *ap_addr, u32 timeout)
a083ee8a
IP
18608{
18609 struct wireless_dev *wdev = netdev->ieee80211_ptr;
18610 struct wiphy *wiphy = wdev->wiphy;
18611 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
18612 struct sk_buff *msg;
18613 void *hdr;
18614
e69dac88 18615 trace_cfg80211_assoc_comeback(wdev, ap_addr, timeout);
a083ee8a
IP
18616
18617 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
18618 if (!msg)
18619 return;
18620
18621 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_ASSOC_COMEBACK);
18622 if (!hdr) {
18623 nlmsg_free(msg);
18624 return;
18625 }
18626
18627 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
18628 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
e69dac88 18629 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, ap_addr) ||
a083ee8a
IP
18630 nla_put_u32(msg, NL80211_ATTR_TIMEOUT, timeout))
18631 goto nla_put_failure;
18632
18633 genlmsg_end(msg, hdr);
18634
18635 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
18636 NL80211_MCGRP_MLME, GFP_KERNEL);
18637 return;
18638
18639 nla_put_failure:
18640 nlmsg_free(msg);
18641}
18642EXPORT_SYMBOL(cfg80211_assoc_comeback);
18643
947add36
JB
18644void cfg80211_ready_on_channel(struct wireless_dev *wdev, u64 cookie,
18645 struct ieee80211_channel *chan,
18646 unsigned int duration, gfp_t gfp)
9588bbd5 18647{
947add36 18648 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 18649 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
947add36
JB
18650
18651 trace_cfg80211_ready_on_channel(wdev, cookie, chan, duration);
9588bbd5 18652 nl80211_send_remain_on_chan_event(NL80211_CMD_REMAIN_ON_CHANNEL,
71bbc994 18653 rdev, wdev, cookie, chan,
42d97a59 18654 duration, gfp);
9588bbd5 18655}
947add36 18656EXPORT_SYMBOL(cfg80211_ready_on_channel);
9588bbd5 18657
947add36
JB
18658void cfg80211_remain_on_channel_expired(struct wireless_dev *wdev, u64 cookie,
18659 struct ieee80211_channel *chan,
18660 gfp_t gfp)
9588bbd5 18661{
947add36 18662 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 18663 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
947add36
JB
18664
18665 trace_cfg80211_ready_on_channel_expired(wdev, cookie, chan);
9588bbd5 18666 nl80211_send_remain_on_chan_event(NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL,
42d97a59 18667 rdev, wdev, cookie, chan, 0, gfp);
9588bbd5 18668}
947add36 18669EXPORT_SYMBOL(cfg80211_remain_on_channel_expired);
9588bbd5 18670
1c38c7f2
JP
18671void cfg80211_tx_mgmt_expired(struct wireless_dev *wdev, u64 cookie,
18672 struct ieee80211_channel *chan,
18673 gfp_t gfp)
18674{
18675 struct wiphy *wiphy = wdev->wiphy;
18676 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
18677
18678 trace_cfg80211_tx_mgmt_expired(wdev, cookie, chan);
18679 nl80211_send_remain_on_chan_event(NL80211_CMD_FRAME_WAIT_CANCEL,
18680 rdev, wdev, cookie, chan, 0, gfp);
18681}
18682EXPORT_SYMBOL(cfg80211_tx_mgmt_expired);
18683
947add36
JB
18684void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr,
18685 struct station_info *sinfo, gfp_t gfp)
98b62183 18686{
947add36 18687 struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
f26cbf40 18688 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
98b62183
JB
18689 struct sk_buff *msg;
18690
947add36
JB
18691 trace_cfg80211_new_sta(dev, mac_addr, sinfo);
18692
58050fce 18693 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
98b62183
JB
18694 if (!msg)
18695 return;
18696
cf5ead82 18697 if (nl80211_send_station(msg, NL80211_CMD_NEW_STATION, 0, 0, 0,
66266b3a 18698 rdev, dev, mac_addr, sinfo) < 0) {
98b62183
JB
18699 nlmsg_free(msg);
18700 return;
18701 }
18702
68eb5503 18703 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18704 NL80211_MCGRP_MLME, gfp);
98b62183 18705}
947add36 18706EXPORT_SYMBOL(cfg80211_new_sta);
98b62183 18707
cf5ead82
JB
18708void cfg80211_del_sta_sinfo(struct net_device *dev, const u8 *mac_addr,
18709 struct station_info *sinfo, gfp_t gfp)
ec15e68b 18710{
947add36 18711 struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
f26cbf40 18712 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
ec15e68b 18713 struct sk_buff *msg;
73887fd9 18714 struct station_info empty_sinfo = {};
cf5ead82 18715
73887fd9
JB
18716 if (!sinfo)
18717 sinfo = &empty_sinfo;
ec15e68b 18718
947add36
JB
18719 trace_cfg80211_del_sta(dev, mac_addr);
18720
58050fce 18721 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
7ea3e110
JB
18722 if (!msg) {
18723 cfg80211_sinfo_release_content(sinfo);
73887fd9 18724 return;
7ea3e110 18725 }
ec15e68b 18726
cf5ead82 18727 if (nl80211_send_station(msg, NL80211_CMD_DEL_STATION, 0, 0, 0,
57007121 18728 rdev, dev, mac_addr, sinfo) < 0) {
ec15e68b 18729 nlmsg_free(msg);
73887fd9 18730 return;
ec15e68b
JM
18731 }
18732
68eb5503 18733 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18734 NL80211_MCGRP_MLME, gfp);
ec15e68b 18735}
cf5ead82 18736EXPORT_SYMBOL(cfg80211_del_sta_sinfo);
ec15e68b 18737
947add36
JB
18738void cfg80211_conn_failed(struct net_device *dev, const u8 *mac_addr,
18739 enum nl80211_connect_failed_reason reason,
18740 gfp_t gfp)
ed44a951 18741{
947add36 18742 struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
f26cbf40 18743 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
ed44a951
PP
18744 struct sk_buff *msg;
18745 void *hdr;
18746
18747 msg = nlmsg_new(NLMSG_GOODSIZE, gfp);
18748 if (!msg)
18749 return;
18750
18751 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CONN_FAILED);
18752 if (!hdr) {
18753 nlmsg_free(msg);
18754 return;
18755 }
18756
18757 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
18758 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr) ||
18759 nla_put_u32(msg, NL80211_ATTR_CONN_FAILED_REASON, reason))
18760 goto nla_put_failure;
18761
18762 genlmsg_end(msg, hdr);
18763
68eb5503 18764 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18765 NL80211_MCGRP_MLME, gfp);
ed44a951
PP
18766 return;
18767
18768 nla_put_failure:
ed44a951
PP
18769 nlmsg_free(msg);
18770}
947add36 18771EXPORT_SYMBOL(cfg80211_conn_failed);
ed44a951 18772
b92ab5d8
JB
18773static bool __nl80211_unexpected_frame(struct net_device *dev, u8 cmd,
18774 const u8 *addr, gfp_t gfp)
28946da7
JB
18775{
18776 struct wireless_dev *wdev = dev->ieee80211_ptr;
f26cbf40 18777 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
28946da7
JB
18778 struct sk_buff *msg;
18779 void *hdr;
6aa7de05 18780 u32 nlportid = READ_ONCE(wdev->ap_unexpected_nlportid);
28946da7 18781
15e47304 18782 if (!nlportid)
28946da7
JB
18783 return false;
18784
18785 msg = nlmsg_new(100, gfp);
18786 if (!msg)
18787 return true;
18788
b92ab5d8 18789 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
28946da7
JB
18790 if (!hdr) {
18791 nlmsg_free(msg);
18792 return true;
18793 }
18794
9360ffd1
DM
18795 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
18796 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
18797 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr))
18798 goto nla_put_failure;
28946da7 18799
9c90a9f6 18800 genlmsg_end(msg, hdr);
15e47304 18801 genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid);
28946da7
JB
18802 return true;
18803
18804 nla_put_failure:
28946da7
JB
18805 nlmsg_free(msg);
18806 return true;
18807}
18808
947add36
JB
18809bool cfg80211_rx_spurious_frame(struct net_device *dev,
18810 const u8 *addr, gfp_t gfp)
b92ab5d8 18811{
947add36
JB
18812 struct wireless_dev *wdev = dev->ieee80211_ptr;
18813 bool ret;
18814
18815 trace_cfg80211_rx_spurious_frame(dev, addr);
18816
18817 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
18818 wdev->iftype != NL80211_IFTYPE_P2P_GO)) {
18819 trace_cfg80211_return_bool(false);
18820 return false;
18821 }
18822 ret = __nl80211_unexpected_frame(dev, NL80211_CMD_UNEXPECTED_FRAME,
18823 addr, gfp);
18824 trace_cfg80211_return_bool(ret);
18825 return ret;
b92ab5d8 18826}
947add36 18827EXPORT_SYMBOL(cfg80211_rx_spurious_frame);
b92ab5d8 18828
947add36
JB
18829bool cfg80211_rx_unexpected_4addr_frame(struct net_device *dev,
18830 const u8 *addr, gfp_t gfp)
b92ab5d8 18831{
947add36
JB
18832 struct wireless_dev *wdev = dev->ieee80211_ptr;
18833 bool ret;
18834
18835 trace_cfg80211_rx_unexpected_4addr_frame(dev, addr);
18836
18837 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
18838 wdev->iftype != NL80211_IFTYPE_P2P_GO &&
18839 wdev->iftype != NL80211_IFTYPE_AP_VLAN)) {
18840 trace_cfg80211_return_bool(false);
18841 return false;
18842 }
18843 ret = __nl80211_unexpected_frame(dev,
18844 NL80211_CMD_UNEXPECTED_4ADDR_FRAME,
18845 addr, gfp);
18846 trace_cfg80211_return_bool(ret);
18847 return ret;
b92ab5d8 18848}
947add36 18849EXPORT_SYMBOL(cfg80211_rx_unexpected_4addr_frame);
b92ab5d8 18850
2e161f78 18851int nl80211_send_mgmt(struct cfg80211_registered_device *rdev,
15e47304 18852 struct wireless_dev *wdev, u32 nlportid,
00b3d840 18853 struct cfg80211_rx_info *info, gfp_t gfp)
026331c4 18854{
71bbc994 18855 struct net_device *netdev = wdev->netdev;
026331c4
JM
18856 struct sk_buff *msg;
18857 void *hdr;
026331c4 18858
00b3d840 18859 msg = nlmsg_new(100 + info->len, gfp);
026331c4
JM
18860 if (!msg)
18861 return -ENOMEM;
18862
2e161f78 18863 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FRAME);
026331c4
JM
18864 if (!hdr) {
18865 nlmsg_free(msg);
18866 return -ENOMEM;
18867 }
18868
9360ffd1 18869 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
71bbc994
JB
18870 (netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
18871 netdev->ifindex)) ||
2dad624e
ND
18872 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
18873 NL80211_ATTR_PAD) ||
6074c9e5
JB
18874 (info->have_link_id &&
18875 nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, info->link_id)) ||
00b3d840
AS
18876 nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, KHZ_TO_MHZ(info->freq)) ||
18877 nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ_OFFSET, info->freq % 1000) ||
18878 (info->sig_dbm &&
18879 nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, info->sig_dbm)) ||
18880 nla_put(msg, NL80211_ATTR_FRAME, info->len, info->buf) ||
18881 (info->flags &&
1ff715ff
AS
18882 nla_put_u32(msg, NL80211_ATTR_RXMGMT_FLAGS, info->flags)) ||
18883 (info->rx_tstamp && nla_put_u64_64bit(msg,
18884 NL80211_ATTR_RX_HW_TIMESTAMP,
18885 info->rx_tstamp,
18886 NL80211_ATTR_PAD)) ||
18887 (info->ack_tstamp && nla_put_u64_64bit(msg,
18888 NL80211_ATTR_TX_HW_TIMESTAMP,
18889 info->ack_tstamp,
18890 NL80211_ATTR_PAD)))
9360ffd1 18891 goto nla_put_failure;
026331c4 18892
3b7b72ee 18893 genlmsg_end(msg, hdr);
026331c4 18894
15e47304 18895 return genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid);
026331c4
JM
18896
18897 nla_put_failure:
026331c4
JM
18898 nlmsg_free(msg);
18899 return -ENOBUFS;
18900}
18901
ea7d50c9
AS
18902static void nl80211_frame_tx_status(struct wireless_dev *wdev,
18903 struct cfg80211_tx_status *status,
dca9ca2d 18904 gfp_t gfp, enum nl80211_commands command)
026331c4 18905{
947add36 18906 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 18907 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
71bbc994 18908 struct net_device *netdev = wdev->netdev;
026331c4
JM
18909 struct sk_buff *msg;
18910 void *hdr;
18911
dca9ca2d 18912 if (command == NL80211_CMD_FRAME_TX_STATUS)
ea7d50c9
AS
18913 trace_cfg80211_mgmt_tx_status(wdev, status->cookie,
18914 status->ack);
dca9ca2d 18915 else
ea7d50c9
AS
18916 trace_cfg80211_control_port_tx_status(wdev, status->cookie,
18917 status->ack);
947add36 18918
ea7d50c9 18919 msg = nlmsg_new(100 + status->len, gfp);
026331c4
JM
18920 if (!msg)
18921 return;
18922
dca9ca2d 18923 hdr = nl80211hdr_put(msg, 0, 0, 0, command);
026331c4
JM
18924 if (!hdr) {
18925 nlmsg_free(msg);
18926 return;
18927 }
18928
9360ffd1 18929 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
71bbc994
JB
18930 (netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
18931 netdev->ifindex)) ||
2dad624e
ND
18932 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
18933 NL80211_ATTR_PAD) ||
ea7d50c9
AS
18934 nla_put(msg, NL80211_ATTR_FRAME, status->len, status->buf) ||
18935 nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, status->cookie,
2dad624e 18936 NL80211_ATTR_PAD) ||
ea7d50c9
AS
18937 (status->ack && nla_put_flag(msg, NL80211_ATTR_ACK)) ||
18938 (status->tx_tstamp &&
18939 nla_put_u64_64bit(msg, NL80211_ATTR_TX_HW_TIMESTAMP,
18940 status->tx_tstamp, NL80211_ATTR_PAD)) ||
18941 (status->ack_tstamp &&
18942 nla_put_u64_64bit(msg, NL80211_ATTR_RX_HW_TIMESTAMP,
18943 status->ack_tstamp, NL80211_ATTR_PAD)))
9360ffd1 18944 goto nla_put_failure;
026331c4 18945
3b7b72ee 18946 genlmsg_end(msg, hdr);
026331c4 18947
68eb5503 18948 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18949 NL80211_MCGRP_MLME, gfp);
026331c4
JM
18950 return;
18951
dca9ca2d 18952nla_put_failure:
026331c4
JM
18953 nlmsg_free(msg);
18954}
dca9ca2d
MT
18955
18956void cfg80211_control_port_tx_status(struct wireless_dev *wdev, u64 cookie,
18957 const u8 *buf, size_t len, bool ack,
18958 gfp_t gfp)
18959{
ea7d50c9
AS
18960 struct cfg80211_tx_status status = {
18961 .cookie = cookie,
18962 .buf = buf,
18963 .len = len,
18964 .ack = ack
18965 };
18966
18967 nl80211_frame_tx_status(wdev, &status, gfp,
dca9ca2d
MT
18968 NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS);
18969}
18970EXPORT_SYMBOL(cfg80211_control_port_tx_status);
18971
ea7d50c9
AS
18972void cfg80211_mgmt_tx_status_ext(struct wireless_dev *wdev,
18973 struct cfg80211_tx_status *status, gfp_t gfp)
dca9ca2d 18974{
ea7d50c9 18975 nl80211_frame_tx_status(wdev, status, gfp, NL80211_CMD_FRAME_TX_STATUS);
dca9ca2d 18976}
ea7d50c9 18977EXPORT_SYMBOL(cfg80211_mgmt_tx_status_ext);
026331c4 18978
6a671a50 18979static int __nl80211_rx_control_port(struct net_device *dev,
a948f713 18980 struct sk_buff *skb,
4c532321
JB
18981 bool unencrypted,
18982 int link_id,
18983 gfp_t gfp)
6a671a50
DK
18984{
18985 struct wireless_dev *wdev = dev->ieee80211_ptr;
18986 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
a948f713 18987 struct ethhdr *ehdr = eth_hdr(skb);
8d74a623 18988 const u8 *addr = ehdr->h_source;
a948f713 18989 u16 proto = be16_to_cpu(skb->protocol);
6a671a50
DK
18990 struct sk_buff *msg;
18991 void *hdr;
a948f713
DK
18992 struct nlattr *frame;
18993
6a671a50
DK
18994 u32 nlportid = READ_ONCE(wdev->conn_owner_nlportid);
18995
18996 if (!nlportid)
18997 return -ENOENT;
18998
a948f713 18999 msg = nlmsg_new(100 + skb->len, gfp);
6a671a50
DK
19000 if (!msg)
19001 return -ENOMEM;
19002
19003 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CONTROL_PORT_FRAME);
19004 if (!hdr) {
19005 nlmsg_free(msg);
19006 return -ENOBUFS;
19007 }
19008
19009 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
19010 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
19011 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
19012 NL80211_ATTR_PAD) ||
8d74a623 19013 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
6a671a50 19014 nla_put_u16(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE, proto) ||
4c532321
JB
19015 (link_id >= 0 &&
19016 nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id)) ||
6a671a50
DK
19017 (unencrypted && nla_put_flag(msg,
19018 NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT)))
19019 goto nla_put_failure;
19020
a948f713
DK
19021 frame = nla_reserve(msg, NL80211_ATTR_FRAME, skb->len);
19022 if (!frame)
19023 goto nla_put_failure;
19024
19025 skb_copy_bits(skb, 0, nla_data(frame), skb->len);
6a671a50
DK
19026 genlmsg_end(msg, hdr);
19027
19028 return genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid);
19029
19030 nla_put_failure:
19031 nlmsg_free(msg);
19032 return -ENOBUFS;
19033}
19034
4c532321
JB
19035bool cfg80211_rx_control_port(struct net_device *dev, struct sk_buff *skb,
19036 bool unencrypted, int link_id)
6a671a50
DK
19037{
19038 int ret;
19039
4c532321
JB
19040 trace_cfg80211_rx_control_port(dev, skb, unencrypted, link_id);
19041 ret = __nl80211_rx_control_port(dev, skb, unencrypted, link_id,
19042 GFP_ATOMIC);
6a671a50
DK
19043 trace_cfg80211_return_bool(ret == 0);
19044 return ret == 0;
19045}
19046EXPORT_SYMBOL(cfg80211_rx_control_port);
19047
5b97f49d
JB
19048static struct sk_buff *cfg80211_prepare_cqm(struct net_device *dev,
19049 const char *mac, gfp_t gfp)
d6dc1a38 19050{
947add36 19051 struct wireless_dev *wdev = dev->ieee80211_ptr;
5b97f49d
JB
19052 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
19053 struct sk_buff *msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
19054 void **cb;
947add36 19055
d6dc1a38 19056 if (!msg)
5b97f49d 19057 return NULL;
d6dc1a38 19058
5b97f49d
JB
19059 cb = (void **)msg->cb;
19060
19061 cb[0] = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NOTIFY_CQM);
19062 if (!cb[0]) {
d6dc1a38 19063 nlmsg_free(msg);
5b97f49d 19064 return NULL;
d6dc1a38
JO
19065 }
19066
9360ffd1 19067 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
947add36 19068 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
9360ffd1 19069 goto nla_put_failure;
d6dc1a38 19070
5b97f49d 19071 if (mac && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac))
d6dc1a38
JO
19072 goto nla_put_failure;
19073
ae0be8de 19074 cb[1] = nla_nest_start_noflag(msg, NL80211_ATTR_CQM);
5b97f49d 19075 if (!cb[1])
9360ffd1 19076 goto nla_put_failure;
d6dc1a38 19077
5b97f49d 19078 cb[2] = rdev;
d6dc1a38 19079
5b97f49d
JB
19080 return msg;
19081 nla_put_failure:
19082 nlmsg_free(msg);
19083 return NULL;
19084}
19085
19086static void cfg80211_send_cqm(struct sk_buff *msg, gfp_t gfp)
19087{
19088 void **cb = (void **)msg->cb;
19089 struct cfg80211_registered_device *rdev = cb[2];
19090
19091 nla_nest_end(msg, cb[1]);
19092 genlmsg_end(msg, cb[0]);
19093
19094 memset(msg->cb, 0, sizeof(msg->cb));
d6dc1a38 19095
68eb5503 19096 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 19097 NL80211_MCGRP_MLME, gfp);
5b97f49d
JB
19098}
19099
19100void cfg80211_cqm_rssi_notify(struct net_device *dev,
19101 enum nl80211_cqm_rssi_threshold_event rssi_event,
bee427b8 19102 s32 rssi_level, gfp_t gfp)
5b97f49d 19103{
4a4b8169 19104 struct wireless_dev *wdev = dev->ieee80211_ptr;
37c20b2e 19105 struct cfg80211_cqm_config *cqm_config;
5b97f49d 19106
bee427b8 19107 trace_cfg80211_cqm_rssi_notify(dev, rssi_event, rssi_level);
5b97f49d 19108
98f03342
JB
19109 if (WARN_ON(rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW &&
19110 rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH))
19111 return;
19112
37c20b2e
JB
19113 rcu_read_lock();
19114 cqm_config = rcu_dereference(wdev->cqm_config);
19115 if (cqm_config) {
19116 cqm_config->last_rssi_event_value = rssi_level;
19117 cqm_config->last_rssi_event_type = rssi_event;
19118 wiphy_work_queue(wdev->wiphy, &wdev->cqm_rssi_work);
19119 }
19120 rcu_read_unlock();
19121}
19122EXPORT_SYMBOL(cfg80211_cqm_rssi_notify);
4a4b8169 19123
37c20b2e
JB
19124void cfg80211_cqm_rssi_notify_work(struct wiphy *wiphy, struct wiphy_work *work)
19125{
19126 struct wireless_dev *wdev = container_of(work, struct wireless_dev,
19127 cqm_rssi_work);
19128 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
19129 enum nl80211_cqm_rssi_threshold_event rssi_event;
19130 struct cfg80211_cqm_config *cqm_config;
19131 struct sk_buff *msg;
19132 s32 rssi_level;
4a4b8169 19133
7d6904bf 19134 cqm_config = wiphy_dereference(wdev->wiphy, wdev->cqm_config);
7e7efdda 19135 if (!cqm_config)
7d6904bf 19136 return;
4a4b8169 19137
7e7efdda
JB
19138 if (cqm_config->use_range_api)
19139 cfg80211_cqm_rssi_update(rdev, wdev->netdev, cqm_config);
37c20b2e
JB
19140
19141 rssi_level = cqm_config->last_rssi_event_value;
19142 rssi_event = cqm_config->last_rssi_event_type;
4a4b8169 19143
37c20b2e 19144 msg = cfg80211_prepare_cqm(wdev->netdev, NULL, GFP_KERNEL);
5b97f49d
JB
19145 if (!msg)
19146 return;
19147
19148 if (nla_put_u32(msg, NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT,
19149 rssi_event))
19150 goto nla_put_failure;
19151
bee427b8
AZ
19152 if (rssi_level && nla_put_s32(msg, NL80211_ATTR_CQM_RSSI_LEVEL,
19153 rssi_level))
19154 goto nla_put_failure;
19155
37c20b2e 19156 cfg80211_send_cqm(msg, GFP_KERNEL);
5b97f49d 19157
d6dc1a38
JO
19158 return;
19159
19160 nla_put_failure:
d6dc1a38
JO
19161 nlmsg_free(msg);
19162}
19163
5b97f49d
JB
19164void cfg80211_cqm_txe_notify(struct net_device *dev,
19165 const u8 *peer, u32 num_packets,
19166 u32 rate, u32 intvl, gfp_t gfp)
19167{
19168 struct sk_buff *msg;
19169
19170 msg = cfg80211_prepare_cqm(dev, peer, gfp);
19171 if (!msg)
19172 return;
19173
19174 if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_PKTS, num_packets))
19175 goto nla_put_failure;
19176
19177 if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_RATE, rate))
19178 goto nla_put_failure;
19179
19180 if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_INTVL, intvl))
19181 goto nla_put_failure;
19182
19183 cfg80211_send_cqm(msg, gfp);
19184 return;
19185
19186 nla_put_failure:
19187 nlmsg_free(msg);
19188}
19189EXPORT_SYMBOL(cfg80211_cqm_txe_notify);
19190
19191void cfg80211_cqm_pktloss_notify(struct net_device *dev,
19192 const u8 *peer, u32 num_packets, gfp_t gfp)
19193{
19194 struct sk_buff *msg;
19195
19196 trace_cfg80211_cqm_pktloss_notify(dev, peer, num_packets);
19197
19198 msg = cfg80211_prepare_cqm(dev, peer, gfp);
19199 if (!msg)
19200 return;
19201
19202 if (nla_put_u32(msg, NL80211_ATTR_CQM_PKT_LOSS_EVENT, num_packets))
19203 goto nla_put_failure;
19204
19205 cfg80211_send_cqm(msg, gfp);
19206 return;
19207
19208 nla_put_failure:
19209 nlmsg_free(msg);
19210}
19211EXPORT_SYMBOL(cfg80211_cqm_pktloss_notify);
19212
98f03342
JB
19213void cfg80211_cqm_beacon_loss_notify(struct net_device *dev, gfp_t gfp)
19214{
19215 struct sk_buff *msg;
19216
19217 msg = cfg80211_prepare_cqm(dev, NULL, gfp);
19218 if (!msg)
19219 return;
19220
19221 if (nla_put_flag(msg, NL80211_ATTR_CQM_BEACON_LOSS_EVENT))
19222 goto nla_put_failure;
19223
19224 cfg80211_send_cqm(msg, gfp);
19225 return;
19226
19227 nla_put_failure:
19228 nlmsg_free(msg);
19229}
19230EXPORT_SYMBOL(cfg80211_cqm_beacon_loss_notify);
19231
947add36
JB
19232static void nl80211_gtk_rekey_notify(struct cfg80211_registered_device *rdev,
19233 struct net_device *netdev, const u8 *bssid,
19234 const u8 *replay_ctr, gfp_t gfp)
e5497d76
JB
19235{
19236 struct sk_buff *msg;
19237 struct nlattr *rekey_attr;
19238 void *hdr;
19239
58050fce 19240 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
e5497d76
JB
19241 if (!msg)
19242 return;
19243
19244 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_SET_REKEY_OFFLOAD);
19245 if (!hdr) {
19246 nlmsg_free(msg);
19247 return;
19248 }
19249
9360ffd1
DM
19250 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
19251 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
19252 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid))
19253 goto nla_put_failure;
e5497d76 19254
ae0be8de 19255 rekey_attr = nla_nest_start_noflag(msg, NL80211_ATTR_REKEY_DATA);
e5497d76
JB
19256 if (!rekey_attr)
19257 goto nla_put_failure;
19258
9360ffd1
DM
19259 if (nla_put(msg, NL80211_REKEY_DATA_REPLAY_CTR,
19260 NL80211_REPLAY_CTR_LEN, replay_ctr))
19261 goto nla_put_failure;
e5497d76
JB
19262
19263 nla_nest_end(msg, rekey_attr);
19264
3b7b72ee 19265 genlmsg_end(msg, hdr);
e5497d76 19266
68eb5503 19267 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 19268 NL80211_MCGRP_MLME, gfp);
e5497d76
JB
19269 return;
19270
19271 nla_put_failure:
e5497d76
JB
19272 nlmsg_free(msg);
19273}
19274
947add36
JB
19275void cfg80211_gtk_rekey_notify(struct net_device *dev, const u8 *bssid,
19276 const u8 *replay_ctr, gfp_t gfp)
19277{
19278 struct wireless_dev *wdev = dev->ieee80211_ptr;
19279 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 19280 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
947add36
JB
19281
19282 trace_cfg80211_gtk_rekey_notify(dev, bssid);
19283 nl80211_gtk_rekey_notify(rdev, dev, bssid, replay_ctr, gfp);
19284}
19285EXPORT_SYMBOL(cfg80211_gtk_rekey_notify);
19286
19287static void
19288nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev,
19289 struct net_device *netdev, int index,
19290 const u8 *bssid, bool preauth, gfp_t gfp)
c9df56b4
JM
19291{
19292 struct sk_buff *msg;
19293 struct nlattr *attr;
19294 void *hdr;
19295
58050fce 19296 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
c9df56b4
JM
19297 if (!msg)
19298 return;
19299
19300 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_PMKSA_CANDIDATE);
19301 if (!hdr) {
19302 nlmsg_free(msg);
19303 return;
19304 }
19305
9360ffd1
DM
19306 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
19307 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex))
19308 goto nla_put_failure;
c9df56b4 19309
ae0be8de 19310 attr = nla_nest_start_noflag(msg, NL80211_ATTR_PMKSA_CANDIDATE);
c9df56b4
JM
19311 if (!attr)
19312 goto nla_put_failure;
19313
9360ffd1
DM
19314 if (nla_put_u32(msg, NL80211_PMKSA_CANDIDATE_INDEX, index) ||
19315 nla_put(msg, NL80211_PMKSA_CANDIDATE_BSSID, ETH_ALEN, bssid) ||
19316 (preauth &&
19317 nla_put_flag(msg, NL80211_PMKSA_CANDIDATE_PREAUTH)))
19318 goto nla_put_failure;
c9df56b4
JM
19319
19320 nla_nest_end(msg, attr);
19321
3b7b72ee 19322 genlmsg_end(msg, hdr);
c9df56b4 19323
68eb5503 19324 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 19325 NL80211_MCGRP_MLME, gfp);
c9df56b4
JM
19326 return;
19327
19328 nla_put_failure:
c9df56b4
JM
19329 nlmsg_free(msg);
19330}
19331
947add36
JB
19332void cfg80211_pmksa_candidate_notify(struct net_device *dev, int index,
19333 const u8 *bssid, bool preauth, gfp_t gfp)
19334{
19335 struct wireless_dev *wdev = dev->ieee80211_ptr;
19336 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 19337 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
947add36
JB
19338
19339 trace_cfg80211_pmksa_candidate_notify(dev, index, bssid, preauth);
19340 nl80211_pmksa_candidate_notify(rdev, dev, index, bssid, preauth, gfp);
19341}
19342EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify);
19343
19344static void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
19345 struct net_device *netdev,
b8c9024e 19346 unsigned int link_id,
947add36 19347 struct cfg80211_chan_def *chandef,
f8d7552e
LC
19348 gfp_t gfp,
19349 enum nl80211_commands notif,
b82730bf 19350 u8 count, bool quiet)
5314526b 19351{
b8c9024e 19352 struct wireless_dev *wdev = netdev->ieee80211_ptr;
5314526b
TP
19353 struct sk_buff *msg;
19354 void *hdr;
19355
58050fce 19356 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
5314526b
TP
19357 if (!msg)
19358 return;
19359
f8d7552e 19360 hdr = nl80211hdr_put(msg, 0, 0, 0, notif);
5314526b
TP
19361 if (!hdr) {
19362 nlmsg_free(msg);
19363 return;
19364 }
19365
683b6d3b
JB
19366 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex))
19367 goto nla_put_failure;
19368
b8c9024e
VJ
19369 if (wdev->valid_links &&
19370 nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id))
19371 goto nla_put_failure;
19372
683b6d3b 19373 if (nl80211_send_chandef(msg, chandef))
7eab0f64 19374 goto nla_put_failure;
5314526b 19375
669b8413
JB
19376 if (notif == NL80211_CMD_CH_SWITCH_STARTED_NOTIFY) {
19377 if (nla_put_u32(msg, NL80211_ATTR_CH_SWITCH_COUNT, count))
f8d7552e 19378 goto nla_put_failure;
669b8413
JB
19379 if (quiet &&
19380 nla_put_flag(msg, NL80211_ATTR_CH_SWITCH_BLOCK_TX))
f8d7552e 19381 goto nla_put_failure;
669b8413 19382 }
f8d7552e 19383
5314526b
TP
19384 genlmsg_end(msg, hdr);
19385
68eb5503 19386 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 19387 NL80211_MCGRP_MLME, gfp);
5314526b
TP
19388 return;
19389
19390 nla_put_failure:
5314526b
TP
19391 nlmsg_free(msg);
19392}
19393
947add36 19394void cfg80211_ch_switch_notify(struct net_device *dev,
7b0a0e3c 19395 struct cfg80211_chan_def *chandef,
b82730bf 19396 unsigned int link_id)
84f10708 19397{
947add36
JB
19398 struct wireless_dev *wdev = dev->ieee80211_ptr;
19399 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 19400 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
947add36 19401
076fc877 19402 lockdep_assert_wiphy(wdev->wiphy);
7b0a0e3c 19403 WARN_INVALID_LINK_ID(wdev, link_id);
947add36 19404
b82730bf 19405 trace_cfg80211_ch_switch_notify(dev, chandef, link_id);
5dc8cdce 19406
7b0a0e3c
JB
19407 switch (wdev->iftype) {
19408 case NL80211_IFTYPE_STATION:
19409 case NL80211_IFTYPE_P2P_CLIENT:
19410 if (!WARN_ON(!wdev->links[link_id].client.current_bss))
19411 cfg80211_update_assoc_bss_entry(wdev, link_id,
19412 chandef->chan);
19413 break;
19414 case NL80211_IFTYPE_MESH_POINT:
19415 wdev->u.mesh.chandef = *chandef;
19416 wdev->u.mesh.preset_chandef = *chandef;
19417 break;
19418 case NL80211_IFTYPE_AP:
19419 case NL80211_IFTYPE_P2P_GO:
19420 wdev->links[link_id].ap.chandef = *chandef;
19421 break;
77e7b6ba
JB
19422 case NL80211_IFTYPE_ADHOC:
19423 wdev->u.ibss.chandef = *chandef;
19424 break;
7b0a0e3c
JB
19425 default:
19426 WARN_ON(1);
19427 break;
19428 }
5dc8cdce 19429
9be61558 19430 cfg80211_schedule_channels_check(wdev);
d34990bb
MV
19431 cfg80211_sched_dfs_chan_update(rdev);
19432
b8c9024e 19433 nl80211_ch_switch_notify(rdev, dev, link_id, chandef, GFP_KERNEL,
b82730bf 19434 NL80211_CMD_CH_SWITCH_NOTIFY, 0, false);
947add36
JB
19435}
19436EXPORT_SYMBOL(cfg80211_ch_switch_notify);
19437
f8d7552e
LC
19438void cfg80211_ch_switch_started_notify(struct net_device *dev,
19439 struct cfg80211_chan_def *chandef,
b8c9024e 19440 unsigned int link_id, u8 count,
b82730bf 19441 bool quiet)
f8d7552e
LC
19442{
19443 struct wireless_dev *wdev = dev->ieee80211_ptr;
19444 struct wiphy *wiphy = wdev->wiphy;
19445 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
19446
076fc877 19447 lockdep_assert_wiphy(wdev->wiphy);
b8c9024e
VJ
19448 WARN_INVALID_LINK_ID(wdev, link_id);
19449
b82730bf 19450 trace_cfg80211_ch_switch_started_notify(dev, chandef, link_id);
b345f063 19451
f8d7552e 19452
b8c9024e 19453 nl80211_ch_switch_notify(rdev, dev, link_id, chandef, GFP_KERNEL,
669b8413 19454 NL80211_CMD_CH_SWITCH_STARTED_NOTIFY,
b82730bf 19455 count, quiet);
f8d7552e
LC
19456}
19457EXPORT_SYMBOL(cfg80211_ch_switch_started_notify);
19458
935ef47b 19459int cfg80211_bss_color_notify(struct net_device *dev,
0d2ab3ae 19460 enum nl80211_commands cmd, u8 count,
91d2b6ee 19461 u64 color_bitmap, u8 link_id)
0d2ab3ae
JC
19462{
19463 struct wireless_dev *wdev = dev->ieee80211_ptr;
19464 struct wiphy *wiphy = wdev->wiphy;
19465 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
19466 struct sk_buff *msg;
19467 void *hdr;
19468
076fc877 19469 lockdep_assert_wiphy(wdev->wiphy);
0d2ab3ae
JC
19470
19471 trace_cfg80211_bss_color_notify(dev, cmd, count, color_bitmap);
19472
935ef47b 19473 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
0d2ab3ae
JC
19474 if (!msg)
19475 return -ENOMEM;
19476
19477 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
19478 if (!hdr)
19479 goto nla_put_failure;
19480
19481 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
19482 goto nla_put_failure;
19483
91d2b6ee
AKS
19484 if (wdev->valid_links &&
19485 nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id))
19486 goto nla_put_failure;
19487
0d2ab3ae
JC
19488 if (cmd == NL80211_CMD_COLOR_CHANGE_STARTED &&
19489 nla_put_u32(msg, NL80211_ATTR_COLOR_CHANGE_COUNT, count))
19490 goto nla_put_failure;
19491
19492 if (cmd == NL80211_CMD_OBSS_COLOR_COLLISION &&
19493 nla_put_u64_64bit(msg, NL80211_ATTR_OBSS_COLOR_BITMAP,
19494 color_bitmap, NL80211_ATTR_PAD))
19495 goto nla_put_failure;
19496
19497 genlmsg_end(msg, hdr);
19498
19499 return genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
935ef47b 19500 msg, 0, NL80211_MCGRP_MLME, GFP_KERNEL);
0d2ab3ae
JC
19501
19502nla_put_failure:
19503 nlmsg_free(msg);
19504 return -EINVAL;
19505}
19506EXPORT_SYMBOL(cfg80211_bss_color_notify);
19507
04f39047
SW
19508void
19509nl80211_radar_notify(struct cfg80211_registered_device *rdev,
d2859df5 19510 const struct cfg80211_chan_def *chandef,
04f39047
SW
19511 enum nl80211_radar_event event,
19512 struct net_device *netdev, gfp_t gfp)
19513{
19514 struct sk_buff *msg;
19515 void *hdr;
19516
19517 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
19518 if (!msg)
19519 return;
19520
19521 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_RADAR_DETECT);
19522 if (!hdr) {
19523 nlmsg_free(msg);
19524 return;
19525 }
19526
19527 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx))
19528 goto nla_put_failure;
19529
19530 /* NOP and radar events don't need a netdev parameter */
19531 if (netdev) {
19532 struct wireless_dev *wdev = netdev->ieee80211_ptr;
19533
19534 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
2dad624e
ND
19535 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
19536 NL80211_ATTR_PAD))
04f39047
SW
19537 goto nla_put_failure;
19538 }
19539
19540 if (nla_put_u32(msg, NL80211_ATTR_RADAR_EVENT, event))
19541 goto nla_put_failure;
19542
19543 if (nl80211_send_chandef(msg, chandef))
19544 goto nla_put_failure;
19545
9c90a9f6 19546 genlmsg_end(msg, hdr);
04f39047 19547
68eb5503 19548 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 19549 NL80211_MCGRP_MLME, gfp);
04f39047
SW
19550 return;
19551
19552 nla_put_failure:
04f39047
SW
19553 nlmsg_free(msg);
19554}
19555
466b9936 19556void cfg80211_sta_opmode_change_notify(struct net_device *dev, const u8 *mac,
19557 struct sta_opmode_info *sta_opmode,
19558 gfp_t gfp)
19559{
19560 struct sk_buff *msg;
19561 struct wireless_dev *wdev = dev->ieee80211_ptr;
19562 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
19563 void *hdr;
19564
19565 if (WARN_ON(!mac))
19566 return;
19567
19568 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
19569 if (!msg)
19570 return;
19571
19572 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_STA_OPMODE_CHANGED);
19573 if (!hdr) {
19574 nlmsg_free(msg);
19575 return;
19576 }
19577
19578 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx))
19579 goto nla_put_failure;
19580
19581 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
19582 goto nla_put_failure;
19583
19584 if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac))
19585 goto nla_put_failure;
19586
19587 if ((sta_opmode->changed & STA_OPMODE_SMPS_MODE_CHANGED) &&
19588 nla_put_u8(msg, NL80211_ATTR_SMPS_MODE, sta_opmode->smps_mode))
19589 goto nla_put_failure;
19590
19591 if ((sta_opmode->changed & STA_OPMODE_MAX_BW_CHANGED) &&
0016d320 19592 nla_put_u32(msg, NL80211_ATTR_CHANNEL_WIDTH, sta_opmode->bw))
466b9936 19593 goto nla_put_failure;
19594
19595 if ((sta_opmode->changed & STA_OPMODE_N_SS_CHANGED) &&
19596 nla_put_u8(msg, NL80211_ATTR_NSS, sta_opmode->rx_nss))
19597 goto nla_put_failure;
19598
19599 genlmsg_end(msg, hdr);
19600
19601 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
19602 NL80211_MCGRP_MLME, gfp);
19603
19604 return;
19605
19606nla_put_failure:
19607 nlmsg_free(msg);
19608}
19609EXPORT_SYMBOL(cfg80211_sta_opmode_change_notify);
19610
7f6cf311 19611void cfg80211_probe_status(struct net_device *dev, const u8 *addr,
c4b50cd3
VN
19612 u64 cookie, bool acked, s32 ack_signal,
19613 bool is_valid_ack_signal, gfp_t gfp)
7f6cf311
JB
19614{
19615 struct wireless_dev *wdev = dev->ieee80211_ptr;
f26cbf40 19616 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
7f6cf311
JB
19617 struct sk_buff *msg;
19618 void *hdr;
7f6cf311 19619
4ee3e063
BL
19620 trace_cfg80211_probe_status(dev, addr, cookie, acked);
19621
58050fce 19622 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
4ee3e063 19623
7f6cf311
JB
19624 if (!msg)
19625 return;
19626
19627 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_PROBE_CLIENT);
19628 if (!hdr) {
19629 nlmsg_free(msg);
19630 return;
19631 }
19632
9360ffd1
DM
19633 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
19634 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
19635 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
2dad624e
ND
19636 nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
19637 NL80211_ATTR_PAD) ||
c4b50cd3
VN
19638 (acked && nla_put_flag(msg, NL80211_ATTR_ACK)) ||
19639 (is_valid_ack_signal && nla_put_s32(msg, NL80211_ATTR_ACK_SIGNAL,
19640 ack_signal)))
9360ffd1 19641 goto nla_put_failure;
7f6cf311 19642
9c90a9f6 19643 genlmsg_end(msg, hdr);
7f6cf311 19644
68eb5503 19645 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 19646 NL80211_MCGRP_MLME, gfp);
7f6cf311
JB
19647 return;
19648
19649 nla_put_failure:
7f6cf311
JB
19650 nlmsg_free(msg);
19651}
19652EXPORT_SYMBOL(cfg80211_probe_status);
19653
e76fede8
TP
19654void cfg80211_report_obss_beacon_khz(struct wiphy *wiphy, const u8 *frame,
19655 size_t len, int freq, int sig_dbm)
5e760230 19656{
f26cbf40 19657 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
5e760230
JB
19658 struct sk_buff *msg;
19659 void *hdr;
37c73b5f 19660 struct cfg80211_beacon_registration *reg;
5e760230 19661
4ee3e063
BL
19662 trace_cfg80211_report_obss_beacon(wiphy, frame, len, freq, sig_dbm);
19663
37c73b5f
BG
19664 spin_lock_bh(&rdev->beacon_registrations_lock);
19665 list_for_each_entry(reg, &rdev->beacon_registrations, list) {
19666 msg = nlmsg_new(len + 100, GFP_ATOMIC);
19667 if (!msg) {
19668 spin_unlock_bh(&rdev->beacon_registrations_lock);
19669 return;
19670 }
5e760230 19671
37c73b5f
BG
19672 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FRAME);
19673 if (!hdr)
19674 goto nla_put_failure;
5e760230 19675
37c73b5f
BG
19676 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
19677 (freq &&
942ba88b
TP
19678 (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
19679 KHZ_TO_MHZ(freq)) ||
19680 nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ_OFFSET,
19681 freq % 1000))) ||
37c73b5f
BG
19682 (sig_dbm &&
19683 nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)) ||
19684 nla_put(msg, NL80211_ATTR_FRAME, len, frame))
19685 goto nla_put_failure;
5e760230 19686
37c73b5f 19687 genlmsg_end(msg, hdr);
5e760230 19688
37c73b5f
BG
19689 genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, reg->nlportid);
19690 }
19691 spin_unlock_bh(&rdev->beacon_registrations_lock);
5e760230
JB
19692 return;
19693
19694 nla_put_failure:
37c73b5f 19695 spin_unlock_bh(&rdev->beacon_registrations_lock);
5e760230
JB
19696 nlmsg_free(msg);
19697}
e76fede8 19698EXPORT_SYMBOL(cfg80211_report_obss_beacon_khz);
5e760230 19699
cd8f7cb4 19700#ifdef CONFIG_PM
8cd4d456
LC
19701static int cfg80211_net_detect_results(struct sk_buff *msg,
19702 struct cfg80211_wowlan_wakeup *wakeup)
19703{
19704 struct cfg80211_wowlan_nd_info *nd = wakeup->net_detect;
19705 struct nlattr *nl_results, *nl_match, *nl_freqs;
19706 int i, j;
19707
ae0be8de
MK
19708 nl_results = nla_nest_start_noflag(msg,
19709 NL80211_WOWLAN_TRIG_NET_DETECT_RESULTS);
8cd4d456
LC
19710 if (!nl_results)
19711 return -EMSGSIZE;
19712
19713 for (i = 0; i < nd->n_matches; i++) {
19714 struct cfg80211_wowlan_nd_match *match = nd->matches[i];
19715
ae0be8de 19716 nl_match = nla_nest_start_noflag(msg, i);
8cd4d456
LC
19717 if (!nl_match)
19718 break;
19719
19720 /* The SSID attribute is optional in nl80211, but for
19721 * simplicity reasons it's always present in the
19722 * cfg80211 structure. If a driver can't pass the
19723 * SSID, that needs to be changed. A zero length SSID
19724 * is still a valid SSID (wildcard), so it cannot be
19725 * used for this purpose.
19726 */
19727 if (nla_put(msg, NL80211_ATTR_SSID, match->ssid.ssid_len,
19728 match->ssid.ssid)) {
19729 nla_nest_cancel(msg, nl_match);
19730 goto out;
19731 }
19732
19733 if (match->n_channels) {
ae0be8de
MK
19734 nl_freqs = nla_nest_start_noflag(msg,
19735 NL80211_ATTR_SCAN_FREQUENCIES);
8cd4d456
LC
19736 if (!nl_freqs) {
19737 nla_nest_cancel(msg, nl_match);
19738 goto out;
19739 }
19740
19741 for (j = 0; j < match->n_channels; j++) {
5528fae8 19742 if (nla_put_u32(msg, j, match->channels[j])) {
8cd4d456
LC
19743 nla_nest_cancel(msg, nl_freqs);
19744 nla_nest_cancel(msg, nl_match);
19745 goto out;
19746 }
19747 }
19748
19749 nla_nest_end(msg, nl_freqs);
19750 }
19751
19752 nla_nest_end(msg, nl_match);
19753 }
19754
19755out:
19756 nla_nest_end(msg, nl_results);
19757 return 0;
19758}
19759
cd8f7cb4
JB
19760void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev,
19761 struct cfg80211_wowlan_wakeup *wakeup,
19762 gfp_t gfp)
19763{
f26cbf40 19764 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
cd8f7cb4
JB
19765 struct sk_buff *msg;
19766 void *hdr;
9c90a9f6 19767 int size = 200;
cd8f7cb4
JB
19768
19769 trace_cfg80211_report_wowlan_wakeup(wdev->wiphy, wdev, wakeup);
19770
19771 if (wakeup)
19772 size += wakeup->packet_present_len;
19773
19774 msg = nlmsg_new(size, gfp);
19775 if (!msg)
19776 return;
19777
19778 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_SET_WOWLAN);
19779 if (!hdr)
19780 goto free_msg;
19781
19782 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
2dad624e
ND
19783 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
19784 NL80211_ATTR_PAD))
cd8f7cb4
JB
19785 goto free_msg;
19786
19787 if (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
19788 wdev->netdev->ifindex))
19789 goto free_msg;
19790
19791 if (wakeup) {
19792 struct nlattr *reasons;
19793
ae0be8de
MK
19794 reasons = nla_nest_start_noflag(msg,
19795 NL80211_ATTR_WOWLAN_TRIGGERS);
7fa322c8
JB
19796 if (!reasons)
19797 goto free_msg;
cd8f7cb4
JB
19798
19799 if (wakeup->disconnect &&
19800 nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT))
19801 goto free_msg;
19802 if (wakeup->magic_pkt &&
19803 nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT))
19804 goto free_msg;
19805 if (wakeup->gtk_rekey_failure &&
19806 nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE))
19807 goto free_msg;
19808 if (wakeup->eap_identity_req &&
19809 nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST))
19810 goto free_msg;
19811 if (wakeup->four_way_handshake &&
19812 nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE))
19813 goto free_msg;
19814 if (wakeup->rfkill_release &&
19815 nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE))
19816 goto free_msg;
19817
19818 if (wakeup->pattern_idx >= 0 &&
19819 nla_put_u32(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN,
19820 wakeup->pattern_idx))
19821 goto free_msg;
19822
ae917c9f
JB
19823 if (wakeup->tcp_match &&
19824 nla_put_flag(msg, NL80211_WOWLAN_TRIG_WAKEUP_TCP_MATCH))
19825 goto free_msg;
2a0e047e 19826
ae917c9f
JB
19827 if (wakeup->tcp_connlost &&
19828 nla_put_flag(msg, NL80211_WOWLAN_TRIG_WAKEUP_TCP_CONNLOST))
19829 goto free_msg;
2a0e047e 19830
ae917c9f
JB
19831 if (wakeup->tcp_nomoretokens &&
19832 nla_put_flag(msg,
19833 NL80211_WOWLAN_TRIG_WAKEUP_TCP_NOMORETOKENS))
19834 goto free_msg;
2a0e047e 19835
a64be829
ST
19836 if (wakeup->unprot_deauth_disassoc &&
19837 nla_put_flag(msg,
19838 NL80211_WOWLAN_TRIG_UNPROTECTED_DEAUTH_DISASSOC))
19839 goto free_msg;
19840
cd8f7cb4
JB
19841 if (wakeup->packet) {
19842 u32 pkt_attr = NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211;
19843 u32 len_attr = NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN;
19844
19845 if (!wakeup->packet_80211) {
19846 pkt_attr =
19847 NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023;
19848 len_attr =
19849 NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023_LEN;
19850 }
19851
19852 if (wakeup->packet_len &&
19853 nla_put_u32(msg, len_attr, wakeup->packet_len))
19854 goto free_msg;
19855
19856 if (nla_put(msg, pkt_attr, wakeup->packet_present_len,
19857 wakeup->packet))
19858 goto free_msg;
19859 }
19860
8cd4d456
LC
19861 if (wakeup->net_detect &&
19862 cfg80211_net_detect_results(msg, wakeup))
19863 goto free_msg;
19864
cd8f7cb4
JB
19865 nla_nest_end(msg, reasons);
19866 }
19867
9c90a9f6 19868 genlmsg_end(msg, hdr);
cd8f7cb4 19869
68eb5503 19870 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 19871 NL80211_MCGRP_MLME, gfp);
cd8f7cb4
JB
19872 return;
19873
19874 free_msg:
19875 nlmsg_free(msg);
19876}
19877EXPORT_SYMBOL(cfg80211_report_wowlan_wakeup);
19878#endif
19879
3475b094
JM
19880void cfg80211_tdls_oper_request(struct net_device *dev, const u8 *peer,
19881 enum nl80211_tdls_operation oper,
19882 u16 reason_code, gfp_t gfp)
19883{
19884 struct wireless_dev *wdev = dev->ieee80211_ptr;
f26cbf40 19885 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
3475b094
JM
19886 struct sk_buff *msg;
19887 void *hdr;
3475b094
JM
19888
19889 trace_cfg80211_tdls_oper_request(wdev->wiphy, dev, peer, oper,
19890 reason_code);
19891
19892 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
19893 if (!msg)
19894 return;
19895
19896 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_TDLS_OPER);
19897 if (!hdr) {
19898 nlmsg_free(msg);
19899 return;
19900 }
19901
19902 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
19903 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
19904 nla_put_u8(msg, NL80211_ATTR_TDLS_OPERATION, oper) ||
19905 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, peer) ||
19906 (reason_code > 0 &&
19907 nla_put_u16(msg, NL80211_ATTR_REASON_CODE, reason_code)))
19908 goto nla_put_failure;
19909
9c90a9f6 19910 genlmsg_end(msg, hdr);
3475b094 19911
68eb5503 19912 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 19913 NL80211_MCGRP_MLME, gfp);
3475b094
JM
19914 return;
19915
19916 nla_put_failure:
3475b094
JM
19917 nlmsg_free(msg);
19918}
19919EXPORT_SYMBOL(cfg80211_tdls_oper_request);
19920
026331c4
JM
19921static int nl80211_netlink_notify(struct notifier_block * nb,
19922 unsigned long state,
19923 void *_notify)
19924{
19925 struct netlink_notify *notify = _notify;
19926 struct cfg80211_registered_device *rdev;
19927 struct wireless_dev *wdev;
37c73b5f 19928 struct cfg80211_beacon_registration *reg, *tmp;
026331c4 19929
8f815cdd 19930 if (state != NETLINK_URELEASE || notify->protocol != NETLINK_GENERIC)
026331c4
JM
19931 return NOTIFY_DONE;
19932
19933 rcu_read_lock();
19934
5e760230 19935 list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) {
ca986ad9 19936 struct cfg80211_sched_scan_request *sched_scan_req;
753aacfd 19937
ca986ad9
AVS
19938 list_for_each_entry_rcu(sched_scan_req,
19939 &rdev->sched_scan_req_list,
19940 list) {
19941 if (sched_scan_req->owner_nlportid == notify->portid) {
19942 sched_scan_req->nl_owner_dead = true;
c88d7178
JB
19943 wiphy_work_queue(&rdev->wiphy,
19944 &rdev->sched_scan_stop_wk);
ca986ad9 19945 }
753aacfd 19946 }
78f22b6a 19947
53873f13 19948 list_for_each_entry_rcu(wdev, &rdev->wiphy.wdev_list, list) {
15e47304 19949 cfg80211_mlme_unregister_socket(wdev, notify->portid);
37c73b5f 19950
ab81007a
JB
19951 if (wdev->owner_nlportid == notify->portid) {
19952 wdev->nl_owner_dead = true;
19953 schedule_work(&rdev->destroy_work);
19954 } else if (wdev->conn_owner_nlportid == notify->portid) {
bd2522b1 19955 schedule_work(&wdev->disconnect_wk);
ab81007a 19956 }
9bb7e0f2
JB
19957
19958 cfg80211_release_pmsr(wdev, notify->portid);
78f22b6a
JB
19959 }
19960
37c73b5f
BG
19961 spin_lock_bh(&rdev->beacon_registrations_lock);
19962 list_for_each_entry_safe(reg, tmp, &rdev->beacon_registrations,
19963 list) {
19964 if (reg->nlportid == notify->portid) {
19965 list_del(&reg->list);
19966 kfree(reg);
19967 break;
19968 }
19969 }
19970 spin_unlock_bh(&rdev->beacon_registrations_lock);
5e760230 19971 }
026331c4
JM
19972
19973 rcu_read_unlock();
19974
05050753
I
19975 /*
19976 * It is possible that the user space process that is controlling the
19977 * indoor setting disappeared, so notify the regulatory core.
19978 */
19979 regulatory_netlink_notify(notify->portid);
6784c7db 19980 return NOTIFY_OK;
026331c4
JM
19981}
19982
19983static struct notifier_block nl80211_netlink_notifier = {
19984 .notifier_call = nl80211_netlink_notify,
19985};
19986
355199e0
JM
19987void cfg80211_ft_event(struct net_device *netdev,
19988 struct cfg80211_ft_event_params *ft_event)
19989{
19990 struct wiphy *wiphy = netdev->ieee80211_ptr->wiphy;
f26cbf40 19991 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
355199e0
JM
19992 struct sk_buff *msg;
19993 void *hdr;
355199e0
JM
19994
19995 trace_cfg80211_ft_event(wiphy, netdev, ft_event);
19996
19997 if (!ft_event->target_ap)
19998 return;
19999
1039d081
DL
20000 msg = nlmsg_new(100 + ft_event->ies_len + ft_event->ric_ies_len,
20001 GFP_KERNEL);
355199e0
JM
20002 if (!msg)
20003 return;
20004
20005 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FT_EVENT);
ae917c9f
JB
20006 if (!hdr)
20007 goto out;
355199e0 20008
ae917c9f
JB
20009 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
20010 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
20011 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, ft_event->target_ap))
20012 goto out;
355199e0 20013
ae917c9f
JB
20014 if (ft_event->ies &&
20015 nla_put(msg, NL80211_ATTR_IE, ft_event->ies_len, ft_event->ies))
20016 goto out;
20017 if (ft_event->ric_ies &&
20018 nla_put(msg, NL80211_ATTR_IE_RIC, ft_event->ric_ies_len,
20019 ft_event->ric_ies))
20020 goto out;
355199e0 20021
9c90a9f6 20022 genlmsg_end(msg, hdr);
355199e0 20023
68eb5503 20024 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 20025 NL80211_MCGRP_MLME, GFP_KERNEL);
ae917c9f
JB
20026 return;
20027 out:
20028 nlmsg_free(msg);
355199e0
JM
20029}
20030EXPORT_SYMBOL(cfg80211_ft_event);
20031
5de17984
AS
20032void cfg80211_crit_proto_stopped(struct wireless_dev *wdev, gfp_t gfp)
20033{
20034 struct cfg80211_registered_device *rdev;
20035 struct sk_buff *msg;
20036 void *hdr;
20037 u32 nlportid;
20038
f26cbf40 20039 rdev = wiphy_to_rdev(wdev->wiphy);
5de17984
AS
20040 if (!rdev->crit_proto_nlportid)
20041 return;
20042
20043 nlportid = rdev->crit_proto_nlportid;
20044 rdev->crit_proto_nlportid = 0;
20045
20046 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
20047 if (!msg)
20048 return;
20049
20050 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CRIT_PROTOCOL_STOP);
20051 if (!hdr)
20052 goto nla_put_failure;
20053
20054 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
2dad624e
ND
20055 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
20056 NL80211_ATTR_PAD))
5de17984
AS
20057 goto nla_put_failure;
20058
20059 genlmsg_end(msg, hdr);
20060
20061 genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid);
20062 return;
20063
20064 nla_put_failure:
5de17984 20065 nlmsg_free(msg);
5de17984
AS
20066}
20067EXPORT_SYMBOL(cfg80211_crit_proto_stopped);
20068
cba7217a 20069void nl80211_send_ap_stopped(struct wireless_dev *wdev, unsigned int link_id)
348baf0e
JB
20070{
20071 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 20072 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
348baf0e
JB
20073 struct sk_buff *msg;
20074 void *hdr;
20075
20076 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
20077 if (!msg)
20078 return;
20079
20080 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_STOP_AP);
20081 if (!hdr)
20082 goto out;
20083
20084 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
20085 nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex) ||
2dad624e 20086 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
cba7217a
20087 NL80211_ATTR_PAD) ||
20088 (wdev->valid_links &&
20089 nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id)))
348baf0e
JB
20090 goto out;
20091
20092 genlmsg_end(msg, hdr);
20093
20094 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(wiphy), msg, 0,
20095 NL80211_MCGRP_MLME, GFP_KERNEL);
20096 return;
20097 out:
20098 nlmsg_free(msg);
20099}
20100
40cbfa90
SD
20101int cfg80211_external_auth_request(struct net_device *dev,
20102 struct cfg80211_external_auth_params *params,
20103 gfp_t gfp)
20104{
20105 struct wireless_dev *wdev = dev->ieee80211_ptr;
20106 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
20107 struct sk_buff *msg;
20108 void *hdr;
20109
20110 if (!wdev->conn_owner_nlportid)
20111 return -EINVAL;
20112
20113 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
20114 if (!msg)
20115 return -ENOMEM;
20116
20117 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_EXTERNAL_AUTH);
20118 if (!hdr)
20119 goto nla_put_failure;
20120
4f4d8be6
AL
20121 /* Some historical mistakes in drivers <-> userspace interface (notably
20122 * between drivers and wpa_supplicant) led to a big-endian conversion
20123 * being needed on NL80211_ATTR_AKM_SUITES _only_ when its value is
20124 * WLAN_AKM_SUITE_SAE. This is now fixed on userspace side, but for the
20125 * benefit of older wpa_supplicant versions, send this particular value
20126 * in big-endian. Note that newer wpa_supplicant will also detect this
20127 * particular value in big endian still, so it all continues to work.
20128 */
20129 if (params->key_mgmt_suite == WLAN_AKM_SUITE_SAE) {
20130 if (nla_put_be32(msg, NL80211_ATTR_AKM_SUITES,
20131 cpu_to_be32(WLAN_AKM_SUITE_SAE)))
20132 goto nla_put_failure;
20133 } else {
20134 if (nla_put_u32(msg, NL80211_ATTR_AKM_SUITES,
20135 params->key_mgmt_suite))
20136 goto nla_put_failure;
20137 }
20138
40cbfa90
SD
20139 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
20140 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
40cbfa90
SD
20141 nla_put_u32(msg, NL80211_ATTR_EXTERNAL_AUTH_ACTION,
20142 params->action) ||
20143 nla_put(msg, NL80211_ATTR_BSSID, ETH_ALEN, params->bssid) ||
20144 nla_put(msg, NL80211_ATTR_SSID, params->ssid.ssid_len,
9a47c1ef
VJ
20145 params->ssid.ssid) ||
20146 (!is_zero_ether_addr(params->mld_addr) &&
20147 nla_put(msg, NL80211_ATTR_MLD_ADDR, ETH_ALEN, params->mld_addr)))
40cbfa90
SD
20148 goto nla_put_failure;
20149
20150 genlmsg_end(msg, hdr);
20151 genlmsg_unicast(wiphy_net(&rdev->wiphy), msg,
20152 wdev->conn_owner_nlportid);
20153 return 0;
20154
20155 nla_put_failure:
20156 nlmsg_free(msg);
20157 return -ENOBUFS;
20158}
20159EXPORT_SYMBOL(cfg80211_external_auth_request);
20160
cb74e977
SD
20161void cfg80211_update_owe_info_event(struct net_device *netdev,
20162 struct cfg80211_update_owe_info *owe_info,
20163 gfp_t gfp)
20164{
20165 struct wiphy *wiphy = netdev->ieee80211_ptr->wiphy;
20166 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
20167 struct sk_buff *msg;
20168 void *hdr;
20169
20170 trace_cfg80211_update_owe_info_event(wiphy, netdev, owe_info);
20171
20172 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
20173 if (!msg)
20174 return;
20175
20176 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_UPDATE_OWE_INFO);
20177 if (!hdr)
20178 goto nla_put_failure;
20179
20180 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
20181 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
20182 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, owe_info->peer))
20183 goto nla_put_failure;
20184
20185 if (!owe_info->ie_len ||
20186 nla_put(msg, NL80211_ATTR_IE, owe_info->ie_len, owe_info->ie))
20187 goto nla_put_failure;
20188
8bb588d9
VJ
20189 if (owe_info->assoc_link_id != -1) {
20190 if (nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID,
20191 owe_info->assoc_link_id))
20192 goto nla_put_failure;
20193
20194 if (!is_zero_ether_addr(owe_info->peer_mld_addr) &&
20195 nla_put(msg, NL80211_ATTR_MLD_ADDR, ETH_ALEN,
20196 owe_info->peer_mld_addr))
20197 goto nla_put_failure;
20198 }
20199
cb74e977
SD
20200 genlmsg_end(msg, hdr);
20201
20202 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
20203 NL80211_MCGRP_MLME, gfp);
20204 return;
20205
20206nla_put_failure:
20207 genlmsg_cancel(msg, hdr);
20208 nlmsg_free(msg);
20209}
20210EXPORT_SYMBOL(cfg80211_update_owe_info_event);
20211
9be61558
AO
20212void cfg80211_schedule_channels_check(struct wireless_dev *wdev)
20213{
20214 struct wiphy *wiphy = wdev->wiphy;
20215
20216 /* Schedule channels check if NO_IR or DFS relaxations are supported */
20217 if (wdev->iftype == NL80211_IFTYPE_STATION &&
20218 (wiphy_ext_feature_isset(wiphy,
20219 NL80211_EXT_FEATURE_DFS_CONCURRENT) ||
20220 (IS_ENABLED(CONFIG_CFG80211_REG_RELAX_NO_IR) &&
20221 wiphy->regulatory_flags & REGULATORY_ENABLE_RELAX_NO_IR)))
20222 reg_check_channels();
20223}
20224EXPORT_SYMBOL(cfg80211_schedule_channels_check);
20225
55682965
JB
20226/* initialisation/exit functions */
20227
56989f6d 20228int __init nl80211_init(void)
55682965 20229{
0d63cbb5 20230 int err;
55682965 20231
489111e5 20232 err = genl_register_family(&nl80211_fam);
55682965
JB
20233 if (err)
20234 return err;
20235
026331c4
JM
20236 err = netlink_register_notifier(&nl80211_netlink_notifier);
20237 if (err)
20238 goto err_out;
20239
55682965
JB
20240 return 0;
20241 err_out:
20242 genl_unregister_family(&nl80211_fam);
20243 return err;
20244}
20245
20246void nl80211_exit(void)
20247{
026331c4 20248 netlink_unregister_notifier(&nl80211_netlink_notifier);
55682965
JB
20249 genl_unregister_family(&nl80211_fam);
20250}