wifi: cfg80211/nl80211: Add support to indicate STA MLD setup links removal
[linux-block.git] / net / wireless / nl80211.c
CommitLineData
457c8996 1// SPDX-License-Identifier: GPL-2.0-only
55682965
JB
2/*
3 * This is the new netlink-based wireless configuration interface.
4 *
026331c4 5 * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
2740f0cf 6 * Copyright 2013-2014 Intel Mobile Communications GmbH
66cd794e 7 * Copyright 2015-2017 Intel Deutschland GmbH
6cf963ed 8 * Copyright (C) 2018-2023 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
89a54e48
JB
109 list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
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 },
9bb7e0f2
JB
326};
327
328static const struct nla_policy
329nl80211_pmsr_req_data_policy[NL80211_PMSR_TYPE_MAX + 1] = {
330 [NL80211_PMSR_TYPE_FTM] =
23323289 331 NLA_POLICY_NESTED(nl80211_pmsr_ftm_req_attr_policy),
9bb7e0f2
JB
332};
333
334static const struct nla_policy
335nl80211_pmsr_req_attr_policy[NL80211_PMSR_REQ_ATTR_MAX + 1] = {
336 [NL80211_PMSR_REQ_ATTR_DATA] =
23323289 337 NLA_POLICY_NESTED(nl80211_pmsr_req_data_policy),
9bb7e0f2
JB
338 [NL80211_PMSR_REQ_ATTR_GET_AP_TSF] = { .type = NLA_FLAG },
339};
340
341static const struct nla_policy
aeddc05f 342nl80211_pmsr_peer_attr_policy[NL80211_PMSR_PEER_ATTR_MAX + 1] = {
9bb7e0f2 343 [NL80211_PMSR_PEER_ATTR_ADDR] = NLA_POLICY_ETH_ADDR,
d15da2a2 344 [NL80211_PMSR_PEER_ATTR_CHAN] = NLA_POLICY_NESTED(nl80211_policy),
9bb7e0f2 345 [NL80211_PMSR_PEER_ATTR_REQ] =
23323289 346 NLA_POLICY_NESTED(nl80211_pmsr_req_attr_policy),
9bb7e0f2
JB
347 [NL80211_PMSR_PEER_ATTR_RESP] = { .type = NLA_REJECT },
348};
349
350static const struct nla_policy
351nl80211_pmsr_attr_policy[NL80211_PMSR_ATTR_MAX + 1] = {
352 [NL80211_PMSR_ATTR_MAX_PEERS] = { .type = NLA_REJECT },
353 [NL80211_PMSR_ATTR_REPORT_AP_TSF] = { .type = NLA_REJECT },
354 [NL80211_PMSR_ATTR_RANDOMIZE_MAC_ADDR] = { .type = NLA_REJECT },
355 [NL80211_PMSR_ATTR_TYPE_CAPA] = { .type = NLA_REJECT },
356 [NL80211_PMSR_ATTR_PEERS] =
aeddc05f 357 NLA_POLICY_NESTED_ARRAY(nl80211_pmsr_peer_attr_policy),
9bb7e0f2
JB
358};
359
796e90f4
JC
360static const struct nla_policy
361he_obss_pd_policy[NL80211_HE_OBSS_PD_ATTR_MAX + 1] = {
362 [NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET] =
363 NLA_POLICY_RANGE(NLA_U8, 1, 20),
364 [NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET] =
365 NLA_POLICY_RANGE(NLA_U8, 1, 20),
f5bec330
RM
366 [NL80211_HE_OBSS_PD_ATTR_NON_SRG_MAX_OFFSET] =
367 NLA_POLICY_RANGE(NLA_U8, 1, 20),
368 [NL80211_HE_OBSS_PD_ATTR_BSS_COLOR_BITMAP] =
369 NLA_POLICY_EXACT_LEN(8),
370 [NL80211_HE_OBSS_PD_ATTR_PARTIAL_BSSID_BITMAP] =
371 NLA_POLICY_EXACT_LEN(8),
372 [NL80211_HE_OBSS_PD_ATTR_SR_CTRL] = { .type = NLA_U8 },
796e90f4
JC
373};
374
5c5e52d1
JC
375static const struct nla_policy
376he_bss_color_policy[NL80211_HE_BSS_COLOR_ATTR_MAX + 1] = {
377 [NL80211_HE_BSS_COLOR_ATTR_COLOR] = NLA_POLICY_RANGE(NLA_U8, 1, 63),
378 [NL80211_HE_BSS_COLOR_ATTR_DISABLED] = { .type = NLA_FLAG },
379 [NL80211_HE_BSS_COLOR_ATTR_PARTIAL] = { .type = NLA_FLAG },
380};
381
9a5f6488
TC
382static const struct nla_policy nl80211_txattr_policy[NL80211_TXRATE_MAX + 1] = {
383 [NL80211_TXRATE_LEGACY] = { .type = NLA_BINARY,
384 .len = NL80211_MAX_SUPP_RATES },
385 [NL80211_TXRATE_HT] = { .type = NLA_BINARY,
386 .len = NL80211_MAX_SUPP_HT_RATES },
387 [NL80211_TXRATE_VHT] = NLA_POLICY_EXACT_LEN_WARN(sizeof(struct nl80211_txrate_vht)),
388 [NL80211_TXRATE_GI] = { .type = NLA_U8 },
eb89a6a6
MH
389 [NL80211_TXRATE_HE] = NLA_POLICY_EXACT_LEN(sizeof(struct nl80211_txrate_he)),
390 [NL80211_TXRATE_HE_GI] = NLA_POLICY_RANGE(NLA_U8,
391 NL80211_RATE_INFO_HE_GI_0_8,
392 NL80211_RATE_INFO_HE_GI_3_2),
393 [NL80211_TXRATE_HE_LTF] = NLA_POLICY_RANGE(NLA_U8,
394 NL80211_RATE_INFO_HE_1XLTF,
395 NL80211_RATE_INFO_HE_4XLTF),
9a5f6488
TC
396};
397
77f576de
T
398static const struct nla_policy
399nl80211_tid_config_attr_policy[NL80211_TID_CONFIG_ATTR_MAX + 1] = {
3710a8a6
JB
400 [NL80211_TID_CONFIG_ATTR_VIF_SUPP] = { .type = NLA_U64 },
401 [NL80211_TID_CONFIG_ATTR_PEER_SUPP] = { .type = NLA_U64 },
77f576de 402 [NL80211_TID_CONFIG_ATTR_OVERRIDE] = { .type = NLA_FLAG },
3710a8a6 403 [NL80211_TID_CONFIG_ATTR_TIDS] = NLA_POLICY_RANGE(NLA_U16, 1, 0xff),
77f576de
T
404 [NL80211_TID_CONFIG_ATTR_NOACK] =
405 NLA_POLICY_MAX(NLA_U8, NL80211_TID_CONFIG_DISABLE),
6a21d16c
T
406 [NL80211_TID_CONFIG_ATTR_RETRY_SHORT] = NLA_POLICY_MIN(NLA_U8, 1),
407 [NL80211_TID_CONFIG_ATTR_RETRY_LONG] = NLA_POLICY_MIN(NLA_U8, 1),
ade274b2
T
408 [NL80211_TID_CONFIG_ATTR_AMPDU_CTRL] =
409 NLA_POLICY_MAX(NLA_U8, NL80211_TID_CONFIG_DISABLE),
04f7d142
T
410 [NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL] =
411 NLA_POLICY_MAX(NLA_U8, NL80211_TID_CONFIG_DISABLE),
33462e68
SM
412 [NL80211_TID_CONFIG_ATTR_AMSDU_CTRL] =
413 NLA_POLICY_MAX(NLA_U8, NL80211_TID_CONFIG_DISABLE),
9a5f6488
TC
414 [NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE] =
415 NLA_POLICY_MAX(NLA_U8, NL80211_TX_RATE_FIXED),
416 [NL80211_TID_CONFIG_ATTR_TX_RATE] =
417 NLA_POLICY_NESTED(nl80211_txattr_policy),
77f576de
T
418};
419
291c49de
AD
420static const struct nla_policy
421nl80211_fils_discovery_policy[NL80211_FILS_DISCOVERY_ATTR_MAX + 1] = {
422 [NL80211_FILS_DISCOVERY_ATTR_INT_MIN] = NLA_POLICY_MAX(NLA_U32, 10000),
423 [NL80211_FILS_DISCOVERY_ATTR_INT_MAX] = NLA_POLICY_MAX(NLA_U32, 10000),
272cd0e8
AD
424 [NL80211_FILS_DISCOVERY_ATTR_TMPL] =
425 NLA_POLICY_RANGE(NLA_BINARY,
426 NL80211_FILS_DISCOVERY_TMPL_MIN_LEN,
427 IEEE80211_MAX_DATA_LEN),
291c49de
AD
428};
429
7443dcd1
AD
430static const struct nla_policy
431nl80211_unsol_bcast_probe_resp_policy[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_MAX + 1] = {
432 [NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INT] = NLA_POLICY_MAX(NLA_U32, 20),
433 [NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL] = { .type = NLA_BINARY,
434 .len = IEEE80211_MAX_DATA_LEN }
435};
436
6bdb68ce
CH
437static const struct nla_policy
438sar_specs_policy[NL80211_SAR_ATTR_SPECS_MAX + 1] = {
439 [NL80211_SAR_ATTR_SPECS_POWER] = { .type = NLA_S32 },
440 [NL80211_SAR_ATTR_SPECS_RANGE_INDEX] = {.type = NLA_U32 },
441};
442
443static const struct nla_policy
444sar_policy[NL80211_SAR_ATTR_MAX + 1] = {
445 [NL80211_SAR_ATTR_TYPE] = NLA_POLICY_MAX(NLA_U32, NUM_NL80211_SAR_TYPE),
446 [NL80211_SAR_ATTR_SPECS] = NLA_POLICY_NESTED_ARRAY(sar_specs_policy),
447};
448
dc1e3cb8
JC
449static const struct nla_policy
450nl80211_mbssid_config_policy[NL80211_MBSSID_CONFIG_ATTR_MAX + 1] = {
451 [NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES] = NLA_POLICY_MIN(NLA_U8, 2),
452 [NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY] =
453 NLA_POLICY_MIN(NLA_U8, 1),
454 [NL80211_MBSSID_CONFIG_ATTR_INDEX] = { .type = NLA_U8 },
455 [NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX] = { .type = NLA_U32 },
456 [NL80211_MBSSID_CONFIG_ATTR_EMA] = { .type = NLA_FLAG },
457};
458
ff5c4dc4
JB
459static const struct nla_policy
460nl80211_sta_wme_policy[NL80211_STA_WME_MAX + 1] = {
461 [NL80211_STA_WME_UAPSD_QUEUES] = { .type = NLA_U8 },
462 [NL80211_STA_WME_MAX_SP] = { .type = NLA_U8 },
463};
464
b27f07c5
JB
465static struct netlink_range_validation nl80211_punct_bitmap_range = {
466 .min = 0,
467 .max = 0xffff,
468};
469
d15da2a2 470static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
6d4dd4ef 471 [0] = { .strict_start_type = NL80211_ATTR_HE_OBSS_PD },
55682965
JB
472 [NL80211_ATTR_WIPHY] = { .type = NLA_U32 },
473 [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING,
079e24ed 474 .len = 20-1 },
31888487 475 [NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED },
3d9d1d66 476
72bdcf34 477 [NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 },
094d05dc 478 [NL80211_ATTR_WIPHY_CHANNEL_TYPE] = { .type = NLA_U32 },
2a38075c
AAL
479 [NL80211_ATTR_WIPHY_EDMG_CHANNELS] = NLA_POLICY_RANGE(NLA_U8,
480 NL80211_EDMG_CHANNELS_MIN,
481 NL80211_EDMG_CHANNELS_MAX),
482 [NL80211_ATTR_WIPHY_EDMG_BW_CONFIG] = NLA_POLICY_RANGE(NLA_U8,
483 NL80211_EDMG_BW_CONFIG_MIN,
484 NL80211_EDMG_BW_CONFIG_MAX),
485
3d9d1d66
JB
486 [NL80211_ATTR_CHANNEL_WIDTH] = { .type = NLA_U32 },
487 [NL80211_ATTR_CENTER_FREQ1] = { .type = NLA_U32 },
942ba88b 488 [NL80211_ATTR_CENTER_FREQ1_OFFSET] = NLA_POLICY_RANGE(NLA_U32, 0, 999),
3d9d1d66
JB
489 [NL80211_ATTR_CENTER_FREQ2] = { .type = NLA_U32 },
490
ab0d76f6
JB
491 [NL80211_ATTR_WIPHY_RETRY_SHORT] = NLA_POLICY_MIN(NLA_U8, 1),
492 [NL80211_ATTR_WIPHY_RETRY_LONG] = NLA_POLICY_MIN(NLA_U8, 1),
b9a5f8ca
JM
493 [NL80211_ATTR_WIPHY_FRAG_THRESHOLD] = { .type = NLA_U32 },
494 [NL80211_ATTR_WIPHY_RTS_THRESHOLD] = { .type = NLA_U32 },
81077e82 495 [NL80211_ATTR_WIPHY_COVERAGE_CLASS] = { .type = NLA_U8 },
3057dbfd 496 [NL80211_ATTR_WIPHY_DYN_ACK] = { .type = NLA_FLAG },
55682965 497
ab0d76f6 498 [NL80211_ATTR_IFTYPE] = NLA_POLICY_MAX(NLA_U32, NL80211_IFTYPE_MAX),
55682965
JB
499 [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 },
500 [NL80211_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 },
41ade00f 501
c7721c05
JB
502 [NL80211_ATTR_MAC] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
503 [NL80211_ATTR_PREV_BSSID] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
41ade00f 504
b9454e83 505 [NL80211_ATTR_KEY] = { .type = NLA_NESTED, },
41ade00f
JB
506 [NL80211_ATTR_KEY_DATA] = { .type = NLA_BINARY,
507 .len = WLAN_MAX_KEY_LEN },
56be393f 508 [NL80211_ATTR_KEY_IDX] = NLA_POLICY_MAX(NLA_U8, 7),
41ade00f
JB
509 [NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 },
510 [NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG },
81962267 511 [NL80211_ATTR_KEY_SEQ] = { .type = NLA_BINARY, .len = 16 },
ab0d76f6
JB
512 [NL80211_ATTR_KEY_TYPE] =
513 NLA_POLICY_MAX(NLA_U32, NUM_NL80211_KEYTYPES),
ed1b6cc7
JB
514
515 [NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 },
516 [NL80211_ATTR_DTIM_PERIOD] = { .type = NLA_U32 },
f88eb7c0
JB
517 [NL80211_ATTR_BEACON_HEAD] =
518 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_beacon_head,
519 IEEE80211_MAX_DATA_LEN),
3d7af878
JB
520 [NL80211_ATTR_BEACON_TAIL] =
521 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr,
522 IEEE80211_MAX_DATA_LEN),
ab0d76f6
JB
523 [NL80211_ATTR_STA_AID] =
524 NLA_POLICY_RANGE(NLA_U16, 1, IEEE80211_MAX_AID),
5727ef1b
JB
525 [NL80211_ATTR_STA_FLAGS] = { .type = NLA_NESTED },
526 [NL80211_ATTR_STA_LISTEN_INTERVAL] = { .type = NLA_U16 },
527 [NL80211_ATTR_STA_SUPPORTED_RATES] = { .type = NLA_BINARY,
528 .len = NL80211_MAX_SUPP_RATES },
ab0d76f6
JB
529 [NL80211_ATTR_STA_PLINK_ACTION] =
530 NLA_POLICY_MAX(NLA_U8, NUM_NL80211_PLINK_ACTIONS - 1),
e96d1cd2
ARN
531 [NL80211_ATTR_STA_TX_POWER_SETTING] =
532 NLA_POLICY_RANGE(NLA_U8,
533 NL80211_TX_POWER_AUTOMATIC,
534 NL80211_TX_POWER_FIXED),
535 [NL80211_ATTR_STA_TX_POWER] = { .type = NLA_S16 },
5727ef1b 536 [NL80211_ATTR_STA_VLAN] = { .type = NLA_U32 },
0a9542ee 537 [NL80211_ATTR_MNTR_FLAGS] = { /* NLA_NESTED can't be empty */ },
2ec600d6 538 [NL80211_ATTR_MESH_ID] = { .type = NLA_BINARY,
a4f606ea 539 .len = IEEE80211_MAX_MESH_ID_LEN },
1fab1b89 540 [NL80211_ATTR_MPATH_NEXT_HOP] = NLA_POLICY_ETH_ADDR_COMPAT,
9f1ba906 541
6624bb34
JB
542 /* allow 3 for NUL-termination, we used to declare this NLA_STRING */
543 [NL80211_ATTR_REG_ALPHA2] = NLA_POLICY_RANGE(NLA_BINARY, 2, 3),
b2e1b302
LR
544 [NL80211_ATTR_REG_RULES] = { .type = NLA_NESTED },
545
9f1ba906
JM
546 [NL80211_ATTR_BSS_CTS_PROT] = { .type = NLA_U8 },
547 [NL80211_ATTR_BSS_SHORT_PREAMBLE] = { .type = NLA_U8 },
548 [NL80211_ATTR_BSS_SHORT_SLOT_TIME] = { .type = NLA_U8 },
90c97a04
JM
549 [NL80211_ATTR_BSS_BASIC_RATES] = { .type = NLA_BINARY,
550 .len = NL80211_MAX_SUPP_RATES },
50b12f59 551 [NL80211_ATTR_BSS_HT_OPMODE] = { .type = NLA_U16 },
36aedc90 552
24bdd9f4 553 [NL80211_ATTR_MESH_CONFIG] = { .type = NLA_NESTED },
15d5dda6 554 [NL80211_ATTR_SUPPORT_MESH_AUTH] = { .type = NLA_FLAG },
93da9cc1 555
c7721c05 556 [NL80211_ATTR_HT_CAPABILITY] = NLA_POLICY_EXACT_LEN_WARN(NL80211_HT_CAPABILITY_LEN),
9aed3cc1
JM
557
558 [NL80211_ATTR_MGMT_SUBTYPE] = { .type = NLA_U8 },
3d7af878
JB
559 [NL80211_ATTR_IE] = NLA_POLICY_VALIDATE_FN(NLA_BINARY,
560 validate_ie_attr,
561 IEEE80211_MAX_DATA_LEN),
2a519311
JB
562 [NL80211_ATTR_SCAN_FREQUENCIES] = { .type = NLA_NESTED },
563 [NL80211_ATTR_SCAN_SSIDS] = { .type = NLA_NESTED },
636a5d36
JM
564
565 [NL80211_ATTR_SSID] = { .type = NLA_BINARY,
566 .len = IEEE80211_MAX_SSID_LEN },
567 [NL80211_ATTR_AUTH_TYPE] = { .type = NLA_U32 },
568 [NL80211_ATTR_REASON_CODE] = { .type = NLA_U16 },
04a773ad 569 [NL80211_ATTR_FREQ_FIXED] = { .type = NLA_FLAG },
1965c853 570 [NL80211_ATTR_TIMED_OUT] = { .type = NLA_FLAG },
ab0d76f6
JB
571 [NL80211_ATTR_USE_MFP] = NLA_POLICY_RANGE(NLA_U32,
572 NL80211_MFP_NO,
573 NL80211_MFP_OPTIONAL),
ff5c4dc4
JB
574 [NL80211_ATTR_STA_FLAGS2] =
575 NLA_POLICY_EXACT_LEN_WARN(sizeof(struct nl80211_sta_flag_update)),
3f77316c 576 [NL80211_ATTR_CONTROL_PORT] = { .type = NLA_FLAG },
c0692b8f
JB
577 [NL80211_ATTR_CONTROL_PORT_ETHERTYPE] = { .type = NLA_U16 },
578 [NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT] = { .type = NLA_FLAG },
64bf3d4b 579 [NL80211_ATTR_CONTROL_PORT_OVER_NL80211] = { .type = NLA_FLAG },
b23aa676 580 [NL80211_ATTR_PRIVACY] = { .type = NLA_FLAG },
ea750801 581 [NL80211_ATTR_STATUS_CODE] = { .type = NLA_U16 },
b23aa676
SO
582 [NL80211_ATTR_CIPHER_SUITE_GROUP] = { .type = NLA_U32 },
583 [NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 },
463d0183 584 [NL80211_ATTR_PID] = { .type = NLA_U32 },
8b787643 585 [NL80211_ATTR_4ADDR] = { .type = NLA_U8 },
c7721c05 586 [NL80211_ATTR_PMKID] = NLA_POLICY_EXACT_LEN_WARN(WLAN_PMKID_LEN),
9588bbd5
JM
587 [NL80211_ATTR_DURATION] = { .type = NLA_U32 },
588 [NL80211_ATTR_COOKIE] = { .type = NLA_U64 },
13ae75b1 589 [NL80211_ATTR_TX_RATES] = { .type = NLA_NESTED },
026331c4
JM
590 [NL80211_ATTR_FRAME] = { .type = NLA_BINARY,
591 .len = IEEE80211_MAX_DATA_LEN },
592 [NL80211_ATTR_FRAME_MATCH] = { .type = NLA_BINARY, },
ab0d76f6
JB
593 [NL80211_ATTR_PS_STATE] = NLA_POLICY_RANGE(NLA_U32,
594 NL80211_PS_DISABLED,
595 NL80211_PS_ENABLED),
d6dc1a38 596 [NL80211_ATTR_CQM] = { .type = NLA_NESTED, },
d5cdfacb 597 [NL80211_ATTR_LOCAL_STATE_CHANGE] = { .type = NLA_FLAG },
fd8aaaf3 598 [NL80211_ATTR_AP_ISOLATE] = { .type = NLA_U8 },
98d2ff8b
JO
599 [NL80211_ATTR_WIPHY_TX_POWER_SETTING] = { .type = NLA_U32 },
600 [NL80211_ATTR_WIPHY_TX_POWER_LEVEL] = { .type = NLA_U32 },
2e161f78 601 [NL80211_ATTR_FRAME_TYPE] = { .type = NLA_U16 },
afe0cbf8
BR
602 [NL80211_ATTR_WIPHY_ANTENNA_TX] = { .type = NLA_U32 },
603 [NL80211_ATTR_WIPHY_ANTENNA_RX] = { .type = NLA_U32 },
885a46d0 604 [NL80211_ATTR_MCAST_RATE] = { .type = NLA_U32 },
f7ca38df 605 [NL80211_ATTR_OFFCHANNEL_TX_OK] = { .type = NLA_FLAG },
dbd2fd65 606 [NL80211_ATTR_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED },
ff1b6e69 607 [NL80211_ATTR_WOWLAN_TRIGGERS] = { .type = NLA_NESTED },
ab0d76f6
JB
608 [NL80211_ATTR_STA_PLINK_STATE] =
609 NLA_POLICY_MAX(NLA_U8, NUM_NL80211_PLINK_STATES - 1),
056e9375
JK
610 [NL80211_ATTR_MEASUREMENT_DURATION] = { .type = NLA_U16 },
611 [NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY] = { .type = NLA_FLAG },
ab0d76f6
JB
612 [NL80211_ATTR_MESH_PEER_AID] =
613 NLA_POLICY_RANGE(NLA_U16, 1, IEEE80211_MAX_AID),
bbe6ad6d 614 [NL80211_ATTR_SCHED_SCAN_INTERVAL] = { .type = NLA_U32 },
e5497d76 615 [NL80211_ATTR_REKEY_DATA] = { .type = NLA_NESTED },
34850ab2 616 [NL80211_ATTR_SCAN_SUPP_RATES] = { .type = NLA_NESTED },
ab0d76f6
JB
617 [NL80211_ATTR_HIDDEN_SSID] =
618 NLA_POLICY_RANGE(NLA_U32,
619 NL80211_HIDDEN_SSID_NOT_IN_USE,
620 NL80211_HIDDEN_SSID_ZERO_CONTENTS),
3d7af878
JB
621 [NL80211_ATTR_IE_PROBE_RESP] =
622 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr,
623 IEEE80211_MAX_DATA_LEN),
624 [NL80211_ATTR_IE_ASSOC_RESP] =
625 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr,
626 IEEE80211_MAX_DATA_LEN),
f4b34b55 627 [NL80211_ATTR_ROAM_SUPPORT] = { .type = NLA_FLAG },
ff5c4dc4 628 [NL80211_ATTR_STA_WME] = NLA_POLICY_NESTED(nl80211_sta_wme_policy),
a1f1c21c 629 [NL80211_ATTR_SCHED_SCAN_MATCH] = { .type = NLA_NESTED },
e9f935e3 630 [NL80211_ATTR_TX_NO_CCK_RATE] = { .type = NLA_FLAG },
109086ce
AN
631 [NL80211_ATTR_TDLS_ACTION] = { .type = NLA_U8 },
632 [NL80211_ATTR_TDLS_DIALOG_TOKEN] = { .type = NLA_U8 },
633 [NL80211_ATTR_TDLS_OPERATION] = { .type = NLA_U8 },
634 [NL80211_ATTR_TDLS_SUPPORT] = { .type = NLA_FLAG },
635 [NL80211_ATTR_TDLS_EXTERNAL_SETUP] = { .type = NLA_FLAG },
31fa97c5 636 [NL80211_ATTR_TDLS_INITIATOR] = { .type = NLA_FLAG },
e247bd90 637 [NL80211_ATTR_DONT_WAIT_FOR_ACK] = { .type = NLA_FLAG },
00f740e1
AN
638 [NL80211_ATTR_PROBE_RESP] = { .type = NLA_BINARY,
639 .len = IEEE80211_MAX_DATA_LEN },
8b60b078 640 [NL80211_ATTR_DFS_REGION] = { .type = NLA_U8 },
7e7c8926
BG
641 [NL80211_ATTR_DISABLE_HT] = { .type = NLA_FLAG },
642 [NL80211_ATTR_HT_CAPABILITY_MASK] = {
643 .len = NL80211_HT_CAPABILITY_LEN
644 },
1d9d9213 645 [NL80211_ATTR_NOACK_MAP] = { .type = NLA_U16 },
1b658f11 646 [NL80211_ATTR_INACTIVITY_TIMEOUT] = { .type = NLA_U16 },
4486ea98 647 [NL80211_ATTR_BG_SCAN_PERIOD] = { .type = NLA_U16 },
89a54e48 648 [NL80211_ATTR_WDEV] = { .type = NLA_U64 },
57b5ce07 649 [NL80211_ATTR_USER_REG_HINT_TYPE] = { .type = NLA_U32 },
cb9abd48
JB
650
651 /* need to include at least Auth Transaction and Status Code */
652 [NL80211_ATTR_AUTH_DATA] = NLA_POLICY_MIN_LEN(4),
653
c7721c05 654 [NL80211_ATTR_VHT_CAPABILITY] = NLA_POLICY_EXACT_LEN_WARN(NL80211_VHT_CAPABILITY_LEN),
ed473771 655 [NL80211_ATTR_SCAN_FLAGS] = { .type = NLA_U32 },
ab0d76f6
JB
656 [NL80211_ATTR_P2P_CTWINDOW] = NLA_POLICY_MAX(NLA_U8, 127),
657 [NL80211_ATTR_P2P_OPPPS] = NLA_POLICY_MAX(NLA_U8, 1),
658 [NL80211_ATTR_LOCAL_MESH_POWER_MODE] =
659 NLA_POLICY_RANGE(NLA_U32,
660 NL80211_MESH_POWER_UNKNOWN + 1,
661 NL80211_MESH_POWER_MAX),
77765eaf
VT
662 [NL80211_ATTR_ACL_POLICY] = {. type = NLA_U32 },
663 [NL80211_ATTR_MAC_ADDRS] = { .type = NLA_NESTED },
9d62a986
JM
664 [NL80211_ATTR_STA_CAPABILITY] = { .type = NLA_U16 },
665 [NL80211_ATTR_STA_EXT_CAPABILITY] = { .type = NLA_BINARY, },
3713b4e3 666 [NL80211_ATTR_SPLIT_WIPHY_DUMP] = { .type = NLA_FLAG, },
ee2aca34
JB
667 [NL80211_ATTR_DISABLE_VHT] = { .type = NLA_FLAG },
668 [NL80211_ATTR_VHT_CAPABILITY_MASK] = {
669 .len = NL80211_VHT_CAPABILITY_LEN,
670 },
355199e0
JM
671 [NL80211_ATTR_MDID] = { .type = NLA_U16 },
672 [NL80211_ATTR_IE_RIC] = { .type = NLA_BINARY,
673 .len = IEEE80211_MAX_DATA_LEN },
0e1a1d85 674 [NL80211_ATTR_CRIT_PROT_ID] = { .type = NLA_U16 },
cb9abd48
JB
675 [NL80211_ATTR_MAX_CRIT_PROT_DURATION] =
676 NLA_POLICY_MAX(NLA_U16, NL80211_CRIT_PROTO_MAX_DURATION),
ab0d76f6
JB
677 [NL80211_ATTR_PEER_AID] =
678 NLA_POLICY_RANGE(NLA_U16, 1, IEEE80211_MAX_AID),
16ef1fe2
SW
679 [NL80211_ATTR_CH_SWITCH_COUNT] = { .type = NLA_U32 },
680 [NL80211_ATTR_CH_SWITCH_BLOCK_TX] = { .type = NLA_FLAG },
681 [NL80211_ATTR_CSA_IES] = { .type = NLA_NESTED },
00c207ed
JC
682 [NL80211_ATTR_CNTDWN_OFFS_BEACON] = { .type = NLA_BINARY },
683 [NL80211_ATTR_CNTDWN_OFFS_PRESP] = { .type = NLA_BINARY },
cb9abd48 684 [NL80211_ATTR_STA_SUPPORTED_CHANNELS] = NLA_POLICY_MIN_LEN(2),
c8b82802
JB
685 /*
686 * The value of the Length field of the Supported Operating
687 * Classes element is between 2 and 253.
688 */
689 [NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES] =
690 NLA_POLICY_RANGE(NLA_BINARY, 2, 253),
5336fa88 691 [NL80211_ATTR_HANDLE_DFS] = { .type = NLA_FLAG },
60f4a7b1 692 [NL80211_ATTR_OPMODE_NOTIF] = { .type = NLA_U8 },
ad7e718c
JB
693 [NL80211_ATTR_VENDOR_ID] = { .type = NLA_U32 },
694 [NL80211_ATTR_VENDOR_SUBCMD] = { .type = NLA_U32 },
695 [NL80211_ATTR_VENDOR_DATA] = { .type = NLA_BINARY },
c8b82802
JB
696 [NL80211_ATTR_QOS_MAP] = NLA_POLICY_RANGE(NLA_BINARY,
697 IEEE80211_QOS_MAP_LEN_MIN,
698 IEEE80211_QOS_MAP_LEN_MAX),
c7721c05 699 [NL80211_ATTR_MAC_HINT] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
1df4a510 700 [NL80211_ATTR_WIPHY_FREQ_HINT] = { .type = NLA_U32 },
df942e7b 701 [NL80211_ATTR_TDLS_PEER_CAPABILITY] = { .type = NLA_U32 },
18e5ca65 702 [NL80211_ATTR_SOCKET_OWNER] = { .type = NLA_FLAG },
34d22ce2 703 [NL80211_ATTR_CSA_C_OFFSETS_TX] = { .type = NLA_BINARY },
bab5ab7d 704 [NL80211_ATTR_USE_RRM] = { .type = NLA_FLAG },
ab0d76f6
JB
705 [NL80211_ATTR_TSID] = NLA_POLICY_MAX(NLA_U8, IEEE80211_NUM_TIDS - 1),
706 [NL80211_ATTR_USER_PRIO] =
707 NLA_POLICY_MAX(NLA_U8, IEEE80211_NUM_UPS - 1),
960d01ac 708 [NL80211_ATTR_ADMITTED_TIME] = { .type = NLA_U16 },
18998c38 709 [NL80211_ATTR_SMPS_MODE] = { .type = NLA_U8 },
5cde05c6 710 [NL80211_ATTR_OPER_CLASS] = { .type = NLA_U8 },
c7721c05 711 [NL80211_ATTR_MAC_MASK] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
1bdd716c 712 [NL80211_ATTR_WIPHY_SELF_MANAGED_REG] = { .type = NLA_FLAG },
4b681c82 713 [NL80211_ATTR_NETNS_FD] = { .type = NLA_U32 },
9c748934 714 [NL80211_ATTR_SCHED_SCAN_DELAY] = { .type = NLA_U32 },
05050753 715 [NL80211_ATTR_REG_INDOOR] = { .type = NLA_FLAG },
34d50519 716 [NL80211_ATTR_PBSS] = { .type = NLA_FLAG },
38de03d2 717 [NL80211_ATTR_BSS_SELECT] = { .type = NLA_NESTED },
ab0d76f6
JB
718 [NL80211_ATTR_STA_SUPPORT_P2P_PS] =
719 NLA_POLICY_MAX(NLA_U8, NUM_NL80211_P2P_PS_STATUS - 1),
c6e6a0c8
AE
720 [NL80211_ATTR_MU_MIMO_GROUP_DATA] = {
721 .len = VHT_MUMIMO_GROUPS_DATA_LEN
722 },
c7721c05 723 [NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
ab0d76f6 724 [NL80211_ATTR_NAN_MASTER_PREF] = NLA_POLICY_MIN(NLA_U8, 1),
8585989d 725 [NL80211_ATTR_BANDS] = { .type = NLA_U32 },
a442b761 726 [NL80211_ATTR_NAN_FUNC] = { .type = NLA_NESTED },
348bd456
JM
727 [NL80211_ATTR_FILS_KEK] = { .type = NLA_BINARY,
728 .len = FILS_MAX_KEK_LEN },
c7721c05 729 [NL80211_ATTR_FILS_NONCES] = NLA_POLICY_EXACT_LEN_WARN(2 * FILS_NONCE_LEN),
ce0ce13a 730 [NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED] = { .type = NLA_FLAG, },
c7721c05 731 [NL80211_ATTR_BSSID] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
bf95ecdb 732 [NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI] = { .type = NLA_S8 },
733 [NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST] = {
734 .len = sizeof(struct nl80211_bss_select_rssi_adjust)
735 },
3093ebbe 736 [NL80211_ATTR_TIMEOUT_REASON] = { .type = NLA_U32 },
a3caf744
VK
737 [NL80211_ATTR_FILS_ERP_USERNAME] = { .type = NLA_BINARY,
738 .len = FILS_ERP_MAX_USERNAME_LEN },
739 [NL80211_ATTR_FILS_ERP_REALM] = { .type = NLA_BINARY,
740 .len = FILS_ERP_MAX_REALM_LEN },
741 [NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] = { .type = NLA_U16 },
742 [NL80211_ATTR_FILS_ERP_RRK] = { .type = NLA_BINARY,
743 .len = FILS_ERP_MAX_RRK_LEN },
c7721c05 744 [NL80211_ATTR_FILS_CACHE_ID] = NLA_POLICY_EXACT_LEN_WARN(2),
a3caf744 745 [NL80211_ATTR_PMK] = { .type = NLA_BINARY, .len = PMK_MAX_LEN },
cb9abd48 746 [NL80211_ATTR_PMKR0_NAME] = NLA_POLICY_EXACT_LEN(WLAN_PMK_NAME_LEN),
ca986ad9 747 [NL80211_ATTR_SCHED_SCAN_MULTI] = { .type = NLA_FLAG },
40cbfa90 748 [NL80211_ATTR_EXTERNAL_AUTH_SUPPORT] = { .type = NLA_FLAG },
52539ca8
THJ
749
750 [NL80211_ATTR_TXQ_LIMIT] = { .type = NLA_U32 },
751 [NL80211_ATTR_TXQ_MEMORY_LIMIT] = { .type = NLA_U32 },
752 [NL80211_ATTR_TXQ_QUANTUM] = { .type = NLA_U32 },
c8b82802 753 [NL80211_ATTR_HE_CAPABILITY] =
a3a20feb
JB
754 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_he_capa,
755 NL80211_HE_MAX_CAPABILITY_LEN),
0e012b4e
JB
756 [NL80211_ATTR_FTM_RESPONDER] =
757 NLA_POLICY_NESTED(nl80211_ftm_responder_policy),
9bb7e0f2
JB
758 [NL80211_ATTR_TIMEOUT] = NLA_POLICY_MIN(NLA_U32, 1),
759 [NL80211_ATTR_PEER_MEASUREMENTS] =
23323289 760 NLA_POLICY_NESTED(nl80211_pmsr_attr_policy),
36647055 761 [NL80211_ATTR_AIRTIME_WEIGHT] = NLA_POLICY_MIN(NLA_U16, 1),
26f7044e
CHH
762 [NL80211_ATTR_SAE_PASSWORD] = { .type = NLA_BINARY,
763 .len = SAE_PASSWORD_MAX_LEN },
a0de1ca3 764 [NL80211_ATTR_TWT_RESPONDER] = { .type = NLA_FLAG },
796e90f4 765 [NL80211_ATTR_HE_OBSS_PD] = NLA_POLICY_NESTED(he_obss_pd_policy),
14f34e36 766 [NL80211_ATTR_VLAN_ID] = NLA_POLICY_RANGE(NLA_U16, 1, VLAN_N_VID - 2),
5c5e52d1 767 [NL80211_ATTR_HE_BSS_COLOR] = NLA_POLICY_NESTED(he_bss_color_policy),
77f576de
T
768 [NL80211_ATTR_TID_CONFIG] =
769 NLA_POLICY_NESTED_ARRAY(nl80211_tid_config_attr_policy),
5631d96a 770 [NL80211_ATTR_CONTROL_PORT_NO_PREAUTH] = { .type = NLA_FLAG },
7fc82af8
VJ
771 [NL80211_ATTR_PMK_LIFETIME] = NLA_POLICY_MIN(NLA_U32, 1),
772 [NL80211_ATTR_PMK_REAUTH_THRESHOLD] = NLA_POLICY_RANGE(NLA_U8, 1, 100),
9dba48a6 773 [NL80211_ATTR_RECEIVE_MULTICAST] = { .type = NLA_FLAG },
942ba88b 774 [NL80211_ATTR_WIPHY_FREQ_OFFSET] = NLA_POLICY_RANGE(NLA_U32, 0, 999),
2032f3b2 775 [NL80211_ATTR_SCAN_FREQ_KHZ] = { .type = NLA_NESTED },
8140860c
JB
776 [NL80211_ATTR_HE_6GHZ_CAPABILITY] =
777 NLA_POLICY_EXACT_LEN(sizeof(struct ieee80211_he_6ghz_capa)),
291c49de
AD
778 [NL80211_ATTR_FILS_DISCOVERY] =
779 NLA_POLICY_NESTED(nl80211_fils_discovery_policy),
7443dcd1
AD
780 [NL80211_ATTR_UNSOL_BCAST_PROBE_RESP] =
781 NLA_POLICY_NESTED(nl80211_unsol_bcast_probe_resp_policy),
d2b7588a
TP
782 [NL80211_ATTR_S1G_CAPABILITY] =
783 NLA_POLICY_EXACT_LEN(IEEE80211_S1G_CAPABILITY_LEN),
784 [NL80211_ATTR_S1G_CAPABILITY_MASK] =
785 NLA_POLICY_EXACT_LEN(IEEE80211_S1G_CAPABILITY_LEN),
9f0ffa41
RD
786 [NL80211_ATTR_SAE_PWE] =
787 NLA_POLICY_RANGE(NLA_U8, NL80211_SAE_PWE_HUNT_AND_PECK,
788 NL80211_SAE_PWE_BOTH),
3bb02143 789 [NL80211_ATTR_RECONNECT_REQUESTED] = { .type = NLA_REJECT },
6bdb68ce 790 [NL80211_ATTR_SAR_SPEC] = NLA_POLICY_NESTED(sar_policy),
b6db0f89 791 [NL80211_ATTR_DISABLE_HE] = { .type = NLA_FLAG },
0d2ab3ae
JC
792 [NL80211_ATTR_OBSS_COLOR_BITMAP] = { .type = NLA_U64 },
793 [NL80211_ATTR_COLOR_CHANGE_COUNT] = { .type = NLA_U8 },
794 [NL80211_ATTR_COLOR_CHANGE_COLOR] = { .type = NLA_U8 },
795 [NL80211_ATTR_COLOR_CHANGE_ELEMS] = NLA_POLICY_NESTED(nl80211_policy),
dc1e3cb8
JC
796 [NL80211_ATTR_MBSSID_CONFIG] =
797 NLA_POLICY_NESTED(nl80211_mbssid_config_policy),
798 [NL80211_ATTR_MBSSID_ELEMS] = { .type = NLA_NESTED },
a95bfb87 799 [NL80211_ATTR_RADAR_BACKGROUND] = { .type = NLA_FLAG },
47301a74 800 [NL80211_ATTR_AP_SETTINGS_FLAGS] = { .type = NLA_U32 },
ea05fd35
IP
801 [NL80211_ATTR_EHT_CAPABILITY] =
802 NLA_POLICY_RANGE(NLA_BINARY,
803 NL80211_EHT_MIN_CAPABILITY_LEN,
804 NL80211_EHT_MAX_CAPABILITY_LEN),
36f84235 805 [NL80211_ATTR_DISABLE_EHT] = { .type = NLA_FLAG },
7b0a0e3c
JB
806 [NL80211_ATTR_MLO_LINKS] =
807 NLA_POLICY_NESTED_ARRAY(nl80211_policy),
808 [NL80211_ATTR_MLO_LINK_ID] =
809 NLA_POLICY_RANGE(NLA_U8, 0, IEEE80211_MLD_MAX_NUM_LINKS),
d648c230 810 [NL80211_ATTR_MLD_ADDR] = NLA_POLICY_EXACT_LEN(ETH_ALEN),
efbabc11 811 [NL80211_ATTR_MLO_SUPPORT] = { .type = NLA_FLAG },
ecad3b0b 812 [NL80211_ATTR_MAX_NUM_AKM_SUITES] = { .type = NLA_REJECT },
b27f07c5
JB
813 [NL80211_ATTR_PUNCT_BITMAP] =
814 NLA_POLICY_FULL_RANGE(NLA_U32, &nl80211_punct_bitmap_range),
cbbaf2bb
AS
815
816 [NL80211_ATTR_MAX_HW_TIMESTAMP_PEERS] = { .type = NLA_U16 },
817 [NL80211_ATTR_HW_TIMESTAMP_ENABLED] = { .type = NLA_FLAG },
dbbb27e1 818 [NL80211_ATTR_EMA_RNR_ELEMS] = { .type = NLA_NESTED },
6cf963ed 819 [NL80211_ATTR_MLO_LINK_DISABLED] = { .type = NLA_FLAG },
55682965
JB
820};
821
e31b8213 822/* policy for the key attributes */
b54452b0 823static const struct nla_policy nl80211_key_policy[NL80211_KEY_MAX + 1] = {
fffd0934 824 [NL80211_KEY_DATA] = { .type = NLA_BINARY, .len = WLAN_MAX_KEY_LEN },
b9454e83
JB
825 [NL80211_KEY_IDX] = { .type = NLA_U8 },
826 [NL80211_KEY_CIPHER] = { .type = NLA_U32 },
81962267 827 [NL80211_KEY_SEQ] = { .type = NLA_BINARY, .len = 16 },
b9454e83
JB
828 [NL80211_KEY_DEFAULT] = { .type = NLA_FLAG },
829 [NL80211_KEY_DEFAULT_MGMT] = { .type = NLA_FLAG },
ab0d76f6 830 [NL80211_KEY_TYPE] = NLA_POLICY_MAX(NLA_U32, NUM_NL80211_KEYTYPES - 1),
dbd2fd65 831 [NL80211_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED },
6cdd3979 832 [NL80211_KEY_MODE] = NLA_POLICY_RANGE(NLA_U8, 0, NL80211_KEY_SET_TX),
dbd2fd65
JB
833};
834
835/* policy for the key default flags */
836static const struct nla_policy
837nl80211_key_default_policy[NUM_NL80211_KEY_DEFAULT_TYPES] = {
838 [NL80211_KEY_DEFAULT_TYPE_UNICAST] = { .type = NLA_FLAG },
839 [NL80211_KEY_DEFAULT_TYPE_MULTICAST] = { .type = NLA_FLAG },
b9454e83
JB
840};
841
f83ace3b 842#ifdef CONFIG_PM
ff1b6e69
JB
843/* policy for WoWLAN attributes */
844static const struct nla_policy
845nl80211_wowlan_policy[NUM_NL80211_WOWLAN_TRIG] = {
846 [NL80211_WOWLAN_TRIG_ANY] = { .type = NLA_FLAG },
847 [NL80211_WOWLAN_TRIG_DISCONNECT] = { .type = NLA_FLAG },
848 [NL80211_WOWLAN_TRIG_MAGIC_PKT] = { .type = NLA_FLAG },
849 [NL80211_WOWLAN_TRIG_PKT_PATTERN] = { .type = NLA_NESTED },
77dbbb13
JB
850 [NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE] = { .type = NLA_FLAG },
851 [NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST] = { .type = NLA_FLAG },
852 [NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE] = { .type = NLA_FLAG },
853 [NL80211_WOWLAN_TRIG_RFKILL_RELEASE] = { .type = NLA_FLAG },
2a0e047e 854 [NL80211_WOWLAN_TRIG_TCP_CONNECTION] = { .type = NLA_NESTED },
8cd4d456 855 [NL80211_WOWLAN_TRIG_NET_DETECT] = { .type = NLA_NESTED },
2a0e047e
JB
856};
857
858static const struct nla_policy
859nl80211_wowlan_tcp_policy[NUM_NL80211_WOWLAN_TCP] = {
860 [NL80211_WOWLAN_TCP_SRC_IPV4] = { .type = NLA_U32 },
861 [NL80211_WOWLAN_TCP_DST_IPV4] = { .type = NLA_U32 },
c7721c05 862 [NL80211_WOWLAN_TCP_DST_MAC] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
2a0e047e
JB
863 [NL80211_WOWLAN_TCP_SRC_PORT] = { .type = NLA_U16 },
864 [NL80211_WOWLAN_TCP_DST_PORT] = { .type = NLA_U16 },
bc043585 865 [NL80211_WOWLAN_TCP_DATA_PAYLOAD] = NLA_POLICY_MIN_LEN(1),
2a0e047e
JB
866 [NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ] = {
867 .len = sizeof(struct nl80211_wowlan_tcp_data_seq)
868 },
869 [NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN] = {
870 .len = sizeof(struct nl80211_wowlan_tcp_data_token)
871 },
872 [NL80211_WOWLAN_TCP_DATA_INTERVAL] = { .type = NLA_U32 },
bc043585
JB
873 [NL80211_WOWLAN_TCP_WAKE_PAYLOAD] = NLA_POLICY_MIN_LEN(1),
874 [NL80211_WOWLAN_TCP_WAKE_MASK] = NLA_POLICY_MIN_LEN(1),
ff1b6e69 875};
f83ace3b 876#endif /* CONFIG_PM */
ff1b6e69 877
be29b99a
AK
878/* policy for coalesce rule attributes */
879static const struct nla_policy
880nl80211_coalesce_policy[NUM_NL80211_ATTR_COALESCE_RULE] = {
881 [NL80211_ATTR_COALESCE_RULE_DELAY] = { .type = NLA_U32 },
ab0d76f6
JB
882 [NL80211_ATTR_COALESCE_RULE_CONDITION] =
883 NLA_POLICY_RANGE(NLA_U32,
884 NL80211_COALESCE_CONDITION_MATCH,
885 NL80211_COALESCE_CONDITION_NO_MATCH),
be29b99a
AK
886 [NL80211_ATTR_COALESCE_RULE_PKT_PATTERN] = { .type = NLA_NESTED },
887};
888
e5497d76
JB
889/* policy for GTK rekey offload attributes */
890static const struct nla_policy
891nl80211_rekey_policy[NUM_NL80211_REKEY_DATA] = {
093a48d2
NE
892 [NL80211_REKEY_DATA_KEK] = {
893 .type = NLA_BINARY,
894 .len = NL80211_KEK_EXT_LEN
895 },
896 [NL80211_REKEY_DATA_KCK] = {
897 .type = NLA_BINARY,
648fba79 898 .len = NL80211_KCK_EXT_LEN_32
093a48d2 899 },
cb9abd48 900 [NL80211_REKEY_DATA_REPLAY_CTR] = NLA_POLICY_EXACT_LEN(NL80211_REPLAY_CTR_LEN),
093a48d2 901 [NL80211_REKEY_DATA_AKM] = { .type = NLA_U32 },
e5497d76
JB
902};
903
1e1b11b6 904static const struct nla_policy
905nl80211_match_band_rssi_policy[NUM_NL80211_BANDS] = {
906 [NL80211_BAND_2GHZ] = { .type = NLA_S32 },
907 [NL80211_BAND_5GHZ] = { .type = NLA_S32 },
e548a1c3 908 [NL80211_BAND_6GHZ] = { .type = NLA_S32 },
1e1b11b6 909 [NL80211_BAND_60GHZ] = { .type = NLA_S32 },
63fa0426 910 [NL80211_BAND_LC] = { .type = NLA_S32 },
1e1b11b6 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 },
1e1b11b6 919 [NL80211_SCHED_SCAN_MATCH_PER_BAND_RSSI] =
920 NLA_POLICY_NESTED(nl80211_match_band_rssi_policy),
a1f1c21c
LC
921};
922
3b06d277
AS
923static const struct nla_policy
924nl80211_plan_policy[NL80211_SCHED_SCAN_PLAN_MAX + 1] = {
925 [NL80211_SCHED_SCAN_PLAN_INTERVAL] = { .type = NLA_U32 },
926 [NL80211_SCHED_SCAN_PLAN_ITERATIONS] = { .type = NLA_U32 },
927};
928
38de03d2
AS
929static const struct nla_policy
930nl80211_bss_select_policy[NL80211_BSS_SELECT_ATTR_MAX + 1] = {
931 [NL80211_BSS_SELECT_ATTR_RSSI] = { .type = NLA_FLAG },
932 [NL80211_BSS_SELECT_ATTR_BAND_PREF] = { .type = NLA_U32 },
933 [NL80211_BSS_SELECT_ATTR_RSSI_ADJUST] = {
934 .len = sizeof(struct nl80211_bss_select_rssi_adjust)
935 },
936};
937
a442b761
AB
938/* policy for NAN function attributes */
939static const struct nla_policy
940nl80211_nan_func_policy[NL80211_NAN_FUNC_ATTR_MAX + 1] = {
cb9abd48
JB
941 [NL80211_NAN_FUNC_TYPE] =
942 NLA_POLICY_MAX(NLA_U8, NL80211_NAN_FUNC_MAX_TYPE),
0a27844c 943 [NL80211_NAN_FUNC_SERVICE_ID] = {
a442b761
AB
944 .len = NL80211_NAN_FUNC_SERVICE_ID_LEN },
945 [NL80211_NAN_FUNC_PUBLISH_TYPE] = { .type = NLA_U8 },
946 [NL80211_NAN_FUNC_PUBLISH_BCAST] = { .type = NLA_FLAG },
947 [NL80211_NAN_FUNC_SUBSCRIBE_ACTIVE] = { .type = NLA_FLAG },
948 [NL80211_NAN_FUNC_FOLLOW_UP_ID] = { .type = NLA_U8 },
949 [NL80211_NAN_FUNC_FOLLOW_UP_REQ_ID] = { .type = NLA_U8 },
c7721c05 950 [NL80211_NAN_FUNC_FOLLOW_UP_DEST] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
a442b761
AB
951 [NL80211_NAN_FUNC_CLOSE_RANGE] = { .type = NLA_FLAG },
952 [NL80211_NAN_FUNC_TTL] = { .type = NLA_U32 },
953 [NL80211_NAN_FUNC_SERVICE_INFO] = { .type = NLA_BINARY,
954 .len = NL80211_NAN_FUNC_SERVICE_SPEC_INFO_MAX_LEN },
955 [NL80211_NAN_FUNC_SRF] = { .type = NLA_NESTED },
956 [NL80211_NAN_FUNC_RX_MATCH_FILTER] = { .type = NLA_NESTED },
957 [NL80211_NAN_FUNC_TX_MATCH_FILTER] = { .type = NLA_NESTED },
958 [NL80211_NAN_FUNC_INSTANCE_ID] = { .type = NLA_U8 },
959 [NL80211_NAN_FUNC_TERM_REASON] = { .type = NLA_U8 },
960};
961
962/* policy for Service Response Filter attributes */
963static const struct nla_policy
964nl80211_nan_srf_policy[NL80211_NAN_SRF_ATTR_MAX + 1] = {
965 [NL80211_NAN_SRF_INCLUDE] = { .type = NLA_FLAG },
966 [NL80211_NAN_SRF_BF] = { .type = NLA_BINARY,
967 .len = NL80211_NAN_FUNC_SRF_MAX_LEN },
968 [NL80211_NAN_SRF_BF_IDX] = { .type = NLA_U8 },
969 [NL80211_NAN_SRF_MAC_ADDRS] = { .type = NLA_NESTED },
970};
971
ad670233
PX
972/* policy for packet pattern attributes */
973static const struct nla_policy
974nl80211_packet_pattern_policy[MAX_NL80211_PKTPAT + 1] = {
975 [NL80211_PKTPAT_MASK] = { .type = NLA_BINARY, },
976 [NL80211_PKTPAT_PATTERN] = { .type = NLA_BINARY, },
977 [NL80211_PKTPAT_OFFSET] = { .type = NLA_U32 },
978};
979
ce6b6974
JB
980static int nl80211_prepare_wdev_dump(struct netlink_callback *cb,
981 struct cfg80211_registered_device **rdev,
982 struct wireless_dev **wdev,
983 struct nlattr **attrbuf)
a043897a 984{
97990a06 985 int err;
a043897a 986
97990a06 987 if (!cb->args[0]) {
ce6b6974
JB
988 struct nlattr **attrbuf_free = NULL;
989
990 if (!attrbuf) {
991 attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf),
992 GFP_KERNEL);
993 if (!attrbuf)
994 return -ENOMEM;
995 attrbuf_free = attrbuf;
996 }
50508d94 997
8cb08174
JB
998 err = nlmsg_parse_deprecated(cb->nlh,
999 GENL_HDRLEN + nl80211_fam.hdrsize,
50508d94 1000 attrbuf, nl80211_fam.maxattr,
8cb08174 1001 nl80211_policy, NULL);
50508d94 1002 if (err) {
ce6b6974 1003 kfree(attrbuf_free);
ea90e0dc 1004 return err;
50508d94 1005 }
67748893 1006
a05829a7
JB
1007 rtnl_lock();
1008 *wdev = __cfg80211_wdev_from_attrs(NULL, sock_net(cb->skb->sk),
50508d94 1009 attrbuf);
ce6b6974 1010 kfree(attrbuf_free);
a05829a7
JB
1011 if (IS_ERR(*wdev)) {
1012 rtnl_unlock();
ea90e0dc 1013 return PTR_ERR(*wdev);
a05829a7 1014 }
f26cbf40 1015 *rdev = wiphy_to_rdev((*wdev)->wiphy);
a05829a7
JB
1016 mutex_lock(&(*rdev)->wiphy.mtx);
1017 rtnl_unlock();
c319d50b
JB
1018 /* 0 is the first index - add 1 to parse only once */
1019 cb->args[0] = (*rdev)->wiphy_idx + 1;
97990a06
JB
1020 cb->args[1] = (*wdev)->identifier;
1021 } else {
c319d50b 1022 /* subtract the 1 again here */
a05829a7 1023 struct wiphy *wiphy;
97990a06 1024 struct wireless_dev *tmp;
67748893 1025
a05829a7
JB
1026 rtnl_lock();
1027 wiphy = wiphy_idx_to_wiphy(cb->args[0] - 1);
1028 if (!wiphy) {
1029 rtnl_unlock();
ea90e0dc 1030 return -ENODEV;
a05829a7 1031 }
f26cbf40 1032 *rdev = wiphy_to_rdev(wiphy);
97990a06 1033 *wdev = NULL;
67748893 1034
53873f13 1035 list_for_each_entry(tmp, &(*rdev)->wiphy.wdev_list, list) {
97990a06
JB
1036 if (tmp->identifier == cb->args[1]) {
1037 *wdev = tmp;
1038 break;
1039 }
1040 }
67748893 1041
a05829a7
JB
1042 if (!*wdev) {
1043 rtnl_unlock();
ea90e0dc 1044 return -ENODEV;
a05829a7
JB
1045 }
1046 mutex_lock(&(*rdev)->wiphy.mtx);
1047 rtnl_unlock();
67748893
JB
1048 }
1049
67748893 1050 return 0;
67748893
JB
1051}
1052
55682965 1053/* message building helper */
9bb7e0f2
JB
1054void *nl80211hdr_put(struct sk_buff *skb, u32 portid, u32 seq,
1055 int flags, u8 cmd)
55682965
JB
1056{
1057 /* since there is no private header just add the generic one */
15e47304 1058 return genlmsg_put(skb, portid, seq, &nl80211_fam, flags, cmd);
55682965
JB
1059}
1060
50f32718
HD
1061static int nl80211_msg_put_wmm_rules(struct sk_buff *msg,
1062 const struct ieee80211_reg_rule *rule)
1063{
1064 int j;
1065 struct nlattr *nl_wmm_rules =
ae0be8de 1066 nla_nest_start_noflag(msg, NL80211_FREQUENCY_ATTR_WMM);
50f32718
HD
1067
1068 if (!nl_wmm_rules)
1069 goto nla_put_failure;
1070
1071 for (j = 0; j < IEEE80211_NUM_ACS; j++) {
ae0be8de 1072 struct nlattr *nl_wmm_rule = nla_nest_start_noflag(msg, j);
50f32718
HD
1073
1074 if (!nl_wmm_rule)
1075 goto nla_put_failure;
1076
1077 if (nla_put_u16(msg, NL80211_WMMR_CW_MIN,
38cb87ee 1078 rule->wmm_rule.client[j].cw_min) ||
50f32718 1079 nla_put_u16(msg, NL80211_WMMR_CW_MAX,
38cb87ee 1080 rule->wmm_rule.client[j].cw_max) ||
50f32718 1081 nla_put_u8(msg, NL80211_WMMR_AIFSN,
38cb87ee 1082 rule->wmm_rule.client[j].aifsn) ||
d3c89bbc
HD
1083 nla_put_u16(msg, NL80211_WMMR_TXOP,
1084 rule->wmm_rule.client[j].cot))
50f32718
HD
1085 goto nla_put_failure;
1086
1087 nla_nest_end(msg, nl_wmm_rule);
1088 }
1089 nla_nest_end(msg, nl_wmm_rules);
1090
1091 return 0;
1092
1093nla_put_failure:
1094 return -ENOBUFS;
1095}
1096
1097static int nl80211_msg_put_channel(struct sk_buff *msg, struct wiphy *wiphy,
cdc89b97
JB
1098 struct ieee80211_channel *chan,
1099 bool large)
5dab3b8a 1100{
ea077c1c
RL
1101 /* Some channels must be completely excluded from the
1102 * list to protect old user-space tools from breaking
1103 */
1104 if (!large && chan->flags &
1105 (IEEE80211_CHAN_NO_10MHZ | IEEE80211_CHAN_NO_20MHZ))
1106 return 0;
f8d504ca
JB
1107 if (!large && chan->freq_offset)
1108 return 0;
ea077c1c 1109
9360ffd1
DM
1110 if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_FREQ,
1111 chan->center_freq))
1112 goto nla_put_failure;
5dab3b8a 1113
942ba88b
TP
1114 if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_OFFSET, chan->freq_offset))
1115 goto nla_put_failure;
1116
9360ffd1
DM
1117 if ((chan->flags & IEEE80211_CHAN_DISABLED) &&
1118 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_DISABLED))
1119 goto nla_put_failure;
8fe02e16
LR
1120 if (chan->flags & IEEE80211_CHAN_NO_IR) {
1121 if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_IR))
1122 goto nla_put_failure;
1123 if (nla_put_flag(msg, __NL80211_FREQUENCY_ATTR_NO_IBSS))
1124 goto nla_put_failure;
1125 }
cdc89b97
JB
1126 if (chan->flags & IEEE80211_CHAN_RADAR) {
1127 if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR))
1128 goto nla_put_failure;
1129 if (large) {
1130 u32 time;
1131
1132 time = elapsed_jiffies_msecs(chan->dfs_state_entered);
1133
1134 if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_STATE,
1135 chan->dfs_state))
1136 goto nla_put_failure;
1137 if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_TIME,
1138 time))
1139 goto nla_put_failure;
089027e5
JD
1140 if (nla_put_u32(msg,
1141 NL80211_FREQUENCY_ATTR_DFS_CAC_TIME,
1142 chan->dfs_cac_ms))
1143 goto nla_put_failure;
cdc89b97
JB
1144 }
1145 }
5dab3b8a 1146
fe1abafd
JB
1147 if (large) {
1148 if ((chan->flags & IEEE80211_CHAN_NO_HT40MINUS) &&
1149 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HT40_MINUS))
1150 goto nla_put_failure;
1151 if ((chan->flags & IEEE80211_CHAN_NO_HT40PLUS) &&
1152 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HT40_PLUS))
1153 goto nla_put_failure;
1154 if ((chan->flags & IEEE80211_CHAN_NO_80MHZ) &&
1155 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_80MHZ))
1156 goto nla_put_failure;
1157 if ((chan->flags & IEEE80211_CHAN_NO_160MHZ) &&
1158 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_160MHZ))
1159 goto nla_put_failure;
570dbde1
DS
1160 if ((chan->flags & IEEE80211_CHAN_INDOOR_ONLY) &&
1161 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_INDOOR_ONLY))
1162 goto nla_put_failure;
06f207fc
AN
1163 if ((chan->flags & IEEE80211_CHAN_IR_CONCURRENT) &&
1164 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_IR_CONCURRENT))
570dbde1 1165 goto nla_put_failure;
ea077c1c
RL
1166 if ((chan->flags & IEEE80211_CHAN_NO_20MHZ) &&
1167 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_20MHZ))
1168 goto nla_put_failure;
1169 if ((chan->flags & IEEE80211_CHAN_NO_10MHZ) &&
1170 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_10MHZ))
1171 goto nla_put_failure;
1e61d82c
HD
1172 if ((chan->flags & IEEE80211_CHAN_NO_HE) &&
1173 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HE))
1174 goto nla_put_failure;
d65a9770
TP
1175 if ((chan->flags & IEEE80211_CHAN_1MHZ) &&
1176 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_1MHZ))
1177 goto nla_put_failure;
1178 if ((chan->flags & IEEE80211_CHAN_2MHZ) &&
1179 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_2MHZ))
1180 goto nla_put_failure;
1181 if ((chan->flags & IEEE80211_CHAN_4MHZ) &&
1182 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_4MHZ))
1183 goto nla_put_failure;
1184 if ((chan->flags & IEEE80211_CHAN_8MHZ) &&
1185 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_8MHZ))
1186 goto nla_put_failure;
1187 if ((chan->flags & IEEE80211_CHAN_16MHZ) &&
1188 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_16MHZ))
1189 goto nla_put_failure;
c2b3d769
S
1190 if ((chan->flags & IEEE80211_CHAN_NO_320MHZ) &&
1191 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_320MHZ))
1192 goto nla_put_failure;
31846b65
IP
1193 if ((chan->flags & IEEE80211_CHAN_NO_EHT) &&
1194 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_EHT))
1195 goto nla_put_failure;
fe1abafd
JB
1196 }
1197
9360ffd1
DM
1198 if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER,
1199 DBM_TO_MBM(chan->max_power)))
1200 goto nla_put_failure;
5dab3b8a 1201
50f32718
HD
1202 if (large) {
1203 const struct ieee80211_reg_rule *rule =
b88d26d9 1204 freq_reg_info(wiphy, MHZ_TO_KHZ(chan->center_freq));
50f32718 1205
38cb87ee 1206 if (!IS_ERR_OR_NULL(rule) && rule->has_wmm) {
50f32718
HD
1207 if (nl80211_msg_put_wmm_rules(msg, rule))
1208 goto nla_put_failure;
1209 }
1210 }
1211
5dab3b8a
LR
1212 return 0;
1213
1214 nla_put_failure:
1215 return -ENOBUFS;
1216}
1217
52539ca8
THJ
1218static bool nl80211_put_txq_stats(struct sk_buff *msg,
1219 struct cfg80211_txq_stats *txqstats,
1220 int attrtype)
1221{
1222 struct nlattr *txqattr;
1223
1224#define PUT_TXQVAL_U32(attr, memb) do { \
1225 if (txqstats->filled & BIT(NL80211_TXQ_STATS_ ## attr) && \
1226 nla_put_u32(msg, NL80211_TXQ_STATS_ ## attr, txqstats->memb)) \
1227 return false; \
1228 } while (0)
1229
ae0be8de 1230 txqattr = nla_nest_start_noflag(msg, attrtype);
52539ca8
THJ
1231 if (!txqattr)
1232 return false;
1233
1234 PUT_TXQVAL_U32(BACKLOG_BYTES, backlog_bytes);
1235 PUT_TXQVAL_U32(BACKLOG_PACKETS, backlog_packets);
1236 PUT_TXQVAL_U32(FLOWS, flows);
1237 PUT_TXQVAL_U32(DROPS, drops);
1238 PUT_TXQVAL_U32(ECN_MARKS, ecn_marks);
1239 PUT_TXQVAL_U32(OVERLIMIT, overlimit);
1240 PUT_TXQVAL_U32(OVERMEMORY, overmemory);
1241 PUT_TXQVAL_U32(COLLISIONS, collisions);
1242 PUT_TXQVAL_U32(TX_BYTES, tx_bytes);
1243 PUT_TXQVAL_U32(TX_PACKETS, tx_packets);
1244 PUT_TXQVAL_U32(MAX_FLOWS, max_flows);
1245 nla_nest_end(msg, txqattr);
1246
1247#undef PUT_TXQVAL_U32
1248 return true;
1249}
1250
55682965
JB
1251/* netlink command implementations */
1252
7b0a0e3c
JB
1253/**
1254 * nl80211_link_id - return link ID
1255 * @attrs: attributes to look at
1256 *
1257 * Returns: the link ID or 0 if not given
1258 *
1259 * Note this function doesn't do any validation of the link
1260 * ID validity wrt. links that were actually added, so it must
1261 * be called only from ops with %NL80211_FLAG_MLO_VALID_LINK_ID
1262 * or if additional validation is done.
1263 */
1264static unsigned int nl80211_link_id(struct nlattr **attrs)
1265{
1266 struct nlattr *linkid = attrs[NL80211_ATTR_MLO_LINK_ID];
1267
1268 if (!linkid)
1269 return 0;
1270
1271 return nla_get_u8(linkid);
1272}
1273
1274static int nl80211_link_id_or_invalid(struct nlattr **attrs)
1275{
1276 struct nlattr *linkid = attrs[NL80211_ATTR_MLO_LINK_ID];
1277
1278 if (!linkid)
1279 return -1;
1280
1281 return nla_get_u8(linkid);
1282}
1283
b9454e83
JB
1284struct key_parse {
1285 struct key_params p;
1286 int idx;
e31b8213 1287 int type;
56be393f 1288 bool def, defmgmt, defbeacon;
dbd2fd65 1289 bool def_uni, def_multi;
b9454e83
JB
1290};
1291
768075eb
JB
1292static int nl80211_parse_key_new(struct genl_info *info, struct nlattr *key,
1293 struct key_parse *k)
b9454e83
JB
1294{
1295 struct nlattr *tb[NL80211_KEY_MAX + 1];
8cb08174
JB
1296 int err = nla_parse_nested_deprecated(tb, NL80211_KEY_MAX, key,
1297 nl80211_key_policy,
1298 info->extack);
b9454e83
JB
1299 if (err)
1300 return err;
1301
1302 k->def = !!tb[NL80211_KEY_DEFAULT];
1303 k->defmgmt = !!tb[NL80211_KEY_DEFAULT_MGMT];
56be393f 1304 k->defbeacon = !!tb[NL80211_KEY_DEFAULT_BEACON];
b9454e83 1305
dbd2fd65
JB
1306 if (k->def) {
1307 k->def_uni = true;
1308 k->def_multi = true;
1309 }
56be393f 1310 if (k->defmgmt || k->defbeacon)
dbd2fd65
JB
1311 k->def_multi = true;
1312
b9454e83
JB
1313 if (tb[NL80211_KEY_IDX])
1314 k->idx = nla_get_u8(tb[NL80211_KEY_IDX]);
1315
1316 if (tb[NL80211_KEY_DATA]) {
1317 k->p.key = nla_data(tb[NL80211_KEY_DATA]);
1318 k->p.key_len = nla_len(tb[NL80211_KEY_DATA]);
1319 }
1320
1321 if (tb[NL80211_KEY_SEQ]) {
1322 k->p.seq = nla_data(tb[NL80211_KEY_SEQ]);
1323 k->p.seq_len = nla_len(tb[NL80211_KEY_SEQ]);
1324 }
1325
1326 if (tb[NL80211_KEY_CIPHER])
1327 k->p.cipher = nla_get_u32(tb[NL80211_KEY_CIPHER]);
1328
ab0d76f6 1329 if (tb[NL80211_KEY_TYPE])
e31b8213 1330 k->type = nla_get_u32(tb[NL80211_KEY_TYPE]);
e31b8213 1331
dbd2fd65
JB
1332 if (tb[NL80211_KEY_DEFAULT_TYPES]) {
1333 struct nlattr *kdt[NUM_NL80211_KEY_DEFAULT_TYPES];
7a087e74 1334
8cb08174
JB
1335 err = nla_parse_nested_deprecated(kdt,
1336 NUM_NL80211_KEY_DEFAULT_TYPES - 1,
1337 tb[NL80211_KEY_DEFAULT_TYPES],
1338 nl80211_key_default_policy,
1339 info->extack);
dbd2fd65
JB
1340 if (err)
1341 return err;
1342
1343 k->def_uni = kdt[NL80211_KEY_DEFAULT_TYPE_UNICAST];
1344 k->def_multi = kdt[NL80211_KEY_DEFAULT_TYPE_MULTICAST];
1345 }
1346
6cdd3979
AW
1347 if (tb[NL80211_KEY_MODE])
1348 k->p.mode = nla_get_u8(tb[NL80211_KEY_MODE]);
1349
b9454e83
JB
1350 return 0;
1351}
1352
1353static int nl80211_parse_key_old(struct genl_info *info, struct key_parse *k)
1354{
1355 if (info->attrs[NL80211_ATTR_KEY_DATA]) {
1356 k->p.key = nla_data(info->attrs[NL80211_ATTR_KEY_DATA]);
1357 k->p.key_len = nla_len(info->attrs[NL80211_ATTR_KEY_DATA]);
1358 }
1359
1360 if (info->attrs[NL80211_ATTR_KEY_SEQ]) {
1361 k->p.seq = nla_data(info->attrs[NL80211_ATTR_KEY_SEQ]);
1362 k->p.seq_len = nla_len(info->attrs[NL80211_ATTR_KEY_SEQ]);
1363 }
1364
1365 if (info->attrs[NL80211_ATTR_KEY_IDX])
1366 k->idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
1367
1368 if (info->attrs[NL80211_ATTR_KEY_CIPHER])
1369 k->p.cipher = nla_get_u32(info->attrs[NL80211_ATTR_KEY_CIPHER]);
1370
1371 k->def = !!info->attrs[NL80211_ATTR_KEY_DEFAULT];
1372 k->defmgmt = !!info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT];
1373
dbd2fd65
JB
1374 if (k->def) {
1375 k->def_uni = true;
1376 k->def_multi = true;
1377 }
1378 if (k->defmgmt)
1379 k->def_multi = true;
1380
ab0d76f6 1381 if (info->attrs[NL80211_ATTR_KEY_TYPE])
e31b8213 1382 k->type = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]);
e31b8213 1383
dbd2fd65
JB
1384 if (info->attrs[NL80211_ATTR_KEY_DEFAULT_TYPES]) {
1385 struct nlattr *kdt[NUM_NL80211_KEY_DEFAULT_TYPES];
8cb08174
JB
1386 int err = nla_parse_nested_deprecated(kdt,
1387 NUM_NL80211_KEY_DEFAULT_TYPES - 1,
1388 info->attrs[NL80211_ATTR_KEY_DEFAULT_TYPES],
1389 nl80211_key_default_policy,
1390 info->extack);
dbd2fd65
JB
1391 if (err)
1392 return err;
1393
1394 k->def_uni = kdt[NL80211_KEY_DEFAULT_TYPE_UNICAST];
1395 k->def_multi = kdt[NL80211_KEY_DEFAULT_TYPE_MULTICAST];
1396 }
1397
b9454e83
JB
1398 return 0;
1399}
1400
1401static int nl80211_parse_key(struct genl_info *info, struct key_parse *k)
1402{
1403 int err;
1404
1405 memset(k, 0, sizeof(*k));
1406 k->idx = -1;
e31b8213 1407 k->type = -1;
b9454e83
JB
1408
1409 if (info->attrs[NL80211_ATTR_KEY])
768075eb 1410 err = nl80211_parse_key_new(info, info->attrs[NL80211_ATTR_KEY], k);
b9454e83
JB
1411 else
1412 err = nl80211_parse_key_old(info, k);
1413
1414 if (err)
1415 return err;
1416
56be393f
JM
1417 if ((k->def ? 1 : 0) + (k->defmgmt ? 1 : 0) +
1418 (k->defbeacon ? 1 : 0) > 1) {
1419 GENL_SET_ERR_MSG(info,
1420 "key with multiple default flags is invalid");
b9454e83 1421 return -EINVAL;
768075eb 1422 }
b9454e83 1423
56be393f 1424 if (k->defmgmt || k->defbeacon) {
768075eb 1425 if (k->def_uni || !k->def_multi) {
56be393f
JM
1426 GENL_SET_ERR_MSG(info,
1427 "defmgmt/defbeacon key must be mcast");
dbd2fd65 1428 return -EINVAL;
768075eb 1429 }
dbd2fd65
JB
1430 }
1431
b9454e83
JB
1432 if (k->idx != -1) {
1433 if (k->defmgmt) {
768075eb
JB
1434 if (k->idx < 4 || k->idx > 5) {
1435 GENL_SET_ERR_MSG(info,
1436 "defmgmt key idx not 4 or 5");
b9454e83 1437 return -EINVAL;
768075eb 1438 }
56be393f
JM
1439 } else if (k->defbeacon) {
1440 if (k->idx < 6 || k->idx > 7) {
1441 GENL_SET_ERR_MSG(info,
1442 "defbeacon key idx not 6 or 7");
1443 return -EINVAL;
1444 }
b9454e83 1445 } else if (k->def) {
768075eb
JB
1446 if (k->idx < 0 || k->idx > 3) {
1447 GENL_SET_ERR_MSG(info, "def key idx not 0-3");
b9454e83 1448 return -EINVAL;
768075eb 1449 }
b9454e83 1450 } else {
56be393f
JM
1451 if (k->idx < 0 || k->idx > 7) {
1452 GENL_SET_ERR_MSG(info, "key idx not 0-7");
b9454e83 1453 return -EINVAL;
768075eb 1454 }
b9454e83
JB
1455 }
1456 }
1457
1458 return 0;
1459}
1460
fffd0934
JB
1461static struct cfg80211_cached_keys *
1462nl80211_parse_connkeys(struct cfg80211_registered_device *rdev,
768075eb 1463 struct genl_info *info, bool *no_ht)
fffd0934 1464{
768075eb 1465 struct nlattr *keys = info->attrs[NL80211_ATTR_KEYS];
fffd0934
JB
1466 struct key_parse parse;
1467 struct nlattr *key;
1468 struct cfg80211_cached_keys *result;
1469 int rem, err, def = 0;
f1c1f17a
JB
1470 bool have_key = false;
1471
1472 nla_for_each_nested(key, keys, rem) {
1473 have_key = true;
1474 break;
1475 }
1476
1477 if (!have_key)
1478 return NULL;
fffd0934
JB
1479
1480 result = kzalloc(sizeof(*result), GFP_KERNEL);
1481 if (!result)
1482 return ERR_PTR(-ENOMEM);
1483
1484 result->def = -1;
fffd0934
JB
1485
1486 nla_for_each_nested(key, keys, rem) {
1487 memset(&parse, 0, sizeof(parse));
1488 parse.idx = -1;
1489
768075eb 1490 err = nl80211_parse_key_new(info, key, &parse);
fffd0934
JB
1491 if (err)
1492 goto error;
1493 err = -EINVAL;
1494 if (!parse.p.key)
1495 goto error;
768075eb
JB
1496 if (parse.idx < 0 || parse.idx > 3) {
1497 GENL_SET_ERR_MSG(info, "key index out of range [0-3]");
fffd0934 1498 goto error;
768075eb 1499 }
fffd0934 1500 if (parse.def) {
768075eb
JB
1501 if (def) {
1502 GENL_SET_ERR_MSG(info,
1503 "only one key can be default");
fffd0934 1504 goto error;
768075eb 1505 }
fffd0934
JB
1506 def = 1;
1507 result->def = parse.idx;
dbd2fd65
JB
1508 if (!parse.def_uni || !parse.def_multi)
1509 goto error;
fffd0934
JB
1510 } else if (parse.defmgmt)
1511 goto error;
1512 err = cfg80211_validate_key_settings(rdev, &parse.p,
e31b8213 1513 parse.idx, false, NULL);
fffd0934
JB
1514 if (err)
1515 goto error;
386b1f27
JB
1516 if (parse.p.cipher != WLAN_CIPHER_SUITE_WEP40 &&
1517 parse.p.cipher != WLAN_CIPHER_SUITE_WEP104) {
768075eb 1518 GENL_SET_ERR_MSG(info, "connect key must be WEP");
386b1f27
JB
1519 err = -EINVAL;
1520 goto error;
1521 }
fffd0934
JB
1522 result->params[parse.idx].cipher = parse.p.cipher;
1523 result->params[parse.idx].key_len = parse.p.key_len;
1524 result->params[parse.idx].key = result->data[parse.idx];
1525 memcpy(result->data[parse.idx], parse.p.key, parse.p.key_len);
de7044ee 1526
386b1f27
JB
1527 /* must be WEP key if we got here */
1528 if (no_ht)
1529 *no_ht = true;
fffd0934
JB
1530 }
1531
f1c1f17a
JB
1532 if (result->def < 0) {
1533 err = -EINVAL;
768075eb 1534 GENL_SET_ERR_MSG(info, "need a default/TX key");
f1c1f17a
JB
1535 goto error;
1536 }
1537
fffd0934
JB
1538 return result;
1539 error:
1540 kfree(result);
1541 return ERR_PTR(err);
1542}
1543
1544static int nl80211_key_allowed(struct wireless_dev *wdev)
1545{
1546 ASSERT_WDEV_LOCK(wdev);
1547
fffd0934
JB
1548 switch (wdev->iftype) {
1549 case NL80211_IFTYPE_AP:
1550 case NL80211_IFTYPE_AP_VLAN:
074ac8df 1551 case NL80211_IFTYPE_P2P_GO:
ff973af7 1552 case NL80211_IFTYPE_MESH_POINT:
fffd0934
JB
1553 break;
1554 case NL80211_IFTYPE_ADHOC:
7b0a0e3c
JB
1555 if (wdev->u.ibss.current_bss)
1556 return 0;
1557 return -ENOLINK;
fffd0934 1558 case NL80211_IFTYPE_STATION:
074ac8df 1559 case NL80211_IFTYPE_P2P_CLIENT:
7b0a0e3c
JB
1560 if (wdev->connected)
1561 return 0;
1562 return -ENOLINK;
9b89495e
VG
1563 case NL80211_IFTYPE_NAN:
1564 if (wiphy_ext_feature_isset(wdev->wiphy,
1565 NL80211_EXT_FEATURE_SECURE_NAN))
1566 return 0;
1567 return -EINVAL;
de4fcbad 1568 case NL80211_IFTYPE_UNSPECIFIED:
6e0bd6c3 1569 case NL80211_IFTYPE_OCB:
de4fcbad
JB
1570 case NL80211_IFTYPE_MONITOR:
1571 case NL80211_IFTYPE_P2P_DEVICE:
1572 case NL80211_IFTYPE_WDS:
1573 case NUM_NL80211_IFTYPES:
fffd0934
JB
1574 return -EINVAL;
1575 }
1576
1577 return 0;
1578}
1579
664834de 1580static struct ieee80211_channel *nl80211_get_valid_chan(struct wiphy *wiphy,
942ba88b 1581 u32 freq)
664834de
JM
1582{
1583 struct ieee80211_channel *chan;
1584
942ba88b 1585 chan = ieee80211_get_channel_khz(wiphy, freq);
664834de
JM
1586 if (!chan || chan->flags & IEEE80211_CHAN_DISABLED)
1587 return NULL;
1588 return chan;
1589}
1590
7527a782
JB
1591static int nl80211_put_iftypes(struct sk_buff *msg, u32 attr, u16 ifmodes)
1592{
ae0be8de 1593 struct nlattr *nl_modes = nla_nest_start_noflag(msg, attr);
7527a782
JB
1594 int i;
1595
1596 if (!nl_modes)
1597 goto nla_put_failure;
1598
1599 i = 0;
1600 while (ifmodes) {
9360ffd1
DM
1601 if ((ifmodes & 1) && nla_put_flag(msg, i))
1602 goto nla_put_failure;
7527a782
JB
1603 ifmodes >>= 1;
1604 i++;
1605 }
1606
1607 nla_nest_end(msg, nl_modes);
1608 return 0;
1609
1610nla_put_failure:
1611 return -ENOBUFS;
1612}
1613
1614static int nl80211_put_iface_combinations(struct wiphy *wiphy,
cdc89b97
JB
1615 struct sk_buff *msg,
1616 bool large)
7527a782
JB
1617{
1618 struct nlattr *nl_combis;
1619 int i, j;
1620
ae0be8de
MK
1621 nl_combis = nla_nest_start_noflag(msg,
1622 NL80211_ATTR_INTERFACE_COMBINATIONS);
7527a782
JB
1623 if (!nl_combis)
1624 goto nla_put_failure;
1625
1626 for (i = 0; i < wiphy->n_iface_combinations; i++) {
1627 const struct ieee80211_iface_combination *c;
1628 struct nlattr *nl_combi, *nl_limits;
1629
1630 c = &wiphy->iface_combinations[i];
1631
ae0be8de 1632 nl_combi = nla_nest_start_noflag(msg, i + 1);
7527a782
JB
1633 if (!nl_combi)
1634 goto nla_put_failure;
1635
ae0be8de
MK
1636 nl_limits = nla_nest_start_noflag(msg,
1637 NL80211_IFACE_COMB_LIMITS);
7527a782
JB
1638 if (!nl_limits)
1639 goto nla_put_failure;
1640
1641 for (j = 0; j < c->n_limits; j++) {
1642 struct nlattr *nl_limit;
1643
ae0be8de 1644 nl_limit = nla_nest_start_noflag(msg, j + 1);
7527a782
JB
1645 if (!nl_limit)
1646 goto nla_put_failure;
9360ffd1
DM
1647 if (nla_put_u32(msg, NL80211_IFACE_LIMIT_MAX,
1648 c->limits[j].max))
1649 goto nla_put_failure;
7527a782
JB
1650 if (nl80211_put_iftypes(msg, NL80211_IFACE_LIMIT_TYPES,
1651 c->limits[j].types))
1652 goto nla_put_failure;
1653 nla_nest_end(msg, nl_limit);
1654 }
1655
1656 nla_nest_end(msg, nl_limits);
1657
9360ffd1
DM
1658 if (c->beacon_int_infra_match &&
1659 nla_put_flag(msg, NL80211_IFACE_COMB_STA_AP_BI_MATCH))
1660 goto nla_put_failure;
1661 if (nla_put_u32(msg, NL80211_IFACE_COMB_NUM_CHANNELS,
1662 c->num_different_channels) ||
1663 nla_put_u32(msg, NL80211_IFACE_COMB_MAXNUM,
1664 c->max_interfaces))
1665 goto nla_put_failure;
cdc89b97 1666 if (large &&
8c48b50a
FF
1667 (nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS,
1668 c->radar_detect_widths) ||
1669 nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_REGIONS,
1670 c->radar_detect_regions)))
cdc89b97 1671 goto nla_put_failure;
0c317a02
PK
1672 if (c->beacon_int_min_gcd &&
1673 nla_put_u32(msg, NL80211_IFACE_COMB_BI_MIN_GCD,
1674 c->beacon_int_min_gcd))
1675 goto nla_put_failure;
7527a782
JB
1676
1677 nla_nest_end(msg, nl_combi);
1678 }
1679
1680 nla_nest_end(msg, nl_combis);
1681
1682 return 0;
1683nla_put_failure:
1684 return -ENOBUFS;
1685}
1686
3713b4e3 1687#ifdef CONFIG_PM
b56cf720
JB
1688static int nl80211_send_wowlan_tcp_caps(struct cfg80211_registered_device *rdev,
1689 struct sk_buff *msg)
1690{
964dc9e2 1691 const struct wiphy_wowlan_tcp_support *tcp = rdev->wiphy.wowlan->tcp;
b56cf720
JB
1692 struct nlattr *nl_tcp;
1693
1694 if (!tcp)
1695 return 0;
1696
ae0be8de
MK
1697 nl_tcp = nla_nest_start_noflag(msg,
1698 NL80211_WOWLAN_TRIG_TCP_CONNECTION);
b56cf720
JB
1699 if (!nl_tcp)
1700 return -ENOBUFS;
1701
1702 if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD,
1703 tcp->data_payload_max))
1704 return -ENOBUFS;
1705
1706 if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD,
1707 tcp->data_payload_max))
1708 return -ENOBUFS;
1709
1710 if (tcp->seq && nla_put_flag(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ))
1711 return -ENOBUFS;
1712
1713 if (tcp->tok && nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN,
1714 sizeof(*tcp->tok), tcp->tok))
1715 return -ENOBUFS;
1716
1717 if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_INTERVAL,
1718 tcp->data_interval_max))
1719 return -ENOBUFS;
1720
1721 if (nla_put_u32(msg, NL80211_WOWLAN_TCP_WAKE_PAYLOAD,
1722 tcp->wake_payload_max))
1723 return -ENOBUFS;
1724
1725 nla_nest_end(msg, nl_tcp);
1726 return 0;
1727}
1728
3713b4e3 1729static int nl80211_send_wowlan(struct sk_buff *msg,
1b8ec87a 1730 struct cfg80211_registered_device *rdev,
b56cf720 1731 bool large)
55682965 1732{
3713b4e3 1733 struct nlattr *nl_wowlan;
55682965 1734
1b8ec87a 1735 if (!rdev->wiphy.wowlan)
3713b4e3 1736 return 0;
55682965 1737
ae0be8de
MK
1738 nl_wowlan = nla_nest_start_noflag(msg,
1739 NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED);
3713b4e3
JB
1740 if (!nl_wowlan)
1741 return -ENOBUFS;
9360ffd1 1742
1b8ec87a 1743 if (((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_ANY) &&
3713b4e3 1744 nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) ||
1b8ec87a 1745 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_DISCONNECT) &&
3713b4e3 1746 nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) ||
1b8ec87a 1747 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_MAGIC_PKT) &&
3713b4e3 1748 nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) ||
1b8ec87a 1749 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_SUPPORTS_GTK_REKEY) &&
3713b4e3 1750 nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED)) ||
1b8ec87a 1751 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE) &&
3713b4e3 1752 nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) ||
1b8ec87a 1753 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ) &&
3713b4e3 1754 nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) ||
1b8ec87a 1755 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_4WAY_HANDSHAKE) &&
3713b4e3 1756 nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) ||
1b8ec87a 1757 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_RFKILL_RELEASE) &&
3713b4e3
JB
1758 nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE)))
1759 return -ENOBUFS;
9360ffd1 1760
1b8ec87a 1761 if (rdev->wiphy.wowlan->n_patterns) {
50ac6607 1762 struct nl80211_pattern_support pat = {
1b8ec87a
ZG
1763 .max_patterns = rdev->wiphy.wowlan->n_patterns,
1764 .min_pattern_len = rdev->wiphy.wowlan->pattern_min_len,
1765 .max_pattern_len = rdev->wiphy.wowlan->pattern_max_len,
1766 .max_pkt_offset = rdev->wiphy.wowlan->max_pkt_offset,
3713b4e3 1767 };
9360ffd1 1768
3713b4e3
JB
1769 if (nla_put(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN,
1770 sizeof(pat), &pat))
1771 return -ENOBUFS;
1772 }
9360ffd1 1773
75453ccb
LC
1774 if ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_NET_DETECT) &&
1775 nla_put_u32(msg, NL80211_WOWLAN_TRIG_NET_DETECT,
1776 rdev->wiphy.wowlan->max_nd_match_sets))
1777 return -ENOBUFS;
1778
1b8ec87a 1779 if (large && nl80211_send_wowlan_tcp_caps(rdev, msg))
b56cf720
JB
1780 return -ENOBUFS;
1781
3713b4e3 1782 nla_nest_end(msg, nl_wowlan);
9360ffd1 1783
3713b4e3
JB
1784 return 0;
1785}
1786#endif
9360ffd1 1787
be29b99a 1788static int nl80211_send_coalesce(struct sk_buff *msg,
1b8ec87a 1789 struct cfg80211_registered_device *rdev)
be29b99a
AK
1790{
1791 struct nl80211_coalesce_rule_support rule;
1792
1b8ec87a 1793 if (!rdev->wiphy.coalesce)
be29b99a
AK
1794 return 0;
1795
1b8ec87a
ZG
1796 rule.max_rules = rdev->wiphy.coalesce->n_rules;
1797 rule.max_delay = rdev->wiphy.coalesce->max_delay;
1798 rule.pat.max_patterns = rdev->wiphy.coalesce->n_patterns;
1799 rule.pat.min_pattern_len = rdev->wiphy.coalesce->pattern_min_len;
1800 rule.pat.max_pattern_len = rdev->wiphy.coalesce->pattern_max_len;
1801 rule.pat.max_pkt_offset = rdev->wiphy.coalesce->max_pkt_offset;
be29b99a
AK
1802
1803 if (nla_put(msg, NL80211_ATTR_COALESCE_RULE, sizeof(rule), &rule))
1804 return -ENOBUFS;
1805
1806 return 0;
1807}
1808
c4cbaf79
LC
1809static int
1810nl80211_send_iftype_data(struct sk_buff *msg,
22395217 1811 const struct ieee80211_supported_band *sband,
c4cbaf79
LC
1812 const struct ieee80211_sband_iftype_data *iftdata)
1813{
1814 const struct ieee80211_sta_he_cap *he_cap = &iftdata->he_cap;
5cd5a8a3 1815 const struct ieee80211_sta_eht_cap *eht_cap = &iftdata->eht_cap;
c4cbaf79
LC
1816
1817 if (nl80211_put_iftypes(msg, NL80211_BAND_IFTYPE_ATTR_IFTYPES,
1818 iftdata->types_mask))
1819 return -ENOBUFS;
1820
1821 if (he_cap->has_he) {
1822 if (nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_CAP_MAC,
1823 sizeof(he_cap->he_cap_elem.mac_cap_info),
1824 he_cap->he_cap_elem.mac_cap_info) ||
1825 nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY,
1826 sizeof(he_cap->he_cap_elem.phy_cap_info),
1827 he_cap->he_cap_elem.phy_cap_info) ||
1828 nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET,
1829 sizeof(he_cap->he_mcs_nss_supp),
1830 &he_cap->he_mcs_nss_supp) ||
1831 nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE,
1832 sizeof(he_cap->ppe_thres), he_cap->ppe_thres))
1833 return -ENOBUFS;
1834 }
1835
5cd5a8a3
IP
1836 if (eht_cap->has_eht && he_cap->has_he) {
1837 u8 mcs_nss_size, ppe_thresh_size;
1838 u16 ppe_thres_hdr;
ea5cba26
JB
1839 bool is_ap;
1840
1841 is_ap = iftdata->types_mask & BIT(NL80211_IFTYPE_AP) ||
1842 iftdata->types_mask & BIT(NL80211_IFTYPE_P2P_GO);
5cd5a8a3
IP
1843
1844 mcs_nss_size =
1845 ieee80211_eht_mcs_nss_size(&he_cap->he_cap_elem,
ea5cba26
JB
1846 &eht_cap->eht_cap_elem,
1847 is_ap);
5cd5a8a3
IP
1848
1849 ppe_thres_hdr = get_unaligned_le16(&eht_cap->eht_ppe_thres[0]);
1850 ppe_thresh_size =
1851 ieee80211_eht_ppe_size(ppe_thres_hdr,
1852 eht_cap->eht_cap_elem.phy_cap_info);
1853
1854 if (nla_put(msg, NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MAC,
1855 sizeof(eht_cap->eht_cap_elem.mac_cap_info),
1856 eht_cap->eht_cap_elem.mac_cap_info) ||
1857 nla_put(msg, NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY,
1858 sizeof(eht_cap->eht_cap_elem.phy_cap_info),
1859 eht_cap->eht_cap_elem.phy_cap_info) ||
1860 nla_put(msg, NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MCS_SET,
1861 mcs_nss_size, &eht_cap->eht_mcs_nss_supp) ||
1862 nla_put(msg, NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PPE,
1863 ppe_thresh_size, eht_cap->eht_ppe_thres))
1864 return -ENOBUFS;
1865 }
1866
22395217
JB
1867 if (sband->band == NL80211_BAND_6GHZ &&
1868 nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA,
1869 sizeof(iftdata->he_6ghz_capa),
1870 &iftdata->he_6ghz_capa))
1871 return -ENOBUFS;
1872
f4f86505
JB
1873 if (iftdata->vendor_elems.data && iftdata->vendor_elems.len &&
1874 nla_put(msg, NL80211_BAND_IFTYPE_ATTR_VENDOR_ELEMS,
1875 iftdata->vendor_elems.len, iftdata->vendor_elems.data))
1876 return -ENOBUFS;
1877
c4cbaf79
LC
1878 return 0;
1879}
1880
3713b4e3 1881static int nl80211_send_band_rateinfo(struct sk_buff *msg,
f8d504ca
JB
1882 struct ieee80211_supported_band *sband,
1883 bool large)
3713b4e3
JB
1884{
1885 struct nlattr *nl_rates, *nl_rate;
1886 struct ieee80211_rate *rate;
1887 int i;
87bbbe22 1888
3713b4e3
JB
1889 /* add HT info */
1890 if (sband->ht_cap.ht_supported &&
1891 (nla_put(msg, NL80211_BAND_ATTR_HT_MCS_SET,
1892 sizeof(sband->ht_cap.mcs),
1893 &sband->ht_cap.mcs) ||
1894 nla_put_u16(msg, NL80211_BAND_ATTR_HT_CAPA,
1895 sband->ht_cap.cap) ||
1896 nla_put_u8(msg, NL80211_BAND_ATTR_HT_AMPDU_FACTOR,
1897 sband->ht_cap.ampdu_factor) ||
1898 nla_put_u8(msg, NL80211_BAND_ATTR_HT_AMPDU_DENSITY,
1899 sband->ht_cap.ampdu_density)))
1900 return -ENOBUFS;
afe0cbf8 1901
3713b4e3
JB
1902 /* add VHT info */
1903 if (sband->vht_cap.vht_supported &&
1904 (nla_put(msg, NL80211_BAND_ATTR_VHT_MCS_SET,
1905 sizeof(sband->vht_cap.vht_mcs),
1906 &sband->vht_cap.vht_mcs) ||
1907 nla_put_u32(msg, NL80211_BAND_ATTR_VHT_CAPA,
1908 sband->vht_cap.cap)))
1909 return -ENOBUFS;
f59ac048 1910
f8d504ca 1911 if (large && sband->n_iftype_data) {
c4cbaf79 1912 struct nlattr *nl_iftype_data =
ae0be8de
MK
1913 nla_nest_start_noflag(msg,
1914 NL80211_BAND_ATTR_IFTYPE_DATA);
c4cbaf79
LC
1915 int err;
1916
1917 if (!nl_iftype_data)
1918 return -ENOBUFS;
1919
1920 for (i = 0; i < sband->n_iftype_data; i++) {
1921 struct nlattr *iftdata;
1922
ae0be8de 1923 iftdata = nla_nest_start_noflag(msg, i + 1);
c4cbaf79
LC
1924 if (!iftdata)
1925 return -ENOBUFS;
1926
22395217 1927 err = nl80211_send_iftype_data(msg, sband,
c4cbaf79
LC
1928 &sband->iftype_data[i]);
1929 if (err)
1930 return err;
1931
1932 nla_nest_end(msg, iftdata);
1933 }
1934
1935 nla_nest_end(msg, nl_iftype_data);
1936 }
1937
2a38075c 1938 /* add EDMG info */
f8d504ca 1939 if (large && sband->edmg_cap.channels &&
2a38075c
AAL
1940 (nla_put_u8(msg, NL80211_BAND_ATTR_EDMG_CHANNELS,
1941 sband->edmg_cap.channels) ||
1942 nla_put_u8(msg, NL80211_BAND_ATTR_EDMG_BW_CONFIG,
1943 sband->edmg_cap.bw_config)))
1944
1945 return -ENOBUFS;
1946
3713b4e3 1947 /* add bitrates */
ae0be8de 1948 nl_rates = nla_nest_start_noflag(msg, NL80211_BAND_ATTR_RATES);
3713b4e3
JB
1949 if (!nl_rates)
1950 return -ENOBUFS;
ee688b00 1951
3713b4e3 1952 for (i = 0; i < sband->n_bitrates; i++) {
ae0be8de 1953 nl_rate = nla_nest_start_noflag(msg, i);
3713b4e3
JB
1954 if (!nl_rate)
1955 return -ENOBUFS;
ee688b00 1956
3713b4e3
JB
1957 rate = &sband->bitrates[i];
1958 if (nla_put_u32(msg, NL80211_BITRATE_ATTR_RATE,
1959 rate->bitrate))
1960 return -ENOBUFS;
1961 if ((rate->flags & IEEE80211_RATE_SHORT_PREAMBLE) &&
1962 nla_put_flag(msg,
1963 NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE))
1964 return -ENOBUFS;
ee688b00 1965
3713b4e3
JB
1966 nla_nest_end(msg, nl_rate);
1967 }
d51626df 1968
3713b4e3 1969 nla_nest_end(msg, nl_rates);
bf0c111e 1970
9a8aac92
KF
1971 /* S1G capabilities */
1972 if (sband->band == NL80211_BAND_S1GHZ && sband->s1g_cap.s1g &&
1973 (nla_put(msg, NL80211_BAND_ATTR_S1G_CAPA,
1974 sizeof(sband->s1g_cap.cap),
1975 sband->s1g_cap.cap) ||
1976 nla_put(msg, NL80211_BAND_ATTR_S1G_MCS_NSS_SET,
1977 sizeof(sband->s1g_cap.nss_mcs),
1978 sband->s1g_cap.nss_mcs)))
1979 return -ENOBUFS;
1980
3713b4e3
JB
1981 return 0;
1982}
ee688b00 1983
3713b4e3
JB
1984static int
1985nl80211_send_mgmt_stypes(struct sk_buff *msg,
1986 const struct ieee80211_txrx_stypes *mgmt_stypes)
1987{
1988 u16 stypes;
1989 struct nlattr *nl_ftypes, *nl_ifs;
1990 enum nl80211_iftype ift;
1991 int i;
ee688b00 1992
3713b4e3
JB
1993 if (!mgmt_stypes)
1994 return 0;
5dab3b8a 1995
ae0be8de 1996 nl_ifs = nla_nest_start_noflag(msg, NL80211_ATTR_TX_FRAME_TYPES);
3713b4e3
JB
1997 if (!nl_ifs)
1998 return -ENOBUFS;
e2f367f2 1999
3713b4e3 2000 for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) {
ae0be8de 2001 nl_ftypes = nla_nest_start_noflag(msg, ift);
3713b4e3
JB
2002 if (!nl_ftypes)
2003 return -ENOBUFS;
2004 i = 0;
2005 stypes = mgmt_stypes[ift].tx;
2006 while (stypes) {
2007 if ((stypes & 1) &&
2008 nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE,
2009 (i << 4) | IEEE80211_FTYPE_MGMT))
2010 return -ENOBUFS;
2011 stypes >>= 1;
2012 i++;
ee688b00 2013 }
3713b4e3
JB
2014 nla_nest_end(msg, nl_ftypes);
2015 }
ee688b00 2016
3713b4e3 2017 nla_nest_end(msg, nl_ifs);
ee688b00 2018
ae0be8de 2019 nl_ifs = nla_nest_start_noflag(msg, NL80211_ATTR_RX_FRAME_TYPES);
3713b4e3
JB
2020 if (!nl_ifs)
2021 return -ENOBUFS;
ee688b00 2022
3713b4e3 2023 for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) {
ae0be8de 2024 nl_ftypes = nla_nest_start_noflag(msg, ift);
3713b4e3
JB
2025 if (!nl_ftypes)
2026 return -ENOBUFS;
2027 i = 0;
2028 stypes = mgmt_stypes[ift].rx;
2029 while (stypes) {
2030 if ((stypes & 1) &&
2031 nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE,
2032 (i << 4) | IEEE80211_FTYPE_MGMT))
2033 return -ENOBUFS;
2034 stypes >>= 1;
2035 i++;
2036 }
2037 nla_nest_end(msg, nl_ftypes);
2038 }
2039 nla_nest_end(msg, nl_ifs);
ee688b00 2040
3713b4e3
JB
2041 return 0;
2042}
ee688b00 2043
1794899e
JB
2044#define CMD(op, n) \
2045 do { \
2046 if (rdev->ops->op) { \
2047 i++; \
2048 if (nla_put_u32(msg, i, NL80211_CMD_ ## n)) \
2049 goto nla_put_failure; \
2050 } \
2051 } while (0)
2052
2053static int nl80211_add_commands_unsplit(struct cfg80211_registered_device *rdev,
2054 struct sk_buff *msg)
2055{
2056 int i = 0;
2057
2058 /*
2059 * do *NOT* add anything into this function, new things need to be
2060 * advertised only to new versions of userspace that can deal with
2061 * the split (and they can't possibly care about new features...
2062 */
2063 CMD(add_virtual_intf, NEW_INTERFACE);
2064 CMD(change_virtual_intf, SET_INTERFACE);
2065 CMD(add_key, NEW_KEY);
2066 CMD(start_ap, START_AP);
2067 CMD(add_station, NEW_STATION);
2068 CMD(add_mpath, NEW_MPATH);
2069 CMD(update_mesh_config, SET_MESH_CONFIG);
2070 CMD(change_bss, SET_BSS);
2071 CMD(auth, AUTHENTICATE);
2072 CMD(assoc, ASSOCIATE);
2073 CMD(deauth, DEAUTHENTICATE);
2074 CMD(disassoc, DISASSOCIATE);
2075 CMD(join_ibss, JOIN_IBSS);
2076 CMD(join_mesh, JOIN_MESH);
2077 CMD(set_pmksa, SET_PMKSA);
2078 CMD(del_pmksa, DEL_PMKSA);
2079 CMD(flush_pmksa, FLUSH_PMKSA);
2080 if (rdev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL)
2081 CMD(remain_on_channel, REMAIN_ON_CHANNEL);
2082 CMD(set_bitrate_mask, SET_TX_BITRATE_MASK);
2083 CMD(mgmt_tx, FRAME);
2084 CMD(mgmt_tx_cancel_wait, FRAME_WAIT_CANCEL);
2085 if (rdev->wiphy.flags & WIPHY_FLAG_NETNS_OK) {
2086 i++;
2087 if (nla_put_u32(msg, i, NL80211_CMD_SET_WIPHY_NETNS))
2088 goto nla_put_failure;
2089 }
2090 if (rdev->ops->set_monitor_channel || rdev->ops->start_ap ||
2091 rdev->ops->join_mesh) {
2092 i++;
2093 if (nla_put_u32(msg, i, NL80211_CMD_SET_CHANNEL))
2094 goto nla_put_failure;
2095 }
1794899e
JB
2096 if (rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) {
2097 CMD(tdls_mgmt, TDLS_MGMT);
2098 CMD(tdls_oper, TDLS_OPER);
2099 }
ca986ad9 2100 if (rdev->wiphy.max_sched_scan_reqs)
1794899e
JB
2101 CMD(sched_scan_start, START_SCHED_SCAN);
2102 CMD(probe_client, PROBE_CLIENT);
2103 CMD(set_noack_map, SET_NOACK_MAP);
2104 if (rdev->wiphy.flags & WIPHY_FLAG_REPORTS_OBSS) {
2105 i++;
2106 if (nla_put_u32(msg, i, NL80211_CMD_REGISTER_BEACONS))
2107 goto nla_put_failure;
2108 }
2109 CMD(start_p2p_device, START_P2P_DEVICE);
2110 CMD(set_mcast_rate, SET_MCAST_RATE);
2111#ifdef CONFIG_NL80211_TESTMODE
2112 CMD(testmode_cmd, TESTMODE);
2113#endif
2114
2115 if (rdev->ops->connect || rdev->ops->auth) {
2116 i++;
2117 if (nla_put_u32(msg, i, NL80211_CMD_CONNECT))
2118 goto nla_put_failure;
2119 }
2120
2121 if (rdev->ops->disconnect || rdev->ops->deauth) {
2122 i++;
2123 if (nla_put_u32(msg, i, NL80211_CMD_DISCONNECT))
2124 goto nla_put_failure;
2125 }
2126
2127 return i;
2128 nla_put_failure:
2129 return -ENOBUFS;
2130}
2131
9bb7e0f2
JB
2132static int
2133nl80211_send_pmsr_ftm_capa(const struct cfg80211_pmsr_capabilities *cap,
2134 struct sk_buff *msg)
2135{
2136 struct nlattr *ftm;
2137
2138 if (!cap->ftm.supported)
2139 return 0;
2140
ae0be8de 2141 ftm = nla_nest_start_noflag(msg, NL80211_PMSR_TYPE_FTM);
9bb7e0f2
JB
2142 if (!ftm)
2143 return -ENOBUFS;
2144
2145 if (cap->ftm.asap && nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_ASAP))
2146 return -ENOBUFS;
2147 if (cap->ftm.non_asap &&
2148 nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_NON_ASAP))
2149 return -ENOBUFS;
2150 if (cap->ftm.request_lci &&
2151 nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_REQ_LCI))
2152 return -ENOBUFS;
2153 if (cap->ftm.request_civicloc &&
2154 nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_REQ_CIVICLOC))
2155 return -ENOBUFS;
2156 if (nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_PREAMBLES,
2157 cap->ftm.preambles))
2158 return -ENOBUFS;
2159 if (nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_BANDWIDTHS,
2160 cap->ftm.bandwidths))
2161 return -ENOBUFS;
2162 if (cap->ftm.max_bursts_exponent >= 0 &&
2163 nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_MAX_BURSTS_EXPONENT,
2164 cap->ftm.max_bursts_exponent))
2165 return -ENOBUFS;
2166 if (cap->ftm.max_ftms_per_burst &&
2167 nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_MAX_FTMS_PER_BURST,
2168 cap->ftm.max_ftms_per_burst))
2169 return -ENOBUFS;
efb5520d
AS
2170 if (cap->ftm.trigger_based &&
2171 nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_TRIGGER_BASED))
2172 return -ENOBUFS;
2173 if (cap->ftm.non_trigger_based &&
2174 nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_NON_TRIGGER_BASED))
2175 return -ENOBUFS;
9bb7e0f2
JB
2176
2177 nla_nest_end(msg, ftm);
2178 return 0;
2179}
2180
2181static int nl80211_send_pmsr_capa(struct cfg80211_registered_device *rdev,
2182 struct sk_buff *msg)
2183{
2184 const struct cfg80211_pmsr_capabilities *cap = rdev->wiphy.pmsr_capa;
2185 struct nlattr *pmsr, *caps;
2186
2187 if (!cap)
2188 return 0;
2189
2190 /*
2191 * we don't need to clean up anything here since the caller
2192 * will genlmsg_cancel() if we fail
2193 */
2194
ae0be8de 2195 pmsr = nla_nest_start_noflag(msg, NL80211_ATTR_PEER_MEASUREMENTS);
9bb7e0f2
JB
2196 if (!pmsr)
2197 return -ENOBUFS;
2198
2199 if (nla_put_u32(msg, NL80211_PMSR_ATTR_MAX_PEERS, cap->max_peers))
2200 return -ENOBUFS;
2201
2202 if (cap->report_ap_tsf &&
2203 nla_put_flag(msg, NL80211_PMSR_ATTR_REPORT_AP_TSF))
2204 return -ENOBUFS;
2205
2206 if (cap->randomize_mac_addr &&
2207 nla_put_flag(msg, NL80211_PMSR_ATTR_RANDOMIZE_MAC_ADDR))
2208 return -ENOBUFS;
2209
ae0be8de 2210 caps = nla_nest_start_noflag(msg, NL80211_PMSR_ATTR_TYPE_CAPA);
9bb7e0f2
JB
2211 if (!caps)
2212 return -ENOBUFS;
2213
2214 if (nl80211_send_pmsr_ftm_capa(cap, msg))
2215 return -ENOBUFS;
2216
2217 nla_nest_end(msg, caps);
2218 nla_nest_end(msg, pmsr);
2219
2220 return 0;
2221}
2222
d6039a34
VJ
2223static int
2224nl80211_put_iftype_akm_suites(struct cfg80211_registered_device *rdev,
2225 struct sk_buff *msg)
2226{
2227 int i;
2228 struct nlattr *nested, *nested_akms;
2229 const struct wiphy_iftype_akm_suites *iftype_akms;
2230
2231 if (!rdev->wiphy.num_iftype_akm_suites ||
2232 !rdev->wiphy.iftype_akm_suites)
2233 return 0;
2234
2235 nested = nla_nest_start(msg, NL80211_ATTR_IFTYPE_AKM_SUITES);
2236 if (!nested)
2237 return -ENOBUFS;
2238
2239 for (i = 0; i < rdev->wiphy.num_iftype_akm_suites; i++) {
2240 nested_akms = nla_nest_start(msg, i + 1);
2241 if (!nested_akms)
2242 return -ENOBUFS;
2243
2244 iftype_akms = &rdev->wiphy.iftype_akm_suites[i];
2245
2246 if (nl80211_put_iftypes(msg, NL80211_IFTYPE_AKM_ATTR_IFTYPES,
2247 iftype_akms->iftypes_mask))
2248 return -ENOBUFS;
2249
2250 if (nla_put(msg, NL80211_IFTYPE_AKM_ATTR_SUITES,
2251 sizeof(u32) * iftype_akms->n_akm_suites,
2252 iftype_akms->akm_suites)) {
2253 return -ENOBUFS;
2254 }
2255 nla_nest_end(msg, nested_akms);
2256 }
2257
2258 nla_nest_end(msg, nested);
2259
2260 return 0;
2261}
2262
3710a8a6
JB
2263static int
2264nl80211_put_tid_config_support(struct cfg80211_registered_device *rdev,
2265 struct sk_buff *msg)
2266{
2267 struct nlattr *supp;
2268
2269 if (!rdev->wiphy.tid_config_support.vif &&
2270 !rdev->wiphy.tid_config_support.peer)
2271 return 0;
2272
2273 supp = nla_nest_start(msg, NL80211_ATTR_TID_CONFIG);
2274 if (!supp)
2275 return -ENOSPC;
2276
2277 if (rdev->wiphy.tid_config_support.vif &&
2278 nla_put_u64_64bit(msg, NL80211_TID_CONFIG_ATTR_VIF_SUPP,
2279 rdev->wiphy.tid_config_support.vif,
2280 NL80211_TID_CONFIG_ATTR_PAD))
2281 goto fail;
2282
2283 if (rdev->wiphy.tid_config_support.peer &&
2284 nla_put_u64_64bit(msg, NL80211_TID_CONFIG_ATTR_PEER_SUPP,
2285 rdev->wiphy.tid_config_support.peer,
2286 NL80211_TID_CONFIG_ATTR_PAD))
2287 goto fail;
2288
6a21d16c
T
2289 /* for now we just use the same value ... makes more sense */
2290 if (nla_put_u8(msg, NL80211_TID_CONFIG_ATTR_RETRY_SHORT,
2291 rdev->wiphy.tid_config_support.max_retry))
2292 goto fail;
2293 if (nla_put_u8(msg, NL80211_TID_CONFIG_ATTR_RETRY_LONG,
2294 rdev->wiphy.tid_config_support.max_retry))
2295 goto fail;
2296
3710a8a6
JB
2297 nla_nest_end(msg, supp);
2298
2299 return 0;
2300fail:
2301 nla_nest_cancel(msg, supp);
2302 return -ENOBUFS;
2303}
2304
6bdb68ce
CH
2305static int
2306nl80211_put_sar_specs(struct cfg80211_registered_device *rdev,
2307 struct sk_buff *msg)
2308{
2309 struct nlattr *sar_capa, *specs, *sub_freq_range;
2310 u8 num_freq_ranges;
2311 int i;
2312
2313 if (!rdev->wiphy.sar_capa)
2314 return 0;
2315
2316 num_freq_ranges = rdev->wiphy.sar_capa->num_freq_ranges;
2317
2318 sar_capa = nla_nest_start(msg, NL80211_ATTR_SAR_SPEC);
2319 if (!sar_capa)
2320 return -ENOSPC;
2321
2322 if (nla_put_u32(msg, NL80211_SAR_ATTR_TYPE, rdev->wiphy.sar_capa->type))
2323 goto fail;
2324
2325 specs = nla_nest_start(msg, NL80211_SAR_ATTR_SPECS);
2326 if (!specs)
2327 goto fail;
2328
2329 /* report supported freq_ranges */
2330 for (i = 0; i < num_freq_ranges; i++) {
2331 sub_freq_range = nla_nest_start(msg, i + 1);
2332 if (!sub_freq_range)
2333 goto fail;
2334
2335 if (nla_put_u32(msg, NL80211_SAR_ATTR_SPECS_START_FREQ,
2336 rdev->wiphy.sar_capa->freq_ranges[i].start_freq))
2337 goto fail;
2338
2339 if (nla_put_u32(msg, NL80211_SAR_ATTR_SPECS_END_FREQ,
2340 rdev->wiphy.sar_capa->freq_ranges[i].end_freq))
2341 goto fail;
2342
2343 nla_nest_end(msg, sub_freq_range);
2344 }
2345
2346 nla_nest_end(msg, specs);
2347 nla_nest_end(msg, sar_capa);
2348
2349 return 0;
2350fail:
2351 nla_nest_cancel(msg, sar_capa);
2352 return -ENOBUFS;
2353}
2354
dc1e3cb8
JC
2355static int nl80211_put_mbssid_support(struct wiphy *wiphy, struct sk_buff *msg)
2356{
2357 struct nlattr *config;
2358
2359 if (!wiphy->mbssid_max_interfaces)
2360 return 0;
2361
2362 config = nla_nest_start(msg, NL80211_ATTR_MBSSID_CONFIG);
2363 if (!config)
2364 return -ENOBUFS;
2365
2366 if (nla_put_u8(msg, NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES,
2367 wiphy->mbssid_max_interfaces))
2368 goto fail;
2369
2370 if (wiphy->ema_max_profile_periodicity &&
2371 nla_put_u8(msg,
2372 NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY,
2373 wiphy->ema_max_profile_periodicity))
2374 goto fail;
2375
2376 nla_nest_end(msg, config);
2377 return 0;
2378
2379fail:
2380 nla_nest_cancel(msg, config);
2381 return -ENOBUFS;
2382}
2383
86e8cf98
JB
2384struct nl80211_dump_wiphy_state {
2385 s64 filter_wiphy;
2386 long start;
019ae3a9 2387 long split_start, band_start, chan_start, capa_start;
86e8cf98
JB
2388 bool split;
2389};
2390
1b8ec87a 2391static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
3bb20556 2392 enum nl80211_commands cmd,
3713b4e3 2393 struct sk_buff *msg, u32 portid, u32 seq,
86e8cf98 2394 int flags, struct nl80211_dump_wiphy_state *state)
3713b4e3
JB
2395{
2396 void *hdr;
2397 struct nlattr *nl_bands, *nl_band;
2398 struct nlattr *nl_freqs, *nl_freq;
2399 struct nlattr *nl_cmds;
57fbcce3 2400 enum nl80211_band band;
3713b4e3
JB
2401 struct ieee80211_channel *chan;
2402 int i;
2403 const struct ieee80211_txrx_stypes *mgmt_stypes =
1b8ec87a 2404 rdev->wiphy.mgmt_stypes;
fe1abafd 2405 u32 features;
ee688b00 2406
3bb20556 2407 hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
3713b4e3
JB
2408 if (!hdr)
2409 return -ENOBUFS;
ee688b00 2410
86e8cf98
JB
2411 if (WARN_ON(!state))
2412 return -EINVAL;
ee688b00 2413
1b8ec87a 2414 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
3713b4e3 2415 nla_put_string(msg, NL80211_ATTR_WIPHY_NAME,
1b8ec87a 2416 wiphy_name(&rdev->wiphy)) ||
3713b4e3
JB
2417 nla_put_u32(msg, NL80211_ATTR_GENERATION,
2418 cfg80211_rdev_list_generation))
8fdc621d
JB
2419 goto nla_put_failure;
2420
3bb20556
JB
2421 if (cmd != NL80211_CMD_NEW_WIPHY)
2422 goto finish;
2423
86e8cf98 2424 switch (state->split_start) {
3713b4e3
JB
2425 case 0:
2426 if (nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_SHORT,
1b8ec87a 2427 rdev->wiphy.retry_short) ||
3713b4e3 2428 nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_LONG,
1b8ec87a 2429 rdev->wiphy.retry_long) ||
3713b4e3 2430 nla_put_u32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD,
1b8ec87a 2431 rdev->wiphy.frag_threshold) ||
3713b4e3 2432 nla_put_u32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD,
1b8ec87a 2433 rdev->wiphy.rts_threshold) ||
3713b4e3 2434 nla_put_u8(msg, NL80211_ATTR_WIPHY_COVERAGE_CLASS,
1b8ec87a 2435 rdev->wiphy.coverage_class) ||
3713b4e3 2436 nla_put_u8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS,
1b8ec87a 2437 rdev->wiphy.max_scan_ssids) ||
3713b4e3 2438 nla_put_u8(msg, NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS,
1b8ec87a 2439 rdev->wiphy.max_sched_scan_ssids) ||
3713b4e3 2440 nla_put_u16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN,
1b8ec87a 2441 rdev->wiphy.max_scan_ie_len) ||
3713b4e3 2442 nla_put_u16(msg, NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN,
1b8ec87a 2443 rdev->wiphy.max_sched_scan_ie_len) ||
3713b4e3 2444 nla_put_u8(msg, NL80211_ATTR_MAX_MATCH_SETS,
f8d504ca 2445 rdev->wiphy.max_match_sets))
9360ffd1 2446 goto nla_put_failure;
3713b4e3 2447
1b8ec87a 2448 if ((rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN) &&
3713b4e3 2449 nla_put_flag(msg, NL80211_ATTR_SUPPORT_IBSS_RSN))
aa430da4 2450 goto nla_put_failure;
1b8ec87a 2451 if ((rdev->wiphy.flags & WIPHY_FLAG_MESH_AUTH) &&
3713b4e3
JB
2452 nla_put_flag(msg, NL80211_ATTR_SUPPORT_MESH_AUTH))
2453 goto nla_put_failure;
1b8ec87a 2454 if ((rdev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) &&
3713b4e3
JB
2455 nla_put_flag(msg, NL80211_ATTR_SUPPORT_AP_UAPSD))
2456 goto nla_put_failure;
1b8ec87a 2457 if ((rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_FW_ROAM) &&
3713b4e3
JB
2458 nla_put_flag(msg, NL80211_ATTR_ROAM_SUPPORT))
2459 goto nla_put_failure;
1b8ec87a 2460 if ((rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) &&
3713b4e3
JB
2461 nla_put_flag(msg, NL80211_ATTR_TDLS_SUPPORT))
2462 goto nla_put_failure;
1b8ec87a 2463 if ((rdev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP) &&
3713b4e3 2464 nla_put_flag(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP))
9360ffd1 2465 goto nla_put_failure;
86e8cf98
JB
2466 state->split_start++;
2467 if (state->split)
3713b4e3 2468 break;
7b506ff6 2469 fallthrough;
3713b4e3
JB
2470 case 1:
2471 if (nla_put(msg, NL80211_ATTR_CIPHER_SUITES,
1b8ec87a
ZG
2472 sizeof(u32) * rdev->wiphy.n_cipher_suites,
2473 rdev->wiphy.cipher_suites))
3713b4e3 2474 goto nla_put_failure;
4745fc09 2475
3713b4e3 2476 if (nla_put_u8(msg, NL80211_ATTR_MAX_NUM_PMKIDS,
1b8ec87a 2477 rdev->wiphy.max_num_pmkids))
3713b4e3 2478 goto nla_put_failure;
b23aa676 2479
1b8ec87a 2480 if ((rdev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) &&
3713b4e3 2481 nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE))
9360ffd1 2482 goto nla_put_failure;
b23aa676 2483
3713b4e3 2484 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX,
1b8ec87a 2485 rdev->wiphy.available_antennas_tx) ||
3713b4e3 2486 nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX,
1b8ec87a 2487 rdev->wiphy.available_antennas_rx))
9360ffd1 2488 goto nla_put_failure;
b23aa676 2489
1b8ec87a 2490 if ((rdev->wiphy.flags & WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD) &&
3713b4e3 2491 nla_put_u32(msg, NL80211_ATTR_PROBE_RESP_OFFLOAD,
1b8ec87a 2492 rdev->wiphy.probe_resp_offload))
3713b4e3 2493 goto nla_put_failure;
8fdc621d 2494
1b8ec87a
ZG
2495 if ((rdev->wiphy.available_antennas_tx ||
2496 rdev->wiphy.available_antennas_rx) &&
2497 rdev->ops->get_antenna) {
3713b4e3
JB
2498 u32 tx_ant = 0, rx_ant = 0;
2499 int res;
7a087e74 2500
1b8ec87a 2501 res = rdev_get_antenna(rdev, &tx_ant, &rx_ant);
3713b4e3
JB
2502 if (!res) {
2503 if (nla_put_u32(msg,
2504 NL80211_ATTR_WIPHY_ANTENNA_TX,
2505 tx_ant) ||
2506 nla_put_u32(msg,
2507 NL80211_ATTR_WIPHY_ANTENNA_RX,
2508 rx_ant))
2509 goto nla_put_failure;
2510 }
2511 }
a293911d 2512
86e8cf98
JB
2513 state->split_start++;
2514 if (state->split)
3713b4e3 2515 break;
7b506ff6 2516 fallthrough;
3713b4e3
JB
2517 case 2:
2518 if (nl80211_put_iftypes(msg, NL80211_ATTR_SUPPORTED_IFTYPES,
1b8ec87a 2519 rdev->wiphy.interface_modes))
3713b4e3 2520 goto nla_put_failure;
86e8cf98
JB
2521 state->split_start++;
2522 if (state->split)
3713b4e3 2523 break;
7b506ff6 2524 fallthrough;
3713b4e3 2525 case 3:
ae0be8de
MK
2526 nl_bands = nla_nest_start_noflag(msg,
2527 NL80211_ATTR_WIPHY_BANDS);
3713b4e3
JB
2528 if (!nl_bands)
2529 goto nla_put_failure;
f7ca38df 2530
86e8cf98 2531 for (band = state->band_start;
0d059964
JB
2532 band < (state->split ?
2533 NUM_NL80211_BANDS :
2534 NL80211_BAND_60GHZ + 1);
2535 band++) {
3713b4e3 2536 struct ieee80211_supported_band *sband;
2e161f78 2537
f8d504ca
JB
2538 /* omit higher bands for ancient software */
2539 if (band > NL80211_BAND_5GHZ && !state->split)
2540 break;
2541
1b8ec87a 2542 sband = rdev->wiphy.bands[band];
2e161f78 2543
3713b4e3
JB
2544 if (!sband)
2545 continue;
2546
ae0be8de 2547 nl_band = nla_nest_start_noflag(msg, band);
3713b4e3 2548 if (!nl_band)
2e161f78 2549 goto nla_put_failure;
3713b4e3 2550
86e8cf98 2551 switch (state->chan_start) {
3713b4e3 2552 case 0:
f8d504ca
JB
2553 if (nl80211_send_band_rateinfo(msg, sband,
2554 state->split))
9360ffd1 2555 goto nla_put_failure;
86e8cf98
JB
2556 state->chan_start++;
2557 if (state->split)
3713b4e3 2558 break;
7b506ff6 2559 fallthrough;
3713b4e3
JB
2560 default:
2561 /* add frequencies */
ae0be8de
MK
2562 nl_freqs = nla_nest_start_noflag(msg,
2563 NL80211_BAND_ATTR_FREQS);
3713b4e3
JB
2564 if (!nl_freqs)
2565 goto nla_put_failure;
2566
86e8cf98 2567 for (i = state->chan_start - 1;
3713b4e3
JB
2568 i < sband->n_channels;
2569 i++) {
ae0be8de
MK
2570 nl_freq = nla_nest_start_noflag(msg,
2571 i);
3713b4e3
JB
2572 if (!nl_freq)
2573 goto nla_put_failure;
2574
2575 chan = &sband->channels[i];
2576
86e8cf98 2577 if (nl80211_msg_put_channel(
50f32718 2578 msg, &rdev->wiphy, chan,
86e8cf98 2579 state->split))
3713b4e3
JB
2580 goto nla_put_failure;
2581
2582 nla_nest_end(msg, nl_freq);
86e8cf98 2583 if (state->split)
3713b4e3
JB
2584 break;
2585 }
2586 if (i < sband->n_channels)
86e8cf98 2587 state->chan_start = i + 2;
3713b4e3 2588 else
86e8cf98 2589 state->chan_start = 0;
3713b4e3
JB
2590 nla_nest_end(msg, nl_freqs);
2591 }
2592
2593 nla_nest_end(msg, nl_band);
2594
86e8cf98 2595 if (state->split) {
3713b4e3 2596 /* start again here */
86e8cf98 2597 if (state->chan_start)
3713b4e3
JB
2598 band--;
2599 break;
2e161f78 2600 }
2e161f78 2601 }
3713b4e3 2602 nla_nest_end(msg, nl_bands);
2e161f78 2603
57fbcce3 2604 if (band < NUM_NL80211_BANDS)
86e8cf98 2605 state->band_start = band + 1;
3713b4e3 2606 else
86e8cf98 2607 state->band_start = 0;
74b70a4e 2608
3713b4e3 2609 /* if bands & channels are done, continue outside */
86e8cf98
JB
2610 if (state->band_start == 0 && state->chan_start == 0)
2611 state->split_start++;
2612 if (state->split)
3713b4e3 2613 break;
7b506ff6 2614 fallthrough;
3713b4e3 2615 case 4:
ae0be8de
MK
2616 nl_cmds = nla_nest_start_noflag(msg,
2617 NL80211_ATTR_SUPPORTED_COMMANDS);
3713b4e3 2618 if (!nl_cmds)
2e161f78
JB
2619 goto nla_put_failure;
2620
1794899e
JB
2621 i = nl80211_add_commands_unsplit(rdev, msg);
2622 if (i < 0)
2623 goto nla_put_failure;
86e8cf98 2624 if (state->split) {
5de17984
AS
2625 CMD(crit_proto_start, CRIT_PROTOCOL_START);
2626 CMD(crit_proto_stop, CRIT_PROTOCOL_STOP);
1b8ec87a 2627 if (rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH)
16ef1fe2 2628 CMD(channel_switch, CHANNEL_SWITCH);
02df00eb 2629 CMD(set_qos_map, SET_QOS_MAP);
723e73ac
JB
2630 if (rdev->wiphy.features &
2631 NL80211_FEATURE_SUPPORTS_WMM_ADMISSION)
960d01ac 2632 CMD(add_tx_ts, ADD_TX_TS);
ce0ce13a 2633 CMD(set_multicast_to_unicast, SET_MULTICAST_TO_UNICAST);
088e8df8 2634 CMD(update_connect_params, UPDATE_CONNECT_PARAMS);
7010998c 2635 CMD(update_ft_ies, UPDATE_FT_IES);
6bdb68ce
CH
2636 if (rdev->wiphy.sar_capa)
2637 CMD(set_sar_specs, SET_SAR_SPECS);
5de17984 2638 }
3713b4e3 2639#undef CMD
ff1b6e69 2640
3713b4e3 2641 nla_nest_end(msg, nl_cmds);
86e8cf98
JB
2642 state->split_start++;
2643 if (state->split)
3713b4e3 2644 break;
7b506ff6 2645 fallthrough;
3713b4e3 2646 case 5:
1b8ec87a
ZG
2647 if (rdev->ops->remain_on_channel &&
2648 (rdev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL) &&
3713b4e3
JB
2649 nla_put_u32(msg,
2650 NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION,
1b8ec87a 2651 rdev->wiphy.max_remain_on_channel_duration))
3713b4e3
JB
2652 goto nla_put_failure;
2653
1b8ec87a 2654 if ((rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX) &&
3713b4e3
JB
2655 nla_put_flag(msg, NL80211_ATTR_OFFCHANNEL_TX_OK))
2656 goto nla_put_failure;
2657
86e8cf98
JB
2658 state->split_start++;
2659 if (state->split)
3713b4e3 2660 break;
7b506ff6 2661 fallthrough;
3713b4e3
JB
2662 case 6:
2663#ifdef CONFIG_PM
1b8ec87a 2664 if (nl80211_send_wowlan(msg, rdev, state->split))
3713b4e3 2665 goto nla_put_failure;
86e8cf98
JB
2666 state->split_start++;
2667 if (state->split)
3713b4e3
JB
2668 break;
2669#else
86e8cf98 2670 state->split_start++;
dfb89c56 2671#endif
7b506ff6 2672 fallthrough;
3713b4e3
JB
2673 case 7:
2674 if (nl80211_put_iftypes(msg, NL80211_ATTR_SOFTWARE_IFTYPES,
1b8ec87a 2675 rdev->wiphy.software_iftypes))
3713b4e3 2676 goto nla_put_failure;
ff1b6e69 2677
1b8ec87a 2678 if (nl80211_put_iface_combinations(&rdev->wiphy, msg,
86e8cf98 2679 state->split))
3713b4e3 2680 goto nla_put_failure;
7527a782 2681
86e8cf98
JB
2682 state->split_start++;
2683 if (state->split)
3713b4e3 2684 break;
7b506ff6 2685 fallthrough;
3713b4e3 2686 case 8:
1b8ec87a 2687 if ((rdev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME) &&
3713b4e3 2688 nla_put_u32(msg, NL80211_ATTR_DEVICE_AP_SME,
1b8ec87a 2689 rdev->wiphy.ap_sme_capa))
3713b4e3 2690 goto nla_put_failure;
7527a782 2691
1b8ec87a 2692 features = rdev->wiphy.features;
fe1abafd
JB
2693 /*
2694 * We can only add the per-channel limit information if the
2695 * dump is split, otherwise it makes it too big. Therefore
2696 * only advertise it in that case.
2697 */
86e8cf98 2698 if (state->split)
fe1abafd
JB
2699 features |= NL80211_FEATURE_ADVERTISE_CHAN_LIMITS;
2700 if (nla_put_u32(msg, NL80211_ATTR_FEATURE_FLAGS, features))
3713b4e3 2701 goto nla_put_failure;
562a7480 2702
1b8ec87a 2703 if (rdev->wiphy.ht_capa_mod_mask &&
3713b4e3 2704 nla_put(msg, NL80211_ATTR_HT_CAPABILITY_MASK,
1b8ec87a
ZG
2705 sizeof(*rdev->wiphy.ht_capa_mod_mask),
2706 rdev->wiphy.ht_capa_mod_mask))
3713b4e3 2707 goto nla_put_failure;
1f074bd8 2708
1b8ec87a
ZG
2709 if (rdev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME &&
2710 rdev->wiphy.max_acl_mac_addrs &&
3713b4e3 2711 nla_put_u32(msg, NL80211_ATTR_MAC_ACL_MAX,
1b8ec87a 2712 rdev->wiphy.max_acl_mac_addrs))
3713b4e3 2713 goto nla_put_failure;
7e7c8926 2714
3713b4e3
JB
2715 /*
2716 * Any information below this point is only available to
2717 * applications that can deal with it being split. This
2718 * helps ensure that newly added capabilities don't break
2719 * older tools by overrunning their buffers.
2720 *
2721 * We still increment split_start so that in the split
2722 * case we'll continue with more data in the next round,
2723 * but break unconditionally so unsplit data stops here.
2724 */
ab10c22b
JB
2725 if (state->split)
2726 state->split_start++;
2727 else
2728 state->split_start = 0;
3713b4e3
JB
2729 break;
2730 case 9:
f8d504ca
JB
2731 if (nl80211_send_mgmt_stypes(msg, mgmt_stypes))
2732 goto nla_put_failure;
2733
2734 if (nla_put_u32(msg, NL80211_ATTR_MAX_NUM_SCHED_SCAN_PLANS,
2735 rdev->wiphy.max_sched_scan_plans) ||
2736 nla_put_u32(msg, NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL,
2737 rdev->wiphy.max_sched_scan_plan_interval) ||
2738 nla_put_u32(msg, NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS,
2739 rdev->wiphy.max_sched_scan_plan_iterations))
2740 goto nla_put_failure;
2741
1b8ec87a 2742 if (rdev->wiphy.extended_capabilities &&
fe1abafd 2743 (nla_put(msg, NL80211_ATTR_EXT_CAPA,
1b8ec87a
ZG
2744 rdev->wiphy.extended_capabilities_len,
2745 rdev->wiphy.extended_capabilities) ||
fe1abafd 2746 nla_put(msg, NL80211_ATTR_EXT_CAPA_MASK,
1b8ec87a
ZG
2747 rdev->wiphy.extended_capabilities_len,
2748 rdev->wiphy.extended_capabilities_mask)))
fe1abafd 2749 goto nla_put_failure;
a50df0c4 2750
1b8ec87a 2751 if (rdev->wiphy.vht_capa_mod_mask &&
ee2aca34 2752 nla_put(msg, NL80211_ATTR_VHT_CAPABILITY_MASK,
1b8ec87a
ZG
2753 sizeof(*rdev->wiphy.vht_capa_mod_mask),
2754 rdev->wiphy.vht_capa_mod_mask))
ee2aca34
JB
2755 goto nla_put_failure;
2756
ae6fa4d5
DK
2757 if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN,
2758 rdev->wiphy.perm_addr))
2759 goto nla_put_failure;
2760
2761 if (!is_zero_ether_addr(rdev->wiphy.addr_mask) &&
2762 nla_put(msg, NL80211_ATTR_MAC_MASK, ETH_ALEN,
2763 rdev->wiphy.addr_mask))
2764 goto nla_put_failure;
2765
2766 if (rdev->wiphy.n_addresses > 1) {
2767 void *attr;
2768
2769 attr = nla_nest_start(msg, NL80211_ATTR_MAC_ADDRS);
2770 if (!attr)
2771 goto nla_put_failure;
2772
2773 for (i = 0; i < rdev->wiphy.n_addresses; i++)
2774 if (nla_put(msg, i + 1, ETH_ALEN,
2775 rdev->wiphy.addresses[i].addr))
2776 goto nla_put_failure;
2777
2778 nla_nest_end(msg, attr);
2779 }
2780
be29b99a
AK
2781 state->split_start++;
2782 break;
2783 case 10:
1b8ec87a 2784 if (nl80211_send_coalesce(msg, rdev))
be29b99a
AK
2785 goto nla_put_failure;
2786
1b8ec87a 2787 if ((rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_5_10_MHZ) &&
01e0daa4
FF
2788 (nla_put_flag(msg, NL80211_ATTR_SUPPORT_5_MHZ) ||
2789 nla_put_flag(msg, NL80211_ATTR_SUPPORT_10_MHZ)))
2790 goto nla_put_failure;
b43504cf 2791
1b8ec87a 2792 if (rdev->wiphy.max_ap_assoc_sta &&
b43504cf 2793 nla_put_u32(msg, NL80211_ATTR_MAX_AP_ASSOC_STA,
1b8ec87a 2794 rdev->wiphy.max_ap_assoc_sta))
b43504cf
JM
2795 goto nla_put_failure;
2796
ad7e718c
JB
2797 state->split_start++;
2798 break;
2799 case 11:
1b8ec87a 2800 if (rdev->wiphy.n_vendor_commands) {
567ffc35
JB
2801 const struct nl80211_vendor_cmd_info *info;
2802 struct nlattr *nested;
2803
ae0be8de
MK
2804 nested = nla_nest_start_noflag(msg,
2805 NL80211_ATTR_VENDOR_DATA);
567ffc35
JB
2806 if (!nested)
2807 goto nla_put_failure;
2808
1b8ec87a
ZG
2809 for (i = 0; i < rdev->wiphy.n_vendor_commands; i++) {
2810 info = &rdev->wiphy.vendor_commands[i].info;
567ffc35
JB
2811 if (nla_put(msg, i + 1, sizeof(*info), info))
2812 goto nla_put_failure;
2813 }
2814 nla_nest_end(msg, nested);
2815 }
2816
1b8ec87a 2817 if (rdev->wiphy.n_vendor_events) {
567ffc35
JB
2818 const struct nl80211_vendor_cmd_info *info;
2819 struct nlattr *nested;
ad7e718c 2820
ae0be8de
MK
2821 nested = nla_nest_start_noflag(msg,
2822 NL80211_ATTR_VENDOR_EVENTS);
567ffc35 2823 if (!nested)
ad7e718c 2824 goto nla_put_failure;
567ffc35 2825
1b8ec87a
ZG
2826 for (i = 0; i < rdev->wiphy.n_vendor_events; i++) {
2827 info = &rdev->wiphy.vendor_events[i];
567ffc35
JB
2828 if (nla_put(msg, i + 1, sizeof(*info), info))
2829 goto nla_put_failure;
2830 }
2831 nla_nest_end(msg, nested);
2832 }
9a774c78
AO
2833 state->split_start++;
2834 break;
2835 case 12:
2836 if (rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH &&
2837 nla_put_u8(msg, NL80211_ATTR_MAX_CSA_COUNTERS,
2838 rdev->wiphy.max_num_csa_counters))
2839 goto nla_put_failure;
01e0daa4 2840
1bdd716c
AN
2841 if (rdev->wiphy.regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED &&
2842 nla_put_flag(msg, NL80211_ATTR_WIPHY_SELF_MANAGED_REG))
2843 goto nla_put_failure;
2844
ca986ad9
AVS
2845 if (rdev->wiphy.max_sched_scan_reqs &&
2846 nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_MAX_REQS,
2847 rdev->wiphy.max_sched_scan_reqs))
2848 goto nla_put_failure;
2849
d75bb06b
GKS
2850 if (nla_put(msg, NL80211_ATTR_EXT_FEATURES,
2851 sizeof(rdev->wiphy.ext_features),
2852 rdev->wiphy.ext_features))
2853 goto nla_put_failure;
2854
38de03d2
AS
2855 if (rdev->wiphy.bss_select_support) {
2856 struct nlattr *nested;
2857 u32 bss_select_support = rdev->wiphy.bss_select_support;
2858
ae0be8de
MK
2859 nested = nla_nest_start_noflag(msg,
2860 NL80211_ATTR_BSS_SELECT);
38de03d2
AS
2861 if (!nested)
2862 goto nla_put_failure;
2863
2864 i = 0;
2865 while (bss_select_support) {
2866 if ((bss_select_support & 1) &&
2867 nla_put_flag(msg, i))
2868 goto nla_put_failure;
2869 i++;
2870 bss_select_support >>= 1;
2871 }
2872 nla_nest_end(msg, nested);
2873 }
2874
019ae3a9
KV
2875 state->split_start++;
2876 break;
2877 case 13:
2878 if (rdev->wiphy.num_iftype_ext_capab &&
2879 rdev->wiphy.iftype_ext_capab) {
2880 struct nlattr *nested_ext_capab, *nested;
2881
ae0be8de
MK
2882 nested = nla_nest_start_noflag(msg,
2883 NL80211_ATTR_IFTYPE_EXT_CAPA);
019ae3a9
KV
2884 if (!nested)
2885 goto nla_put_failure;
2886
2887 for (i = state->capa_start;
2888 i < rdev->wiphy.num_iftype_ext_capab; i++) {
2889 const struct wiphy_iftype_ext_capab *capab;
2890
2891 capab = &rdev->wiphy.iftype_ext_capab[i];
2892
ae0be8de
MK
2893 nested_ext_capab = nla_nest_start_noflag(msg,
2894 i);
019ae3a9
KV
2895 if (!nested_ext_capab ||
2896 nla_put_u32(msg, NL80211_ATTR_IFTYPE,
2897 capab->iftype) ||
2898 nla_put(msg, NL80211_ATTR_EXT_CAPA,
2899 capab->extended_capabilities_len,
2900 capab->extended_capabilities) ||
2901 nla_put(msg, NL80211_ATTR_EXT_CAPA_MASK,
2902 capab->extended_capabilities_len,
2903 capab->extended_capabilities_mask))
2904 goto nla_put_failure;
2905
4e9c3af3
JB
2906 if (rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_MLO &&
2907 (nla_put_u16(msg,
2908 NL80211_ATTR_EML_CAPABILITY,
2909 capab->eml_capabilities) ||
2910 nla_put_u16(msg,
2911 NL80211_ATTR_MLD_CAPA_AND_OPS,
2912 capab->mld_capa_and_ops)))
2913 goto nla_put_failure;
2914
019ae3a9
KV
2915 nla_nest_end(msg, nested_ext_capab);
2916 if (state->split)
2917 break;
2918 }
2919 nla_nest_end(msg, nested);
2920 if (i < rdev->wiphy.num_iftype_ext_capab) {
2921 state->capa_start = i + 1;
2922 break;
2923 }
2924 }
2925
8585989d
LC
2926 if (nla_put_u32(msg, NL80211_ATTR_BANDS,
2927 rdev->wiphy.nan_supported_bands))
2928 goto nla_put_failure;
2929
52539ca8
THJ
2930 if (wiphy_ext_feature_isset(&rdev->wiphy,
2931 NL80211_EXT_FEATURE_TXQS)) {
2932 struct cfg80211_txq_stats txqstats = {};
2933 int res;
2934
2935 res = rdev_get_txq_stats(rdev, NULL, &txqstats);
2936 if (!res &&
2937 !nl80211_put_txq_stats(msg, &txqstats,
2938 NL80211_ATTR_TXQ_STATS))
2939 goto nla_put_failure;
2940
2941 if (nla_put_u32(msg, NL80211_ATTR_TXQ_LIMIT,
2942 rdev->wiphy.txq_limit))
2943 goto nla_put_failure;
2944 if (nla_put_u32(msg, NL80211_ATTR_TXQ_MEMORY_LIMIT,
2945 rdev->wiphy.txq_memory_limit))
2946 goto nla_put_failure;
2947 if (nla_put_u32(msg, NL80211_ATTR_TXQ_QUANTUM,
2948 rdev->wiphy.txq_quantum))
2949 goto nla_put_failure;
2950 }
2951
9bb7e0f2
JB
2952 state->split_start++;
2953 break;
2954 case 14:
2955 if (nl80211_send_pmsr_capa(rdev, msg))
2956 goto nla_put_failure;
2957
ab4dfa20
VJ
2958 state->split_start++;
2959 break;
2960 case 15:
2961 if (rdev->wiphy.akm_suites &&
2962 nla_put(msg, NL80211_ATTR_AKM_SUITES,
2963 sizeof(u32) * rdev->wiphy.n_akm_suites,
2964 rdev->wiphy.akm_suites))
2965 goto nla_put_failure;
2966
d6039a34
VJ
2967 if (nl80211_put_iftype_akm_suites(rdev, msg))
2968 goto nla_put_failure;
2969
3710a8a6
JB
2970 if (nl80211_put_tid_config_support(rdev, msg))
2971 goto nla_put_failure;
6bdb68ce
CH
2972 state->split_start++;
2973 break;
2974 case 16:
2975 if (nl80211_put_sar_specs(rdev, msg))
2976 goto nla_put_failure;
3710a8a6 2977
dc1e3cb8
JC
2978 if (nl80211_put_mbssid_support(&rdev->wiphy, msg))
2979 goto nla_put_failure;
2980
ecad3b0b
VJ
2981 if (nla_put_u16(msg, NL80211_ATTR_MAX_NUM_AKM_SUITES,
2982 rdev->wiphy.max_num_akm_suites))
2983 goto nla_put_failure;
2984
fa2ca639
JB
2985 if (rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_MLO)
2986 nla_put_flag(msg, NL80211_ATTR_MLO_SUPPORT);
2987
cbbaf2bb
AS
2988 if (rdev->wiphy.hw_timestamp_max_peers &&
2989 nla_put_u16(msg, NL80211_ATTR_MAX_HW_TIMESTAMP_PEERS,
2990 rdev->wiphy.hw_timestamp_max_peers))
2991 goto nla_put_failure;
2992
3713b4e3 2993 /* done */
86e8cf98 2994 state->split_start = 0;
3713b4e3
JB
2995 break;
2996 }
3bb20556 2997 finish:
053c095a
JB
2998 genlmsg_end(msg, hdr);
2999 return 0;
55682965
JB
3000
3001 nla_put_failure:
bc3ed28c
TG
3002 genlmsg_cancel(msg, hdr);
3003 return -EMSGSIZE;
55682965
JB
3004}
3005
86e8cf98
JB
3006static int nl80211_dump_wiphy_parse(struct sk_buff *skb,
3007 struct netlink_callback *cb,
3008 struct nl80211_dump_wiphy_state *state)
3009{
50508d94
JB
3010 struct nlattr **tb = kcalloc(NUM_NL80211_ATTR, sizeof(*tb), GFP_KERNEL);
3011 int ret;
3012
3013 if (!tb)
3014 return -ENOMEM;
3015
3016 ret = nlmsg_parse_deprecated(cb->nlh,
3017 GENL_HDRLEN + nl80211_fam.hdrsize,
3018 tb, nl80211_fam.maxattr,
3019 nl80211_policy, NULL);
86e8cf98 3020 /* ignore parse errors for backward compatibility */
50508d94
JB
3021 if (ret) {
3022 ret = 0;
3023 goto out;
3024 }
86e8cf98
JB
3025
3026 state->split = tb[NL80211_ATTR_SPLIT_WIPHY_DUMP];
3027 if (tb[NL80211_ATTR_WIPHY])
3028 state->filter_wiphy = nla_get_u32(tb[NL80211_ATTR_WIPHY]);
3029 if (tb[NL80211_ATTR_WDEV])
3030 state->filter_wiphy = nla_get_u64(tb[NL80211_ATTR_WDEV]) >> 32;
3031 if (tb[NL80211_ATTR_IFINDEX]) {
3032 struct net_device *netdev;
3033 struct cfg80211_registered_device *rdev;
3034 int ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
3035
7f2b8562 3036 netdev = __dev_get_by_index(sock_net(skb->sk), ifidx);
50508d94
JB
3037 if (!netdev) {
3038 ret = -ENODEV;
3039 goto out;
3040 }
86e8cf98 3041 if (netdev->ieee80211_ptr) {
f26cbf40 3042 rdev = wiphy_to_rdev(
86e8cf98
JB
3043 netdev->ieee80211_ptr->wiphy);
3044 state->filter_wiphy = rdev->wiphy_idx;
3045 }
86e8cf98
JB
3046 }
3047
50508d94
JB
3048 ret = 0;
3049out:
3050 kfree(tb);
3051 return ret;
86e8cf98
JB
3052}
3053
55682965
JB
3054static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
3055{
645e77de 3056 int idx = 0, ret;
86e8cf98 3057 struct nl80211_dump_wiphy_state *state = (void *)cb->args[0];
1b8ec87a 3058 struct cfg80211_registered_device *rdev;
3a5a423b 3059
5fe231e8 3060 rtnl_lock();
86e8cf98
JB
3061 if (!state) {
3062 state = kzalloc(sizeof(*state), GFP_KERNEL);
57ed5cd6
JL
3063 if (!state) {
3064 rtnl_unlock();
86e8cf98 3065 return -ENOMEM;
3713b4e3 3066 }
86e8cf98
JB
3067 state->filter_wiphy = -1;
3068 ret = nl80211_dump_wiphy_parse(skb, cb, state);
3069 if (ret) {
3070 kfree(state);
3071 rtnl_unlock();
3072 return ret;
3713b4e3 3073 }
86e8cf98 3074 cb->args[0] = (long)state;
3713b4e3
JB
3075 }
3076
1b8ec87a
ZG
3077 list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
3078 if (!net_eq(wiphy_net(&rdev->wiphy), sock_net(skb->sk)))
463d0183 3079 continue;
86e8cf98 3080 if (++idx <= state->start)
55682965 3081 continue;
86e8cf98 3082 if (state->filter_wiphy != -1 &&
1b8ec87a 3083 state->filter_wiphy != rdev->wiphy_idx)
3713b4e3 3084 continue;
4d45145b 3085 wiphy_lock(&rdev->wiphy);
3713b4e3
JB
3086 /* attempt to fit multiple wiphy data chunks into the skb */
3087 do {
3bb20556
JB
3088 ret = nl80211_send_wiphy(rdev, NL80211_CMD_NEW_WIPHY,
3089 skb,
3713b4e3
JB
3090 NETLINK_CB(cb->skb).portid,
3091 cb->nlh->nlmsg_seq,
86e8cf98 3092 NLM_F_MULTI, state);
3713b4e3
JB
3093 if (ret < 0) {
3094 /*
3095 * If sending the wiphy data didn't fit (ENOBUFS
3096 * or EMSGSIZE returned), this SKB is still
3097 * empty (so it's not too big because another
3098 * wiphy dataset is already in the skb) and
3099 * we've not tried to adjust the dump allocation
3100 * yet ... then adjust the alloc size to be
3101 * bigger, and return 1 but with the empty skb.
3102 * This results in an empty message being RX'ed
3103 * in userspace, but that is ignored.
3104 *
3105 * We can then retry with the larger buffer.
3106 */
3107 if ((ret == -ENOBUFS || ret == -EMSGSIZE) &&
f12cb289 3108 !skb->len && !state->split &&
3713b4e3
JB
3109 cb->min_dump_alloc < 4096) {
3110 cb->min_dump_alloc = 4096;
f12cb289 3111 state->split_start = 0;
4d45145b 3112 wiphy_unlock(&rdev->wiphy);
d98cae64 3113 rtnl_unlock();
3713b4e3
JB
3114 return 1;
3115 }
3116 idx--;
3117 break;
645e77de 3118 }
86e8cf98 3119 } while (state->split_start > 0);
4d45145b 3120 wiphy_unlock(&rdev->wiphy);
3713b4e3 3121 break;
55682965 3122 }
5fe231e8 3123 rtnl_unlock();
55682965 3124
86e8cf98 3125 state->start = idx;
55682965
JB
3126
3127 return skb->len;
3128}
3129
86e8cf98
JB
3130static int nl80211_dump_wiphy_done(struct netlink_callback *cb)
3131{
3132 kfree((void *)cb->args[0]);
3133 return 0;
3134}
3135
55682965
JB
3136static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info)
3137{
3138 struct sk_buff *msg;
1b8ec87a 3139 struct cfg80211_registered_device *rdev = info->user_ptr[0];
86e8cf98 3140 struct nl80211_dump_wiphy_state state = {};
55682965 3141
645e77de 3142 msg = nlmsg_new(4096, GFP_KERNEL);
55682965 3143 if (!msg)
4c476991 3144 return -ENOMEM;
55682965 3145
3bb20556
JB
3146 if (nl80211_send_wiphy(rdev, NL80211_CMD_NEW_WIPHY, msg,
3147 info->snd_portid, info->snd_seq, 0,
86e8cf98 3148 &state) < 0) {
4c476991
JB
3149 nlmsg_free(msg);
3150 return -ENOBUFS;
3151 }
55682965 3152
134e6375 3153 return genlmsg_reply(msg, info);
55682965
JB
3154}
3155
31888487
JM
3156static const struct nla_policy txq_params_policy[NL80211_TXQ_ATTR_MAX + 1] = {
3157 [NL80211_TXQ_ATTR_QUEUE] = { .type = NLA_U8 },
3158 [NL80211_TXQ_ATTR_TXOP] = { .type = NLA_U16 },
3159 [NL80211_TXQ_ATTR_CWMIN] = { .type = NLA_U16 },
3160 [NL80211_TXQ_ATTR_CWMAX] = { .type = NLA_U16 },
3161 [NL80211_TXQ_ATTR_AIFS] = { .type = NLA_U8 },
3162};
3163
3164static int parse_txq_params(struct nlattr *tb[],
3165 struct ieee80211_txq_params *txq_params)
3166{
259d8c1e
DW
3167 u8 ac;
3168
a3304b0a 3169 if (!tb[NL80211_TXQ_ATTR_AC] || !tb[NL80211_TXQ_ATTR_TXOP] ||
31888487
JM
3170 !tb[NL80211_TXQ_ATTR_CWMIN] || !tb[NL80211_TXQ_ATTR_CWMAX] ||
3171 !tb[NL80211_TXQ_ATTR_AIFS])
3172 return -EINVAL;
3173
259d8c1e 3174 ac = nla_get_u8(tb[NL80211_TXQ_ATTR_AC]);
31888487
JM
3175 txq_params->txop = nla_get_u16(tb[NL80211_TXQ_ATTR_TXOP]);
3176 txq_params->cwmin = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMIN]);
3177 txq_params->cwmax = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMAX]);
3178 txq_params->aifs = nla_get_u8(tb[NL80211_TXQ_ATTR_AIFS]);
3179
259d8c1e 3180 if (ac >= NL80211_NUM_ACS)
a3304b0a 3181 return -EINVAL;
259d8c1e 3182 txq_params->ac = array_index_nospec(ac, NL80211_NUM_ACS);
31888487
JM
3183 return 0;
3184}
3185
f444de05
JB
3186static bool nl80211_can_set_dev_channel(struct wireless_dev *wdev)
3187{
3188 /*
e7e0517c
JB
3189 * You can only set the channel explicitly for some interfaces,
3190 * most have their channel managed via their respective
cc1d2806
JB
3191 * "establish a connection" command (connect, join, ...)
3192 *
3193 * For AP/GO and mesh mode, the channel can be set with the
3194 * channel userspace API, but is only stored and passed to the
3195 * low-level driver when the AP starts or the mesh is joined.
3196 * This is for backward compatibility, userspace can also give
3197 * the channel in the start-ap or join-mesh commands instead.
f444de05
JB
3198 *
3199 * Monitors are special as they are normally slaved to
e8c9bd5b
JB
3200 * whatever else is going on, so they have their own special
3201 * operation to set the monitor channel if possible.
f444de05
JB
3202 */
3203 return !wdev ||
3204 wdev->iftype == NL80211_IFTYPE_AP ||
f444de05 3205 wdev->iftype == NL80211_IFTYPE_MESH_POINT ||
074ac8df
JB
3206 wdev->iftype == NL80211_IFTYPE_MONITOR ||
3207 wdev->iftype == NL80211_IFTYPE_P2P_GO;
f444de05
JB
3208}
3209
d7c1a9a0
AD
3210static int nl80211_parse_punct_bitmap(struct cfg80211_registered_device *rdev,
3211 struct genl_info *info,
3212 const struct cfg80211_chan_def *chandef,
3213 u16 *punct_bitmap)
3214{
3215 if (!wiphy_ext_feature_isset(&rdev->wiphy, NL80211_EXT_FEATURE_PUNCT))
3216 return -EINVAL;
3217
3218 *punct_bitmap = nla_get_u32(info->attrs[NL80211_ATTR_PUNCT_BITMAP]);
3219 if (!cfg80211_valid_disable_subchannel_bitmap(punct_bitmap, chandef))
3220 return -EINVAL;
3221
3222 return 0;
3223}
3224
9bb7e0f2
JB
3225int nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
3226 struct genl_info *info,
3227 struct cfg80211_chan_def *chandef)
683b6d3b 3228{
49f9cf0e
JB
3229 struct netlink_ext_ack *extack = info->extack;
3230 struct nlattr **attrs = info->attrs;
dbeca2ea 3231 u32 control_freq;
683b6d3b 3232
90b2c3cc
JK
3233 if (!attrs[NL80211_ATTR_WIPHY_FREQ]) {
3234 NL_SET_ERR_MSG_ATTR(extack, attrs[NL80211_ATTR_WIPHY_FREQ],
3235 "Frequency is missing");
683b6d3b 3236 return -EINVAL;
90b2c3cc 3237 }
683b6d3b 3238
942ba88b
TP
3239 control_freq = MHZ_TO_KHZ(
3240 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
3241 if (info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET])
3242 control_freq +=
3243 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET]);
683b6d3b 3244
f43e5210 3245 memset(chandef, 0, sizeof(*chandef));
942ba88b 3246 chandef->chan = ieee80211_get_channel_khz(&rdev->wiphy, control_freq);
3d9d1d66 3247 chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
942ba88b
TP
3248 chandef->center_freq1 = KHZ_TO_MHZ(control_freq);
3249 chandef->freq1_offset = control_freq % 1000;
3d9d1d66 3250 chandef->center_freq2 = 0;
683b6d3b
JB
3251
3252 /* Primary channel not allowed */
49f9cf0e
JB
3253 if (!chandef->chan || chandef->chan->flags & IEEE80211_CHAN_DISABLED) {
3254 NL_SET_ERR_MSG_ATTR(extack, attrs[NL80211_ATTR_WIPHY_FREQ],
3255 "Channel is disabled");
683b6d3b 3256 return -EINVAL;
49f9cf0e 3257 }
683b6d3b 3258
49f9cf0e 3259 if (attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
3d9d1d66
JB
3260 enum nl80211_channel_type chantype;
3261
49f9cf0e 3262 chantype = nla_get_u32(attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
3d9d1d66
JB
3263
3264 switch (chantype) {
3265 case NL80211_CHAN_NO_HT:
3266 case NL80211_CHAN_HT20:
3267 case NL80211_CHAN_HT40PLUS:
3268 case NL80211_CHAN_HT40MINUS:
3269 cfg80211_chandef_create(chandef, chandef->chan,
3270 chantype);
ffa4629e 3271 /* user input for center_freq is incorrect */
49f9cf0e
JB
3272 if (attrs[NL80211_ATTR_CENTER_FREQ1] &&
3273 chandef->center_freq1 != nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ1])) {
3274 NL_SET_ERR_MSG_ATTR(extack,
3275 attrs[NL80211_ATTR_CENTER_FREQ1],
3276 "bad center frequency 1");
ffa4629e 3277 return -EINVAL;
49f9cf0e 3278 }
ffa4629e 3279 /* center_freq2 must be zero */
49f9cf0e
JB
3280 if (attrs[NL80211_ATTR_CENTER_FREQ2] &&
3281 nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ2])) {
3282 NL_SET_ERR_MSG_ATTR(extack,
3283 attrs[NL80211_ATTR_CENTER_FREQ2],
3284 "center frequency 2 can't be used");
ffa4629e 3285 return -EINVAL;
49f9cf0e 3286 }
3d9d1d66
JB
3287 break;
3288 default:
49f9cf0e
JB
3289 NL_SET_ERR_MSG_ATTR(extack,
3290 attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE],
3291 "invalid channel type");
3d9d1d66
JB
3292 return -EINVAL;
3293 }
49f9cf0e 3294 } else if (attrs[NL80211_ATTR_CHANNEL_WIDTH]) {
3d9d1d66 3295 chandef->width =
49f9cf0e 3296 nla_get_u32(attrs[NL80211_ATTR_CHANNEL_WIDTH]);
5d087aa7
KF
3297 if (chandef->chan->band == NL80211_BAND_S1GHZ) {
3298 /* User input error for channel width doesn't match channel */
3299 if (chandef->width != ieee80211_s1g_channel_width(chandef->chan)) {
3300 NL_SET_ERR_MSG_ATTR(extack,
3301 attrs[NL80211_ATTR_CHANNEL_WIDTH],
3302 "bad channel width");
3303 return -EINVAL;
3304 }
3305 }
942ba88b 3306 if (attrs[NL80211_ATTR_CENTER_FREQ1]) {
3d9d1d66 3307 chandef->center_freq1 =
49f9cf0e 3308 nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ1]);
942ba88b
TP
3309 if (attrs[NL80211_ATTR_CENTER_FREQ1_OFFSET])
3310 chandef->freq1_offset = nla_get_u32(
3311 attrs[NL80211_ATTR_CENTER_FREQ1_OFFSET]);
3312 else
3313 chandef->freq1_offset = 0;
3314 }
49f9cf0e 3315 if (attrs[NL80211_ATTR_CENTER_FREQ2])
3d9d1d66 3316 chandef->center_freq2 =
49f9cf0e 3317 nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ2]);
3d9d1d66
JB
3318 }
3319
2a38075c
AAL
3320 if (info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]) {
3321 chandef->edmg.channels =
3322 nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]);
3323
3324 if (info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG])
3325 chandef->edmg.bw_config =
3326 nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG]);
3327 } else {
3328 chandef->edmg.bw_config = 0;
3329 chandef->edmg.channels = 0;
3330 }
3331
49f9cf0e
JB
3332 if (!cfg80211_chandef_valid(chandef)) {
3333 NL_SET_ERR_MSG(extack, "invalid channel definition");
3d9d1d66 3334 return -EINVAL;
49f9cf0e 3335 }
3d9d1d66 3336
9f5e8f6e 3337 if (!cfg80211_chandef_usable(&rdev->wiphy, chandef,
49f9cf0e
JB
3338 IEEE80211_CHAN_DISABLED)) {
3339 NL_SET_ERR_MSG(extack, "(extension) channel is disabled");
3d9d1d66 3340 return -EINVAL;
49f9cf0e 3341 }
3d9d1d66 3342
2f301ab2
SW
3343 if ((chandef->width == NL80211_CHAN_WIDTH_5 ||
3344 chandef->width == NL80211_CHAN_WIDTH_10) &&
49f9cf0e
JB
3345 !(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_5_10_MHZ)) {
3346 NL_SET_ERR_MSG(extack, "5/10 MHz not supported");
2f301ab2 3347 return -EINVAL;
49f9cf0e 3348 }
2f301ab2 3349
683b6d3b
JB
3350 return 0;
3351}
3352
f444de05 3353static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
e16821bc 3354 struct net_device *dev,
7b0a0e3c
JB
3355 struct genl_info *info,
3356 int _link_id)
f444de05 3357{
683b6d3b 3358 struct cfg80211_chan_def chandef;
f444de05 3359 int result;
e8c9bd5b 3360 enum nl80211_iftype iftype = NL80211_IFTYPE_MONITOR;
e16821bc 3361 struct wireless_dev *wdev = NULL;
7b0a0e3c 3362 int link_id = _link_id;
e8c9bd5b 3363
e16821bc
JM
3364 if (dev)
3365 wdev = dev->ieee80211_ptr;
f444de05
JB
3366 if (!nl80211_can_set_dev_channel(wdev))
3367 return -EOPNOTSUPP;
e16821bc
JM
3368 if (wdev)
3369 iftype = wdev->iftype;
f444de05 3370
7b0a0e3c
JB
3371 if (link_id < 0) {
3372 if (wdev && wdev->valid_links)
3373 return -EINVAL;
3374 link_id = 0;
3375 }
3376
683b6d3b
JB
3377 result = nl80211_parse_chandef(rdev, info, &chandef);
3378 if (result)
3379 return result;
f444de05 3380
e8c9bd5b 3381 switch (iftype) {
aa430da4
JB
3382 case NL80211_IFTYPE_AP:
3383 case NL80211_IFTYPE_P2P_GO:
923b352f 3384 if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &chandef,
7b0a0e3c
JB
3385 iftype))
3386 return -EINVAL;
3387 if (wdev->links[link_id].ap.beacon_interval) {
3388 struct ieee80211_channel *cur_chan;
3389
e16821bc
JM
3390 if (!dev || !rdev->ops->set_ap_chanwidth ||
3391 !(rdev->wiphy.features &
7b0a0e3c
JB
3392 NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE))
3393 return -EBUSY;
e16821bc
JM
3394
3395 /* Only allow dynamic channel width changes */
7b0a0e3c
JB
3396 cur_chan = wdev->links[link_id].ap.chandef.chan;
3397 if (chandef.chan != cur_chan)
3398 return -EBUSY;
3399
3400 result = rdev_set_ap_chanwidth(rdev, dev, link_id,
3401 &chandef);
e16821bc 3402 if (result)
7b0a0e3c
JB
3403 return result;
3404 wdev->links[link_id].ap.chandef = chandef;
3405 } else {
3406 wdev->u.ap.preset_chandef = chandef;
e16821bc 3407 }
7b0a0e3c 3408 return 0;
cc1d2806 3409 case NL80211_IFTYPE_MESH_POINT:
7b0a0e3c 3410 return cfg80211_set_mesh_channel(rdev, wdev, &chandef);
e8c9bd5b 3411 case NL80211_IFTYPE_MONITOR:
7b0a0e3c 3412 return cfg80211_set_monitor_channel(rdev, &chandef);
aa430da4 3413 default:
7b0a0e3c 3414 break;
f444de05 3415 }
f444de05 3416
7b0a0e3c 3417 return -EINVAL;
f444de05
JB
3418}
3419
3420static int nl80211_set_channel(struct sk_buff *skb, struct genl_info *info)
3421{
4c476991 3422 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7b0a0e3c 3423 int link_id = nl80211_link_id_or_invalid(info->attrs);
4c476991 3424 struct net_device *netdev = info->user_ptr[1];
4e2f3d67
JB
3425 int ret;
3426
3427 wdev_lock(netdev->ieee80211_ptr);
3428 ret = __nl80211_set_channel(rdev, netdev, info, link_id);
3429 wdev_unlock(netdev->ieee80211_ptr);
f444de05 3430
4e2f3d67 3431 return ret;
f444de05
JB
3432}
3433
55682965
JB
3434static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
3435{
a05829a7 3436 struct cfg80211_registered_device *rdev = NULL;
f444de05
JB
3437 struct net_device *netdev = NULL;
3438 struct wireless_dev *wdev;
a1e567c8 3439 int result = 0, rem_txq_params = 0;
31888487 3440 struct nlattr *nl_txq_params;
b9a5f8ca
JM
3441 u32 changed;
3442 u8 retry_short = 0, retry_long = 0;
3443 u32 frag_threshold = 0, rts_threshold = 0;
81077e82 3444 u8 coverage_class = 0;
52539ca8 3445 u32 txq_limit = 0, txq_memory_limit = 0, txq_quantum = 0;
55682965 3446
a05829a7 3447 rtnl_lock();
f444de05
JB
3448 /*
3449 * Try to find the wiphy and netdev. Normally this
3450 * function shouldn't need the netdev, but this is
3451 * done for backward compatibility -- previously
3452 * setting the channel was done per wiphy, but now
3453 * it is per netdev. Previous userland like hostapd
3454 * also passed a netdev to set_wiphy, so that it is
3455 * possible to let that go to the right netdev!
3456 */
4bbf4d56 3457
f444de05
JB
3458 if (info->attrs[NL80211_ATTR_IFINDEX]) {
3459 int ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]);
3460
7f2b8562 3461 netdev = __dev_get_by_index(genl_info_net(info), ifindex);
5fe231e8 3462 if (netdev && netdev->ieee80211_ptr)
f26cbf40 3463 rdev = wiphy_to_rdev(netdev->ieee80211_ptr->wiphy);
5fe231e8 3464 else
f444de05 3465 netdev = NULL;
4bbf4d56
JB
3466 }
3467
f444de05 3468 if (!netdev) {
878d9ec7
JB
3469 rdev = __cfg80211_rdev_from_attrs(genl_info_net(info),
3470 info->attrs);
a05829a7
JB
3471 if (IS_ERR(rdev)) {
3472 rtnl_unlock();
4c476991 3473 return PTR_ERR(rdev);
a05829a7 3474 }
f444de05
JB
3475 wdev = NULL;
3476 netdev = NULL;
3477 result = 0;
71fe96bf 3478 } else
f444de05 3479 wdev = netdev->ieee80211_ptr;
f444de05 3480
a05829a7 3481 wiphy_lock(&rdev->wiphy);
a05829a7 3482
f444de05
JB
3483 /*
3484 * end workaround code, by now the rdev is available
3485 * and locked, and wdev may or may not be NULL.
3486 */
4bbf4d56
JB
3487
3488 if (info->attrs[NL80211_ATTR_WIPHY_NAME])
31888487
JM
3489 result = cfg80211_dev_rename(
3490 rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME]));
0391a45c 3491 rtnl_unlock();
4bbf4d56 3492
4bbf4d56 3493 if (result)
a05829a7 3494 goto out;
31888487
JM
3495
3496 if (info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS]) {
3497 struct ieee80211_txq_params txq_params;
3498 struct nlattr *tb[NL80211_TXQ_ATTR_MAX + 1];
3499
a05829a7
JB
3500 if (!rdev->ops->set_txq_params) {
3501 result = -EOPNOTSUPP;
3502 goto out;
3503 }
31888487 3504
a05829a7
JB
3505 if (!netdev) {
3506 result = -EINVAL;
3507 goto out;
3508 }
f70f01c2 3509
133a3ff2 3510 if (netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
a05829a7
JB
3511 netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
3512 result = -EINVAL;
3513 goto out;
3514 }
133a3ff2 3515
a05829a7
JB
3516 if (!netif_running(netdev)) {
3517 result = -ENETDOWN;
3518 goto out;
3519 }
2b5f8b0b 3520
31888487
JM
3521 nla_for_each_nested(nl_txq_params,
3522 info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS],
3523 rem_txq_params) {
8cb08174
JB
3524 result = nla_parse_nested_deprecated(tb,
3525 NL80211_TXQ_ATTR_MAX,
3526 nl_txq_params,
3527 txq_params_policy,
3528 info->extack);
ae811e21 3529 if (result)
a05829a7 3530 goto out;
31888487
JM
3531 result = parse_txq_params(tb, &txq_params);
3532 if (result)
a05829a7 3533 goto out;
31888487 3534
9d2bb84d
ST
3535 txq_params.link_id =
3536 nl80211_link_id_or_invalid(info->attrs);
3537
3538 wdev_lock(netdev->ieee80211_ptr);
3539 if (txq_params.link_id >= 0 &&
3540 !(netdev->ieee80211_ptr->valid_links &
3541 BIT(txq_params.link_id)))
3542 result = -ENOLINK;
3543 else if (txq_params.link_id >= 0 &&
3544 !netdev->ieee80211_ptr->valid_links)
3545 result = -EINVAL;
3546 else
3547 result = rdev_set_txq_params(rdev, netdev,
3548 &txq_params);
3549 wdev_unlock(netdev->ieee80211_ptr);
31888487 3550 if (result)
a05829a7 3551 goto out;
31888487
JM
3552 }
3553 }
55682965 3554
72bdcf34 3555 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
69c3f2d3
IP
3556 int link_id = nl80211_link_id_or_invalid(info->attrs);
3557
4e2f3d67
JB
3558 if (wdev) {
3559 wdev_lock(wdev);
3560 result = __nl80211_set_channel(
3561 rdev,
3562 nl80211_can_set_dev_channel(wdev) ? netdev : NULL,
69c3f2d3 3563 info, link_id);
4e2f3d67
JB
3564 wdev_unlock(wdev);
3565 } else {
69c3f2d3 3566 result = __nl80211_set_channel(rdev, netdev, info, link_id);
4e2f3d67 3567 }
69c3f2d3 3568
72bdcf34 3569 if (result)
a05829a7 3570 goto out;
72bdcf34
JM
3571 }
3572
98d2ff8b 3573 if (info->attrs[NL80211_ATTR_WIPHY_TX_POWER_SETTING]) {
c8442118 3574 struct wireless_dev *txp_wdev = wdev;
98d2ff8b
JO
3575 enum nl80211_tx_power_setting type;
3576 int idx, mbm = 0;
3577
c8442118
JB
3578 if (!(rdev->wiphy.features & NL80211_FEATURE_VIF_TXPOWER))
3579 txp_wdev = NULL;
3580
a05829a7
JB
3581 if (!rdev->ops->set_tx_power) {
3582 result = -EOPNOTSUPP;
3583 goto out;
3584 }
98d2ff8b
JO
3585
3586 idx = NL80211_ATTR_WIPHY_TX_POWER_SETTING;
3587 type = nla_get_u32(info->attrs[idx]);
3588
3589 if (!info->attrs[NL80211_ATTR_WIPHY_TX_POWER_LEVEL] &&
a05829a7
JB
3590 (type != NL80211_TX_POWER_AUTOMATIC)) {
3591 result = -EINVAL;
3592 goto out;
3593 }
98d2ff8b
JO
3594
3595 if (type != NL80211_TX_POWER_AUTOMATIC) {
3596 idx = NL80211_ATTR_WIPHY_TX_POWER_LEVEL;
3597 mbm = nla_get_u32(info->attrs[idx]);
3598 }
3599
c8442118 3600 result = rdev_set_tx_power(rdev, txp_wdev, type, mbm);
98d2ff8b 3601 if (result)
a05829a7 3602 goto out;
98d2ff8b
JO
3603 }
3604
afe0cbf8
BR
3605 if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX] &&
3606 info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]) {
3607 u32 tx_ant, rx_ant;
7a087e74 3608
7f531e03
BR
3609 if ((!rdev->wiphy.available_antennas_tx &&
3610 !rdev->wiphy.available_antennas_rx) ||
a05829a7
JB
3611 !rdev->ops->set_antenna) {
3612 result = -EOPNOTSUPP;
3613 goto out;
3614 }
afe0cbf8
BR
3615
3616 tx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX]);
3617 rx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]);
3618
a7ffac95 3619 /* reject antenna configurations which don't match the
7f531e03
BR
3620 * available antenna masks, except for the "all" mask */
3621 if ((~tx_ant && (tx_ant & ~rdev->wiphy.available_antennas_tx)) ||
a05829a7
JB
3622 (~rx_ant && (rx_ant & ~rdev->wiphy.available_antennas_rx))) {
3623 result = -EINVAL;
3624 goto out;
3625 }
a7ffac95 3626
7f531e03
BR
3627 tx_ant = tx_ant & rdev->wiphy.available_antennas_tx;
3628 rx_ant = rx_ant & rdev->wiphy.available_antennas_rx;
a7ffac95 3629
e35e4d28 3630 result = rdev_set_antenna(rdev, tx_ant, rx_ant);
afe0cbf8 3631 if (result)
a05829a7 3632 goto out;
afe0cbf8
BR
3633 }
3634
b9a5f8ca
JM
3635 changed = 0;
3636
3637 if (info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]) {
3638 retry_short = nla_get_u8(
3639 info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]);
7f2b8562 3640
b9a5f8ca
JM
3641 changed |= WIPHY_PARAM_RETRY_SHORT;
3642 }
3643
3644 if (info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]) {
3645 retry_long = nla_get_u8(
3646 info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]);
7f2b8562 3647
b9a5f8ca
JM
3648 changed |= WIPHY_PARAM_RETRY_LONG;
3649 }
3650
3651 if (info->attrs[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]) {
3652 frag_threshold = nla_get_u32(
3653 info->attrs[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]);
a05829a7
JB
3654 if (frag_threshold < 256) {
3655 result = -EINVAL;
3656 goto out;
3657 }
7f2b8562 3658
b9a5f8ca
JM
3659 if (frag_threshold != (u32) -1) {
3660 /*
3661 * Fragments (apart from the last one) are required to
3662 * have even length. Make the fragmentation code
3663 * simpler by stripping LSB should someone try to use
3664 * odd threshold value.
3665 */
3666 frag_threshold &= ~0x1;
3667 }
3668 changed |= WIPHY_PARAM_FRAG_THRESHOLD;
3669 }
3670
3671 if (info->attrs[NL80211_ATTR_WIPHY_RTS_THRESHOLD]) {
3672 rts_threshold = nla_get_u32(
3673 info->attrs[NL80211_ATTR_WIPHY_RTS_THRESHOLD]);
3674 changed |= WIPHY_PARAM_RTS_THRESHOLD;
3675 }
3676
81077e82 3677 if (info->attrs[NL80211_ATTR_WIPHY_COVERAGE_CLASS]) {
a05829a7
JB
3678 if (info->attrs[NL80211_ATTR_WIPHY_DYN_ACK]) {
3679 result = -EINVAL;
3680 goto out;
3681 }
3057dbfd 3682
81077e82
LT
3683 coverage_class = nla_get_u8(
3684 info->attrs[NL80211_ATTR_WIPHY_COVERAGE_CLASS]);
3685 changed |= WIPHY_PARAM_COVERAGE_CLASS;
3686 }
3687
3057dbfd 3688 if (info->attrs[NL80211_ATTR_WIPHY_DYN_ACK]) {
a05829a7
JB
3689 if (!(rdev->wiphy.features & NL80211_FEATURE_ACKTO_ESTIMATION)) {
3690 result = -EOPNOTSUPP;
3691 goto out;
3692 }
3057dbfd
LB
3693
3694 changed |= WIPHY_PARAM_DYN_ACK;
81077e82
LT
3695 }
3696
52539ca8
THJ
3697 if (info->attrs[NL80211_ATTR_TXQ_LIMIT]) {
3698 if (!wiphy_ext_feature_isset(&rdev->wiphy,
a05829a7
JB
3699 NL80211_EXT_FEATURE_TXQS)) {
3700 result = -EOPNOTSUPP;
3701 goto out;
3702 }
52539ca8
THJ
3703 txq_limit = nla_get_u32(
3704 info->attrs[NL80211_ATTR_TXQ_LIMIT]);
3705 changed |= WIPHY_PARAM_TXQ_LIMIT;
3706 }
3707
3708 if (info->attrs[NL80211_ATTR_TXQ_MEMORY_LIMIT]) {
3709 if (!wiphy_ext_feature_isset(&rdev->wiphy,
a05829a7
JB
3710 NL80211_EXT_FEATURE_TXQS)) {
3711 result = -EOPNOTSUPP;
3712 goto out;
3713 }
52539ca8
THJ
3714 txq_memory_limit = nla_get_u32(
3715 info->attrs[NL80211_ATTR_TXQ_MEMORY_LIMIT]);
3716 changed |= WIPHY_PARAM_TXQ_MEMORY_LIMIT;
3717 }
3718
3719 if (info->attrs[NL80211_ATTR_TXQ_QUANTUM]) {
3720 if (!wiphy_ext_feature_isset(&rdev->wiphy,
a05829a7
JB
3721 NL80211_EXT_FEATURE_TXQS)) {
3722 result = -EOPNOTSUPP;
3723 goto out;
3724 }
52539ca8
THJ
3725 txq_quantum = nla_get_u32(
3726 info->attrs[NL80211_ATTR_TXQ_QUANTUM]);
3727 changed |= WIPHY_PARAM_TXQ_QUANTUM;
3728 }
3729
b9a5f8ca
JM
3730 if (changed) {
3731 u8 old_retry_short, old_retry_long;
3732 u32 old_frag_threshold, old_rts_threshold;
81077e82 3733 u8 old_coverage_class;
52539ca8 3734 u32 old_txq_limit, old_txq_memory_limit, old_txq_quantum;
b9a5f8ca 3735
a05829a7
JB
3736 if (!rdev->ops->set_wiphy_params) {
3737 result = -EOPNOTSUPP;
3738 goto out;
3739 }
b9a5f8ca
JM
3740
3741 old_retry_short = rdev->wiphy.retry_short;
3742 old_retry_long = rdev->wiphy.retry_long;
3743 old_frag_threshold = rdev->wiphy.frag_threshold;
3744 old_rts_threshold = rdev->wiphy.rts_threshold;
81077e82 3745 old_coverage_class = rdev->wiphy.coverage_class;
52539ca8
THJ
3746 old_txq_limit = rdev->wiphy.txq_limit;
3747 old_txq_memory_limit = rdev->wiphy.txq_memory_limit;
3748 old_txq_quantum = rdev->wiphy.txq_quantum;
b9a5f8ca
JM
3749
3750 if (changed & WIPHY_PARAM_RETRY_SHORT)
3751 rdev->wiphy.retry_short = retry_short;
3752 if (changed & WIPHY_PARAM_RETRY_LONG)
3753 rdev->wiphy.retry_long = retry_long;
3754 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
3755 rdev->wiphy.frag_threshold = frag_threshold;
3756 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
3757 rdev->wiphy.rts_threshold = rts_threshold;
81077e82
LT
3758 if (changed & WIPHY_PARAM_COVERAGE_CLASS)
3759 rdev->wiphy.coverage_class = coverage_class;
52539ca8
THJ
3760 if (changed & WIPHY_PARAM_TXQ_LIMIT)
3761 rdev->wiphy.txq_limit = txq_limit;
3762 if (changed & WIPHY_PARAM_TXQ_MEMORY_LIMIT)
3763 rdev->wiphy.txq_memory_limit = txq_memory_limit;
3764 if (changed & WIPHY_PARAM_TXQ_QUANTUM)
3765 rdev->wiphy.txq_quantum = txq_quantum;
b9a5f8ca 3766
e35e4d28 3767 result = rdev_set_wiphy_params(rdev, changed);
b9a5f8ca
JM
3768 if (result) {
3769 rdev->wiphy.retry_short = old_retry_short;
3770 rdev->wiphy.retry_long = old_retry_long;
3771 rdev->wiphy.frag_threshold = old_frag_threshold;
3772 rdev->wiphy.rts_threshold = old_rts_threshold;
81077e82 3773 rdev->wiphy.coverage_class = old_coverage_class;
52539ca8
THJ
3774 rdev->wiphy.txq_limit = old_txq_limit;
3775 rdev->wiphy.txq_memory_limit = old_txq_memory_limit;
3776 rdev->wiphy.txq_quantum = old_txq_quantum;
a05829a7 3777 goto out;
b9a5f8ca
JM
3778 }
3779 }
a05829a7
JB
3780
3781 result = 0;
3782
3783out:
3784 wiphy_unlock(&rdev->wiphy);
3785 return result;
55682965
JB
3786}
3787
5097f844 3788int nl80211_send_chandef(struct sk_buff *msg, const struct cfg80211_chan_def *chandef)
683b6d3b 3789{
601555cd
JB
3790 if (WARN_ON(!cfg80211_chandef_valid(chandef)))
3791 return -EINVAL;
3d9d1d66 3792
683b6d3b
JB
3793 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
3794 chandef->chan->center_freq))
3795 return -ENOBUFS;
942ba88b
TP
3796 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ_OFFSET,
3797 chandef->chan->freq_offset))
3798 return -ENOBUFS;
3d9d1d66
JB
3799 switch (chandef->width) {
3800 case NL80211_CHAN_WIDTH_20_NOHT:
3801 case NL80211_CHAN_WIDTH_20:
3802 case NL80211_CHAN_WIDTH_40:
3803 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
3804 cfg80211_get_chandef_type(chandef)))
3805 return -ENOBUFS;
3806 break;
3807 default:
3808 break;
3809 }
3810 if (nla_put_u32(msg, NL80211_ATTR_CHANNEL_WIDTH, chandef->width))
3811 return -ENOBUFS;
3812 if (nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ1, chandef->center_freq1))
3813 return -ENOBUFS;
3814 if (chandef->center_freq2 &&
3815 nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ2, chandef->center_freq2))
683b6d3b
JB
3816 return -ENOBUFS;
3817 return 0;
3818}
5097f844 3819EXPORT_SYMBOL(nl80211_send_chandef);
683b6d3b 3820
15e47304 3821static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flags,
d726405a 3822 struct cfg80211_registered_device *rdev,
3d1a5bbf
AZ
3823 struct wireless_dev *wdev,
3824 enum nl80211_commands cmd)
55682965 3825{
72fb2abc 3826 struct net_device *dev = wdev->netdev;
55682965
JB
3827 void *hdr;
3828
3d1a5bbf
AZ
3829 WARN_ON(cmd != NL80211_CMD_NEW_INTERFACE &&
3830 cmd != NL80211_CMD_DEL_INTERFACE &&
3831 cmd != NL80211_CMD_SET_INTERFACE);
8f894be2
TB
3832
3833 hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
55682965
JB
3834 if (!hdr)
3835 return -1;
3836
72fb2abc
JB
3837 if (dev &&
3838 (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
98104fde 3839 nla_put_string(msg, NL80211_ATTR_IFNAME, dev->name)))
72fb2abc
JB
3840 goto nla_put_failure;
3841
3842 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
3843 nla_put_u32(msg, NL80211_ATTR_IFTYPE, wdev->iftype) ||
2dad624e
ND
3844 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
3845 NL80211_ATTR_PAD) ||
98104fde 3846 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, wdev_address(wdev)) ||
9360ffd1
DM
3847 nla_put_u32(msg, NL80211_ATTR_GENERATION,
3848 rdev->devlist_generation ^
446faa15
AQ
3849 (cfg80211_rdev_list_generation << 2)) ||
3850 nla_put_u8(msg, NL80211_ATTR_4ADDR, wdev->use_4addr))
9360ffd1 3851 goto nla_put_failure;
f5ea9120 3852
7b0a0e3c 3853 if (rdev->ops->get_channel && !wdev->valid_links) {
f43e5210 3854 struct cfg80211_chan_def chandef = {};
7b0a0e3c 3855 int ret;
683b6d3b 3856
7b0a0e3c
JB
3857 ret = rdev_get_channel(rdev, wdev, 0, &chandef);
3858 if (ret == 0 && nl80211_send_chandef(msg, &chandef))
3859 goto nla_put_failure;
d91df0e3
PF
3860 }
3861
d55d0d59
RM
3862 if (rdev->ops->get_tx_power) {
3863 int dbm, ret;
3864
3865 ret = rdev_get_tx_power(rdev, wdev, &dbm);
3866 if (ret == 0 &&
3867 nla_put_u32(msg, NL80211_ATTR_WIPHY_TX_POWER_LEVEL,
3868 DBM_TO_MBM(dbm)))
3869 goto nla_put_failure;
3870 }
3871
44905265
JB
3872 wdev_lock(wdev);
3873 switch (wdev->iftype) {
3874 case NL80211_IFTYPE_AP:
a75971bc 3875 case NL80211_IFTYPE_P2P_GO:
7b0a0e3c
JB
3876 if (wdev->u.ap.ssid_len &&
3877 nla_put(msg, NL80211_ATTR_SSID, wdev->u.ap.ssid_len,
3878 wdev->u.ap.ssid))
4564b187 3879 goto nla_put_failure_locked;
44905265
JB
3880 break;
3881 case NL80211_IFTYPE_STATION:
3882 case NL80211_IFTYPE_P2P_CLIENT:
7b0a0e3c
JB
3883 if (wdev->u.client.ssid_len &&
3884 nla_put(msg, NL80211_ATTR_SSID, wdev->u.client.ssid_len,
3885 wdev->u.client.ssid))
3886 goto nla_put_failure_locked;
3887 break;
3888 case NL80211_IFTYPE_ADHOC:
3889 if (wdev->u.ibss.ssid_len &&
3890 nla_put(msg, NL80211_ATTR_SSID, wdev->u.ibss.ssid_len,
3891 wdev->u.ibss.ssid))
3892 goto nla_put_failure_locked;
44905265 3893 break;
44905265
JB
3894 default:
3895 /* nothing */
3896 break;
b84e7a05 3897 }
44905265 3898 wdev_unlock(wdev);
b84e7a05 3899
52539ca8
THJ
3900 if (rdev->ops->get_txq_stats) {
3901 struct cfg80211_txq_stats txqstats = {};
3902 int ret = rdev_get_txq_stats(rdev, wdev, &txqstats);
3903
3904 if (ret == 0 &&
3905 !nl80211_put_txq_stats(msg, &txqstats,
3906 NL80211_ATTR_TXQ_STATS))
3907 goto nla_put_failure;
3908 }
3909
ce08cd34
JB
3910 if (wdev->valid_links) {
3911 unsigned int link_id;
3912 struct nlattr *links = nla_nest_start(msg,
3913 NL80211_ATTR_MLO_LINKS);
3914
3915 if (!links)
3916 goto nla_put_failure;
3917
3918 for_each_valid_link(wdev, link_id) {
3919 struct nlattr *link = nla_nest_start(msg, link_id + 1);
7a77cd47
VJ
3920 struct cfg80211_chan_def chandef = {};
3921 int ret;
ce08cd34 3922
5cc58b37
YC
3923 if (!link)
3924 goto nla_put_failure;
3925
ce08cd34
JB
3926 if (nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id))
3927 goto nla_put_failure;
3928 if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN,
3929 wdev->links[link_id].addr))
3930 goto nla_put_failure;
7a77cd47
VJ
3931
3932 ret = rdev_get_channel(rdev, wdev, link_id, &chandef);
3933 if (ret == 0 && nl80211_send_chandef(msg, &chandef))
3934 goto nla_put_failure;
3935
ce08cd34
JB
3936 nla_nest_end(msg, link);
3937 }
3938
3939 nla_nest_end(msg, links);
3940 }
3941
053c095a
JB
3942 genlmsg_end(msg, hdr);
3943 return 0;
55682965 3944
4564b187
JB
3945 nla_put_failure_locked:
3946 wdev_unlock(wdev);
55682965 3947 nla_put_failure:
bc3ed28c
TG
3948 genlmsg_cancel(msg, hdr);
3949 return -EMSGSIZE;
55682965
JB
3950}
3951
3952static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *cb)
3953{
3954 int wp_idx = 0;
3955 int if_idx = 0;
3956 int wp_start = cb->args[0];
3957 int if_start = cb->args[1];
b7fb44da 3958 int filter_wiphy = -1;
f5ea9120 3959 struct cfg80211_registered_device *rdev;
55682965 3960 struct wireless_dev *wdev;
ea90e0dc 3961 int ret;
55682965 3962
5fe231e8 3963 rtnl_lock();
b7fb44da
DK
3964 if (!cb->args[2]) {
3965 struct nl80211_dump_wiphy_state state = {
3966 .filter_wiphy = -1,
3967 };
b7fb44da
DK
3968
3969 ret = nl80211_dump_wiphy_parse(skb, cb, &state);
3970 if (ret)
ea90e0dc 3971 goto out_unlock;
b7fb44da
DK
3972
3973 filter_wiphy = state.filter_wiphy;
3974
3975 /*
3976 * if filtering, set cb->args[2] to +1 since 0 is the default
3977 * value needed to determine that parsing is necessary.
3978 */
3979 if (filter_wiphy >= 0)
3980 cb->args[2] = filter_wiphy + 1;
3981 else
3982 cb->args[2] = -1;
3983 } else if (cb->args[2] > 0) {
3984 filter_wiphy = cb->args[2] - 1;
3985 }
3986
f5ea9120
JB
3987 list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
3988 if (!net_eq(wiphy_net(&rdev->wiphy), sock_net(skb->sk)))
463d0183 3989 continue;
bba95fef
JB
3990 if (wp_idx < wp_start) {
3991 wp_idx++;
55682965 3992 continue;
bba95fef 3993 }
b7fb44da
DK
3994
3995 if (filter_wiphy >= 0 && filter_wiphy != rdev->wiphy_idx)
3996 continue;
3997
55682965
JB
3998 if_idx = 0;
3999
53873f13 4000 list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
bba95fef
JB
4001 if (if_idx < if_start) {
4002 if_idx++;
55682965 4003 continue;
bba95fef 4004 }
15e47304 4005 if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).portid,
55682965 4006 cb->nlh->nlmsg_seq, NLM_F_MULTI,
3d1a5bbf
AZ
4007 rdev, wdev,
4008 NL80211_CMD_NEW_INTERFACE) < 0) {
bba95fef
JB
4009 goto out;
4010 }
4011 if_idx++;
55682965 4012 }
bba95fef
JB
4013
4014 wp_idx++;
55682965 4015 }
bba95fef 4016 out:
55682965
JB
4017 cb->args[0] = wp_idx;
4018 cb->args[1] = if_idx;
4019
ea90e0dc
JB
4020 ret = skb->len;
4021 out_unlock:
4022 rtnl_unlock();
4023
4024 return ret;
55682965
JB
4025}
4026
4027static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info)
4028{
4029 struct sk_buff *msg;
1b8ec87a 4030 struct cfg80211_registered_device *rdev = info->user_ptr[0];
72fb2abc 4031 struct wireless_dev *wdev = info->user_ptr[1];
55682965 4032
fd2120ca 4033 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
55682965 4034 if (!msg)
4c476991 4035 return -ENOMEM;
55682965 4036
15e47304 4037 if (nl80211_send_iface(msg, info->snd_portid, info->snd_seq, 0,
3d1a5bbf 4038 rdev, wdev, NL80211_CMD_NEW_INTERFACE) < 0) {
4c476991
JB
4039 nlmsg_free(msg);
4040 return -ENOBUFS;
4041 }
55682965 4042
134e6375 4043 return genlmsg_reply(msg, info);
55682965
JB
4044}
4045
66f7ac50
MW
4046static const struct nla_policy mntr_flags_policy[NL80211_MNTR_FLAG_MAX + 1] = {
4047 [NL80211_MNTR_FLAG_FCSFAIL] = { .type = NLA_FLAG },
4048 [NL80211_MNTR_FLAG_PLCPFAIL] = { .type = NLA_FLAG },
4049 [NL80211_MNTR_FLAG_CONTROL] = { .type = NLA_FLAG },
4050 [NL80211_MNTR_FLAG_OTHER_BSS] = { .type = NLA_FLAG },
4051 [NL80211_MNTR_FLAG_COOK_FRAMES] = { .type = NLA_FLAG },
e057d3c3 4052 [NL80211_MNTR_FLAG_ACTIVE] = { .type = NLA_FLAG },
66f7ac50
MW
4053};
4054
4055static int parse_monitor_flags(struct nlattr *nla, u32 *mntrflags)
4056{
4057 struct nlattr *flags[NL80211_MNTR_FLAG_MAX + 1];
4058 int flag;
4059
4060 *mntrflags = 0;
4061
4062 if (!nla)
4063 return -EINVAL;
4064
8cb08174 4065 if (nla_parse_nested_deprecated(flags, NL80211_MNTR_FLAG_MAX, nla, mntr_flags_policy, NULL))
66f7ac50
MW
4066 return -EINVAL;
4067
4068 for (flag = 1; flag <= NL80211_MNTR_FLAG_MAX; flag++)
4069 if (flags[flag])
4070 *mntrflags |= (1<<flag);
4071
818a986e
JB
4072 *mntrflags |= MONITOR_FLAG_CHANGED;
4073
66f7ac50
MW
4074 return 0;
4075}
4076
1db77596
JB
4077static int nl80211_parse_mon_options(struct cfg80211_registered_device *rdev,
4078 enum nl80211_iftype type,
4079 struct genl_info *info,
4080 struct vif_params *params)
4081{
4082 bool change = false;
4083 int err;
4084
4085 if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) {
4086 if (type != NL80211_IFTYPE_MONITOR)
4087 return -EINVAL;
4088
4089 err = parse_monitor_flags(info->attrs[NL80211_ATTR_MNTR_FLAGS],
4090 &params->flags);
4091 if (err)
4092 return err;
4093
4094 change = true;
4095 }
4096
4097 if (params->flags & MONITOR_FLAG_ACTIVE &&
4098 !(rdev->wiphy.features & NL80211_FEATURE_ACTIVE_MONITOR))
4099 return -EOPNOTSUPP;
4100
4101 if (info->attrs[NL80211_ATTR_MU_MIMO_GROUP_DATA]) {
4102 const u8 *mumimo_groups;
4103 u32 cap_flag = NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER;
4104
4105 if (type != NL80211_IFTYPE_MONITOR)
4106 return -EINVAL;
4107
4108 if (!wiphy_ext_feature_isset(&rdev->wiphy, cap_flag))
4109 return -EOPNOTSUPP;
4110
4111 mumimo_groups =
4112 nla_data(info->attrs[NL80211_ATTR_MU_MIMO_GROUP_DATA]);
4113
4114 /* bits 0 and 63 are reserved and must be zero */
4954601f
JB
4115 if ((mumimo_groups[0] & BIT(0)) ||
4116 (mumimo_groups[VHT_MUMIMO_GROUPS_DATA_LEN - 1] & BIT(7)))
1db77596
JB
4117 return -EINVAL;
4118
4119 params->vht_mumimo_groups = mumimo_groups;
4120 change = true;
4121 }
4122
4123 if (info->attrs[NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR]) {
4124 u32 cap_flag = NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER;
4125
4126 if (type != NL80211_IFTYPE_MONITOR)
4127 return -EINVAL;
4128
4129 if (!wiphy_ext_feature_isset(&rdev->wiphy, cap_flag))
4130 return -EOPNOTSUPP;
4131
4132 params->vht_mumimo_follow_addr =
4133 nla_data(info->attrs[NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR]);
4134 change = true;
4135 }
4136
4137 return change ? 1 : 0;
4138}
4139
9bc383de 4140static int nl80211_valid_4addr(struct cfg80211_registered_device *rdev,
ad4bb6f8
JB
4141 struct net_device *netdev, u8 use_4addr,
4142 enum nl80211_iftype iftype)
9bc383de 4143{
ad4bb6f8 4144 if (!use_4addr) {
2e92a2d0 4145 if (netdev && netif_is_bridge_port(netdev))
ad4bb6f8 4146 return -EBUSY;
9bc383de 4147 return 0;
ad4bb6f8 4148 }
9bc383de
JB
4149
4150 switch (iftype) {
4151 case NL80211_IFTYPE_AP_VLAN:
4152 if (rdev->wiphy.flags & WIPHY_FLAG_4ADDR_AP)
4153 return 0;
4154 break;
4155 case NL80211_IFTYPE_STATION:
4156 if (rdev->wiphy.flags & WIPHY_FLAG_4ADDR_STATION)
4157 return 0;
4158 break;
4159 default:
4160 break;
4161 }
4162
4163 return -EOPNOTSUPP;
4164}
4165
55682965
JB
4166static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
4167{
4c476991 4168 struct cfg80211_registered_device *rdev = info->user_ptr[0];
2ec600d6 4169 struct vif_params params;
e36d56b6 4170 int err;
04a773ad 4171 enum nl80211_iftype otype, ntype;
4c476991 4172 struct net_device *dev = info->user_ptr[1];
ac7f9cfa 4173 bool change = false;
55682965 4174
2ec600d6
LCC
4175 memset(&params, 0, sizeof(params));
4176
04a773ad 4177 otype = ntype = dev->ieee80211_ptr->iftype;
55682965 4178
723b038d 4179 if (info->attrs[NL80211_ATTR_IFTYPE]) {
ac7f9cfa 4180 ntype = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
04a773ad 4181 if (otype != ntype)
ac7f9cfa 4182 change = true;
723b038d
JB
4183 }
4184
92ffe055 4185 if (info->attrs[NL80211_ATTR_MESH_ID]) {
29cbe68c
JB
4186 struct wireless_dev *wdev = dev->ieee80211_ptr;
4187
4c476991
JB
4188 if (ntype != NL80211_IFTYPE_MESH_POINT)
4189 return -EINVAL;
29cbe68c
JB
4190 if (netif_running(dev))
4191 return -EBUSY;
4192
4193 wdev_lock(wdev);
4194 BUILD_BUG_ON(IEEE80211_MAX_SSID_LEN !=
4195 IEEE80211_MAX_MESH_ID_LEN);
7b0a0e3c 4196 wdev->u.mesh.id_up_len =
29cbe68c 4197 nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
7b0a0e3c
JB
4198 memcpy(wdev->u.mesh.id,
4199 nla_data(info->attrs[NL80211_ATTR_MESH_ID]),
4200 wdev->u.mesh.id_up_len);
29cbe68c 4201 wdev_unlock(wdev);
2ec600d6
LCC
4202 }
4203
8b787643
FF
4204 if (info->attrs[NL80211_ATTR_4ADDR]) {
4205 params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]);
4206 change = true;
ad4bb6f8 4207 err = nl80211_valid_4addr(rdev, dev, params.use_4addr, ntype);
9bc383de 4208 if (err)
4c476991 4209 return err;
8b787643
FF
4210 } else {
4211 params.use_4addr = -1;
4212 }
4213
1db77596
JB
4214 err = nl80211_parse_mon_options(rdev, ntype, info, &params);
4215 if (err < 0)
4216 return err;
4217 if (err > 0)
c6e6a0c8 4218 change = true;
e057d3c3 4219
ac7f9cfa 4220 if (change)
818a986e 4221 err = cfg80211_change_iface(rdev, dev, ntype, &params);
ac7f9cfa
JB
4222 else
4223 err = 0;
60719ffd 4224
9bc383de
JB
4225 if (!err && params.use_4addr != -1)
4226 dev->ieee80211_ptr->use_4addr = params.use_4addr;
4227
3d1a5bbf
AZ
4228 if (change && !err) {
4229 struct wireless_dev *wdev = dev->ieee80211_ptr;
4230
4231 nl80211_notify_iface(rdev, wdev, NL80211_CMD_SET_INTERFACE);
4232 }
4233
55682965
JB
4234 return err;
4235}
4236
ea6b2098 4237static int _nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
55682965 4238{
4c476991 4239 struct cfg80211_registered_device *rdev = info->user_ptr[0];
2ec600d6 4240 struct vif_params params;
84efbb84 4241 struct wireless_dev *wdev;
896ff063 4242 struct sk_buff *msg;
55682965
JB
4243 int err;
4244 enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED;
4245
2ec600d6
LCC
4246 memset(&params, 0, sizeof(params));
4247
55682965
JB
4248 if (!info->attrs[NL80211_ATTR_IFNAME])
4249 return -EINVAL;
4250
ab0d76f6 4251 if (info->attrs[NL80211_ATTR_IFTYPE])
55682965 4252 type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
55682965 4253
33d915d9 4254 if (!rdev->ops->add_virtual_intf)
4c476991 4255 return -EOPNOTSUPP;
55682965 4256
cb3b7d87 4257 if ((type == NL80211_IFTYPE_P2P_DEVICE || type == NL80211_IFTYPE_NAN ||
e8f479b1
BG
4258 rdev->wiphy.features & NL80211_FEATURE_MAC_ON_CREATE) &&
4259 info->attrs[NL80211_ATTR_MAC]) {
1c18f145
AS
4260 nla_memcpy(params.macaddr, info->attrs[NL80211_ATTR_MAC],
4261 ETH_ALEN);
4262 if (!is_valid_ether_addr(params.macaddr))
4263 return -EADDRNOTAVAIL;
4264 }
4265
9bc383de 4266 if (info->attrs[NL80211_ATTR_4ADDR]) {
8b787643 4267 params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]);
ad4bb6f8 4268 err = nl80211_valid_4addr(rdev, NULL, params.use_4addr, type);
9bc383de 4269 if (err)
4c476991 4270 return err;
9bc383de 4271 }
8b787643 4272
e6f40511 4273 if (!cfg80211_iftype_allowed(&rdev->wiphy, type, params.use_4addr, 0))
33d915d9
MP
4274 return -EOPNOTSUPP;
4275
1db77596
JB
4276 err = nl80211_parse_mon_options(rdev, type, info, &params);
4277 if (err < 0)
4278 return err;
e057d3c3 4279
a18c7192
JB
4280 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4281 if (!msg)
4282 return -ENOMEM;
4283
e35e4d28
HG
4284 wdev = rdev_add_virtual_intf(rdev,
4285 nla_data(info->attrs[NL80211_ATTR_IFNAME]),
818a986e 4286 NET_NAME_USER, type, &params);
d687cbb7
RM
4287 if (WARN_ON(!wdev)) {
4288 nlmsg_free(msg);
4289 return -EPROTO;
4290 } else if (IS_ERR(wdev)) {
1c90f9d4 4291 nlmsg_free(msg);
84efbb84 4292 return PTR_ERR(wdev);
1c90f9d4 4293 }
2ec600d6 4294
18e5ca65 4295 if (info->attrs[NL80211_ATTR_SOCKET_OWNER])
78f22b6a
JB
4296 wdev->owner_nlportid = info->snd_portid;
4297
98104fde
JB
4298 switch (type) {
4299 case NL80211_IFTYPE_MESH_POINT:
4300 if (!info->attrs[NL80211_ATTR_MESH_ID])
4301 break;
29cbe68c
JB
4302 wdev_lock(wdev);
4303 BUILD_BUG_ON(IEEE80211_MAX_SSID_LEN !=
4304 IEEE80211_MAX_MESH_ID_LEN);
7b0a0e3c 4305 wdev->u.mesh.id_up_len =
29cbe68c 4306 nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
7b0a0e3c
JB
4307 memcpy(wdev->u.mesh.id,
4308 nla_data(info->attrs[NL80211_ATTR_MESH_ID]),
4309 wdev->u.mesh.id_up_len);
29cbe68c 4310 wdev_unlock(wdev);
98104fde 4311 break;
cb3b7d87 4312 case NL80211_IFTYPE_NAN:
98104fde
JB
4313 case NL80211_IFTYPE_P2P_DEVICE:
4314 /*
cb3b7d87 4315 * P2P Device and NAN do not have a netdev, so don't go
98104fde
JB
4316 * through the netdev notifier and must be added here
4317 */
9bdaf3b9
JB
4318 cfg80211_init_wdev(wdev);
4319 cfg80211_register_wdev(rdev, wdev);
98104fde
JB
4320 break;
4321 default:
4322 break;
29cbe68c
JB
4323 }
4324
15e47304 4325 if (nl80211_send_iface(msg, info->snd_portid, info->snd_seq, 0,
3d1a5bbf 4326 rdev, wdev, NL80211_CMD_NEW_INTERFACE) < 0) {
1c90f9d4
JB
4327 nlmsg_free(msg);
4328 return -ENOBUFS;
4329 }
4330
4331 return genlmsg_reply(msg, info);
55682965
JB
4332}
4333
ea6b2098
JB
4334static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
4335{
4336 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4337 int ret;
4338
4339 /* to avoid failing a new interface creation due to pending removal */
4340 cfg80211_destroy_ifaces(rdev);
4341
4342 wiphy_lock(&rdev->wiphy);
4343 ret = _nl80211_new_interface(skb, info);
4344 wiphy_unlock(&rdev->wiphy);
4345
4346 return ret;
4347}
4348
55682965
JB
4349static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
4350{
4c476991 4351 struct cfg80211_registered_device *rdev = info->user_ptr[0];
84efbb84 4352 struct wireless_dev *wdev = info->user_ptr[1];
55682965 4353
4c476991
JB
4354 if (!rdev->ops->del_virtual_intf)
4355 return -EOPNOTSUPP;
55682965 4356
a05829a7
JB
4357 /*
4358 * We hold RTNL, so this is safe, without RTNL opencount cannot
4359 * reach 0, and thus the rdev cannot be deleted.
4360 *
4361 * We need to do it for the dev_close(), since that will call
4362 * the netdev notifiers, and we need to acquire the mutex there
4363 * but don't know if we get there from here or from some other
4364 * place (e.g. "ip link set ... down").
4365 */
4366 mutex_unlock(&rdev->wiphy.mtx);
4367
84efbb84
JB
4368 /*
4369 * If we remove a wireless device without a netdev then clear
4370 * user_ptr[1] so that nl80211_post_doit won't dereference it
4371 * to check if it needs to do dev_put(). Otherwise it crashes
4372 * since the wdev has been freed, unlike with a netdev where
4373 * we need the dev_put() for the netdev to really be freed.
4374 */
4375 if (!wdev->netdev)
4376 info->user_ptr[1] = NULL;
a05829a7
JB
4377 else
4378 dev_close(wdev->netdev);
4379
4380 mutex_lock(&rdev->wiphy.mtx);
84efbb84 4381
cdf0a0a8 4382 return cfg80211_remove_virtual_intf(rdev, wdev);
55682965
JB
4383}
4384
1d9d9213
SW
4385static int nl80211_set_noack_map(struct sk_buff *skb, struct genl_info *info)
4386{
4387 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4388 struct net_device *dev = info->user_ptr[1];
4389 u16 noack_map;
4390
4391 if (!info->attrs[NL80211_ATTR_NOACK_MAP])
4392 return -EINVAL;
4393
4394 if (!rdev->ops->set_noack_map)
4395 return -EOPNOTSUPP;
4396
4397 noack_map = nla_get_u16(info->attrs[NL80211_ATTR_NOACK_MAP]);
4398
e35e4d28 4399 return rdev_set_noack_map(rdev, dev, noack_map);
1d9d9213
SW
4400}
4401
e7a7b84e
VJ
4402static int nl80211_validate_key_link_id(struct genl_info *info,
4403 struct wireless_dev *wdev,
4404 int link_id, bool pairwise)
4405{
4406 if (pairwise) {
4407 if (link_id != -1) {
4408 GENL_SET_ERR_MSG(info,
4409 "link ID not allowed for pairwise key");
4410 return -EINVAL;
4411 }
4412
4413 return 0;
4414 }
4415
4416 if (wdev->valid_links) {
4417 if (link_id == -1) {
4418 GENL_SET_ERR_MSG(info,
4419 "link ID must for MLO group key");
4420 return -EINVAL;
4421 }
4422 if (!(wdev->valid_links & BIT(link_id))) {
4423 GENL_SET_ERR_MSG(info, "invalid link ID for MLO group key");
4424 return -EINVAL;
4425 }
4426 } else if (link_id != -1) {
4427 GENL_SET_ERR_MSG(info, "link ID not allowed for non-MLO group key");
4428 return -EINVAL;
4429 }
4430
4431 return 0;
4432}
4433
41ade00f
JB
4434struct get_key_cookie {
4435 struct sk_buff *msg;
4436 int error;
b9454e83 4437 int idx;
41ade00f
JB
4438};
4439
4440static void get_key_callback(void *c, struct key_params *params)
4441{
b9454e83 4442 struct nlattr *key;
41ade00f
JB
4443 struct get_key_cookie *cookie = c;
4444
9360ffd1
DM
4445 if ((params->key &&
4446 nla_put(cookie->msg, NL80211_ATTR_KEY_DATA,
4447 params->key_len, params->key)) ||
4448 (params->seq &&
4449 nla_put(cookie->msg, NL80211_ATTR_KEY_SEQ,
4450 params->seq_len, params->seq)) ||
4451 (params->cipher &&
4452 nla_put_u32(cookie->msg, NL80211_ATTR_KEY_CIPHER,
4453 params->cipher)))
4454 goto nla_put_failure;
41ade00f 4455
ae0be8de 4456 key = nla_nest_start_noflag(cookie->msg, NL80211_ATTR_KEY);
b9454e83
JB
4457 if (!key)
4458 goto nla_put_failure;
4459
9360ffd1
DM
4460 if ((params->key &&
4461 nla_put(cookie->msg, NL80211_KEY_DATA,
4462 params->key_len, params->key)) ||
4463 (params->seq &&
4464 nla_put(cookie->msg, NL80211_KEY_SEQ,
4465 params->seq_len, params->seq)) ||
4466 (params->cipher &&
4467 nla_put_u32(cookie->msg, NL80211_KEY_CIPHER,
4468 params->cipher)))
4469 goto nla_put_failure;
b9454e83 4470
efdfce72 4471 if (nla_put_u8(cookie->msg, NL80211_KEY_IDX, cookie->idx))
9360ffd1 4472 goto nla_put_failure;
b9454e83
JB
4473
4474 nla_nest_end(cookie->msg, key);
4475
41ade00f
JB
4476 return;
4477 nla_put_failure:
4478 cookie->error = 1;
4479}
4480
4481static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
4482{
4c476991 4483 struct cfg80211_registered_device *rdev = info->user_ptr[0];
41ade00f 4484 int err;
4c476991 4485 struct net_device *dev = info->user_ptr[1];
41ade00f 4486 u8 key_idx = 0;
e31b8213
JB
4487 const u8 *mac_addr = NULL;
4488 bool pairwise;
41ade00f
JB
4489 struct get_key_cookie cookie = {
4490 .error = 0,
4491 };
4492 void *hdr;
4493 struct sk_buff *msg;
155d7c73 4494 bool bigtk_support = false;
e7a7b84e
VJ
4495 int link_id = nl80211_link_id_or_invalid(info->attrs);
4496 struct wireless_dev *wdev = dev->ieee80211_ptr;
155d7c73
JB
4497
4498 if (wiphy_ext_feature_isset(&rdev->wiphy,
4499 NL80211_EXT_FEATURE_BEACON_PROTECTION))
4500 bigtk_support = true;
4501
e7a7b84e
VJ
4502 if ((wdev->iftype == NL80211_IFTYPE_STATION ||
4503 wdev->iftype == NL80211_IFTYPE_P2P_CLIENT) &&
155d7c73
JB
4504 wiphy_ext_feature_isset(&rdev->wiphy,
4505 NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT))
4506 bigtk_support = true;
41ade00f 4507
56be393f 4508 if (info->attrs[NL80211_ATTR_KEY_IDX]) {
41ade00f 4509 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
155d7c73
JB
4510
4511 if (key_idx >= 6 && key_idx <= 7 && !bigtk_support) {
4512 GENL_SET_ERR_MSG(info, "BIGTK not supported");
56be393f 4513 return -EINVAL;
155d7c73 4514 }
56be393f 4515 }
41ade00f 4516
41ade00f
JB
4517 if (info->attrs[NL80211_ATTR_MAC])
4518 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
4519
e31b8213
JB
4520 pairwise = !!mac_addr;
4521 if (info->attrs[NL80211_ATTR_KEY_TYPE]) {
4522 u32 kt = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]);
7a087e74 4523
e31b8213
JB
4524 if (kt != NL80211_KEYTYPE_GROUP &&
4525 kt != NL80211_KEYTYPE_PAIRWISE)
4526 return -EINVAL;
4527 pairwise = kt == NL80211_KEYTYPE_PAIRWISE;
4528 }
4529
4c476991
JB
4530 if (!rdev->ops->get_key)
4531 return -EOPNOTSUPP;
41ade00f 4532
0fa7b391
JB
4533 if (!pairwise && mac_addr && !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
4534 return -ENOENT;
4535
fd2120ca 4536 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4c476991
JB
4537 if (!msg)
4538 return -ENOMEM;
41ade00f 4539
15e47304 4540 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
41ade00f 4541 NL80211_CMD_NEW_KEY);
cb35fba3 4542 if (!hdr)
9fe271af 4543 goto nla_put_failure;
41ade00f
JB
4544
4545 cookie.msg = msg;
b9454e83 4546 cookie.idx = key_idx;
41ade00f 4547
9360ffd1
DM
4548 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
4549 nla_put_u8(msg, NL80211_ATTR_KEY_IDX, key_idx))
4550 goto nla_put_failure;
4551 if (mac_addr &&
4552 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr))
4553 goto nla_put_failure;
41ade00f 4554
e7a7b84e
VJ
4555 err = nl80211_validate_key_link_id(info, wdev, link_id, pairwise);
4556 if (err)
4557 goto free_msg;
4558
4559 err = rdev_get_key(rdev, dev, link_id, key_idx, pairwise, mac_addr,
4560 &cookie, get_key_callback);
41ade00f
JB
4561
4562 if (err)
6c95e2a2 4563 goto free_msg;
41ade00f
JB
4564
4565 if (cookie.error)
4566 goto nla_put_failure;
4567
4568 genlmsg_end(msg, hdr);
4c476991 4569 return genlmsg_reply(msg, info);
41ade00f
JB
4570
4571 nla_put_failure:
4572 err = -ENOBUFS;
6c95e2a2 4573 free_msg:
41ade00f 4574 nlmsg_free(msg);
41ade00f
JB
4575 return err;
4576}
4577
4578static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
4579{
4c476991 4580 struct cfg80211_registered_device *rdev = info->user_ptr[0];
b9454e83 4581 struct key_parse key;
41ade00f 4582 int err;
4c476991 4583 struct net_device *dev = info->user_ptr[1];
e7a7b84e
VJ
4584 int link_id = nl80211_link_id_or_invalid(info->attrs);
4585 struct wireless_dev *wdev = dev->ieee80211_ptr;
41ade00f 4586
b9454e83
JB
4587 err = nl80211_parse_key(info, &key);
4588 if (err)
4589 return err;
41ade00f 4590
b9454e83 4591 if (key.idx < 0)
41ade00f
JB
4592 return -EINVAL;
4593
6cdd3979
AW
4594 /* Only support setting default key and
4595 * Extended Key ID action NL80211_KEY_SET_TX.
4596 */
56be393f 4597 if (!key.def && !key.defmgmt && !key.defbeacon &&
6cdd3979 4598 !(key.p.mode == NL80211_KEY_SET_TX))
41ade00f
JB
4599 return -EINVAL;
4600
e7a7b84e 4601 wdev_lock(wdev);
3cfcf6ac 4602
dbd2fd65
JB
4603 if (key.def) {
4604 if (!rdev->ops->set_default_key) {
4605 err = -EOPNOTSUPP;
4606 goto out;
4607 }
41ade00f 4608
e7a7b84e
VJ
4609 err = nl80211_key_allowed(wdev);
4610 if (err)
4611 goto out;
4612
4613 err = nl80211_validate_key_link_id(info, wdev, link_id, false);
dbd2fd65
JB
4614 if (err)
4615 goto out;
4616
e7a7b84e
VJ
4617 err = rdev_set_default_key(rdev, dev, link_id, key.idx,
4618 key.def_uni, key.def_multi);
dbd2fd65
JB
4619
4620 if (err)
4621 goto out;
fffd0934 4622
3d23e349 4623#ifdef CONFIG_CFG80211_WEXT
e7a7b84e 4624 wdev->wext.default_key = key.idx;
dbd2fd65 4625#endif
6cdd3979 4626 } else if (key.defmgmt) {
dbd2fd65
JB
4627 if (key.def_uni || !key.def_multi) {
4628 err = -EINVAL;
4629 goto out;
4630 }
4631
4632 if (!rdev->ops->set_default_mgmt_key) {
4633 err = -EOPNOTSUPP;
4634 goto out;
4635 }
4636
e7a7b84e
VJ
4637 err = nl80211_key_allowed(wdev);
4638 if (err)
4639 goto out;
4640
4641 err = nl80211_validate_key_link_id(info, wdev, link_id, false);
dbd2fd65
JB
4642 if (err)
4643 goto out;
4644
e7a7b84e 4645 err = rdev_set_default_mgmt_key(rdev, dev, link_id, key.idx);
dbd2fd65
JB
4646 if (err)
4647 goto out;
4648
4649#ifdef CONFIG_CFG80211_WEXT
e7a7b84e 4650 wdev->wext.default_mgmt_key = key.idx;
08645126 4651#endif
56be393f
JM
4652 } else if (key.defbeacon) {
4653 if (key.def_uni || !key.def_multi) {
4654 err = -EINVAL;
4655 goto out;
4656 }
4657
4658 if (!rdev->ops->set_default_beacon_key) {
4659 err = -EOPNOTSUPP;
4660 goto out;
4661 }
4662
e7a7b84e 4663 err = nl80211_key_allowed(wdev);
56be393f
JM
4664 if (err)
4665 goto out;
4666
e7a7b84e
VJ
4667 err = nl80211_validate_key_link_id(info, wdev, link_id, false);
4668 if (err)
4669 goto out;
4670
4671 err = rdev_set_default_beacon_key(rdev, dev, link_id, key.idx);
56be393f
JM
4672 if (err)
4673 goto out;
6cdd3979
AW
4674 } else if (key.p.mode == NL80211_KEY_SET_TX &&
4675 wiphy_ext_feature_isset(&rdev->wiphy,
4676 NL80211_EXT_FEATURE_EXT_KEY_ID)) {
4677 u8 *mac_addr = NULL;
4678
4679 if (info->attrs[NL80211_ATTR_MAC])
4680 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
4681
4682 if (!mac_addr || key.idx < 0 || key.idx > 1) {
4683 err = -EINVAL;
4684 goto out;
4685 }
dbd2fd65 4686
e7a7b84e
VJ
4687 err = nl80211_validate_key_link_id(info, wdev, link_id, true);
4688 if (err)
4689 goto out;
4690
4691 err = rdev_add_key(rdev, dev, link_id, key.idx,
6cdd3979
AW
4692 NL80211_KEYTYPE_PAIRWISE,
4693 mac_addr, &key.p);
4694 } else {
4695 err = -EINVAL;
4696 }
dbd2fd65 4697 out:
e7a7b84e 4698 wdev_unlock(wdev);
41ade00f 4699
41ade00f
JB
4700 return err;
4701}
4702
4703static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
4704{
4c476991 4705 struct cfg80211_registered_device *rdev = info->user_ptr[0];
fffd0934 4706 int err;
4c476991 4707 struct net_device *dev = info->user_ptr[1];
b9454e83 4708 struct key_parse key;
e31b8213 4709 const u8 *mac_addr = NULL;
e7a7b84e
VJ
4710 int link_id = nl80211_link_id_or_invalid(info->attrs);
4711 struct wireless_dev *wdev = dev->ieee80211_ptr;
41ade00f 4712
b9454e83
JB
4713 err = nl80211_parse_key(info, &key);
4714 if (err)
4715 return err;
41ade00f 4716
f8af764b
JM
4717 if (!key.p.key) {
4718 GENL_SET_ERR_MSG(info, "no key");
41ade00f 4719 return -EINVAL;
f8af764b 4720 }
41ade00f 4721
41ade00f
JB
4722 if (info->attrs[NL80211_ATTR_MAC])
4723 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
4724
e31b8213
JB
4725 if (key.type == -1) {
4726 if (mac_addr)
4727 key.type = NL80211_KEYTYPE_PAIRWISE;
4728 else
4729 key.type = NL80211_KEYTYPE_GROUP;
4730 }
4731
4732 /* for now */
4733 if (key.type != NL80211_KEYTYPE_PAIRWISE &&
f8af764b
JM
4734 key.type != NL80211_KEYTYPE_GROUP) {
4735 GENL_SET_ERR_MSG(info, "key type not pairwise or group");
e31b8213 4736 return -EINVAL;
f8af764b 4737 }
e31b8213 4738
14f34e36
GG
4739 if (key.type == NL80211_KEYTYPE_GROUP &&
4740 info->attrs[NL80211_ATTR_VLAN_ID])
4741 key.p.vlan_id = nla_get_u16(info->attrs[NL80211_ATTR_VLAN_ID]);
4742
4c476991
JB
4743 if (!rdev->ops->add_key)
4744 return -EOPNOTSUPP;
25e47c18 4745
e31b8213
JB
4746 if (cfg80211_validate_key_settings(rdev, &key.p, key.idx,
4747 key.type == NL80211_KEYTYPE_PAIRWISE,
f8af764b
JM
4748 mac_addr)) {
4749 GENL_SET_ERR_MSG(info, "key setting validation failed");
4c476991 4750 return -EINVAL;
f8af764b 4751 }
41ade00f 4752
e7a7b84e
VJ
4753 wdev_lock(wdev);
4754 err = nl80211_key_allowed(wdev);
f8af764b
JM
4755 if (err)
4756 GENL_SET_ERR_MSG(info, "key not allowed");
e7a7b84e
VJ
4757
4758 if (!err)
4759 err = nl80211_validate_key_link_id(info, wdev, link_id,
4760 key.type == NL80211_KEYTYPE_PAIRWISE);
4761
f8af764b 4762 if (!err) {
e7a7b84e 4763 err = rdev_add_key(rdev, dev, link_id, key.idx,
e35e4d28
HG
4764 key.type == NL80211_KEYTYPE_PAIRWISE,
4765 mac_addr, &key.p);
f8af764b
JM
4766 if (err)
4767 GENL_SET_ERR_MSG(info, "key addition failed");
4768 }
e7a7b84e 4769 wdev_unlock(wdev);
41ade00f 4770
41ade00f
JB
4771 return err;
4772}
4773
4774static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
4775{
4c476991 4776 struct cfg80211_registered_device *rdev = info->user_ptr[0];
41ade00f 4777 int err;
4c476991 4778 struct net_device *dev = info->user_ptr[1];
41ade00f 4779 u8 *mac_addr = NULL;
b9454e83 4780 struct key_parse key;
e7a7b84e
VJ
4781 int link_id = nl80211_link_id_or_invalid(info->attrs);
4782 struct wireless_dev *wdev = dev->ieee80211_ptr;
41ade00f 4783
b9454e83
JB
4784 err = nl80211_parse_key(info, &key);
4785 if (err)
4786 return err;
41ade00f
JB
4787
4788 if (info->attrs[NL80211_ATTR_MAC])
4789 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
4790
e31b8213
JB
4791 if (key.type == -1) {
4792 if (mac_addr)
4793 key.type = NL80211_KEYTYPE_PAIRWISE;
4794 else
4795 key.type = NL80211_KEYTYPE_GROUP;
4796 }
4797
4798 /* for now */
4799 if (key.type != NL80211_KEYTYPE_PAIRWISE &&
4800 key.type != NL80211_KEYTYPE_GROUP)
4801 return -EINVAL;
4802
2d946308
AT
4803 if (!cfg80211_valid_key_idx(rdev, key.idx,
4804 key.type == NL80211_KEYTYPE_PAIRWISE))
4805 return -EINVAL;
4806
4c476991
JB
4807 if (!rdev->ops->del_key)
4808 return -EOPNOTSUPP;
41ade00f 4809
e7a7b84e
VJ
4810 wdev_lock(wdev);
4811 err = nl80211_key_allowed(wdev);
e31b8213 4812
0fa7b391 4813 if (key.type == NL80211_KEYTYPE_GROUP && mac_addr &&
e31b8213
JB
4814 !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
4815 err = -ENOENT;
4816
fffd0934 4817 if (!err)
e7a7b84e
VJ
4818 err = nl80211_validate_key_link_id(info, wdev, link_id,
4819 key.type == NL80211_KEYTYPE_PAIRWISE);
4820
4821 if (!err)
4822 err = rdev_del_key(rdev, dev, link_id, key.idx,
e35e4d28
HG
4823 key.type == NL80211_KEYTYPE_PAIRWISE,
4824 mac_addr);
41ade00f 4825
3d23e349 4826#ifdef CONFIG_CFG80211_WEXT
08645126 4827 if (!err) {
e7a7b84e
VJ
4828 if (key.idx == wdev->wext.default_key)
4829 wdev->wext.default_key = -1;
4830 else if (key.idx == wdev->wext.default_mgmt_key)
4831 wdev->wext.default_mgmt_key = -1;
08645126
JB
4832 }
4833#endif
e7a7b84e 4834 wdev_unlock(wdev);
08645126 4835
41ade00f
JB
4836 return err;
4837}
4838
77765eaf
VT
4839/* This function returns an error or the number of nested attributes */
4840static int validate_acl_mac_addrs(struct nlattr *nl_attr)
4841{
4842 struct nlattr *attr;
4843 int n_entries = 0, tmp;
4844
4845 nla_for_each_nested(attr, nl_attr, tmp) {
4846 if (nla_len(attr) != ETH_ALEN)
4847 return -EINVAL;
4848
4849 n_entries++;
4850 }
4851
4852 return n_entries;
4853}
4854
4855/*
4856 * This function parses ACL information and allocates memory for ACL data.
4857 * On successful return, the calling function is responsible to free the
4858 * ACL buffer returned by this function.
4859 */
4860static struct cfg80211_acl_data *parse_acl_data(struct wiphy *wiphy,
4861 struct genl_info *info)
4862{
4863 enum nl80211_acl_policy acl_policy;
4864 struct nlattr *attr;
4865 struct cfg80211_acl_data *acl;
4866 int i = 0, n_entries, tmp;
4867
4868 if (!wiphy->max_acl_mac_addrs)
4869 return ERR_PTR(-EOPNOTSUPP);
4870
4871 if (!info->attrs[NL80211_ATTR_ACL_POLICY])
4872 return ERR_PTR(-EINVAL);
4873
4874 acl_policy = nla_get_u32(info->attrs[NL80211_ATTR_ACL_POLICY]);
4875 if (acl_policy != NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED &&
4876 acl_policy != NL80211_ACL_POLICY_DENY_UNLESS_LISTED)
4877 return ERR_PTR(-EINVAL);
4878
4879 if (!info->attrs[NL80211_ATTR_MAC_ADDRS])
4880 return ERR_PTR(-EINVAL);
4881
4882 n_entries = validate_acl_mac_addrs(info->attrs[NL80211_ATTR_MAC_ADDRS]);
4883 if (n_entries < 0)
4884 return ERR_PTR(n_entries);
4885
4886 if (n_entries > wiphy->max_acl_mac_addrs)
4887 return ERR_PTR(-ENOTSUPP);
4888
391d132c 4889 acl = kzalloc(struct_size(acl, mac_addrs, n_entries), GFP_KERNEL);
77765eaf
VT
4890 if (!acl)
4891 return ERR_PTR(-ENOMEM);
4892
4893 nla_for_each_nested(attr, info->attrs[NL80211_ATTR_MAC_ADDRS], tmp) {
4894 memcpy(acl->mac_addrs[i].addr, nla_data(attr), ETH_ALEN);
4895 i++;
4896 }
4897
4898 acl->n_acl_entries = n_entries;
4899 acl->acl_policy = acl_policy;
4900
4901 return acl;
4902}
4903
4904static int nl80211_set_mac_acl(struct sk_buff *skb, struct genl_info *info)
4905{
4906 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4907 struct net_device *dev = info->user_ptr[1];
4908 struct cfg80211_acl_data *acl;
4909 int err;
4910
4911 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
4912 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
4913 return -EOPNOTSUPP;
4914
7b0a0e3c 4915 if (!dev->ieee80211_ptr->links[0].ap.beacon_interval)
77765eaf
VT
4916 return -EINVAL;
4917
4918 acl = parse_acl_data(&rdev->wiphy, info);
4919 if (IS_ERR(acl))
4920 return PTR_ERR(acl);
4921
4922 err = rdev_set_mac_acl(rdev, dev, acl);
4923
4924 kfree(acl);
4925
4926 return err;
4927}
4928
a7c7fbff
PK
4929static u32 rateset_to_mask(struct ieee80211_supported_band *sband,
4930 u8 *rates, u8 rates_len)
4931{
4932 u8 i;
4933 u32 mask = 0;
4934
4935 for (i = 0; i < rates_len; i++) {
4936 int rate = (rates[i] & 0x7f) * 5;
4937 int ridx;
4938
4939 for (ridx = 0; ridx < sband->n_bitrates; ridx++) {
4940 struct ieee80211_rate *srate =
4941 &sband->bitrates[ridx];
4942 if (rate == srate->bitrate) {
4943 mask |= 1 << ridx;
4944 break;
4945 }
4946 }
4947 if (ridx == sband->n_bitrates)
4948 return 0; /* rate not found */
4949 }
4950
4951 return mask;
4952}
4953
4954static bool ht_rateset_to_mask(struct ieee80211_supported_band *sband,
4955 u8 *rates, u8 rates_len,
4956 u8 mcs[IEEE80211_HT_MCS_MASK_LEN])
4957{
4958 u8 i;
4959
4960 memset(mcs, 0, IEEE80211_HT_MCS_MASK_LEN);
4961
4962 for (i = 0; i < rates_len; i++) {
4963 int ridx, rbit;
4964
4965 ridx = rates[i] / 8;
4966 rbit = BIT(rates[i] % 8);
4967
4968 /* check validity */
4969 if ((ridx < 0) || (ridx >= IEEE80211_HT_MCS_MASK_LEN))
4970 return false;
4971
4972 /* check availability */
30fe6d50 4973 ridx = array_index_nospec(ridx, IEEE80211_HT_MCS_MASK_LEN);
a7c7fbff
PK
4974 if (sband->ht_cap.mcs.rx_mask[ridx] & rbit)
4975 mcs[ridx] |= rbit;
4976 else
4977 return false;
4978 }
4979
4980 return true;
4981}
4982
4983static u16 vht_mcs_map_to_mcs_mask(u8 vht_mcs_map)
4984{
4985 u16 mcs_mask = 0;
4986
4987 switch (vht_mcs_map) {
4988 case IEEE80211_VHT_MCS_NOT_SUPPORTED:
4989 break;
4990 case IEEE80211_VHT_MCS_SUPPORT_0_7:
4991 mcs_mask = 0x00FF;
4992 break;
4993 case IEEE80211_VHT_MCS_SUPPORT_0_8:
4994 mcs_mask = 0x01FF;
4995 break;
4996 case IEEE80211_VHT_MCS_SUPPORT_0_9:
4997 mcs_mask = 0x03FF;
4998 break;
4999 default:
5000 break;
5001 }
5002
5003 return mcs_mask;
5004}
5005
5006static void vht_build_mcs_mask(u16 vht_mcs_map,
5007 u16 vht_mcs_mask[NL80211_VHT_NSS_MAX])
5008{
5009 u8 nss;
5010
5011 for (nss = 0; nss < NL80211_VHT_NSS_MAX; nss++) {
5012 vht_mcs_mask[nss] = vht_mcs_map_to_mcs_mask(vht_mcs_map & 0x03);
5013 vht_mcs_map >>= 2;
5014 }
5015}
5016
5017static bool vht_set_mcs_mask(struct ieee80211_supported_band *sband,
5018 struct nl80211_txrate_vht *txrate,
5019 u16 mcs[NL80211_VHT_NSS_MAX])
5020{
5021 u16 tx_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map);
5022 u16 tx_mcs_mask[NL80211_VHT_NSS_MAX] = {};
5023 u8 i;
5024
5025 if (!sband->vht_cap.vht_supported)
5026 return false;
5027
5028 memset(mcs, 0, sizeof(u16) * NL80211_VHT_NSS_MAX);
5029
5030 /* Build vht_mcs_mask from VHT capabilities */
5031 vht_build_mcs_mask(tx_mcs_map, tx_mcs_mask);
5032
5033 for (i = 0; i < NL80211_VHT_NSS_MAX; i++) {
5034 if ((tx_mcs_mask[i] & txrate->mcs[i]) == txrate->mcs[i])
5035 mcs[i] = txrate->mcs[i];
5036 else
5037 return false;
5038 }
5039
5040 return true;
5041}
5042
eb89a6a6
MH
5043static u16 he_mcs_map_to_mcs_mask(u8 he_mcs_map)
5044{
5045 switch (he_mcs_map) {
5046 case IEEE80211_HE_MCS_NOT_SUPPORTED:
5047 return 0;
5048 case IEEE80211_HE_MCS_SUPPORT_0_7:
5049 return 0x00FF;
5050 case IEEE80211_HE_MCS_SUPPORT_0_9:
5051 return 0x03FF;
5052 case IEEE80211_HE_MCS_SUPPORT_0_11:
5053 return 0xFFF;
5054 default:
5055 break;
5056 }
5057 return 0;
5058}
5059
5060static void he_build_mcs_mask(u16 he_mcs_map,
5061 u16 he_mcs_mask[NL80211_HE_NSS_MAX])
5062{
5063 u8 nss;
5064
5065 for (nss = 0; nss < NL80211_HE_NSS_MAX; nss++) {
5066 he_mcs_mask[nss] = he_mcs_map_to_mcs_mask(he_mcs_map & 0x03);
5067 he_mcs_map >>= 2;
5068 }
5069}
5070
7b0a0e3c 5071static u16 he_get_txmcsmap(struct genl_info *info, unsigned int link_id,
eb89a6a6
MH
5072 const struct ieee80211_sta_he_cap *he_cap)
5073{
5074 struct net_device *dev = info->user_ptr[1];
5075 struct wireless_dev *wdev = dev->ieee80211_ptr;
7b0a0e3c
JB
5076 struct cfg80211_chan_def *chandef;
5077 __le16 tx_mcs;
eb89a6a6 5078
7b0a0e3c
JB
5079 chandef = wdev_chandef(wdev, link_id);
5080 if (!chandef) {
5081 /*
5082 * This is probably broken, but we never maintained
5083 * a chandef in these cases, so it always was.
5084 */
5085 return le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_80);
5086 }
5087
5088 switch (chandef->width) {
eb89a6a6
MH
5089 case NL80211_CHAN_WIDTH_80P80:
5090 tx_mcs = he_cap->he_mcs_nss_supp.tx_mcs_80p80;
5091 break;
5092 case NL80211_CHAN_WIDTH_160:
5093 tx_mcs = he_cap->he_mcs_nss_supp.tx_mcs_160;
5094 break;
5095 default:
5096 tx_mcs = he_cap->he_mcs_nss_supp.tx_mcs_80;
5097 break;
5098 }
7b0a0e3c 5099
eb89a6a6
MH
5100 return le16_to_cpu(tx_mcs);
5101}
5102
5103static bool he_set_mcs_mask(struct genl_info *info,
5104 struct wireless_dev *wdev,
5105 struct ieee80211_supported_band *sband,
5106 struct nl80211_txrate_he *txrate,
7b0a0e3c
JB
5107 u16 mcs[NL80211_HE_NSS_MAX],
5108 unsigned int link_id)
eb89a6a6
MH
5109{
5110 const struct ieee80211_sta_he_cap *he_cap;
5111 u16 tx_mcs_mask[NL80211_HE_NSS_MAX] = {};
5112 u16 tx_mcs_map = 0;
5113 u8 i;
5114
5115 he_cap = ieee80211_get_he_iftype_cap(sband, wdev->iftype);
5116 if (!he_cap)
5117 return false;
5118
5119 memset(mcs, 0, sizeof(u16) * NL80211_HE_NSS_MAX);
5120
7b0a0e3c 5121 tx_mcs_map = he_get_txmcsmap(info, link_id, he_cap);
eb89a6a6
MH
5122
5123 /* Build he_mcs_mask from HE capabilities */
5124 he_build_mcs_mask(tx_mcs_map, tx_mcs_mask);
5125
5126 for (i = 0; i < NL80211_HE_NSS_MAX; i++) {
5127 if ((tx_mcs_mask[i] & txrate->mcs[i]) == txrate->mcs[i])
5128 mcs[i] = txrate->mcs[i];
5129 else
5130 return false;
5131 }
5132
5133 return true;
5134}
5135
a7c7fbff 5136static int nl80211_parse_tx_bitrate_mask(struct genl_info *info,
9a5f6488
TC
5137 struct nlattr *attrs[],
5138 enum nl80211_attrs attr,
eb89a6a6 5139 struct cfg80211_bitrate_mask *mask,
857b34c4 5140 struct net_device *dev,
7b0a0e3c
JB
5141 bool default_all_enabled,
5142 unsigned int link_id)
a7c7fbff
PK
5143{
5144 struct nlattr *tb[NL80211_TXRATE_MAX + 1];
5145 struct cfg80211_registered_device *rdev = info->user_ptr[0];
eb89a6a6 5146 struct wireless_dev *wdev = dev->ieee80211_ptr;
a7c7fbff
PK
5147 int rem, i;
5148 struct nlattr *tx_rates;
5149 struct ieee80211_supported_band *sband;
eb89a6a6 5150 u16 vht_tx_mcs_map, he_tx_mcs_map;
a7c7fbff
PK
5151
5152 memset(mask, 0, sizeof(*mask));
5153 /* Default to all rates enabled */
5154 for (i = 0; i < NUM_NL80211_BANDS; i++) {
eb89a6a6
MH
5155 const struct ieee80211_sta_he_cap *he_cap;
5156
857b34c4
RM
5157 if (!default_all_enabled)
5158 break;
5159
a7c7fbff
PK
5160 sband = rdev->wiphy.bands[i];
5161
5162 if (!sband)
5163 continue;
5164
5165 mask->control[i].legacy = (1 << sband->n_bitrates) - 1;
5166 memcpy(mask->control[i].ht_mcs,
5167 sband->ht_cap.mcs.rx_mask,
5168 sizeof(mask->control[i].ht_mcs));
5169
9df66d5b
PKS
5170 if (sband->vht_cap.vht_supported) {
5171 vht_tx_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map);
5172 vht_build_mcs_mask(vht_tx_mcs_map, mask->control[i].vht_mcs);
5173 }
eb89a6a6
MH
5174
5175 he_cap = ieee80211_get_he_iftype_cap(sband, wdev->iftype);
5176 if (!he_cap)
5177 continue;
5178
7b0a0e3c 5179 he_tx_mcs_map = he_get_txmcsmap(info, link_id, he_cap);
eb89a6a6
MH
5180 he_build_mcs_mask(he_tx_mcs_map, mask->control[i].he_mcs);
5181
5182 mask->control[i].he_gi = 0xFF;
5183 mask->control[i].he_ltf = 0xFF;
a7c7fbff
PK
5184 }
5185
5186 /* if no rates are given set it back to the defaults */
9a5f6488 5187 if (!attrs[attr])
a7c7fbff
PK
5188 goto out;
5189
5190 /* The nested attribute uses enum nl80211_band as the index. This maps
5191 * directly to the enum nl80211_band values used in cfg80211.
5192 */
5193 BUILD_BUG_ON(NL80211_MAX_SUPP_HT_RATES > IEEE80211_HT_MCS_MASK_LEN * 8);
9a5f6488 5194 nla_for_each_nested(tx_rates, attrs[attr], rem) {
a7c7fbff
PK
5195 enum nl80211_band band = nla_type(tx_rates);
5196 int err;
5197
5198 if (band < 0 || band >= NUM_NL80211_BANDS)
5199 return -EINVAL;
5200 sband = rdev->wiphy.bands[band];
5201 if (sband == NULL)
5202 return -EINVAL;
8cb08174
JB
5203 err = nla_parse_nested_deprecated(tb, NL80211_TXRATE_MAX,
5204 tx_rates,
5205 nl80211_txattr_policy,
5206 info->extack);
a7c7fbff
PK
5207 if (err)
5208 return err;
5209 if (tb[NL80211_TXRATE_LEGACY]) {
5210 mask->control[band].legacy = rateset_to_mask(
5211 sband,
5212 nla_data(tb[NL80211_TXRATE_LEGACY]),
5213 nla_len(tb[NL80211_TXRATE_LEGACY]));
5214 if ((mask->control[band].legacy == 0) &&
5215 nla_len(tb[NL80211_TXRATE_LEGACY]))
5216 return -EINVAL;
5217 }
5218 if (tb[NL80211_TXRATE_HT]) {
5219 if (!ht_rateset_to_mask(
5220 sband,
5221 nla_data(tb[NL80211_TXRATE_HT]),
5222 nla_len(tb[NL80211_TXRATE_HT]),
5223 mask->control[band].ht_mcs))
5224 return -EINVAL;
5225 }
c4a30446 5226
a7c7fbff
PK
5227 if (tb[NL80211_TXRATE_VHT]) {
5228 if (!vht_set_mcs_mask(
5229 sband,
5230 nla_data(tb[NL80211_TXRATE_VHT]),
5231 mask->control[band].vht_mcs))
5232 return -EINVAL;
5233 }
c4a30446 5234
a7c7fbff
PK
5235 if (tb[NL80211_TXRATE_GI]) {
5236 mask->control[band].gi =
5237 nla_get_u8(tb[NL80211_TXRATE_GI]);
5238 if (mask->control[band].gi > NL80211_TXRATE_FORCE_LGI)
5239 return -EINVAL;
5240 }
eb89a6a6
MH
5241 if (tb[NL80211_TXRATE_HE] &&
5242 !he_set_mcs_mask(info, wdev, sband,
5243 nla_data(tb[NL80211_TXRATE_HE]),
7b0a0e3c
JB
5244 mask->control[band].he_mcs,
5245 link_id))
eb89a6a6 5246 return -EINVAL;
c4a30446 5247
eb89a6a6
MH
5248 if (tb[NL80211_TXRATE_HE_GI])
5249 mask->control[band].he_gi =
5250 nla_get_u8(tb[NL80211_TXRATE_HE_GI]);
5251 if (tb[NL80211_TXRATE_HE_LTF])
5252 mask->control[band].he_ltf =
5253 nla_get_u8(tb[NL80211_TXRATE_HE_LTF]);
a7c7fbff
PK
5254
5255 if (mask->control[band].legacy == 0) {
eb89a6a6 5256 /* don't allow empty legacy rates if HT, VHT or HE
a7c7fbff
PK
5257 * are not even supported.
5258 */
5259 if (!(rdev->wiphy.bands[band]->ht_cap.ht_supported ||
eb89a6a6
MH
5260 rdev->wiphy.bands[band]->vht_cap.vht_supported ||
5261 ieee80211_get_he_iftype_cap(sband, wdev->iftype)))
a7c7fbff
PK
5262 return -EINVAL;
5263
5264 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++)
5265 if (mask->control[band].ht_mcs[i])
5266 goto out;
5267
5268 for (i = 0; i < NL80211_VHT_NSS_MAX; i++)
5269 if (mask->control[band].vht_mcs[i])
5270 goto out;
5271
eb89a6a6
MH
5272 for (i = 0; i < NL80211_HE_NSS_MAX; i++)
5273 if (mask->control[band].he_mcs[i])
5274 goto out;
5275
a7c7fbff
PK
5276 /* legacy and mcs rates may not be both empty */
5277 return -EINVAL;
5278 }
5279 }
5280
5281out:
5282 return 0;
5283}
5284
8564e382
JB
5285static int validate_beacon_tx_rate(struct cfg80211_registered_device *rdev,
5286 enum nl80211_band band,
5287 struct cfg80211_bitrate_mask *beacon_rate)
a7c7fbff 5288{
c4a30446 5289 u32 count_ht, count_vht, count_he, i;
8564e382 5290 u32 rate = beacon_rate->control[band].legacy;
a7c7fbff
PK
5291
5292 /* Allow only one rate */
5293 if (hweight32(rate) > 1)
5294 return -EINVAL;
5295
5296 count_ht = 0;
5297 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
8564e382 5298 if (hweight8(beacon_rate->control[band].ht_mcs[i]) > 1) {
a7c7fbff 5299 return -EINVAL;
8564e382 5300 } else if (beacon_rate->control[band].ht_mcs[i]) {
a7c7fbff
PK
5301 count_ht++;
5302 if (count_ht > 1)
5303 return -EINVAL;
5304 }
5305 if (count_ht && rate)
5306 return -EINVAL;
5307 }
5308
5309 count_vht = 0;
5310 for (i = 0; i < NL80211_VHT_NSS_MAX; i++) {
8564e382 5311 if (hweight16(beacon_rate->control[band].vht_mcs[i]) > 1) {
a7c7fbff 5312 return -EINVAL;
8564e382 5313 } else if (beacon_rate->control[band].vht_mcs[i]) {
a7c7fbff
PK
5314 count_vht++;
5315 if (count_vht > 1)
5316 return -EINVAL;
5317 }
5318 if (count_vht && rate)
5319 return -EINVAL;
5320 }
5321
c4a30446
RM
5322 count_he = 0;
5323 for (i = 0; i < NL80211_HE_NSS_MAX; i++) {
5324 if (hweight16(beacon_rate->control[band].he_mcs[i]) > 1) {
5325 return -EINVAL;
5326 } else if (beacon_rate->control[band].he_mcs[i]) {
5327 count_he++;
5328 if (count_he > 1)
5329 return -EINVAL;
5330 }
5331 if (count_he && rate)
5332 return -EINVAL;
5333 }
5334
5335 if ((count_ht && count_vht && count_he) ||
5336 (!rate && !count_ht && !count_vht && !count_he))
a7c7fbff
PK
5337 return -EINVAL;
5338
8564e382
JB
5339 if (rate &&
5340 !wiphy_ext_feature_isset(&rdev->wiphy,
5341 NL80211_EXT_FEATURE_BEACON_RATE_LEGACY))
5342 return -EINVAL;
5343 if (count_ht &&
5344 !wiphy_ext_feature_isset(&rdev->wiphy,
5345 NL80211_EXT_FEATURE_BEACON_RATE_HT))
5346 return -EINVAL;
5347 if (count_vht &&
5348 !wiphy_ext_feature_isset(&rdev->wiphy,
5349 NL80211_EXT_FEATURE_BEACON_RATE_VHT))
5350 return -EINVAL;
c4a30446
RM
5351 if (count_he &&
5352 !wiphy_ext_feature_isset(&rdev->wiphy,
5353 NL80211_EXT_FEATURE_BEACON_RATE_HE))
5354 return -EINVAL;
8564e382 5355
a7c7fbff
PK
5356 return 0;
5357}
5358
dc1e3cb8
JC
5359static int nl80211_parse_mbssid_config(struct wiphy *wiphy,
5360 struct net_device *dev,
5361 struct nlattr *attrs,
5362 struct cfg80211_mbssid_config *config,
5363 u8 num_elems)
5364{
5365 struct nlattr *tb[NL80211_MBSSID_CONFIG_ATTR_MAX + 1];
5366
5367 if (!wiphy->mbssid_max_interfaces)
5368 return -EOPNOTSUPP;
5369
5370 if (nla_parse_nested(tb, NL80211_MBSSID_CONFIG_ATTR_MAX, attrs, NULL,
5371 NULL) ||
5372 !tb[NL80211_MBSSID_CONFIG_ATTR_INDEX])
5373 return -EINVAL;
5374
5375 config->ema = nla_get_flag(tb[NL80211_MBSSID_CONFIG_ATTR_EMA]);
5376 if (config->ema) {
5377 if (!wiphy->ema_max_profile_periodicity)
5378 return -EOPNOTSUPP;
5379
5380 if (num_elems > wiphy->ema_max_profile_periodicity)
5381 return -EINVAL;
5382 }
5383
5384 config->index = nla_get_u8(tb[NL80211_MBSSID_CONFIG_ATTR_INDEX]);
5385 if (config->index >= wiphy->mbssid_max_interfaces ||
5386 (!config->index && !num_elems))
5387 return -EINVAL;
5388
5389 if (tb[NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX]) {
5390 u32 tx_ifindex =
5391 nla_get_u32(tb[NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX]);
5392
5393 if ((!config->index && tx_ifindex != dev->ifindex) ||
5394 (config->index && tx_ifindex == dev->ifindex))
5395 return -EINVAL;
5396
5397 if (tx_ifindex != dev->ifindex) {
5398 struct net_device *tx_netdev =
5399 dev_get_by_index(wiphy_net(wiphy), tx_ifindex);
5400
5401 if (!tx_netdev || !tx_netdev->ieee80211_ptr ||
5402 tx_netdev->ieee80211_ptr->wiphy != wiphy ||
5403 tx_netdev->ieee80211_ptr->iftype !=
5404 NL80211_IFTYPE_AP) {
5405 dev_put(tx_netdev);
5406 return -EINVAL;
5407 }
5408
5409 config->tx_wdev = tx_netdev->ieee80211_ptr;
5410 } else {
5411 config->tx_wdev = dev->ieee80211_ptr;
5412 }
5413 } else if (!config->index) {
5414 config->tx_wdev = dev->ieee80211_ptr;
5415 } else {
5416 return -EINVAL;
5417 }
5418
5419 return 0;
5420}
5421
5422static struct cfg80211_mbssid_elems *
5423nl80211_parse_mbssid_elems(struct wiphy *wiphy, struct nlattr *attrs)
5424{
5425 struct nlattr *nl_elems;
5426 struct cfg80211_mbssid_elems *elems;
5427 int rem_elems;
5428 u8 i = 0, num_elems = 0;
5429
5430 if (!wiphy->mbssid_max_interfaces)
5431 return ERR_PTR(-EINVAL);
5432
5433 nla_for_each_nested(nl_elems, attrs, rem_elems)
5434 num_elems++;
5435
5436 elems = kzalloc(struct_size(elems, elem, num_elems), GFP_KERNEL);
5437 if (!elems)
5438 return ERR_PTR(-ENOMEM);
5439
5440 nla_for_each_nested(nl_elems, attrs, rem_elems) {
5441 elems->elem[i].data = nla_data(nl_elems);
5442 elems->elem[i].len = nla_len(nl_elems);
5443 i++;
5444 }
5445 elems->cnt = num_elems;
5446 return elems;
5447}
5448
dbbb27e1
AD
5449static struct cfg80211_rnr_elems *
5450nl80211_parse_rnr_elems(struct wiphy *wiphy, struct nlattr *attrs,
5451 struct netlink_ext_ack *extack)
5452{
5453 struct nlattr *nl_elems;
5454 struct cfg80211_rnr_elems *elems;
5455 int rem_elems;
5456 u8 i = 0, num_elems = 0;
5457
5458 nla_for_each_nested(nl_elems, attrs, rem_elems) {
5459 int ret;
5460
5461 ret = validate_ie_attr(nl_elems, extack);
5462 if (ret)
5463 return ERR_PTR(ret);
5464
5465 num_elems++;
5466 }
5467
5468 elems = kzalloc(struct_size(elems, elem, num_elems), GFP_KERNEL);
5469 if (!elems)
5470 return ERR_PTR(-ENOMEM);
5471
5472 nla_for_each_nested(nl_elems, attrs, rem_elems) {
5473 elems->elem[i].data = nla_data(nl_elems);
5474 elems->elem[i].len = nla_len(nl_elems);
5475 i++;
5476 }
5477 elems->cnt = num_elems;
5478 return elems;
5479}
5480
3d48cb74
RS
5481static int nl80211_parse_he_bss_color(struct nlattr *attrs,
5482 struct cfg80211_he_bss_color *he_bss_color)
5483{
5484 struct nlattr *tb[NL80211_HE_BSS_COLOR_ATTR_MAX + 1];
5485 int err;
5486
5487 err = nla_parse_nested(tb, NL80211_HE_BSS_COLOR_ATTR_MAX, attrs,
5488 he_bss_color_policy, NULL);
5489 if (err)
5490 return err;
5491
5492 if (!tb[NL80211_HE_BSS_COLOR_ATTR_COLOR])
5493 return -EINVAL;
5494
5495 he_bss_color->color =
5496 nla_get_u8(tb[NL80211_HE_BSS_COLOR_ATTR_COLOR]);
5497 he_bss_color->enabled =
5498 !nla_get_flag(tb[NL80211_HE_BSS_COLOR_ATTR_DISABLED]);
5499 he_bss_color->partial =
5500 nla_get_flag(tb[NL80211_HE_BSS_COLOR_ATTR_PARTIAL]);
5501
5502 return 0;
5503}
5504
81e54d08
PKC
5505static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev,
5506 struct nlattr *attrs[],
dbbb27e1
AD
5507 struct cfg80211_beacon_data *bcn,
5508 struct netlink_ext_ack *extack)
ed1b6cc7 5509{
8860020e 5510 bool haveinfo = false;
81e54d08 5511 int err;
ed1b6cc7 5512
8860020e 5513 memset(bcn, 0, sizeof(*bcn));
ed1b6cc7 5514
7b0a0e3c
JB
5515 bcn->link_id = nl80211_link_id(attrs);
5516
a1193be8
SW
5517 if (attrs[NL80211_ATTR_BEACON_HEAD]) {
5518 bcn->head = nla_data(attrs[NL80211_ATTR_BEACON_HEAD]);
5519 bcn->head_len = nla_len(attrs[NL80211_ATTR_BEACON_HEAD]);
8860020e
JB
5520 if (!bcn->head_len)
5521 return -EINVAL;
5522 haveinfo = true;
ed1b6cc7
JB
5523 }
5524
a1193be8
SW
5525 if (attrs[NL80211_ATTR_BEACON_TAIL]) {
5526 bcn->tail = nla_data(attrs[NL80211_ATTR_BEACON_TAIL]);
5527 bcn->tail_len = nla_len(attrs[NL80211_ATTR_BEACON_TAIL]);
8860020e 5528 haveinfo = true;
ed1b6cc7
JB
5529 }
5530
4c476991
JB
5531 if (!haveinfo)
5532 return -EINVAL;
3b85875a 5533
a1193be8
SW
5534 if (attrs[NL80211_ATTR_IE]) {
5535 bcn->beacon_ies = nla_data(attrs[NL80211_ATTR_IE]);
5536 bcn->beacon_ies_len = nla_len(attrs[NL80211_ATTR_IE]);
9946ecfb
JM
5537 }
5538
a1193be8 5539 if (attrs[NL80211_ATTR_IE_PROBE_RESP]) {
8860020e 5540 bcn->proberesp_ies =
a1193be8 5541 nla_data(attrs[NL80211_ATTR_IE_PROBE_RESP]);
8860020e 5542 bcn->proberesp_ies_len =
a1193be8 5543 nla_len(attrs[NL80211_ATTR_IE_PROBE_RESP]);
9946ecfb
JM
5544 }
5545
a1193be8 5546 if (attrs[NL80211_ATTR_IE_ASSOC_RESP]) {
8860020e 5547 bcn->assocresp_ies =
a1193be8 5548 nla_data(attrs[NL80211_ATTR_IE_ASSOC_RESP]);
8860020e 5549 bcn->assocresp_ies_len =
a1193be8 5550 nla_len(attrs[NL80211_ATTR_IE_ASSOC_RESP]);
9946ecfb
JM
5551 }
5552
a1193be8
SW
5553 if (attrs[NL80211_ATTR_PROBE_RESP]) {
5554 bcn->probe_resp = nla_data(attrs[NL80211_ATTR_PROBE_RESP]);
5555 bcn->probe_resp_len = nla_len(attrs[NL80211_ATTR_PROBE_RESP]);
00f740e1
AN
5556 }
5557
81e54d08
PKC
5558 if (attrs[NL80211_ATTR_FTM_RESPONDER]) {
5559 struct nlattr *tb[NL80211_FTM_RESP_ATTR_MAX + 1];
5560
8cb08174
JB
5561 err = nla_parse_nested_deprecated(tb,
5562 NL80211_FTM_RESP_ATTR_MAX,
5563 attrs[NL80211_ATTR_FTM_RESPONDER],
5564 NULL, NULL);
81e54d08
PKC
5565 if (err)
5566 return err;
5567
5568 if (tb[NL80211_FTM_RESP_ATTR_ENABLED] &&
5569 wiphy_ext_feature_isset(&rdev->wiphy,
5570 NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER))
5571 bcn->ftm_responder = 1;
5572 else
5573 return -EOPNOTSUPP;
5574
5575 if (tb[NL80211_FTM_RESP_ATTR_LCI]) {
5576 bcn->lci = nla_data(tb[NL80211_FTM_RESP_ATTR_LCI]);
5577 bcn->lci_len = nla_len(tb[NL80211_FTM_RESP_ATTR_LCI]);
5578 }
5579
5580 if (tb[NL80211_FTM_RESP_ATTR_CIVICLOC]) {
5581 bcn->civicloc = nla_data(tb[NL80211_FTM_RESP_ATTR_CIVICLOC]);
5582 bcn->civicloc_len = nla_len(tb[NL80211_FTM_RESP_ATTR_CIVICLOC]);
5583 }
5584 } else {
5585 bcn->ftm_responder = -1;
5586 }
5587
3d48cb74
RS
5588 if (attrs[NL80211_ATTR_HE_BSS_COLOR]) {
5589 err = nl80211_parse_he_bss_color(attrs[NL80211_ATTR_HE_BSS_COLOR],
5590 &bcn->he_bss_color);
5591 if (err)
5592 return err;
5593 bcn->he_bss_color_valid = true;
5594 }
5595
dc1e3cb8
JC
5596 if (attrs[NL80211_ATTR_MBSSID_ELEMS]) {
5597 struct cfg80211_mbssid_elems *mbssid =
5598 nl80211_parse_mbssid_elems(&rdev->wiphy,
5599 attrs[NL80211_ATTR_MBSSID_ELEMS]);
5600
5601 if (IS_ERR(mbssid))
5602 return PTR_ERR(mbssid);
5603
5604 bcn->mbssid_ies = mbssid;
dbbb27e1
AD
5605
5606 if (bcn->mbssid_ies && attrs[NL80211_ATTR_EMA_RNR_ELEMS]) {
5607 struct cfg80211_rnr_elems *rnr =
5608 nl80211_parse_rnr_elems(&rdev->wiphy,
5609 attrs[NL80211_ATTR_EMA_RNR_ELEMS],
5610 extack);
5611
5612 if (IS_ERR(rnr))
5613 return PTR_ERR(rnr);
5614
5615 if (rnr && rnr->cnt < bcn->mbssid_ies->cnt)
5616 return -EINVAL;
5617
5618 bcn->rnr_ies = rnr;
5619 }
dc1e3cb8
JC
5620 }
5621
8860020e
JB
5622 return 0;
5623}
5624
796e90f4
JC
5625static int nl80211_parse_he_obss_pd(struct nlattr *attrs,
5626 struct ieee80211_he_obss_pd *he_obss_pd)
5627{
5628 struct nlattr *tb[NL80211_HE_OBSS_PD_ATTR_MAX + 1];
5629 int err;
5630
5631 err = nla_parse_nested(tb, NL80211_HE_OBSS_PD_ATTR_MAX, attrs,
5632 he_obss_pd_policy, NULL);
5633 if (err)
5634 return err;
5635
f5bec330
RM
5636 if (!tb[NL80211_HE_OBSS_PD_ATTR_SR_CTRL])
5637 return -EINVAL;
5638
5639 he_obss_pd->sr_ctrl = nla_get_u8(tb[NL80211_HE_OBSS_PD_ATTR_SR_CTRL]);
5640
6c8b6e4a
RM
5641 if (tb[NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET])
5642 he_obss_pd->min_offset =
5643 nla_get_u8(tb[NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET]);
5644 if (tb[NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET])
5645 he_obss_pd->max_offset =
5646 nla_get_u8(tb[NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET]);
f5bec330
RM
5647 if (tb[NL80211_HE_OBSS_PD_ATTR_NON_SRG_MAX_OFFSET])
5648 he_obss_pd->non_srg_max_offset =
5649 nla_get_u8(tb[NL80211_HE_OBSS_PD_ATTR_NON_SRG_MAX_OFFSET]);
6c8b6e4a
RM
5650
5651 if (he_obss_pd->min_offset > he_obss_pd->max_offset)
796e90f4
JC
5652 return -EINVAL;
5653
f5bec330
RM
5654 if (tb[NL80211_HE_OBSS_PD_ATTR_BSS_COLOR_BITMAP])
5655 memcpy(he_obss_pd->bss_color_bitmap,
5656 nla_data(tb[NL80211_HE_OBSS_PD_ATTR_BSS_COLOR_BITMAP]),
5657 sizeof(he_obss_pd->bss_color_bitmap));
5658
5659 if (tb[NL80211_HE_OBSS_PD_ATTR_PARTIAL_BSSID_BITMAP])
5660 memcpy(he_obss_pd->partial_bssid_bitmap,
5661 nla_data(tb[NL80211_HE_OBSS_PD_ATTR_PARTIAL_BSSID_BITMAP]),
5662 sizeof(he_obss_pd->partial_bssid_bitmap));
5663
796e90f4
JC
5664 he_obss_pd->enable = true;
5665
5666 return 0;
5667}
5668
291c49de
AD
5669static int nl80211_parse_fils_discovery(struct cfg80211_registered_device *rdev,
5670 struct nlattr *attrs,
5671 struct cfg80211_ap_settings *params)
5672{
5673 struct nlattr *tb[NL80211_FILS_DISCOVERY_ATTR_MAX + 1];
5674 int ret;
5675 struct cfg80211_fils_discovery *fd = &params->fils_discovery;
5676
5677 if (!wiphy_ext_feature_isset(&rdev->wiphy,
5678 NL80211_EXT_FEATURE_FILS_DISCOVERY))
5679 return -EINVAL;
5680
5681 ret = nla_parse_nested(tb, NL80211_FILS_DISCOVERY_ATTR_MAX, attrs,
5682 NULL, NULL);
5683 if (ret)
5684 return ret;
5685
5686 if (!tb[NL80211_FILS_DISCOVERY_ATTR_INT_MIN] ||
5687 !tb[NL80211_FILS_DISCOVERY_ATTR_INT_MAX] ||
5688 !tb[NL80211_FILS_DISCOVERY_ATTR_TMPL])
5689 return -EINVAL;
5690
5691 fd->tmpl_len = nla_len(tb[NL80211_FILS_DISCOVERY_ATTR_TMPL]);
5692 fd->tmpl = nla_data(tb[NL80211_FILS_DISCOVERY_ATTR_TMPL]);
5693 fd->min_interval = nla_get_u32(tb[NL80211_FILS_DISCOVERY_ATTR_INT_MIN]);
5694 fd->max_interval = nla_get_u32(tb[NL80211_FILS_DISCOVERY_ATTR_INT_MAX]);
5695
5696 return 0;
5697}
5698
7443dcd1
AD
5699static int
5700nl80211_parse_unsol_bcast_probe_resp(struct cfg80211_registered_device *rdev,
5701 struct nlattr *attrs,
5702 struct cfg80211_ap_settings *params)
5703{
5704 struct nlattr *tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_MAX + 1];
5705 int ret;
5706 struct cfg80211_unsol_bcast_probe_resp *presp =
5707 &params->unsol_bcast_probe_resp;
5708
5709 if (!wiphy_ext_feature_isset(&rdev->wiphy,
5710 NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP))
5711 return -EINVAL;
5712
5713 ret = nla_parse_nested(tb, NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_MAX,
5714 attrs, NULL, NULL);
5715 if (ret)
5716 return ret;
5717
5718 if (!tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INT] ||
5719 !tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL])
5720 return -EINVAL;
5721
5722 presp->tmpl = nla_data(tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL]);
5723 presp->tmpl_len = nla_len(tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL]);
5724 presp->interval = nla_get_u32(tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INT]);
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
8860020e
JB
5909static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
5910{
5911 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7b0a0e3c 5912 unsigned int link_id = nl80211_link_id(info->attrs);
8860020e
JB
5913 struct net_device *dev = info->user_ptr[1];
5914 struct wireless_dev *wdev = dev->ieee80211_ptr;
9e263e19 5915 struct cfg80211_ap_settings *params;
8860020e
JB
5916 int err;
5917
5918 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
5919 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
5920 return -EOPNOTSUPP;
5921
5922 if (!rdev->ops->start_ap)
5923 return -EOPNOTSUPP;
5924
7b0a0e3c 5925 if (wdev->links[link_id].ap.beacon_interval)
8860020e
JB
5926 return -EALREADY;
5927
8860020e
JB
5928 /* these are required for START_AP */
5929 if (!info->attrs[NL80211_ATTR_BEACON_INTERVAL] ||
5930 !info->attrs[NL80211_ATTR_DTIM_PERIOD] ||
5931 !info->attrs[NL80211_ATTR_BEACON_HEAD])
5932 return -EINVAL;
5933
9e263e19
JB
5934 params = kzalloc(sizeof(*params), GFP_KERNEL);
5935 if (!params)
5936 return -ENOMEM;
5937
dbbb27e1
AD
5938 err = nl80211_parse_beacon(rdev, info->attrs, &params->beacon,
5939 info->extack);
8860020e 5940 if (err)
9e263e19 5941 goto out;
8860020e 5942
9e263e19 5943 params->beacon_interval =
8860020e 5944 nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
9e263e19 5945 params->dtim_period =
8860020e
JB
5946 nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);
5947
0c317a02 5948 err = cfg80211_validate_beacon_int(rdev, dev->ieee80211_ptr->iftype,
9e263e19 5949 params->beacon_interval);
8860020e 5950 if (err)
9e263e19 5951 goto out;
8860020e
JB
5952
5953 /*
5954 * In theory, some of these attributes should be required here
5955 * but since they were not used when the command was originally
5956 * added, keep them optional for old user space programs to let
5957 * them continue to work with drivers that do not need the
5958 * additional information -- drivers must check!
5959 */
5960 if (info->attrs[NL80211_ATTR_SSID]) {
9e263e19
JB
5961 params->ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
5962 params->ssid_len =
8860020e 5963 nla_len(info->attrs[NL80211_ATTR_SSID]);
9e263e19
JB
5964 if (params->ssid_len == 0) {
5965 err = -EINVAL;
5966 goto out;
5967 }
7b0a0e3c
JB
5968
5969 if (wdev->u.ap.ssid_len &&
5970 (wdev->u.ap.ssid_len != params->ssid_len ||
5971 memcmp(wdev->u.ap.ssid, params->ssid, params->ssid_len))) {
5972 /* require identical SSID for MLO */
5973 err = -EINVAL;
5974 goto out;
5975 }
5976 } else if (wdev->valid_links) {
5977 /* require SSID for MLO */
5978 err = -EINVAL;
5979 goto out;
8860020e
JB
5980 }
5981
ab0d76f6 5982 if (info->attrs[NL80211_ATTR_HIDDEN_SSID])
9e263e19 5983 params->hidden_ssid = nla_get_u32(
8860020e 5984 info->attrs[NL80211_ATTR_HIDDEN_SSID]);
8860020e 5985
9e263e19 5986 params->privacy = !!info->attrs[NL80211_ATTR_PRIVACY];
8860020e
JB
5987
5988 if (info->attrs[NL80211_ATTR_AUTH_TYPE]) {
9e263e19 5989 params->auth_type = nla_get_u32(
8860020e 5990 info->attrs[NL80211_ATTR_AUTH_TYPE]);
9e263e19
JB
5991 if (!nl80211_valid_auth_type(rdev, params->auth_type,
5992 NL80211_CMD_START_AP)) {
5993 err = -EINVAL;
5994 goto out;
5995 }
8860020e 5996 } else
9e263e19 5997 params->auth_type = NL80211_AUTHTYPE_AUTOMATIC;
8860020e 5998
9e263e19 5999 err = nl80211_crypto_settings(rdev, info, &params->crypto,
8860020e
JB
6000 NL80211_MAX_NR_CIPHER_SUITES);
6001 if (err)
9e263e19 6002 goto out;
8860020e 6003
1b658f11 6004 if (info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]) {
9e263e19
JB
6005 if (!(rdev->wiphy.features & NL80211_FEATURE_INACTIVITY_TIMER)) {
6006 err = -EOPNOTSUPP;
6007 goto out;
6008 }
6009 params->inactivity_timeout = nla_get_u16(
1b658f11
VT
6010 info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]);
6011 }
6012
53cabad7 6013 if (info->attrs[NL80211_ATTR_P2P_CTWINDOW]) {
9e263e19
JB
6014 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
6015 err = -EINVAL;
6016 goto out;
6017 }
6018 params->p2p_ctwindow =
53cabad7 6019 nla_get_u8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]);
9e263e19
JB
6020 if (params->p2p_ctwindow != 0 &&
6021 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN)) {
6022 err = -EINVAL;
6023 goto out;
6024 }
53cabad7
JB
6025 }
6026
6027 if (info->attrs[NL80211_ATTR_P2P_OPPPS]) {
6028 u8 tmp;
6029
9e263e19
JB
6030 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
6031 err = -EINVAL;
6032 goto out;
6033 }
53cabad7 6034 tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]);
9e263e19
JB
6035 params->p2p_opp_ps = tmp;
6036 if (params->p2p_opp_ps != 0 &&
6037 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS)) {
6038 err = -EINVAL;
6039 goto out;
6040 }
53cabad7
JB
6041 }
6042
aa430da4 6043 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
9e263e19 6044 err = nl80211_parse_chandef(rdev, info, &params->chandef);
683b6d3b 6045 if (err)
9e263e19 6046 goto out;
7b0a0e3c
JB
6047 } else if (wdev->valid_links) {
6048 /* with MLD need to specify the channel configuration */
6049 err = -EINVAL;
6050 goto out;
6051 } else if (wdev->u.ap.preset_chandef.chan) {
6052 params->chandef = wdev->u.ap.preset_chandef;
9e263e19
JB
6053 } else if (!nl80211_get_ap_channel(rdev, params)) {
6054 err = -EINVAL;
6055 goto out;
6056 }
aa430da4 6057
d7c1a9a0
AD
6058 if (info->attrs[NL80211_ATTR_PUNCT_BITMAP]) {
6059 err = nl80211_parse_punct_bitmap(rdev, info,
6060 &params->chandef,
6061 &params->punct_bitmap);
6062 if (err)
6063 goto out;
6064 }
6065
9e263e19
JB
6066 if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &params->chandef,
6067 wdev->iftype)) {
6068 err = -EINVAL;
6069 goto out;
6070 }
aa430da4 6071
c2653990
JB
6072 wdev_lock(wdev);
6073
a7c7fbff 6074 if (info->attrs[NL80211_ATTR_TX_RATES]) {
9a5f6488
TC
6075 err = nl80211_parse_tx_bitrate_mask(info, info->attrs,
6076 NL80211_ATTR_TX_RATES,
9e263e19 6077 &params->beacon_rate,
7b0a0e3c 6078 dev, false, link_id);
a7c7fbff 6079 if (err)
c2653990 6080 goto out_unlock;
a7c7fbff 6081
9e263e19
JB
6082 err = validate_beacon_tx_rate(rdev, params->chandef.chan->band,
6083 &params->beacon_rate);
a7c7fbff 6084 if (err)
c2653990 6085 goto out_unlock;
a7c7fbff
PK
6086 }
6087
18998c38 6088 if (info->attrs[NL80211_ATTR_SMPS_MODE]) {
9e263e19 6089 params->smps_mode =
18998c38 6090 nla_get_u8(info->attrs[NL80211_ATTR_SMPS_MODE]);
9e263e19 6091 switch (params->smps_mode) {
18998c38
EP
6092 case NL80211_SMPS_OFF:
6093 break;
6094 case NL80211_SMPS_STATIC:
6095 if (!(rdev->wiphy.features &
9e263e19
JB
6096 NL80211_FEATURE_STATIC_SMPS)) {
6097 err = -EINVAL;
c2653990 6098 goto out_unlock;
9e263e19 6099 }
18998c38
EP
6100 break;
6101 case NL80211_SMPS_DYNAMIC:
6102 if (!(rdev->wiphy.features &
9e263e19
JB
6103 NL80211_FEATURE_DYNAMIC_SMPS)) {
6104 err = -EINVAL;
c2653990 6105 goto out_unlock;
9e263e19 6106 }
18998c38
EP
6107 break;
6108 default:
9e263e19 6109 err = -EINVAL;
c2653990 6110 goto out_unlock;
18998c38
EP
6111 }
6112 } else {
9e263e19 6113 params->smps_mode = NL80211_SMPS_OFF;
18998c38
EP
6114 }
6115
9e263e19
JB
6116 params->pbss = nla_get_flag(info->attrs[NL80211_ATTR_PBSS]);
6117 if (params->pbss && !rdev->wiphy.bands[NL80211_BAND_60GHZ]) {
6118 err = -EOPNOTSUPP;
c2653990 6119 goto out_unlock;
9e263e19 6120 }
6e8ef842 6121
4baf6bea 6122 if (info->attrs[NL80211_ATTR_ACL_POLICY]) {
9e263e19
JB
6123 params->acl = parse_acl_data(&rdev->wiphy, info);
6124 if (IS_ERR(params->acl)) {
6125 err = PTR_ERR(params->acl);
05075fe7 6126 params->acl = NULL;
c2653990 6127 goto out_unlock;
9e263e19 6128 }
4baf6bea
OO
6129 }
6130
9e263e19 6131 params->twt_responder =
a0de1ca3
JC
6132 nla_get_flag(info->attrs[NL80211_ATTR_TWT_RESPONDER]);
6133
796e90f4
JC
6134 if (info->attrs[NL80211_ATTR_HE_OBSS_PD]) {
6135 err = nl80211_parse_he_obss_pd(
6136 info->attrs[NL80211_ATTR_HE_OBSS_PD],
9e263e19 6137 &params->he_obss_pd);
bc7a39b4 6138 if (err)
c2653990 6139 goto out_unlock;
796e90f4
JC
6140 }
6141
291c49de
AD
6142 if (info->attrs[NL80211_ATTR_FILS_DISCOVERY]) {
6143 err = nl80211_parse_fils_discovery(rdev,
6144 info->attrs[NL80211_ATTR_FILS_DISCOVERY],
9e263e19 6145 params);
291c49de 6146 if (err)
c2653990 6147 goto out_unlock;
291c49de
AD
6148 }
6149
7443dcd1
AD
6150 if (info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP]) {
6151 err = nl80211_parse_unsol_bcast_probe_resp(
6152 rdev, info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP],
9e263e19 6153 params);
7443dcd1 6154 if (err)
c2653990 6155 goto out_unlock;
7443dcd1
AD
6156 }
6157
dc1e3cb8
JC
6158 if (info->attrs[NL80211_ATTR_MBSSID_CONFIG]) {
6159 err = nl80211_parse_mbssid_config(&rdev->wiphy, dev,
6160 info->attrs[NL80211_ATTR_MBSSID_CONFIG],
6161 &params->mbssid_config,
6162 params->beacon.mbssid_ies ?
6163 params->beacon.mbssid_ies->cnt :
6164 0);
6165 if (err)
c2653990 6166 goto out_unlock;
dc1e3cb8
JC
6167 }
6168
dbbb27e1
AD
6169 if (!params->mbssid_config.ema && params->beacon.rnr_ies) {
6170 err = -EINVAL;
6171 goto out_unlock;
6172 }
6173
8bc65d38
AD
6174 err = nl80211_calculate_ap_params(params);
6175 if (err)
6176 goto out_unlock;
66cd794e 6177
47301a74
VJ
6178 if (info->attrs[NL80211_ATTR_AP_SETTINGS_FLAGS])
6179 params->flags = nla_get_u32(
6180 info->attrs[NL80211_ATTR_AP_SETTINGS_FLAGS]);
6181 else if (info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])
6182 params->flags |= NL80211_AP_SETTINGS_EXTERNAL_AUTH_SUPPORT;
fe494370 6183
7b0a0e3c
JB
6184 if (wdev->conn_owner_nlportid &&
6185 info->attrs[NL80211_ATTR_SOCKET_OWNER] &&
6186 wdev->conn_owner_nlportid != info->snd_portid) {
6187 err = -EINVAL;
6188 goto out_unlock;
6189 }
6190
6191 /* FIXME: validate MLO/link-id against driver capabilities */
6192
9e263e19 6193 err = rdev_start_ap(rdev, dev, params);
46c1dd0c 6194 if (!err) {
7b0a0e3c
JB
6195 wdev->links[link_id].ap.beacon_interval = params->beacon_interval;
6196 wdev->links[link_id].ap.chandef = params->chandef;
6197 wdev->u.ap.ssid_len = params->ssid_len;
6198 memcpy(wdev->u.ap.ssid, params->ssid,
6199 params->ssid_len);
466a3061
DK
6200
6201 if (info->attrs[NL80211_ATTR_SOCKET_OWNER])
6202 wdev->conn_owner_nlportid = info->snd_portid;
77669c15
6203
6204 nl80211_send_ap_started(wdev, link_id);
46c1dd0c 6205 }
7b0a0e3c 6206out_unlock:
c56589ed 6207 wdev_unlock(wdev);
9951ebfc 6208out:
9e263e19 6209 kfree(params->acl);
dc1e3cb8
JC
6210 kfree(params->beacon.mbssid_ies);
6211 if (params->mbssid_config.tx_wdev &&
6212 params->mbssid_config.tx_wdev->netdev &&
6213 params->mbssid_config.tx_wdev->netdev != dev)
6214 dev_put(params->mbssid_config.tx_wdev->netdev);
dbbb27e1 6215 kfree(params->beacon.rnr_ies);
9e263e19 6216 kfree(params);
77765eaf 6217
56d1893d 6218 return err;
ed1b6cc7
JB
6219}
6220
8860020e
JB
6221static int nl80211_set_beacon(struct sk_buff *skb, struct genl_info *info)
6222{
6223 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7b0a0e3c 6224 unsigned int link_id = nl80211_link_id(info->attrs);
8860020e
JB
6225 struct net_device *dev = info->user_ptr[1];
6226 struct wireless_dev *wdev = dev->ieee80211_ptr;
6227 struct cfg80211_beacon_data params;
6228 int err;
6229
6230 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
6231 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
6232 return -EOPNOTSUPP;
6233
6234 if (!rdev->ops->change_beacon)
6235 return -EOPNOTSUPP;
6236
7b0a0e3c 6237 if (!wdev->links[link_id].ap.beacon_interval)
8860020e
JB
6238 return -EINVAL;
6239
dbbb27e1 6240 err = nl80211_parse_beacon(rdev, info->attrs, &params, info->extack);
8860020e 6241 if (err)
dc1e3cb8 6242 goto out;
8860020e 6243
c56589ed
SW
6244 wdev_lock(wdev);
6245 err = rdev_change_beacon(rdev, dev, &params);
6246 wdev_unlock(wdev);
6247
dc1e3cb8
JC
6248out:
6249 kfree(params.mbssid_ies);
dbbb27e1 6250 kfree(params.rnr_ies);
c56589ed 6251 return err;
8860020e
JB
6252}
6253
6254static int nl80211_stop_ap(struct sk_buff *skb, struct genl_info *info)
ed1b6cc7 6255{
4c476991 6256 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7b0a0e3c 6257 unsigned int link_id = nl80211_link_id(info->attrs);
4c476991 6258 struct net_device *dev = info->user_ptr[1];
ed1b6cc7 6259
7b0a0e3c 6260 return cfg80211_stop_ap(rdev, dev, link_id, false);
ed1b6cc7
JB
6261}
6262
5727ef1b
JB
6263static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = {
6264 [NL80211_STA_FLAG_AUTHORIZED] = { .type = NLA_FLAG },
6265 [NL80211_STA_FLAG_SHORT_PREAMBLE] = { .type = NLA_FLAG },
6266 [NL80211_STA_FLAG_WME] = { .type = NLA_FLAG },
0e46724a 6267 [NL80211_STA_FLAG_MFP] = { .type = NLA_FLAG },
b39c48fa 6268 [NL80211_STA_FLAG_AUTHENTICATED] = { .type = NLA_FLAG },
d83023da 6269 [NL80211_STA_FLAG_TDLS_PEER] = { .type = NLA_FLAG },
5727ef1b
JB
6270};
6271
eccb8e8f 6272static int parse_station_flags(struct genl_info *info,
bdd3ae3d 6273 enum nl80211_iftype iftype,
eccb8e8f 6274 struct station_parameters *params)
5727ef1b
JB
6275{
6276 struct nlattr *flags[NL80211_STA_FLAG_MAX + 1];
eccb8e8f 6277 struct nlattr *nla;
5727ef1b
JB
6278 int flag;
6279
eccb8e8f
JB
6280 /*
6281 * Try parsing the new attribute first so userspace
6282 * can specify both for older kernels.
6283 */
6284 nla = info->attrs[NL80211_ATTR_STA_FLAGS2];
6285 if (nla) {
6286 struct nl80211_sta_flag_update *sta_flags;
6287
6288 sta_flags = nla_data(nla);
6289 params->sta_flags_mask = sta_flags->mask;
6290 params->sta_flags_set = sta_flags->set;
77ee7c89 6291 params->sta_flags_set &= params->sta_flags_mask;
eccb8e8f
JB
6292 if ((params->sta_flags_mask |
6293 params->sta_flags_set) & BIT(__NL80211_STA_FLAG_INVALID))
6294 return -EINVAL;
6295 return 0;
6296 }
6297
6298 /* if present, parse the old attribute */
5727ef1b 6299
eccb8e8f 6300 nla = info->attrs[NL80211_ATTR_STA_FLAGS];
5727ef1b
JB
6301 if (!nla)
6302 return 0;
6303
8cb08174 6304 if (nla_parse_nested_deprecated(flags, NL80211_STA_FLAG_MAX, nla, sta_flags_policy, info->extack))
5727ef1b
JB
6305 return -EINVAL;
6306
bdd3ae3d
JB
6307 /*
6308 * Only allow certain flags for interface types so that
6309 * other attributes are silently ignored. Remember that
6310 * this is backward compatibility code with old userspace
6311 * and shouldn't be hit in other cases anyway.
6312 */
6313 switch (iftype) {
6314 case NL80211_IFTYPE_AP:
6315 case NL80211_IFTYPE_AP_VLAN:
6316 case NL80211_IFTYPE_P2P_GO:
6317 params->sta_flags_mask = BIT(NL80211_STA_FLAG_AUTHORIZED) |
6318 BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) |
6319 BIT(NL80211_STA_FLAG_WME) |
6320 BIT(NL80211_STA_FLAG_MFP);
6321 break;
6322 case NL80211_IFTYPE_P2P_CLIENT:
6323 case NL80211_IFTYPE_STATION:
6324 params->sta_flags_mask = BIT(NL80211_STA_FLAG_AUTHORIZED) |
6325 BIT(NL80211_STA_FLAG_TDLS_PEER);
6326 break;
6327 case NL80211_IFTYPE_MESH_POINT:
6328 params->sta_flags_mask = BIT(NL80211_STA_FLAG_AUTHENTICATED) |
6329 BIT(NL80211_STA_FLAG_MFP) |
6330 BIT(NL80211_STA_FLAG_AUTHORIZED);
5cf3006c 6331 break;
bdd3ae3d
JB
6332 default:
6333 return -EINVAL;
6334 }
5727ef1b 6335
3383b5a6
JB
6336 for (flag = 1; flag <= NL80211_STA_FLAG_MAX; flag++) {
6337 if (flags[flag]) {
eccb8e8f 6338 params->sta_flags_set |= (1<<flag);
5727ef1b 6339
3383b5a6
JB
6340 /* no longer support new API additions in old API */
6341 if (flag > NL80211_STA_FLAG_MAX_OLD_API)
6342 return -EINVAL;
6343 }
6344 }
6345
5727ef1b
JB
6346 return 0;
6347}
6348
9bb7e0f2 6349bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, int attr)
c8dcfd8a
FF
6350{
6351 struct nlattr *rate;
8eb41c8d
VK
6352 u32 bitrate;
6353 u16 bitrate_compat;
bbf67e45 6354 enum nl80211_rate_info rate_flg;
c8dcfd8a 6355
ae0be8de 6356 rate = nla_nest_start_noflag(msg, attr);
c8dcfd8a 6357 if (!rate)
db9c64cf 6358 return false;
c8dcfd8a
FF
6359
6360 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
6361 bitrate = cfg80211_calculate_bitrate(info);
8eb41c8d
VK
6362 /* report 16-bit bitrate only if we can */
6363 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
db9c64cf
JB
6364 if (bitrate > 0 &&
6365 nla_put_u32(msg, NL80211_RATE_INFO_BITRATE32, bitrate))
6366 return false;
6367 if (bitrate_compat > 0 &&
6368 nla_put_u16(msg, NL80211_RATE_INFO_BITRATE, bitrate_compat))
6369 return false;
6370
b51f3bee 6371 switch (info->bw) {
2ad66fcb
GI
6372 case RATE_INFO_BW_1:
6373 rate_flg = NL80211_RATE_INFO_1_MHZ_WIDTH;
6374 break;
6375 case RATE_INFO_BW_2:
6376 rate_flg = NL80211_RATE_INFO_2_MHZ_WIDTH;
6377 break;
6378 case RATE_INFO_BW_4:
6379 rate_flg = NL80211_RATE_INFO_4_MHZ_WIDTH;
6380 break;
b51f3bee
JB
6381 case RATE_INFO_BW_5:
6382 rate_flg = NL80211_RATE_INFO_5_MHZ_WIDTH;
6383 break;
2ad66fcb
GI
6384 case RATE_INFO_BW_8:
6385 rate_flg = NL80211_RATE_INFO_8_MHZ_WIDTH;
6386 break;
b51f3bee
JB
6387 case RATE_INFO_BW_10:
6388 rate_flg = NL80211_RATE_INFO_10_MHZ_WIDTH;
6389 break;
2ad66fcb
GI
6390 case RATE_INFO_BW_16:
6391 rate_flg = NL80211_RATE_INFO_16_MHZ_WIDTH;
6392 break;
b51f3bee
JB
6393 default:
6394 WARN_ON(1);
7b506ff6 6395 fallthrough;
b51f3bee
JB
6396 case RATE_INFO_BW_20:
6397 rate_flg = 0;
6398 break;
6399 case RATE_INFO_BW_40:
6400 rate_flg = NL80211_RATE_INFO_40_MHZ_WIDTH;
6401 break;
6402 case RATE_INFO_BW_80:
6403 rate_flg = NL80211_RATE_INFO_80_MHZ_WIDTH;
6404 break;
6405 case RATE_INFO_BW_160:
6406 rate_flg = NL80211_RATE_INFO_160_MHZ_WIDTH;
6407 break;
c4cbaf79
LC
6408 case RATE_INFO_BW_HE_RU:
6409 rate_flg = 0;
6410 WARN_ON(!(info->flags & RATE_INFO_FLAGS_HE_MCS));
cfb14110
VJ
6411 break;
6412 case RATE_INFO_BW_320:
6413 rate_flg = NL80211_RATE_INFO_320_MHZ_WIDTH;
6414 break;
6415 case RATE_INFO_BW_EHT_RU:
6416 rate_flg = 0;
6417 WARN_ON(!(info->flags & RATE_INFO_FLAGS_EHT_MCS));
6418 break;
b51f3bee
JB
6419 }
6420
6421 if (rate_flg && nla_put_flag(msg, rate_flg))
6422 return false;
6423
db9c64cf
JB
6424 if (info->flags & RATE_INFO_FLAGS_MCS) {
6425 if (nla_put_u8(msg, NL80211_RATE_INFO_MCS, info->mcs))
6426 return false;
db9c64cf
JB
6427 if (info->flags & RATE_INFO_FLAGS_SHORT_GI &&
6428 nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI))
6429 return false;
6430 } else if (info->flags & RATE_INFO_FLAGS_VHT_MCS) {
6431 if (nla_put_u8(msg, NL80211_RATE_INFO_VHT_MCS, info->mcs))
6432 return false;
6433 if (nla_put_u8(msg, NL80211_RATE_INFO_VHT_NSS, info->nss))
6434 return false;
db9c64cf
JB
6435 if (info->flags & RATE_INFO_FLAGS_SHORT_GI &&
6436 nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI))
6437 return false;
c4cbaf79
LC
6438 } else if (info->flags & RATE_INFO_FLAGS_HE_MCS) {
6439 if (nla_put_u8(msg, NL80211_RATE_INFO_HE_MCS, info->mcs))
6440 return false;
6441 if (nla_put_u8(msg, NL80211_RATE_INFO_HE_NSS, info->nss))
6442 return false;
6443 if (nla_put_u8(msg, NL80211_RATE_INFO_HE_GI, info->he_gi))
6444 return false;
6445 if (nla_put_u8(msg, NL80211_RATE_INFO_HE_DCM, info->he_dcm))
6446 return false;
6447 if (info->bw == RATE_INFO_BW_HE_RU &&
6448 nla_put_u8(msg, NL80211_RATE_INFO_HE_RU_ALLOC,
6449 info->he_ru_alloc))
6450 return false;
2ad66fcb
GI
6451 } else if (info->flags & RATE_INFO_FLAGS_S1G_MCS) {
6452 if (nla_put_u8(msg, NL80211_RATE_INFO_S1G_MCS, info->mcs))
6453 return false;
6454 if (nla_put_u8(msg, NL80211_RATE_INFO_S1G_NSS, info->nss))
6455 return false;
6456 if (info->flags & RATE_INFO_FLAGS_SHORT_GI &&
6457 nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI))
6458 return false;
cfb14110
VJ
6459 } else if (info->flags & RATE_INFO_FLAGS_EHT_MCS) {
6460 if (nla_put_u8(msg, NL80211_RATE_INFO_EHT_MCS, info->mcs))
6461 return false;
6462 if (nla_put_u8(msg, NL80211_RATE_INFO_EHT_NSS, info->nss))
6463 return false;
6464 if (nla_put_u8(msg, NL80211_RATE_INFO_EHT_GI, info->eht_gi))
6465 return false;
6466 if (info->bw == RATE_INFO_BW_EHT_RU &&
6467 nla_put_u8(msg, NL80211_RATE_INFO_EHT_RU_ALLOC,
6468 info->eht_ru_alloc))
6469 return false;
db9c64cf 6470 }
c8dcfd8a
FF
6471
6472 nla_nest_end(msg, rate);
6473 return true;
c8dcfd8a
FF
6474}
6475
119363c7
FF
6476static bool nl80211_put_signal(struct sk_buff *msg, u8 mask, s8 *signal,
6477 int id)
6478{
6479 void *attr;
6480 int i = 0;
6481
6482 if (!mask)
6483 return true;
6484
ae0be8de 6485 attr = nla_nest_start_noflag(msg, id);
119363c7
FF
6486 if (!attr)
6487 return false;
6488
6489 for (i = 0; i < IEEE80211_MAX_CHAINS; i++) {
6490 if (!(mask & BIT(i)))
6491 continue;
6492
6493 if (nla_put_u8(msg, i, signal[i]))
6494 return false;
6495 }
6496
6497 nla_nest_end(msg, attr);
6498
6499 return true;
6500}
6501
cf5ead82
JB
6502static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
6503 u32 seq, int flags,
66266b3a
JL
6504 struct cfg80211_registered_device *rdev,
6505 struct net_device *dev,
98b62183 6506 const u8 *mac_addr, struct station_info *sinfo)
fd5b74dc
JB
6507{
6508 void *hdr;
f4263c98 6509 struct nlattr *sinfoattr, *bss_param;
fd5b74dc 6510
cf5ead82 6511 hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
f77bf486
AS
6512 if (!hdr) {
6513 cfg80211_sinfo_release_content(sinfo);
fd5b74dc 6514 return -1;
f77bf486 6515 }
fd5b74dc 6516
9360ffd1
DM
6517 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
6518 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr) ||
6519 nla_put_u32(msg, NL80211_ATTR_GENERATION, sinfo->generation))
6520 goto nla_put_failure;
f5ea9120 6521
ae0be8de 6522 sinfoattr = nla_nest_start_noflag(msg, NL80211_ATTR_STA_INFO);
2ec600d6 6523 if (!sinfoattr)
fd5b74dc 6524 goto nla_put_failure;
319090bf
JB
6525
6526#define PUT_SINFO(attr, memb, type) do { \
d686b920 6527 BUILD_BUG_ON(sizeof(type) == sizeof(u64)); \
397c657a 6528 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_ ## attr) && \
319090bf
JB
6529 nla_put_ ## type(msg, NL80211_STA_INFO_ ## attr, \
6530 sinfo->memb)) \
6531 goto nla_put_failure; \
6532 } while (0)
d686b920 6533#define PUT_SINFO_U64(attr, memb) do { \
397c657a 6534 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_ ## attr) && \
d686b920
JB
6535 nla_put_u64_64bit(msg, NL80211_STA_INFO_ ## attr, \
6536 sinfo->memb, NL80211_STA_INFO_PAD)) \
6537 goto nla_put_failure; \
6538 } while (0)
319090bf
JB
6539
6540 PUT_SINFO(CONNECTED_TIME, connected_time, u32);
6541 PUT_SINFO(INACTIVE_TIME, inactive_time, u32);
6c7a0033 6542 PUT_SINFO_U64(ASSOC_AT_BOOTTIME, assoc_at);
319090bf 6543
397c657a
OE
6544 if (sinfo->filled & (BIT_ULL(NL80211_STA_INFO_RX_BYTES) |
6545 BIT_ULL(NL80211_STA_INFO_RX_BYTES64)) &&
9360ffd1 6546 nla_put_u32(msg, NL80211_STA_INFO_RX_BYTES,
42745e03 6547 (u32)sinfo->rx_bytes))
9360ffd1 6548 goto nla_put_failure;
319090bf 6549
397c657a
OE
6550 if (sinfo->filled & (BIT_ULL(NL80211_STA_INFO_TX_BYTES) |
6551 BIT_ULL(NL80211_STA_INFO_TX_BYTES64)) &&
9360ffd1 6552 nla_put_u32(msg, NL80211_STA_INFO_TX_BYTES,
42745e03
VK
6553 (u32)sinfo->tx_bytes))
6554 goto nla_put_failure;
319090bf 6555
d686b920
JB
6556 PUT_SINFO_U64(RX_BYTES64, rx_bytes);
6557 PUT_SINFO_U64(TX_BYTES64, tx_bytes);
319090bf
JB
6558 PUT_SINFO(LLID, llid, u16);
6559 PUT_SINFO(PLID, plid, u16);
6560 PUT_SINFO(PLINK_STATE, plink_state, u8);
d686b920 6561 PUT_SINFO_U64(RX_DURATION, rx_duration);
36647055
THJ
6562 PUT_SINFO_U64(TX_DURATION, tx_duration);
6563
6564 if (wiphy_ext_feature_isset(&rdev->wiphy,
6565 NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))
6566 PUT_SINFO(AIRTIME_WEIGHT, airtime_weight, u16);
319090bf 6567
66266b3a
JL
6568 switch (rdev->wiphy.signal_type) {
6569 case CFG80211_SIGNAL_TYPE_MBM:
319090bf
JB
6570 PUT_SINFO(SIGNAL, signal, u8);
6571 PUT_SINFO(SIGNAL_AVG, signal_avg, u8);
66266b3a
JL
6572 break;
6573 default:
6574 break;
6575 }
397c657a 6576 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL)) {
119363c7
FF
6577 if (!nl80211_put_signal(msg, sinfo->chains,
6578 sinfo->chain_signal,
6579 NL80211_STA_INFO_CHAIN_SIGNAL))
6580 goto nla_put_failure;
6581 }
397c657a 6582 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL_AVG)) {
119363c7
FF
6583 if (!nl80211_put_signal(msg, sinfo->chains,
6584 sinfo->chain_signal_avg,
6585 NL80211_STA_INFO_CHAIN_SIGNAL_AVG))
6586 goto nla_put_failure;
6587 }
397c657a 6588 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_BITRATE)) {
c8dcfd8a
FF
6589 if (!nl80211_put_sta_rate(msg, &sinfo->txrate,
6590 NL80211_STA_INFO_TX_BITRATE))
6591 goto nla_put_failure;
6592 }
397c657a 6593 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_RX_BITRATE)) {
c8dcfd8a
FF
6594 if (!nl80211_put_sta_rate(msg, &sinfo->rxrate,
6595 NL80211_STA_INFO_RX_BITRATE))
420e7fab 6596 goto nla_put_failure;
420e7fab 6597 }
319090bf
JB
6598
6599 PUT_SINFO(RX_PACKETS, rx_packets, u32);
6600 PUT_SINFO(TX_PACKETS, tx_packets, u32);
6601 PUT_SINFO(TX_RETRIES, tx_retries, u32);
6602 PUT_SINFO(TX_FAILED, tx_failed, u32);
6603 PUT_SINFO(EXPECTED_THROUGHPUT, expected_throughput, u32);
ab60633c 6604 PUT_SINFO(AIRTIME_LINK_METRIC, airtime_link_metric, u32);
319090bf
JB
6605 PUT_SINFO(BEACON_LOSS, beacon_loss_count, u32);
6606 PUT_SINFO(LOCAL_PM, local_pm, u32);
6607 PUT_SINFO(PEER_PM, peer_pm, u32);
6608 PUT_SINFO(NONPEER_PM, nonpeer_pm, u32);
dbdaee7a 6609 PUT_SINFO(CONNECTED_TO_GATE, connected_to_gate, u8);
1303a51c 6610 PUT_SINFO(CONNECTED_TO_AS, connected_to_as, u8);
319090bf 6611
397c657a 6612 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_BSS_PARAM)) {
ae0be8de
MK
6613 bss_param = nla_nest_start_noflag(msg,
6614 NL80211_STA_INFO_BSS_PARAM);
f4263c98
PS
6615 if (!bss_param)
6616 goto nla_put_failure;
6617
9360ffd1
DM
6618 if (((sinfo->bss_param.flags & BSS_PARAM_FLAGS_CTS_PROT) &&
6619 nla_put_flag(msg, NL80211_STA_BSS_PARAM_CTS_PROT)) ||
6620 ((sinfo->bss_param.flags & BSS_PARAM_FLAGS_SHORT_PREAMBLE) &&
6621 nla_put_flag(msg, NL80211_STA_BSS_PARAM_SHORT_PREAMBLE)) ||
6622 ((sinfo->bss_param.flags & BSS_PARAM_FLAGS_SHORT_SLOT_TIME) &&
6623 nla_put_flag(msg, NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME)) ||
6624 nla_put_u8(msg, NL80211_STA_BSS_PARAM_DTIM_PERIOD,
6625 sinfo->bss_param.dtim_period) ||
6626 nla_put_u16(msg, NL80211_STA_BSS_PARAM_BEACON_INTERVAL,
6627 sinfo->bss_param.beacon_interval))
6628 goto nla_put_failure;
f4263c98
PS
6629
6630 nla_nest_end(msg, bss_param);
6631 }
397c657a 6632 if ((sinfo->filled & BIT_ULL(NL80211_STA_INFO_STA_FLAGS)) &&
9360ffd1
DM
6633 nla_put(msg, NL80211_STA_INFO_STA_FLAGS,
6634 sizeof(struct nl80211_sta_flag_update),
6635 &sinfo->sta_flags))
6636 goto nla_put_failure;
319090bf 6637
d686b920
JB
6638 PUT_SINFO_U64(T_OFFSET, t_offset);
6639 PUT_SINFO_U64(RX_DROP_MISC, rx_dropped_misc);
6640 PUT_SINFO_U64(BEACON_RX, rx_beacon);
a76b1942 6641 PUT_SINFO(BEACON_SIGNAL_AVG, rx_beacon_signal_avg, u8);
0d4e14a3
AB
6642 PUT_SINFO(RX_MPDUS, rx_mpdu_count, u32);
6643 PUT_SINFO(FCS_ERROR_COUNT, fcs_err_count, u32);
81d5439d 6644 if (wiphy_ext_feature_isset(&rdev->wiphy,
9c06602b
BP
6645 NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT)) {
6646 PUT_SINFO(ACK_SIGNAL, ack_signal, u8);
6647 PUT_SINFO(ACK_SIGNAL_AVG, avg_ack_signal, s8);
6648 }
319090bf
JB
6649
6650#undef PUT_SINFO
d686b920 6651#undef PUT_SINFO_U64
6de39808 6652
8689c051 6653 if (sinfo->pertid) {
6de39808
JB
6654 struct nlattr *tidsattr;
6655 int tid;
6656
ae0be8de
MK
6657 tidsattr = nla_nest_start_noflag(msg,
6658 NL80211_STA_INFO_TID_STATS);
6de39808
JB
6659 if (!tidsattr)
6660 goto nla_put_failure;
6661
6662 for (tid = 0; tid < IEEE80211_NUM_TIDS + 1; tid++) {
6663 struct cfg80211_tid_stats *tidstats;
6664 struct nlattr *tidattr;
6665
6666 tidstats = &sinfo->pertid[tid];
6667
6668 if (!tidstats->filled)
6669 continue;
6670
ae0be8de 6671 tidattr = nla_nest_start_noflag(msg, tid + 1);
6de39808
JB
6672 if (!tidattr)
6673 goto nla_put_failure;
6674
d686b920 6675#define PUT_TIDVAL_U64(attr, memb) do { \
6de39808 6676 if (tidstats->filled & BIT(NL80211_TID_STATS_ ## attr) && \
d686b920
JB
6677 nla_put_u64_64bit(msg, NL80211_TID_STATS_ ## attr, \
6678 tidstats->memb, NL80211_TID_STATS_PAD)) \
6de39808
JB
6679 goto nla_put_failure; \
6680 } while (0)
6681
d686b920
JB
6682 PUT_TIDVAL_U64(RX_MSDU, rx_msdu);
6683 PUT_TIDVAL_U64(TX_MSDU, tx_msdu);
6684 PUT_TIDVAL_U64(TX_MSDU_RETRIES, tx_msdu_retries);
6685 PUT_TIDVAL_U64(TX_MSDU_FAILED, tx_msdu_failed);
6de39808 6686
d686b920 6687#undef PUT_TIDVAL_U64
52539ca8
THJ
6688 if ((tidstats->filled &
6689 BIT(NL80211_TID_STATS_TXQ_STATS)) &&
6690 !nl80211_put_txq_stats(msg, &tidstats->txq_stats,
6691 NL80211_TID_STATS_TXQ_STATS))
6692 goto nla_put_failure;
6693
6de39808
JB
6694 nla_nest_end(msg, tidattr);
6695 }
6696
6697 nla_nest_end(msg, tidsattr);
6698 }
6699
2ec600d6 6700 nla_nest_end(msg, sinfoattr);
fd5b74dc 6701
319090bf 6702 if (sinfo->assoc_req_ies_len &&
9360ffd1
DM
6703 nla_put(msg, NL80211_ATTR_IE, sinfo->assoc_req_ies_len,
6704 sinfo->assoc_req_ies))
6705 goto nla_put_failure;
50d3dfb7 6706
a42e59eb
VJ
6707 if (sinfo->assoc_resp_ies_len &&
6708 nla_put(msg, NL80211_ATTR_RESP_IE, sinfo->assoc_resp_ies_len,
6709 sinfo->assoc_resp_ies))
6710 goto nla_put_failure;
6711
6712 if (sinfo->mlo_params_valid) {
6713 if (nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID,
6714 sinfo->assoc_link_id))
6715 goto nla_put_failure;
6716
6717 if (!is_zero_ether_addr(sinfo->mld_addr) &&
6718 nla_put(msg, NL80211_ATTR_MLD_ADDR, ETH_ALEN,
6719 sinfo->mld_addr))
6720 goto nla_put_failure;
6721 }
6722
7ea3e110 6723 cfg80211_sinfo_release_content(sinfo);
053c095a
JB
6724 genlmsg_end(msg, hdr);
6725 return 0;
fd5b74dc
JB
6726
6727 nla_put_failure:
7ea3e110 6728 cfg80211_sinfo_release_content(sinfo);
bc3ed28c
TG
6729 genlmsg_cancel(msg, hdr);
6730 return -EMSGSIZE;
fd5b74dc
JB
6731}
6732
2ec600d6 6733static int nl80211_dump_station(struct sk_buff *skb,
bba95fef 6734 struct netlink_callback *cb)
2ec600d6 6735{
73887fd9 6736 struct station_info sinfo;
1b8ec87a 6737 struct cfg80211_registered_device *rdev;
97990a06 6738 struct wireless_dev *wdev;
2ec600d6 6739 u8 mac_addr[ETH_ALEN];
97990a06 6740 int sta_idx = cb->args[2];
2ec600d6 6741 int err;
2ec600d6 6742
ce6b6974 6743 err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev, NULL);
67748893 6744 if (err)
a05829a7
JB
6745 return err;
6746 /* nl80211_prepare_wdev_dump acquired it in the successful case */
6747 __acquire(&rdev->wiphy.mtx);
bba95fef 6748
97990a06
JB
6749 if (!wdev->netdev) {
6750 err = -EINVAL;
6751 goto out_err;
6752 }
6753
1b8ec87a 6754 if (!rdev->ops->dump_station) {
eec60b03 6755 err = -EOPNOTSUPP;
bba95fef
JB
6756 goto out_err;
6757 }
6758
bba95fef 6759 while (1) {
73887fd9 6760 memset(&sinfo, 0, sizeof(sinfo));
1b8ec87a 6761 err = rdev_dump_station(rdev, wdev->netdev, sta_idx,
73887fd9 6762 mac_addr, &sinfo);
bba95fef
JB
6763 if (err == -ENOENT)
6764 break;
6765 if (err)
3b85875a 6766 goto out_err;
bba95fef 6767
cf5ead82 6768 if (nl80211_send_station(skb, NL80211_CMD_NEW_STATION,
15e47304 6769 NETLINK_CB(cb->skb).portid,
bba95fef 6770 cb->nlh->nlmsg_seq, NLM_F_MULTI,
1b8ec87a 6771 rdev, wdev->netdev, mac_addr,
73887fd9 6772 &sinfo) < 0)
bba95fef
JB
6773 goto out;
6774
6775 sta_idx++;
6776 }
6777
bba95fef 6778 out:
97990a06 6779 cb->args[2] = sta_idx;
bba95fef 6780 err = skb->len;
bba95fef 6781 out_err:
a05829a7 6782 wiphy_unlock(&rdev->wiphy);
bba95fef
JB
6783
6784 return err;
2ec600d6 6785}
fd5b74dc 6786
5727ef1b
JB
6787static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
6788{
4c476991
JB
6789 struct cfg80211_registered_device *rdev = info->user_ptr[0];
6790 struct net_device *dev = info->user_ptr[1];
73887fd9 6791 struct station_info sinfo;
fd5b74dc
JB
6792 struct sk_buff *msg;
6793 u8 *mac_addr = NULL;
4c476991 6794 int err;
fd5b74dc 6795
73887fd9 6796 memset(&sinfo, 0, sizeof(sinfo));
fd5b74dc 6797
73887fd9
JB
6798 if (!info->attrs[NL80211_ATTR_MAC])
6799 return -EINVAL;
fd5b74dc
JB
6800
6801 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
6802
73887fd9
JB
6803 if (!rdev->ops->get_station)
6804 return -EOPNOTSUPP;
3b85875a 6805
73887fd9 6806 err = rdev_get_station(rdev, dev, mac_addr, &sinfo);
fd5b74dc 6807 if (err)
73887fd9 6808 return err;
2ec600d6 6809
fd2120ca 6810 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
7ea3e110 6811 if (!msg) {
ba8f566a 6812 cfg80211_sinfo_release_content(&sinfo);
73887fd9 6813 return -ENOMEM;
7ea3e110 6814 }
fd5b74dc 6815
cf5ead82
JB
6816 if (nl80211_send_station(msg, NL80211_CMD_NEW_STATION,
6817 info->snd_portid, info->snd_seq, 0,
73887fd9 6818 rdev, dev, mac_addr, &sinfo) < 0) {
4c476991 6819 nlmsg_free(msg);
73887fd9 6820 return -ENOBUFS;
4c476991 6821 }
3b85875a 6822
73887fd9 6823 return genlmsg_reply(msg, info);
5727ef1b
JB
6824}
6825
77ee7c89
JB
6826int cfg80211_check_station_change(struct wiphy *wiphy,
6827 struct station_parameters *params,
6828 enum cfg80211_station_type statype)
6829{
e4208427
AB
6830 if (params->listen_interval != -1 &&
6831 statype != CFG80211_STA_AP_CLIENT_UNASSOC)
77ee7c89 6832 return -EINVAL;
e4208427 6833
17b94247
AB
6834 if (params->support_p2p_ps != -1 &&
6835 statype != CFG80211_STA_AP_CLIENT_UNASSOC)
6836 return -EINVAL;
6837
c72e1140 6838 if (params->aid &&
e4208427
AB
6839 !(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) &&
6840 statype != CFG80211_STA_AP_CLIENT_UNASSOC)
77ee7c89
JB
6841 return -EINVAL;
6842
6843 /* When you run into this, adjust the code below for the new flag */
6844 BUILD_BUG_ON(NL80211_STA_FLAG_MAX != 7);
6845
6846 switch (statype) {
eef941e6
TP
6847 case CFG80211_STA_MESH_PEER_KERNEL:
6848 case CFG80211_STA_MESH_PEER_USER:
77ee7c89
JB
6849 /*
6850 * No ignoring the TDLS flag here -- the userspace mesh
6851 * code doesn't have the bug of including TDLS in the
6852 * mask everywhere.
6853 */
6854 if (params->sta_flags_mask &
6855 ~(BIT(NL80211_STA_FLAG_AUTHENTICATED) |
6856 BIT(NL80211_STA_FLAG_MFP) |
6857 BIT(NL80211_STA_FLAG_AUTHORIZED)))
6858 return -EINVAL;
6859 break;
6860 case CFG80211_STA_TDLS_PEER_SETUP:
6861 case CFG80211_STA_TDLS_PEER_ACTIVE:
6862 if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))
6863 return -EINVAL;
6864 /* ignore since it can't change */
6865 params->sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
6866 break;
6867 default:
6868 /* disallow mesh-specific things */
6869 if (params->plink_action != NL80211_PLINK_ACTION_NO_ACTION)
6870 return -EINVAL;
6871 if (params->local_pm)
6872 return -EINVAL;
6873 if (params->sta_modify_mask & STATION_PARAM_APPLY_PLINK_STATE)
6874 return -EINVAL;
6875 }
6876
6877 if (statype != CFG80211_STA_TDLS_PEER_SETUP &&
6878 statype != CFG80211_STA_TDLS_PEER_ACTIVE) {
6879 /* TDLS can't be set, ... */
6880 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))
6881 return -EINVAL;
6882 /*
6883 * ... but don't bother the driver with it. This works around
6884 * a hostapd/wpa_supplicant issue -- it always includes the
6885 * TLDS_PEER flag in the mask even for AP mode.
6886 */
6887 params->sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
6888 }
6889
47edb11b
AB
6890 if (statype != CFG80211_STA_TDLS_PEER_SETUP &&
6891 statype != CFG80211_STA_AP_CLIENT_UNASSOC) {
77ee7c89
JB
6892 /* reject other things that can't change */
6893 if (params->sta_modify_mask & STATION_PARAM_APPLY_UAPSD)
6894 return -EINVAL;
6895 if (params->sta_modify_mask & STATION_PARAM_APPLY_CAPABILITY)
6896 return -EINVAL;
b95eb7f0 6897 if (params->link_sta_params.supported_rates)
77ee7c89 6898 return -EINVAL;
b95eb7f0
ST
6899 if (params->ext_capab || params->link_sta_params.ht_capa ||
6900 params->link_sta_params.vht_capa ||
6901 params->link_sta_params.he_capa ||
6902 params->link_sta_params.eht_capa)
77ee7c89
JB
6903 return -EINVAL;
6904 }
6905
47edb11b
AB
6906 if (statype != CFG80211_STA_AP_CLIENT &&
6907 statype != CFG80211_STA_AP_CLIENT_UNASSOC) {
77ee7c89
JB
6908 if (params->vlan)
6909 return -EINVAL;
6910 }
6911
6912 switch (statype) {
6913 case CFG80211_STA_AP_MLME_CLIENT:
6914 /* Use this only for authorizing/unauthorizing a station */
6915 if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)))
6916 return -EOPNOTSUPP;
6917 break;
6918 case CFG80211_STA_AP_CLIENT:
47edb11b 6919 case CFG80211_STA_AP_CLIENT_UNASSOC:
77ee7c89
JB
6920 /* accept only the listed bits */
6921 if (params->sta_flags_mask &
6922 ~(BIT(NL80211_STA_FLAG_AUTHORIZED) |
6923 BIT(NL80211_STA_FLAG_AUTHENTICATED) |
6924 BIT(NL80211_STA_FLAG_ASSOCIATED) |
6925 BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) |
6926 BIT(NL80211_STA_FLAG_WME) |
6927 BIT(NL80211_STA_FLAG_MFP)))
6928 return -EINVAL;
6929
6930 /* but authenticated/associated only if driver handles it */
6931 if (!(wiphy->features & NL80211_FEATURE_FULL_AP_CLIENT_STATE) &&
6932 params->sta_flags_mask &
6933 (BIT(NL80211_STA_FLAG_AUTHENTICATED) |
6934 BIT(NL80211_STA_FLAG_ASSOCIATED)))
6935 return -EINVAL;
6936 break;
6937 case CFG80211_STA_IBSS:
6938 case CFG80211_STA_AP_STA:
6939 /* reject any changes other than AUTHORIZED */
6940 if (params->sta_flags_mask & ~BIT(NL80211_STA_FLAG_AUTHORIZED))
6941 return -EINVAL;
6942 break;
6943 case CFG80211_STA_TDLS_PEER_SETUP:
6944 /* reject any changes other than AUTHORIZED or WME */
6945 if (params->sta_flags_mask & ~(BIT(NL80211_STA_FLAG_AUTHORIZED) |
6946 BIT(NL80211_STA_FLAG_WME)))
6947 return -EINVAL;
6948 /* force (at least) rates when authorizing */
6949 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED) &&
b95eb7f0 6950 !params->link_sta_params.supported_rates)
77ee7c89
JB
6951 return -EINVAL;
6952 break;
6953 case CFG80211_STA_TDLS_PEER_ACTIVE:
6954 /* reject any changes */
6955 return -EINVAL;
eef941e6 6956 case CFG80211_STA_MESH_PEER_KERNEL:
77ee7c89
JB
6957 if (params->sta_modify_mask & STATION_PARAM_APPLY_PLINK_STATE)
6958 return -EINVAL;
6959 break;
eef941e6 6960 case CFG80211_STA_MESH_PEER_USER:
42925040
CYY
6961 if (params->plink_action != NL80211_PLINK_ACTION_NO_ACTION &&
6962 params->plink_action != NL80211_PLINK_ACTION_BLOCK)
77ee7c89
JB
6963 return -EINVAL;
6964 break;
6965 }
6966
06f7c88c
BL
6967 /*
6968 * Older kernel versions ignored this attribute entirely, so don't
6969 * reject attempts to update it but mark it as unused instead so the
6970 * driver won't look at the data.
6971 */
6972 if (statype != CFG80211_STA_AP_CLIENT_UNASSOC &&
6973 statype != CFG80211_STA_TDLS_PEER_SETUP)
b95eb7f0 6974 params->link_sta_params.opmode_notif_used = false;
06f7c88c 6975
77ee7c89
JB
6976 return 0;
6977}
6978EXPORT_SYMBOL(cfg80211_check_station_change);
6979
5727ef1b 6980/*
c258d2de 6981 * Get vlan interface making sure it is running and on the right wiphy.
5727ef1b 6982 */
80b99899
JB
6983static struct net_device *get_vlan(struct genl_info *info,
6984 struct cfg80211_registered_device *rdev)
5727ef1b 6985{
463d0183 6986 struct nlattr *vlanattr = info->attrs[NL80211_ATTR_STA_VLAN];
80b99899
JB
6987 struct net_device *v;
6988 int ret;
6989
6990 if (!vlanattr)
6991 return NULL;
6992
6993 v = dev_get_by_index(genl_info_net(info), nla_get_u32(vlanattr));
6994 if (!v)
6995 return ERR_PTR(-ENODEV);
6996
6997 if (!v->ieee80211_ptr || v->ieee80211_ptr->wiphy != &rdev->wiphy) {
6998 ret = -EINVAL;
6999 goto error;
5727ef1b 7000 }
80b99899 7001
77ee7c89
JB
7002 if (v->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
7003 v->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
7004 v->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
7005 ret = -EINVAL;
7006 goto error;
7007 }
7008
80b99899
JB
7009 if (!netif_running(v)) {
7010 ret = -ENETDOWN;
7011 goto error;
7012 }
7013
7014 return v;
7015 error:
7016 dev_put(v);
7017 return ERR_PTR(ret);
5727ef1b
JB
7018}
7019
ff276691
JB
7020static int nl80211_parse_sta_wme(struct genl_info *info,
7021 struct station_parameters *params)
df881293 7022{
df881293
JM
7023 struct nlattr *tb[NL80211_STA_WME_MAX + 1];
7024 struct nlattr *nla;
7025 int err;
7026
df881293
JM
7027 /* parse WME attributes if present */
7028 if (!info->attrs[NL80211_ATTR_STA_WME])
7029 return 0;
7030
7031 nla = info->attrs[NL80211_ATTR_STA_WME];
8cb08174
JB
7032 err = nla_parse_nested_deprecated(tb, NL80211_STA_WME_MAX, nla,
7033 nl80211_sta_wme_policy,
7034 info->extack);
df881293
JM
7035 if (err)
7036 return err;
7037
7038 if (tb[NL80211_STA_WME_UAPSD_QUEUES])
7039 params->uapsd_queues = nla_get_u8(
7040 tb[NL80211_STA_WME_UAPSD_QUEUES]);
7041 if (params->uapsd_queues & ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK)
7042 return -EINVAL;
7043
7044 if (tb[NL80211_STA_WME_MAX_SP])
7045 params->max_sp = nla_get_u8(tb[NL80211_STA_WME_MAX_SP]);
7046
7047 if (params->max_sp & ~IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK)
7048 return -EINVAL;
7049
7050 params->sta_modify_mask |= STATION_PARAM_APPLY_UAPSD;
7051
7052 return 0;
7053}
7054
c01fc9ad
SD
7055static int nl80211_parse_sta_channel_info(struct genl_info *info,
7056 struct station_parameters *params)
7057{
7058 if (info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]) {
7059 params->supported_channels =
7060 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]);
7061 params->supported_channels_len =
7062 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]);
7063 /*
7064 * Need to include at least one (first channel, number of
cb9abd48
JB
7065 * channels) tuple for each subband (checked in policy),
7066 * and must have proper tuples for the rest of the data as well.
c01fc9ad 7067 */
c01fc9ad
SD
7068 if (params->supported_channels_len % 2)
7069 return -EINVAL;
7070 }
7071
7072 if (info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]) {
7073 params->supported_oper_classes =
7074 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]);
7075 params->supported_oper_classes_len =
7076 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]);
c01fc9ad
SD
7077 }
7078 return 0;
7079}
7080
ff276691
JB
7081static int nl80211_set_station_tdls(struct genl_info *info,
7082 struct station_parameters *params)
7083{
c01fc9ad 7084 int err;
ff276691 7085 /* Dummy STA entry gets updated once the peer capabilities are known */
5e4b6f56
JM
7086 if (info->attrs[NL80211_ATTR_PEER_AID])
7087 params->aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]);
ff276691 7088 if (info->attrs[NL80211_ATTR_HT_CAPABILITY])
b95eb7f0 7089 params->link_sta_params.ht_capa =
ff276691
JB
7090 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
7091 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY])
b95eb7f0 7092 params->link_sta_params.vht_capa =
ff276691 7093 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);
c4cbaf79 7094 if (info->attrs[NL80211_ATTR_HE_CAPABILITY]) {
b95eb7f0 7095 params->link_sta_params.he_capa =
c4cbaf79 7096 nla_data(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
b95eb7f0 7097 params->link_sta_params.he_capa_len =
c4cbaf79 7098 nla_len(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
ea05fd35
IP
7099
7100 if (info->attrs[NL80211_ATTR_EHT_CAPABILITY]) {
b95eb7f0 7101 params->link_sta_params.eht_capa =
ea05fd35 7102 nla_data(info->attrs[NL80211_ATTR_EHT_CAPABILITY]);
b95eb7f0 7103 params->link_sta_params.eht_capa_len =
ea05fd35
IP
7104 nla_len(info->attrs[NL80211_ATTR_EHT_CAPABILITY]);
7105
b95eb7f0
ST
7106 if (!ieee80211_eht_capa_size_ok((const u8 *)params->link_sta_params.he_capa,
7107 (const u8 *)params->link_sta_params.eht_capa,
ea5cba26
JB
7108 params->link_sta_params.eht_capa_len,
7109 false))
ea05fd35
IP
7110 return -EINVAL;
7111 }
c4cbaf79 7112 }
ff276691 7113
c01fc9ad
SD
7114 err = nl80211_parse_sta_channel_info(info, params);
7115 if (err)
7116 return err;
7117
ff276691
JB
7118 return nl80211_parse_sta_wme(info, params);
7119}
7120
e96d1cd2 7121static int nl80211_parse_sta_txpower_setting(struct genl_info *info,
577e5b8c
ST
7122 struct sta_txpwr *txpwr,
7123 bool *txpwr_set)
e96d1cd2
ARN
7124{
7125 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7126 int idx;
7127
7128 if (info->attrs[NL80211_ATTR_STA_TX_POWER_SETTING]) {
7129 if (!rdev->ops->set_tx_power ||
7130 !wiphy_ext_feature_isset(&rdev->wiphy,
7131 NL80211_EXT_FEATURE_STA_TX_PWR))
7132 return -EOPNOTSUPP;
7133
7134 idx = NL80211_ATTR_STA_TX_POWER_SETTING;
577e5b8c 7135 txpwr->type = nla_get_u8(info->attrs[idx]);
e96d1cd2 7136
577e5b8c 7137 if (txpwr->type == NL80211_TX_POWER_LIMITED) {
e96d1cd2
ARN
7138 idx = NL80211_ATTR_STA_TX_POWER;
7139
7140 if (info->attrs[idx])
577e5b8c 7141 txpwr->power = nla_get_s16(info->attrs[idx]);
e96d1cd2
ARN
7142 else
7143 return -EINVAL;
7144 }
577e5b8c
ST
7145
7146 *txpwr_set = true;
7147 } else {
7148 *txpwr_set = false;
e96d1cd2
ARN
7149 }
7150
7151 return 0;
7152}
7153
5727ef1b
JB
7154static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
7155{
4c476991 7156 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4c476991 7157 struct net_device *dev = info->user_ptr[1];
5727ef1b 7158 struct station_parameters params;
77ee7c89
JB
7159 u8 *mac_addr;
7160 int err;
5727ef1b
JB
7161
7162 memset(&params, 0, sizeof(params));
7163
77ee7c89
JB
7164 if (!rdev->ops->change_station)
7165 return -EOPNOTSUPP;
7166
e4208427
AB
7167 /*
7168 * AID and listen_interval properties can be set only for unassociated
7169 * station. Include these parameters here and will check them in
7170 * cfg80211_check_station_change().
7171 */
a9bc31e4
AB
7172 if (info->attrs[NL80211_ATTR_STA_AID])
7173 params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
e4208427 7174
14f34e36
GG
7175 if (info->attrs[NL80211_ATTR_VLAN_ID])
7176 params.vlan_id = nla_get_u16(info->attrs[NL80211_ATTR_VLAN_ID]);
7177
e4208427
AB
7178 if (info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
7179 params.listen_interval =
7180 nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
7181 else
7182 params.listen_interval = -1;
5727ef1b 7183
ab0d76f6
JB
7184 if (info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS])
7185 params.support_p2p_ps =
7186 nla_get_u8(info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]);
7187 else
17b94247 7188 params.support_p2p_ps = -1;
17b94247 7189
5727ef1b
JB
7190 if (!info->attrs[NL80211_ATTR_MAC])
7191 return -EINVAL;
7192
d2bc5249
AO
7193 params.link_sta_params.link_id =
7194 nl80211_link_id_or_invalid(info->attrs);
7195
7196 if (info->attrs[NL80211_ATTR_MLD_ADDR]) {
7197 /* If MLD_ADDR attribute is set then this is an MLD station
7198 * and the MLD_ADDR attribute holds the MLD address and the
7199 * MAC attribute holds for the LINK address.
7200 * In that case, the link_id is also expected to be valid.
7201 */
7202 if (params.link_sta_params.link_id < 0)
7203 return -EINVAL;
7204
7205 mac_addr = nla_data(info->attrs[NL80211_ATTR_MLD_ADDR]);
7206 params.link_sta_params.mld_mac = mac_addr;
7207 params.link_sta_params.link_mac =
7208 nla_data(info->attrs[NL80211_ATTR_MAC]);
7209 if (!is_valid_ether_addr(params.link_sta_params.link_mac))
7210 return -EINVAL;
7211 } else {
7212 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
7213 }
7214
5727ef1b
JB
7215
7216 if (info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]) {
b95eb7f0 7217 params.link_sta_params.supported_rates =
5727ef1b 7218 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
b95eb7f0 7219 params.link_sta_params.supported_rates_len =
5727ef1b
JB
7220 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
7221 }
7222
9d62a986
JM
7223 if (info->attrs[NL80211_ATTR_STA_CAPABILITY]) {
7224 params.capability =
7225 nla_get_u16(info->attrs[NL80211_ATTR_STA_CAPABILITY]);
7226 params.sta_modify_mask |= STATION_PARAM_APPLY_CAPABILITY;
7227 }
7228
7229 if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]) {
7230 params.ext_capab =
7231 nla_data(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]);
7232 params.ext_capab_len =
7233 nla_len(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]);
7234 }
7235
bdd3ae3d 7236 if (parse_station_flags(info, dev->ieee80211_ptr->iftype, &params))
5727ef1b
JB
7237 return -EINVAL;
7238
ab0d76f6 7239 if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION])
2ec600d6 7240 params.plink_action =
f8bacc21 7241 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
2ec600d6 7242
f8bacc21 7243 if (info->attrs[NL80211_ATTR_STA_PLINK_STATE]) {
9c3990aa 7244 params.plink_state =
f8bacc21 7245 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_STATE]);
ab0d76f6 7246 if (info->attrs[NL80211_ATTR_MESH_PEER_AID])
7d27a0ba
MH
7247 params.peer_aid = nla_get_u16(
7248 info->attrs[NL80211_ATTR_MESH_PEER_AID]);
f8bacc21
JB
7249 params.sta_modify_mask |= STATION_PARAM_APPLY_PLINK_STATE;
7250 }
9c3990aa 7251
ab0d76f6
JB
7252 if (info->attrs[NL80211_ATTR_LOCAL_MESH_POWER_MODE])
7253 params.local_pm = nla_get_u32(
3b1c5a53
MP
7254 info->attrs[NL80211_ATTR_LOCAL_MESH_POWER_MODE]);
7255
06f7c88c 7256 if (info->attrs[NL80211_ATTR_OPMODE_NOTIF]) {
b95eb7f0
ST
7257 params.link_sta_params.opmode_notif_used = true;
7258 params.link_sta_params.opmode_notif =
06f7c88c
BL
7259 nla_get_u8(info->attrs[NL80211_ATTR_OPMODE_NOTIF]);
7260 }
7261
43e64bf3 7262 if (info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY])
b95eb7f0 7263 params.link_sta_params.he_6ghz_capa =
fce2ff72 7264 nla_data(info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY]);
43e64bf3 7265
36647055
THJ
7266 if (info->attrs[NL80211_ATTR_AIRTIME_WEIGHT])
7267 params.airtime_weight =
7268 nla_get_u16(info->attrs[NL80211_ATTR_AIRTIME_WEIGHT]);
7269
7270 if (params.airtime_weight &&
7271 !wiphy_ext_feature_isset(&rdev->wiphy,
7272 NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))
7273 return -EOPNOTSUPP;
7274
b95eb7f0
ST
7275 err = nl80211_parse_sta_txpower_setting(info,
7276 &params.link_sta_params.txpwr,
7277 &params.link_sta_params.txpwr_set);
e96d1cd2
ARN
7278 if (err)
7279 return err;
7280
77ee7c89
JB
7281 /* Include parameters for TDLS peer (will check later) */
7282 err = nl80211_set_station_tdls(info, &params);
7283 if (err)
7284 return err;
7285
7286 params.vlan = get_vlan(info, rdev);
7287 if (IS_ERR(params.vlan))
7288 return PTR_ERR(params.vlan);
7289
a97f4424
JB
7290 switch (dev->ieee80211_ptr->iftype) {
7291 case NL80211_IFTYPE_AP:
7292 case NL80211_IFTYPE_AP_VLAN:
074ac8df 7293 case NL80211_IFTYPE_P2P_GO:
074ac8df 7294 case NL80211_IFTYPE_P2P_CLIENT:
a97f4424 7295 case NL80211_IFTYPE_STATION:
267335d6 7296 case NL80211_IFTYPE_ADHOC:
a97f4424 7297 case NL80211_IFTYPE_MESH_POINT:
a97f4424
JB
7298 break;
7299 default:
77ee7c89
JB
7300 err = -EOPNOTSUPP;
7301 goto out_put_vlan;
034d655e
JB
7302 }
7303
77ee7c89 7304 /* driver will call cfg80211_check_station_change() */
3d1cc7cd 7305 wdev_lock(dev->ieee80211_ptr);
e35e4d28 7306 err = rdev_change_station(rdev, dev, mac_addr, &params);
3d1cc7cd 7307 wdev_unlock(dev->ieee80211_ptr);
5727ef1b 7308
77ee7c89 7309 out_put_vlan:
1160dfa1 7310 dev_put(params.vlan);
3b85875a 7311
5727ef1b
JB
7312 return err;
7313}
7314
7315static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
7316{
4c476991 7317 struct cfg80211_registered_device *rdev = info->user_ptr[0];
5727ef1b 7318 int err;
4c476991 7319 struct net_device *dev = info->user_ptr[1];
efbfe516 7320 struct wireless_dev *wdev = dev->ieee80211_ptr;
5727ef1b
JB
7321 struct station_parameters params;
7322 u8 *mac_addr = NULL;
bda95eb1
JB
7323 u32 auth_assoc = BIT(NL80211_STA_FLAG_AUTHENTICATED) |
7324 BIT(NL80211_STA_FLAG_ASSOCIATED);
5727ef1b
JB
7325
7326 memset(&params, 0, sizeof(params));
7327
984c311b
JB
7328 if (!rdev->ops->add_station)
7329 return -EOPNOTSUPP;
7330
5727ef1b
JB
7331 if (!info->attrs[NL80211_ATTR_MAC])
7332 return -EINVAL;
7333
5727ef1b
JB
7334 if (!info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
7335 return -EINVAL;
7336
7337 if (!info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES])
7338 return -EINVAL;
7339
5e4b6f56
JM
7340 if (!info->attrs[NL80211_ATTR_STA_AID] &&
7341 !info->attrs[NL80211_ATTR_PEER_AID])
0e956c13
TLSC
7342 return -EINVAL;
7343
b95eb7f0
ST
7344 params.link_sta_params.link_id =
7345 nl80211_link_id_or_invalid(info->attrs);
7346
c0d67012 7347 if (info->attrs[NL80211_ATTR_MLD_ADDR]) {
c0d67012
ST
7348 mac_addr = nla_data(info->attrs[NL80211_ATTR_MLD_ADDR]);
7349 params.link_sta_params.mld_mac = mac_addr;
7350 params.link_sta_params.link_mac =
7351 nla_data(info->attrs[NL80211_ATTR_MAC]);
7352 if (!is_valid_ether_addr(params.link_sta_params.link_mac))
7353 return -EINVAL;
7354 } else {
7355 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
7356 }
7357
b95eb7f0 7358 params.link_sta_params.supported_rates =
5727ef1b 7359 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
b95eb7f0 7360 params.link_sta_params.supported_rates_len =
5727ef1b
JB
7361 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
7362 params.listen_interval =
7363 nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
51b50fbe 7364
14f34e36
GG
7365 if (info->attrs[NL80211_ATTR_VLAN_ID])
7366 params.vlan_id = nla_get_u16(info->attrs[NL80211_ATTR_VLAN_ID]);
7367
17b94247 7368 if (info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]) {
ab0d76f6
JB
7369 params.support_p2p_ps =
7370 nla_get_u8(info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]);
17b94247
AB
7371 } else {
7372 /*
7373 * if not specified, assume it's supported for P2P GO interface,
7374 * and is NOT supported for AP interface
7375 */
7376 params.support_p2p_ps =
7377 dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO;
7378 }
7379
3d124ea2 7380 if (info->attrs[NL80211_ATTR_PEER_AID])
5e4b6f56 7381 params.aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]);
3d124ea2
JM
7382 else
7383 params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
51b50fbe 7384
9d62a986
JM
7385 if (info->attrs[NL80211_ATTR_STA_CAPABILITY]) {
7386 params.capability =
7387 nla_get_u16(info->attrs[NL80211_ATTR_STA_CAPABILITY]);
7388 params.sta_modify_mask |= STATION_PARAM_APPLY_CAPABILITY;
7389 }
7390
7391 if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]) {
7392 params.ext_capab =
7393 nla_data(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]);
7394 params.ext_capab_len =
7395 nla_len(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]);
7396 }
7397
36aedc90 7398 if (info->attrs[NL80211_ATTR_HT_CAPABILITY])
b95eb7f0 7399 params.link_sta_params.ht_capa =
36aedc90 7400 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
5727ef1b 7401
f461be3e 7402 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY])
b95eb7f0 7403 params.link_sta_params.vht_capa =
f461be3e
MP
7404 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);
7405
c4cbaf79 7406 if (info->attrs[NL80211_ATTR_HE_CAPABILITY]) {
b95eb7f0 7407 params.link_sta_params.he_capa =
c4cbaf79 7408 nla_data(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
b95eb7f0 7409 params.link_sta_params.he_capa_len =
c4cbaf79 7410 nla_len(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
ea05fd35
IP
7411
7412 if (info->attrs[NL80211_ATTR_EHT_CAPABILITY]) {
b95eb7f0 7413 params.link_sta_params.eht_capa =
ea05fd35 7414 nla_data(info->attrs[NL80211_ATTR_EHT_CAPABILITY]);
b95eb7f0 7415 params.link_sta_params.eht_capa_len =
ea05fd35
IP
7416 nla_len(info->attrs[NL80211_ATTR_EHT_CAPABILITY]);
7417
b95eb7f0
ST
7418 if (!ieee80211_eht_capa_size_ok((const u8 *)params.link_sta_params.he_capa,
7419 (const u8 *)params.link_sta_params.eht_capa,
ea5cba26
JB
7420 params.link_sta_params.eht_capa_len,
7421 false))
ea05fd35
IP
7422 return -EINVAL;
7423 }
c4cbaf79
LC
7424 }
7425
43e64bf3 7426 if (info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY])
b95eb7f0 7427 params.link_sta_params.he_6ghz_capa =
43e64bf3
RM
7428 nla_data(info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY]);
7429
60f4a7b1 7430 if (info->attrs[NL80211_ATTR_OPMODE_NOTIF]) {
b95eb7f0
ST
7431 params.link_sta_params.opmode_notif_used = true;
7432 params.link_sta_params.opmode_notif =
60f4a7b1
MK
7433 nla_get_u8(info->attrs[NL80211_ATTR_OPMODE_NOTIF]);
7434 }
7435
ab0d76f6 7436 if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION])
96b78dff 7437 params.plink_action =
f8bacc21 7438 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
96b78dff 7439
36647055
THJ
7440 if (info->attrs[NL80211_ATTR_AIRTIME_WEIGHT])
7441 params.airtime_weight =
7442 nla_get_u16(info->attrs[NL80211_ATTR_AIRTIME_WEIGHT]);
7443
7444 if (params.airtime_weight &&
7445 !wiphy_ext_feature_isset(&rdev->wiphy,
7446 NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))
7447 return -EOPNOTSUPP;
7448
b95eb7f0
ST
7449 err = nl80211_parse_sta_txpower_setting(info,
7450 &params.link_sta_params.txpwr,
7451 &params.link_sta_params.txpwr_set);
e96d1cd2
ARN
7452 if (err)
7453 return err;
7454
c01fc9ad
SD
7455 err = nl80211_parse_sta_channel_info(info, &params);
7456 if (err)
7457 return err;
7458
ff276691
JB
7459 err = nl80211_parse_sta_wme(info, &params);
7460 if (err)
7461 return err;
bdd90d5e 7462
bdd3ae3d 7463 if (parse_station_flags(info, dev->ieee80211_ptr->iftype, &params))
5727ef1b
JB
7464 return -EINVAL;
7465
496fcc29
JB
7466 /* HT/VHT requires QoS, but if we don't have that just ignore HT/VHT
7467 * as userspace might just pass through the capabilities from the IEs
7468 * directly, rather than enforcing this restriction and returning an
7469 * error in this case.
7470 */
7471 if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_WME))) {
b95eb7f0
ST
7472 params.link_sta_params.ht_capa = NULL;
7473 params.link_sta_params.vht_capa = NULL;
c4cbaf79 7474
ea05fd35 7475 /* HE and EHT require WME */
b95eb7f0
ST
7476 if (params.link_sta_params.he_capa_len ||
7477 params.link_sta_params.he_6ghz_capa ||
7478 params.link_sta_params.eht_capa_len)
c4cbaf79 7479 return -EINVAL;
496fcc29
JB
7480 }
7481
43e64bf3 7482 /* Ensure that HT/VHT capabilities are not set for 6 GHz HE STA */
b95eb7f0
ST
7483 if (params.link_sta_params.he_6ghz_capa &&
7484 (params.link_sta_params.ht_capa || params.link_sta_params.vht_capa))
43e64bf3
RM
7485 return -EINVAL;
7486
77ee7c89
JB
7487 /* When you run into this, adjust the code below for the new flag */
7488 BUILD_BUG_ON(NL80211_STA_FLAG_MAX != 7);
7489
bdd90d5e
JB
7490 switch (dev->ieee80211_ptr->iftype) {
7491 case NL80211_IFTYPE_AP:
7492 case NL80211_IFTYPE_AP_VLAN:
7493 case NL80211_IFTYPE_P2P_GO:
984c311b
JB
7494 /* ignore WME attributes if iface/sta is not capable */
7495 if (!(rdev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) ||
7496 !(params.sta_flags_set & BIT(NL80211_STA_FLAG_WME)))
7497 params.sta_modify_mask &= ~STATION_PARAM_APPLY_UAPSD;
c75786c9 7498
bdd90d5e 7499 /* TDLS peers cannot be added */
3d124ea2
JM
7500 if ((params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) ||
7501 info->attrs[NL80211_ATTR_PEER_AID])
4319e193 7502 return -EINVAL;
bdd90d5e
JB
7503 /* but don't bother the driver with it */
7504 params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
3b9ce80c 7505
d582cffb
JB
7506 /* allow authenticated/associated only if driver handles it */
7507 if (!(rdev->wiphy.features &
7508 NL80211_FEATURE_FULL_AP_CLIENT_STATE) &&
bda95eb1 7509 params.sta_flags_mask & auth_assoc)
d582cffb
JB
7510 return -EINVAL;
7511
bda95eb1
JB
7512 /* Older userspace, or userspace wanting to be compatible with
7513 * !NL80211_FEATURE_FULL_AP_CLIENT_STATE, will not set the auth
7514 * and assoc flags in the mask, but assumes the station will be
7515 * added as associated anyway since this was the required driver
7516 * behaviour before NL80211_FEATURE_FULL_AP_CLIENT_STATE was
7517 * introduced.
7518 * In order to not bother drivers with this quirk in the API
7519 * set the flags in both the mask and set for new stations in
7520 * this case.
7521 */
7522 if (!(params.sta_flags_mask & auth_assoc)) {
7523 params.sta_flags_mask |= auth_assoc;
7524 params.sta_flags_set |= auth_assoc;
7525 }
7526
bdd90d5e
JB
7527 /* must be last in here for error handling */
7528 params.vlan = get_vlan(info, rdev);
7529 if (IS_ERR(params.vlan))
7530 return PTR_ERR(params.vlan);
7531 break;
7532 case NL80211_IFTYPE_MESH_POINT:
984c311b
JB
7533 /* ignore uAPSD data */
7534 params.sta_modify_mask &= ~STATION_PARAM_APPLY_UAPSD;
7535
d582cffb
JB
7536 /* associated is disallowed */
7537 if (params.sta_flags_mask & BIT(NL80211_STA_FLAG_ASSOCIATED))
7538 return -EINVAL;
bdd90d5e 7539 /* TDLS peers cannot be added */
3d124ea2
JM
7540 if ((params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) ||
7541 info->attrs[NL80211_ATTR_PEER_AID])
bdd90d5e
JB
7542 return -EINVAL;
7543 break;
7544 case NL80211_IFTYPE_STATION:
93d08f0b 7545 case NL80211_IFTYPE_P2P_CLIENT:
984c311b
JB
7546 /* ignore uAPSD data */
7547 params.sta_modify_mask &= ~STATION_PARAM_APPLY_UAPSD;
7548
77ee7c89
JB
7549 /* these are disallowed */
7550 if (params.sta_flags_mask &
7551 (BIT(NL80211_STA_FLAG_ASSOCIATED) |
7552 BIT(NL80211_STA_FLAG_AUTHENTICATED)))
d582cffb 7553 return -EINVAL;
bdd90d5e
JB
7554 /* Only TDLS peers can be added */
7555 if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))
7556 return -EINVAL;
7557 /* Can only add if TDLS ... */
7558 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS))
7559 return -EOPNOTSUPP;
7560 /* ... with external setup is supported */
7561 if (!(rdev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP))
7562 return -EOPNOTSUPP;
77ee7c89
JB
7563 /*
7564 * Older wpa_supplicant versions always mark the TDLS peer
7565 * as authorized, but it shouldn't yet be.
7566 */
7567 params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_AUTHORIZED);
bdd90d5e
JB
7568 break;
7569 default:
7570 return -EOPNOTSUPP;
c75786c9
EP
7571 }
7572
bdd90d5e 7573 /* be aware of params.vlan when changing code here */
5727ef1b 7574
3d1cc7cd 7575 wdev_lock(dev->ieee80211_ptr);
efbfe516
JB
7576 if (wdev->valid_links) {
7577 if (params.link_sta_params.link_id < 0) {
7578 err = -EINVAL;
7579 goto out;
7580 }
7581 if (!(wdev->valid_links & BIT(params.link_sta_params.link_id))) {
7582 err = -ENOLINK;
7583 goto out;
7584 }
7585 } else {
7586 if (params.link_sta_params.link_id >= 0) {
7587 err = -EINVAL;
7588 goto out;
7589 }
7590 }
e35e4d28 7591 err = rdev_add_station(rdev, dev, mac_addr, &params);
efbfe516 7592out:
3d1cc7cd 7593 wdev_unlock(dev->ieee80211_ptr);
1160dfa1 7594 dev_put(params.vlan);
5727ef1b
JB
7595 return err;
7596}
7597
7598static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info)
7599{
4c476991
JB
7600 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7601 struct net_device *dev = info->user_ptr[1];
89c771e5 7602 struct station_del_parameters params;
3d1cc7cd 7603 int ret;
89c771e5
JM
7604
7605 memset(&params, 0, sizeof(params));
5727ef1b
JB
7606
7607 if (info->attrs[NL80211_ATTR_MAC])
89c771e5 7608 params.mac = nla_data(info->attrs[NL80211_ATTR_MAC]);
5727ef1b 7609
306b79ea
JB
7610 switch (dev->ieee80211_ptr->iftype) {
7611 case NL80211_IFTYPE_AP:
7612 case NL80211_IFTYPE_AP_VLAN:
7613 case NL80211_IFTYPE_MESH_POINT:
7614 case NL80211_IFTYPE_P2P_GO:
7615 /* always accept these */
7616 break;
7617 case NL80211_IFTYPE_ADHOC:
7618 /* conditionally accept */
7619 if (wiphy_ext_feature_isset(&rdev->wiphy,
7620 NL80211_EXT_FEATURE_DEL_IBSS_STA))
7621 break;
edafcf42 7622 return -EINVAL;
306b79ea 7623 default:
4c476991 7624 return -EINVAL;
306b79ea 7625 }
5727ef1b 7626
4c476991
JB
7627 if (!rdev->ops->del_station)
7628 return -EOPNOTSUPP;
3b85875a 7629
98856866
JM
7630 if (info->attrs[NL80211_ATTR_MGMT_SUBTYPE]) {
7631 params.subtype =
7632 nla_get_u8(info->attrs[NL80211_ATTR_MGMT_SUBTYPE]);
7633 if (params.subtype != IEEE80211_STYPE_DISASSOC >> 4 &&
7634 params.subtype != IEEE80211_STYPE_DEAUTH >> 4)
7635 return -EINVAL;
7636 } else {
7637 /* Default to Deauthentication frame */
7638 params.subtype = IEEE80211_STYPE_DEAUTH >> 4;
7639 }
7640
7641 if (info->attrs[NL80211_ATTR_REASON_CODE]) {
7642 params.reason_code =
7643 nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
7644 if (params.reason_code == 0)
7645 return -EINVAL; /* 0 is reserved */
7646 } else {
7647 /* Default to reason code 2 */
7648 params.reason_code = WLAN_REASON_PREV_AUTH_NOT_VALID;
7649 }
7650
3d1cc7cd
JB
7651 wdev_lock(dev->ieee80211_ptr);
7652 ret = rdev_del_station(rdev, dev, &params);
7653 wdev_unlock(dev->ieee80211_ptr);
7654
7655 return ret;
5727ef1b
JB
7656}
7657
15e47304 7658static int nl80211_send_mpath(struct sk_buff *msg, u32 portid, u32 seq,
2ec600d6
LCC
7659 int flags, struct net_device *dev,
7660 u8 *dst, u8 *next_hop,
7661 struct mpath_info *pinfo)
7662{
7663 void *hdr;
7664 struct nlattr *pinfoattr;
7665
1ef4c850 7666 hdr = nl80211hdr_put(msg, portid, seq, flags, NL80211_CMD_NEW_MPATH);
2ec600d6
LCC
7667 if (!hdr)
7668 return -1;
7669
9360ffd1
DM
7670 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
7671 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, dst) ||
7672 nla_put(msg, NL80211_ATTR_MPATH_NEXT_HOP, ETH_ALEN, next_hop) ||
7673 nla_put_u32(msg, NL80211_ATTR_GENERATION, pinfo->generation))
7674 goto nla_put_failure;
f5ea9120 7675
ae0be8de 7676 pinfoattr = nla_nest_start_noflag(msg, NL80211_ATTR_MPATH_INFO);
2ec600d6
LCC
7677 if (!pinfoattr)
7678 goto nla_put_failure;
9360ffd1
DM
7679 if ((pinfo->filled & MPATH_INFO_FRAME_QLEN) &&
7680 nla_put_u32(msg, NL80211_MPATH_INFO_FRAME_QLEN,
7681 pinfo->frame_qlen))
7682 goto nla_put_failure;
7683 if (((pinfo->filled & MPATH_INFO_SN) &&
7684 nla_put_u32(msg, NL80211_MPATH_INFO_SN, pinfo->sn)) ||
7685 ((pinfo->filled & MPATH_INFO_METRIC) &&
7686 nla_put_u32(msg, NL80211_MPATH_INFO_METRIC,
7687 pinfo->metric)) ||
7688 ((pinfo->filled & MPATH_INFO_EXPTIME) &&
7689 nla_put_u32(msg, NL80211_MPATH_INFO_EXPTIME,
7690 pinfo->exptime)) ||
7691 ((pinfo->filled & MPATH_INFO_FLAGS) &&
7692 nla_put_u8(msg, NL80211_MPATH_INFO_FLAGS,
7693 pinfo->flags)) ||
7694 ((pinfo->filled & MPATH_INFO_DISCOVERY_TIMEOUT) &&
7695 nla_put_u32(msg, NL80211_MPATH_INFO_DISCOVERY_TIMEOUT,
7696 pinfo->discovery_timeout)) ||
7697 ((pinfo->filled & MPATH_INFO_DISCOVERY_RETRIES) &&
7698 nla_put_u8(msg, NL80211_MPATH_INFO_DISCOVERY_RETRIES,
cc241636
JH
7699 pinfo->discovery_retries)) ||
7700 ((pinfo->filled & MPATH_INFO_HOP_COUNT) &&
7701 nla_put_u8(msg, NL80211_MPATH_INFO_HOP_COUNT,
540bbcb9
JH
7702 pinfo->hop_count)) ||
7703 ((pinfo->filled & MPATH_INFO_PATH_CHANGE) &&
7704 nla_put_u32(msg, NL80211_MPATH_INFO_PATH_CHANGE,
7705 pinfo->path_change_count)))
9360ffd1 7706 goto nla_put_failure;
2ec600d6
LCC
7707
7708 nla_nest_end(msg, pinfoattr);
7709
053c095a
JB
7710 genlmsg_end(msg, hdr);
7711 return 0;
2ec600d6
LCC
7712
7713 nla_put_failure:
bc3ed28c
TG
7714 genlmsg_cancel(msg, hdr);
7715 return -EMSGSIZE;
2ec600d6
LCC
7716}
7717
7718static int nl80211_dump_mpath(struct sk_buff *skb,
bba95fef 7719 struct netlink_callback *cb)
2ec600d6 7720{
2ec600d6 7721 struct mpath_info pinfo;
1b8ec87a 7722 struct cfg80211_registered_device *rdev;
97990a06 7723 struct wireless_dev *wdev;
2ec600d6
LCC
7724 u8 dst[ETH_ALEN];
7725 u8 next_hop[ETH_ALEN];
97990a06 7726 int path_idx = cb->args[2];
2ec600d6 7727 int err;
2ec600d6 7728
ce6b6974 7729 err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev, NULL);
67748893 7730 if (err)
a05829a7
JB
7731 return err;
7732 /* nl80211_prepare_wdev_dump acquired it in the successful case */
7733 __acquire(&rdev->wiphy.mtx);
bba95fef 7734
1b8ec87a 7735 if (!rdev->ops->dump_mpath) {
eec60b03 7736 err = -EOPNOTSUPP;
bba95fef
JB
7737 goto out_err;
7738 }
7739
97990a06 7740 if (wdev->iftype != NL80211_IFTYPE_MESH_POINT) {
eec60b03 7741 err = -EOPNOTSUPP;
0448b5fc 7742 goto out_err;
eec60b03
JM
7743 }
7744
bba95fef 7745 while (1) {
1b8ec87a 7746 err = rdev_dump_mpath(rdev, wdev->netdev, path_idx, dst,
97990a06 7747 next_hop, &pinfo);
bba95fef 7748 if (err == -ENOENT)
2ec600d6 7749 break;
bba95fef 7750 if (err)
3b85875a 7751 goto out_err;
2ec600d6 7752
15e47304 7753 if (nl80211_send_mpath(skb, NETLINK_CB(cb->skb).portid,
bba95fef 7754 cb->nlh->nlmsg_seq, NLM_F_MULTI,
97990a06 7755 wdev->netdev, dst, next_hop,
bba95fef
JB
7756 &pinfo) < 0)
7757 goto out;
2ec600d6 7758
bba95fef 7759 path_idx++;
2ec600d6 7760 }
2ec600d6 7761
bba95fef 7762 out:
97990a06 7763 cb->args[2] = path_idx;
bba95fef 7764 err = skb->len;
bba95fef 7765 out_err:
a05829a7 7766 wiphy_unlock(&rdev->wiphy);
bba95fef 7767 return err;
2ec600d6
LCC
7768}
7769
7770static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info)
7771{
4c476991 7772 struct cfg80211_registered_device *rdev = info->user_ptr[0];
2ec600d6 7773 int err;
4c476991 7774 struct net_device *dev = info->user_ptr[1];
2ec600d6
LCC
7775 struct mpath_info pinfo;
7776 struct sk_buff *msg;
7777 u8 *dst = NULL;
7778 u8 next_hop[ETH_ALEN];
7779
7780 memset(&pinfo, 0, sizeof(pinfo));
7781
7782 if (!info->attrs[NL80211_ATTR_MAC])
7783 return -EINVAL;
7784
7785 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
7786
4c476991
JB
7787 if (!rdev->ops->get_mpath)
7788 return -EOPNOTSUPP;
2ec600d6 7789
4c476991
JB
7790 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
7791 return -EOPNOTSUPP;
eec60b03 7792
e35e4d28 7793 err = rdev_get_mpath(rdev, dev, dst, next_hop, &pinfo);
2ec600d6 7794 if (err)
4c476991 7795 return err;
2ec600d6 7796
fd2120ca 7797 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2ec600d6 7798 if (!msg)
4c476991 7799 return -ENOMEM;
2ec600d6 7800
15e47304 7801 if (nl80211_send_mpath(msg, info->snd_portid, info->snd_seq, 0,
4c476991
JB
7802 dev, dst, next_hop, &pinfo) < 0) {
7803 nlmsg_free(msg);
7804 return -ENOBUFS;
7805 }
3b85875a 7806
4c476991 7807 return genlmsg_reply(msg, info);
2ec600d6
LCC
7808}
7809
7810static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info)
7811{
4c476991
JB
7812 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7813 struct net_device *dev = info->user_ptr[1];
2ec600d6
LCC
7814 u8 *dst = NULL;
7815 u8 *next_hop = NULL;
7816
7817 if (!info->attrs[NL80211_ATTR_MAC])
7818 return -EINVAL;
7819
7820 if (!info->attrs[NL80211_ATTR_MPATH_NEXT_HOP])
7821 return -EINVAL;
7822
7823 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
7824 next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);
7825
4c476991
JB
7826 if (!rdev->ops->change_mpath)
7827 return -EOPNOTSUPP;
35a8efe1 7828
4c476991
JB
7829 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
7830 return -EOPNOTSUPP;
2ec600d6 7831
e35e4d28 7832 return rdev_change_mpath(rdev, dev, dst, next_hop);
2ec600d6 7833}
4c476991 7834
2ec600d6
LCC
7835static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info)
7836{
4c476991
JB
7837 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7838 struct net_device *dev = info->user_ptr[1];
2ec600d6
LCC
7839 u8 *dst = NULL;
7840 u8 *next_hop = NULL;
7841
7842 if (!info->attrs[NL80211_ATTR_MAC])
7843 return -EINVAL;
7844
7845 if (!info->attrs[NL80211_ATTR_MPATH_NEXT_HOP])
7846 return -EINVAL;
7847
7848 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
7849 next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);
7850
4c476991
JB
7851 if (!rdev->ops->add_mpath)
7852 return -EOPNOTSUPP;
35a8efe1 7853
4c476991
JB
7854 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
7855 return -EOPNOTSUPP;
2ec600d6 7856
e35e4d28 7857 return rdev_add_mpath(rdev, dev, dst, next_hop);
2ec600d6
LCC
7858}
7859
7860static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info)
7861{
4c476991
JB
7862 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7863 struct net_device *dev = info->user_ptr[1];
2ec600d6
LCC
7864 u8 *dst = NULL;
7865
7866 if (info->attrs[NL80211_ATTR_MAC])
7867 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
7868
4c476991
JB
7869 if (!rdev->ops->del_mpath)
7870 return -EOPNOTSUPP;
3b85875a 7871
b501426c
MP
7872 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
7873 return -EOPNOTSUPP;
7874
e35e4d28 7875 return rdev_del_mpath(rdev, dev, dst);
2ec600d6
LCC
7876}
7877
66be7d2b
HR
7878static int nl80211_get_mpp(struct sk_buff *skb, struct genl_info *info)
7879{
7880 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7881 int err;
7882 struct net_device *dev = info->user_ptr[1];
7883 struct mpath_info pinfo;
7884 struct sk_buff *msg;
7885 u8 *dst = NULL;
7886 u8 mpp[ETH_ALEN];
7887
7888 memset(&pinfo, 0, sizeof(pinfo));
7889
7890 if (!info->attrs[NL80211_ATTR_MAC])
7891 return -EINVAL;
7892
7893 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
7894
7895 if (!rdev->ops->get_mpp)
7896 return -EOPNOTSUPP;
7897
7898 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
7899 return -EOPNOTSUPP;
7900
7901 err = rdev_get_mpp(rdev, dev, dst, mpp, &pinfo);
7902 if (err)
7903 return err;
7904
7905 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
7906 if (!msg)
7907 return -ENOMEM;
7908
7909 if (nl80211_send_mpath(msg, info->snd_portid, info->snd_seq, 0,
7910 dev, dst, mpp, &pinfo) < 0) {
7911 nlmsg_free(msg);
7912 return -ENOBUFS;
7913 }
7914
7915 return genlmsg_reply(msg, info);
7916}
7917
7918static int nl80211_dump_mpp(struct sk_buff *skb,
7919 struct netlink_callback *cb)
7920{
7921 struct mpath_info pinfo;
7922 struct cfg80211_registered_device *rdev;
7923 struct wireless_dev *wdev;
7924 u8 dst[ETH_ALEN];
7925 u8 mpp[ETH_ALEN];
7926 int path_idx = cb->args[2];
7927 int err;
7928
ce6b6974 7929 err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev, NULL);
66be7d2b 7930 if (err)
a05829a7
JB
7931 return err;
7932 /* nl80211_prepare_wdev_dump acquired it in the successful case */
7933 __acquire(&rdev->wiphy.mtx);
66be7d2b
HR
7934
7935 if (!rdev->ops->dump_mpp) {
7936 err = -EOPNOTSUPP;
7937 goto out_err;
7938 }
7939
7940 if (wdev->iftype != NL80211_IFTYPE_MESH_POINT) {
7941 err = -EOPNOTSUPP;
7942 goto out_err;
7943 }
7944
7945 while (1) {
7946 err = rdev_dump_mpp(rdev, wdev->netdev, path_idx, dst,
7947 mpp, &pinfo);
7948 if (err == -ENOENT)
7949 break;
7950 if (err)
7951 goto out_err;
7952
7953 if (nl80211_send_mpath(skb, NETLINK_CB(cb->skb).portid,
7954 cb->nlh->nlmsg_seq, NLM_F_MULTI,
7955 wdev->netdev, dst, mpp,
7956 &pinfo) < 0)
7957 goto out;
7958
7959 path_idx++;
7960 }
7961
7962 out:
7963 cb->args[2] = path_idx;
7964 err = skb->len;
7965 out_err:
a05829a7 7966 wiphy_unlock(&rdev->wiphy);
66be7d2b
HR
7967 return err;
7968}
7969
9f1ba906
JM
7970static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
7971{
4c476991
JB
7972 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7973 struct net_device *dev = info->user_ptr[1];
c56589ed 7974 struct wireless_dev *wdev = dev->ieee80211_ptr;
9f1ba906 7975 struct bss_parameters params;
c56589ed 7976 int err;
9f1ba906
JM
7977
7978 memset(&params, 0, sizeof(params));
1e0f8cc9 7979 params.link_id = nl80211_link_id_or_invalid(info->attrs);
9f1ba906
JM
7980 /* default to not changing parameters */
7981 params.use_cts_prot = -1;
7982 params.use_short_preamble = -1;
7983 params.use_short_slot_time = -1;
fd8aaaf3 7984 params.ap_isolate = -1;
50b12f59 7985 params.ht_opmode = -1;
53cabad7
JB
7986 params.p2p_ctwindow = -1;
7987 params.p2p_opp_ps = -1;
9f1ba906
JM
7988
7989 if (info->attrs[NL80211_ATTR_BSS_CTS_PROT])
7990 params.use_cts_prot =
7991 nla_get_u8(info->attrs[NL80211_ATTR_BSS_CTS_PROT]);
7992 if (info->attrs[NL80211_ATTR_BSS_SHORT_PREAMBLE])
7993 params.use_short_preamble =
7994 nla_get_u8(info->attrs[NL80211_ATTR_BSS_SHORT_PREAMBLE]);
7995 if (info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME])
7996 params.use_short_slot_time =
7997 nla_get_u8(info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME]);
90c97a04
JM
7998 if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) {
7999 params.basic_rates =
8000 nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
8001 params.basic_rates_len =
8002 nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
8003 }
fd8aaaf3
FF
8004 if (info->attrs[NL80211_ATTR_AP_ISOLATE])
8005 params.ap_isolate = !!nla_get_u8(info->attrs[NL80211_ATTR_AP_ISOLATE]);
50b12f59
HS
8006 if (info->attrs[NL80211_ATTR_BSS_HT_OPMODE])
8007 params.ht_opmode =
8008 nla_get_u16(info->attrs[NL80211_ATTR_BSS_HT_OPMODE]);
9f1ba906 8009
53cabad7
JB
8010 if (info->attrs[NL80211_ATTR_P2P_CTWINDOW]) {
8011 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
8012 return -EINVAL;
8013 params.p2p_ctwindow =
ab0d76f6 8014 nla_get_u8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]);
53cabad7
JB
8015 if (params.p2p_ctwindow != 0 &&
8016 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN))
8017 return -EINVAL;
8018 }
8019
8020 if (info->attrs[NL80211_ATTR_P2P_OPPPS]) {
8021 u8 tmp;
8022
8023 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
8024 return -EINVAL;
8025 tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]);
53cabad7
JB
8026 params.p2p_opp_ps = tmp;
8027 if (params.p2p_opp_ps &&
8028 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS))
8029 return -EINVAL;
8030 }
8031
4c476991
JB
8032 if (!rdev->ops->change_bss)
8033 return -EOPNOTSUPP;
9f1ba906 8034
074ac8df 8035 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
4c476991
JB
8036 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
8037 return -EOPNOTSUPP;
3b85875a 8038
c56589ed
SW
8039 wdev_lock(wdev);
8040 err = rdev_change_bss(rdev, dev, &params);
8041 wdev_unlock(wdev);
8042
8043 return err;
9f1ba906
JM
8044}
8045
b2e1b302
LR
8046static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info)
8047{
b2e1b302 8048 char *data = NULL;
05050753 8049 bool is_indoor;
57b5ce07 8050 enum nl80211_user_reg_hint_type user_reg_hint_type;
05050753
I
8051 u32 owner_nlportid;
8052
80778f18
LR
8053 /*
8054 * You should only get this when cfg80211 hasn't yet initialized
8055 * completely when built-in to the kernel right between the time
8056 * window between nl80211_init() and regulatory_init(), if that is
8057 * even possible.
8058 */
458f4f9e 8059 if (unlikely(!rcu_access_pointer(cfg80211_regdomain)))
fe33eb39 8060 return -EINPROGRESS;
80778f18 8061
57b5ce07
LR
8062 if (info->attrs[NL80211_ATTR_USER_REG_HINT_TYPE])
8063 user_reg_hint_type =
8064 nla_get_u32(info->attrs[NL80211_ATTR_USER_REG_HINT_TYPE]);
8065 else
8066 user_reg_hint_type = NL80211_USER_REG_HINT_USER;
8067
8068 switch (user_reg_hint_type) {
8069 case NL80211_USER_REG_HINT_USER:
8070 case NL80211_USER_REG_HINT_CELL_BASE:
52616f2b
IP
8071 if (!info->attrs[NL80211_ATTR_REG_ALPHA2])
8072 return -EINVAL;
8073
8074 data = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]);
8075 return regulatory_hint_user(data, user_reg_hint_type);
8076 case NL80211_USER_REG_HINT_INDOOR:
05050753
I
8077 if (info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
8078 owner_nlportid = info->snd_portid;
8079 is_indoor = !!info->attrs[NL80211_ATTR_REG_INDOOR];
8080 } else {
8081 owner_nlportid = 0;
8082 is_indoor = true;
8083 }
8084
8085 return regulatory_hint_indoor(is_indoor, owner_nlportid);
57b5ce07
LR
8086 default:
8087 return -EINVAL;
8088 }
b2e1b302
LR
8089}
8090
1ea4ff3e
JB
8091static int nl80211_reload_regdb(struct sk_buff *skb, struct genl_info *info)
8092{
8093 return reg_reload_regdb();
8094}
8095
24bdd9f4 8096static int nl80211_get_mesh_config(struct sk_buff *skb,
29cbe68c 8097 struct genl_info *info)
93da9cc1 8098{
4c476991 8099 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4c476991 8100 struct net_device *dev = info->user_ptr[1];
29cbe68c
JB
8101 struct wireless_dev *wdev = dev->ieee80211_ptr;
8102 struct mesh_config cur_params;
8103 int err = 0;
93da9cc1 8104 void *hdr;
8105 struct nlattr *pinfoattr;
8106 struct sk_buff *msg;
8107
29cbe68c
JB
8108 if (wdev->iftype != NL80211_IFTYPE_MESH_POINT)
8109 return -EOPNOTSUPP;
8110
24bdd9f4 8111 if (!rdev->ops->get_mesh_config)
4c476991 8112 return -EOPNOTSUPP;
f3f92586 8113
29cbe68c
JB
8114 wdev_lock(wdev);
8115 /* If not connected, get default parameters */
7b0a0e3c 8116 if (!wdev->u.mesh.id_len)
29cbe68c
JB
8117 memcpy(&cur_params, &default_mesh_config, sizeof(cur_params));
8118 else
e35e4d28 8119 err = rdev_get_mesh_config(rdev, dev, &cur_params);
29cbe68c
JB
8120 wdev_unlock(wdev);
8121
93da9cc1 8122 if (err)
4c476991 8123 return err;
93da9cc1 8124
8125 /* Draw up a netlink message to send back */
fd2120ca 8126 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4c476991
JB
8127 if (!msg)
8128 return -ENOMEM;
15e47304 8129 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
24bdd9f4 8130 NL80211_CMD_GET_MESH_CONFIG);
93da9cc1 8131 if (!hdr)
efe1cf0c 8132 goto out;
ae0be8de 8133 pinfoattr = nla_nest_start_noflag(msg, NL80211_ATTR_MESH_CONFIG);
93da9cc1 8134 if (!pinfoattr)
8135 goto nla_put_failure;
9360ffd1
DM
8136 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
8137 nla_put_u16(msg, NL80211_MESHCONF_RETRY_TIMEOUT,
8138 cur_params.dot11MeshRetryTimeout) ||
8139 nla_put_u16(msg, NL80211_MESHCONF_CONFIRM_TIMEOUT,
8140 cur_params.dot11MeshConfirmTimeout) ||
8141 nla_put_u16(msg, NL80211_MESHCONF_HOLDING_TIMEOUT,
8142 cur_params.dot11MeshHoldingTimeout) ||
8143 nla_put_u16(msg, NL80211_MESHCONF_MAX_PEER_LINKS,
8144 cur_params.dot11MeshMaxPeerLinks) ||
8145 nla_put_u8(msg, NL80211_MESHCONF_MAX_RETRIES,
8146 cur_params.dot11MeshMaxRetries) ||
8147 nla_put_u8(msg, NL80211_MESHCONF_TTL,
8148 cur_params.dot11MeshTTL) ||
8149 nla_put_u8(msg, NL80211_MESHCONF_ELEMENT_TTL,
8150 cur_params.element_ttl) ||
8151 nla_put_u8(msg, NL80211_MESHCONF_AUTO_OPEN_PLINKS,
8152 cur_params.auto_open_plinks) ||
7eab0f64
JL
8153 nla_put_u32(msg, NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR,
8154 cur_params.dot11MeshNbrOffsetMaxNeighbor) ||
9360ffd1
DM
8155 nla_put_u8(msg, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES,
8156 cur_params.dot11MeshHWMPmaxPREQretries) ||
8157 nla_put_u32(msg, NL80211_MESHCONF_PATH_REFRESH_TIME,
8158 cur_params.path_refresh_time) ||
8159 nla_put_u16(msg, NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT,
8160 cur_params.min_discovery_timeout) ||
8161 nla_put_u32(msg, NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT,
8162 cur_params.dot11MeshHWMPactivePathTimeout) ||
8163 nla_put_u16(msg, NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL,
8164 cur_params.dot11MeshHWMPpreqMinInterval) ||
8165 nla_put_u16(msg, NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL,
8166 cur_params.dot11MeshHWMPperrMinInterval) ||
8167 nla_put_u16(msg, NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
8168 cur_params.dot11MeshHWMPnetDiameterTraversalTime) ||
8169 nla_put_u8(msg, NL80211_MESHCONF_HWMP_ROOTMODE,
8170 cur_params.dot11MeshHWMPRootMode) ||
8171 nla_put_u16(msg, NL80211_MESHCONF_HWMP_RANN_INTERVAL,
8172 cur_params.dot11MeshHWMPRannInterval) ||
8173 nla_put_u8(msg, NL80211_MESHCONF_GATE_ANNOUNCEMENTS,
8174 cur_params.dot11MeshGateAnnouncementProtocol) ||
8175 nla_put_u8(msg, NL80211_MESHCONF_FORWARDING,
8176 cur_params.dot11MeshForwarding) ||
335d5349 8177 nla_put_s32(msg, NL80211_MESHCONF_RSSI_THRESHOLD,
70c33eaa
AN
8178 cur_params.rssi_threshold) ||
8179 nla_put_u32(msg, NL80211_MESHCONF_HT_OPMODE,
ac1073a6
CYY
8180 cur_params.ht_opmode) ||
8181 nla_put_u32(msg, NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT,
8182 cur_params.dot11MeshHWMPactivePathToRootTimeout) ||
8183 nla_put_u16(msg, NL80211_MESHCONF_HWMP_ROOT_INTERVAL,
728b19e5
CYY
8184 cur_params.dot11MeshHWMProotInterval) ||
8185 nla_put_u16(msg, NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL,
3b1c5a53
MP
8186 cur_params.dot11MeshHWMPconfirmationInterval) ||
8187 nla_put_u32(msg, NL80211_MESHCONF_POWER_MODE,
8188 cur_params.power_mode) ||
8189 nla_put_u16(msg, NL80211_MESHCONF_AWAKE_WINDOW,
8e7c0538
CT
8190 cur_params.dot11MeshAwakeWindowDuration) ||
8191 nla_put_u32(msg, NL80211_MESHCONF_PLINK_TIMEOUT,
01d66fbd
BC
8192 cur_params.plink_timeout) ||
8193 nla_put_u8(msg, NL80211_MESHCONF_CONNECTED_TO_GATE,
e3718a61
LL
8194 cur_params.dot11MeshConnectedToMeshGate) ||
8195 nla_put_u8(msg, NL80211_MESHCONF_NOLEARN,
184eebe6
MT
8196 cur_params.dot11MeshNolearn) ||
8197 nla_put_u8(msg, NL80211_MESHCONF_CONNECTED_TO_AS,
8198 cur_params.dot11MeshConnectedToAuthServer))
9360ffd1 8199 goto nla_put_failure;
93da9cc1 8200 nla_nest_end(msg, pinfoattr);
8201 genlmsg_end(msg, hdr);
4c476991 8202 return genlmsg_reply(msg, info);
93da9cc1 8203
3b85875a 8204 nla_put_failure:
efe1cf0c 8205 out:
d080e275 8206 nlmsg_free(msg);
4c476991 8207 return -ENOBUFS;
93da9cc1 8208}
8209
ab0d76f6
JB
8210static const struct nla_policy
8211nl80211_meshconf_params_policy[NL80211_MESHCONF_ATTR_MAX+1] = {
8212 [NL80211_MESHCONF_RETRY_TIMEOUT] =
8213 NLA_POLICY_RANGE(NLA_U16, 1, 255),
8214 [NL80211_MESHCONF_CONFIRM_TIMEOUT] =
8215 NLA_POLICY_RANGE(NLA_U16, 1, 255),
8216 [NL80211_MESHCONF_HOLDING_TIMEOUT] =
8217 NLA_POLICY_RANGE(NLA_U16, 1, 255),
8218 [NL80211_MESHCONF_MAX_PEER_LINKS] =
8219 NLA_POLICY_RANGE(NLA_U16, 0, 255),
8220 [NL80211_MESHCONF_MAX_RETRIES] = NLA_POLICY_MAX(NLA_U8, 16),
8221 [NL80211_MESHCONF_TTL] = NLA_POLICY_MIN(NLA_U8, 1),
8222 [NL80211_MESHCONF_ELEMENT_TTL] = NLA_POLICY_MIN(NLA_U8, 1),
8223 [NL80211_MESHCONF_AUTO_OPEN_PLINKS] = NLA_POLICY_MAX(NLA_U8, 1),
8224 [NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR] =
8225 NLA_POLICY_RANGE(NLA_U32, 1, 255),
93da9cc1 8226 [NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES] = { .type = NLA_U8 },
8227 [NL80211_MESHCONF_PATH_REFRESH_TIME] = { .type = NLA_U32 },
ab0d76f6 8228 [NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT] = NLA_POLICY_MIN(NLA_U16, 1),
93da9cc1 8229 [NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT] = { .type = NLA_U32 },
ab0d76f6
JB
8230 [NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL] =
8231 NLA_POLICY_MIN(NLA_U16, 1),
8232 [NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL] =
8233 NLA_POLICY_MIN(NLA_U16, 1),
8234 [NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME] =
8235 NLA_POLICY_MIN(NLA_U16, 1),
8236 [NL80211_MESHCONF_HWMP_ROOTMODE] = NLA_POLICY_MAX(NLA_U8, 4),
8237 [NL80211_MESHCONF_HWMP_RANN_INTERVAL] =
8238 NLA_POLICY_MIN(NLA_U16, 1),
8239 [NL80211_MESHCONF_GATE_ANNOUNCEMENTS] = NLA_POLICY_MAX(NLA_U8, 1),
8240 [NL80211_MESHCONF_FORWARDING] = NLA_POLICY_MAX(NLA_U8, 1),
8241 [NL80211_MESHCONF_RSSI_THRESHOLD] =
8242 NLA_POLICY_RANGE(NLA_S32, -255, 0),
a4f606ea 8243 [NL80211_MESHCONF_HT_OPMODE] = { .type = NLA_U16 },
ac1073a6 8244 [NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT] = { .type = NLA_U32 },
ab0d76f6
JB
8245 [NL80211_MESHCONF_HWMP_ROOT_INTERVAL] =
8246 NLA_POLICY_MIN(NLA_U16, 1),
8247 [NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL] =
8248 NLA_POLICY_MIN(NLA_U16, 1),
8249 [NL80211_MESHCONF_POWER_MODE] =
8250 NLA_POLICY_RANGE(NLA_U32,
8251 NL80211_MESH_POWER_ACTIVE,
8252 NL80211_MESH_POWER_MAX),
3b1c5a53 8253 [NL80211_MESHCONF_AWAKE_WINDOW] = { .type = NLA_U16 },
8e7c0538 8254 [NL80211_MESHCONF_PLINK_TIMEOUT] = { .type = NLA_U32 },
01d66fbd 8255 [NL80211_MESHCONF_CONNECTED_TO_GATE] = NLA_POLICY_RANGE(NLA_U8, 0, 1),
e3718a61 8256 [NL80211_MESHCONF_NOLEARN] = NLA_POLICY_RANGE(NLA_U8, 0, 1),
184eebe6 8257 [NL80211_MESHCONF_CONNECTED_TO_AS] = NLA_POLICY_RANGE(NLA_U8, 0, 1),
93da9cc1 8258};
8259
c80d545d
JC
8260static const struct nla_policy
8261 nl80211_mesh_setup_params_policy[NL80211_MESH_SETUP_ATTR_MAX+1] = {
d299a1f2 8262 [NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC] = { .type = NLA_U8 },
c80d545d
JC
8263 [NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL] = { .type = NLA_U8 },
8264 [NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC] = { .type = NLA_U8 },
15d5dda6 8265 [NL80211_MESH_SETUP_USERSPACE_AUTH] = { .type = NLA_FLAG },
6e16d90b 8266 [NL80211_MESH_SETUP_AUTH_PROTOCOL] = { .type = NLA_U8 },
bb2798d4 8267 [NL80211_MESH_SETUP_USERSPACE_MPM] = { .type = NLA_FLAG },
3d7af878
JB
8268 [NL80211_MESH_SETUP_IE] =
8269 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr,
8270 IEEE80211_MAX_DATA_LEN),
b130e5ce 8271 [NL80211_MESH_SETUP_USERSPACE_AMPE] = { .type = NLA_FLAG },
c80d545d
JC
8272};
8273
24bdd9f4 8274static int nl80211_parse_mesh_config(struct genl_info *info,
bd90fdcc
JB
8275 struct mesh_config *cfg,
8276 u32 *mask_out)
93da9cc1 8277{
93da9cc1 8278 struct nlattr *tb[NL80211_MESHCONF_ATTR_MAX + 1];
bd90fdcc 8279 u32 mask = 0;
9757235f 8280 u16 ht_opmode;
93da9cc1 8281
ab0d76f6
JB
8282#define FILL_IN_MESH_PARAM_IF_SET(tb, cfg, param, mask, attr, fn) \
8283do { \
8284 if (tb[attr]) { \
8285 cfg->param = fn(tb[attr]); \
8286 mask |= BIT((attr) - 1); \
8287 } \
ea54fba2 8288} while (0)
bd90fdcc 8289
24bdd9f4 8290 if (!info->attrs[NL80211_ATTR_MESH_CONFIG])
93da9cc1 8291 return -EINVAL;
8cb08174 8292 if (nla_parse_nested_deprecated(tb, NL80211_MESHCONF_ATTR_MAX, info->attrs[NL80211_ATTR_MESH_CONFIG], nl80211_meshconf_params_policy, info->extack))
93da9cc1 8293 return -EINVAL;
8294
93da9cc1 8295 /* This makes sure that there aren't more than 32 mesh config
8296 * parameters (otherwise our bitfield scheme would not work.) */
8297 BUILD_BUG_ON(NL80211_MESHCONF_ATTR_MAX > 32);
8298
8299 /* Fill in the params struct */
ab0d76f6
JB
8300 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshRetryTimeout, mask,
8301 NL80211_MESHCONF_RETRY_TIMEOUT, nla_get_u16);
8302 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConfirmTimeout, mask,
8303 NL80211_MESHCONF_CONFIRM_TIMEOUT,
8304 nla_get_u16);
8305 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHoldingTimeout, mask,
8306 NL80211_MESHCONF_HOLDING_TIMEOUT,
8307 nla_get_u16);
8308 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxPeerLinks, mask,
8309 NL80211_MESHCONF_MAX_PEER_LINKS,
8310 nla_get_u16);
8311 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxRetries, mask,
8312 NL80211_MESHCONF_MAX_RETRIES, nla_get_u8);
8313 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshTTL, mask,
8314 NL80211_MESHCONF_TTL, nla_get_u8);
8315 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, element_ttl, mask,
8316 NL80211_MESHCONF_ELEMENT_TTL, nla_get_u8);
8317 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, auto_open_plinks, mask,
8318 NL80211_MESHCONF_AUTO_OPEN_PLINKS,
8319 nla_get_u8);
ea54fba2 8320 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshNbrOffsetMaxNeighbor,
ab0d76f6 8321 mask,
a4f606ea 8322 NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR,
ab0d76f6
JB
8323 nla_get_u32);
8324 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPmaxPREQretries, mask,
8325 NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES,
8326 nla_get_u8);
8327 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, path_refresh_time, mask,
8328 NL80211_MESHCONF_PATH_REFRESH_TIME,
8329 nla_get_u32);
8330 if (mask & BIT(NL80211_MESHCONF_PATH_REFRESH_TIME) &&
8331 (cfg->path_refresh_time < 1 || cfg->path_refresh_time > 65535))
8332 return -EINVAL;
8333 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, min_discovery_timeout, mask,
8334 NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT,
8335 nla_get_u16);
ea54fba2 8336 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathTimeout,
ab0d76f6 8337 mask,
a4f606ea 8338 NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT,
ab0d76f6
JB
8339 nla_get_u32);
8340 if (mask & BIT(NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT) &&
8341 (cfg->dot11MeshHWMPactivePathTimeout < 1 ||
8342 cfg->dot11MeshHWMPactivePathTimeout > 65535))
8343 return -EINVAL;
8344 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPpreqMinInterval, mask,
ea54fba2 8345 NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL,
ab0d76f6
JB
8346 nla_get_u16);
8347 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPperrMinInterval, mask,
ea54fba2 8348 NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL,
ab0d76f6 8349 nla_get_u16);
93da9cc1 8350 FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
ab0d76f6 8351 dot11MeshHWMPnetDiameterTraversalTime, mask,
a4f606ea 8352 NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
ab0d76f6
JB
8353 nla_get_u16);
8354 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRootMode, mask,
8355 NL80211_MESHCONF_HWMP_ROOTMODE, nla_get_u8);
8356 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRannInterval, mask,
8357 NL80211_MESHCONF_HWMP_RANN_INTERVAL,
8358 nla_get_u16);
8359 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshGateAnnouncementProtocol,
ea54fba2 8360 mask, NL80211_MESHCONF_GATE_ANNOUNCEMENTS,
ab0d76f6
JB
8361 nla_get_u8);
8362 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshForwarding, mask,
8363 NL80211_MESHCONF_FORWARDING, nla_get_u8);
8364 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, rssi_threshold, mask,
8365 NL80211_MESHCONF_RSSI_THRESHOLD,
8366 nla_get_s32);
01d66fbd
BC
8367 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConnectedToMeshGate, mask,
8368 NL80211_MESHCONF_CONNECTED_TO_GATE,
8369 nla_get_u8);
184eebe6
MT
8370 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConnectedToAuthServer, mask,
8371 NL80211_MESHCONF_CONNECTED_TO_AS,
8372 nla_get_u8);
9757235f
MH
8373 /*
8374 * Check HT operation mode based on
188f60ab 8375 * IEEE 802.11-2016 9.4.2.57 HT Operation element.
9757235f
MH
8376 */
8377 if (tb[NL80211_MESHCONF_HT_OPMODE]) {
8378 ht_opmode = nla_get_u16(tb[NL80211_MESHCONF_HT_OPMODE]);
8379
8380 if (ht_opmode & ~(IEEE80211_HT_OP_MODE_PROTECTION |
8381 IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT |
8382 IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT))
8383 return -EINVAL;
8384
188f60ab
BC
8385 /* NON_HT_STA bit is reserved, but some programs set it */
8386 ht_opmode &= ~IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT;
9757235f 8387
9757235f 8388 cfg->ht_opmode = ht_opmode;
fd551bac 8389 mask |= (1 << (NL80211_MESHCONF_HT_OPMODE - 1));
9757235f 8390 }
728b19e5 8391 FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
ab0d76f6
JB
8392 dot11MeshHWMPactivePathToRootTimeout, mask,
8393 NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT,
8394 nla_get_u32);
8395 if (mask & BIT(NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT) &&
8396 (cfg->dot11MeshHWMPactivePathToRootTimeout < 1 ||
8397 cfg->dot11MeshHWMPactivePathToRootTimeout > 65535))
8398 return -EINVAL;
8399 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMProotInterval, mask,
8400 NL80211_MESHCONF_HWMP_ROOT_INTERVAL,
8401 nla_get_u16);
8402 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPconfirmationInterval,
8403 mask,
728b19e5 8404 NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL,
ab0d76f6
JB
8405 nla_get_u16);
8406 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, power_mode, mask,
8407 NL80211_MESHCONF_POWER_MODE, nla_get_u32);
8408 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshAwakeWindowDuration, mask,
8409 NL80211_MESHCONF_AWAKE_WINDOW, nla_get_u16);
8410 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, plink_timeout, mask,
8411 NL80211_MESHCONF_PLINK_TIMEOUT, nla_get_u32);
e3718a61
LL
8412 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshNolearn, mask,
8413 NL80211_MESHCONF_NOLEARN, nla_get_u8);
bd90fdcc
JB
8414 if (mask_out)
8415 *mask_out = mask;
c80d545d 8416
bd90fdcc
JB
8417 return 0;
8418
8419#undef FILL_IN_MESH_PARAM_IF_SET
8420}
8421
c80d545d
JC
8422static int nl80211_parse_mesh_setup(struct genl_info *info,
8423 struct mesh_setup *setup)
8424{
bb2798d4 8425 struct cfg80211_registered_device *rdev = info->user_ptr[0];
c80d545d
JC
8426 struct nlattr *tb[NL80211_MESH_SETUP_ATTR_MAX + 1];
8427
8428 if (!info->attrs[NL80211_ATTR_MESH_SETUP])
8429 return -EINVAL;
8cb08174 8430 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
8431 return -EINVAL;
8432
d299a1f2
JC
8433 if (tb[NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC])
8434 setup->sync_method =
8435 (nla_get_u8(tb[NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC])) ?
8436 IEEE80211_SYNC_METHOD_VENDOR :
8437 IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET;
8438
c80d545d
JC
8439 if (tb[NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL])
8440 setup->path_sel_proto =
8441 (nla_get_u8(tb[NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL])) ?
8442 IEEE80211_PATH_PROTOCOL_VENDOR :
8443 IEEE80211_PATH_PROTOCOL_HWMP;
8444
8445 if (tb[NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC])
8446 setup->path_metric =
8447 (nla_get_u8(tb[NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC])) ?
8448 IEEE80211_PATH_METRIC_VENDOR :
8449 IEEE80211_PATH_METRIC_AIRTIME;
8450
581a8b0f 8451 if (tb[NL80211_MESH_SETUP_IE]) {
c80d545d 8452 struct nlattr *ieattr =
581a8b0f 8453 tb[NL80211_MESH_SETUP_IE];
581a8b0f
JC
8454 setup->ie = nla_data(ieattr);
8455 setup->ie_len = nla_len(ieattr);
c80d545d 8456 }
bb2798d4
TP
8457 if (tb[NL80211_MESH_SETUP_USERSPACE_MPM] &&
8458 !(rdev->wiphy.features & NL80211_FEATURE_USERSPACE_MPM))
8459 return -EINVAL;
8460 setup->user_mpm = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_MPM]);
b130e5ce
JC
8461 setup->is_authenticated = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AUTH]);
8462 setup->is_secure = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AMPE]);
bb2798d4
TP
8463 if (setup->is_secure)
8464 setup->user_mpm = true;
c80d545d 8465
6e16d90b
CT
8466 if (tb[NL80211_MESH_SETUP_AUTH_PROTOCOL]) {
8467 if (!setup->user_mpm)
8468 return -EINVAL;
8469 setup->auth_id =
8470 nla_get_u8(tb[NL80211_MESH_SETUP_AUTH_PROTOCOL]);
8471 }
8472
c80d545d
JC
8473 return 0;
8474}
8475
24bdd9f4 8476static int nl80211_update_mesh_config(struct sk_buff *skb,
29cbe68c 8477 struct genl_info *info)
bd90fdcc
JB
8478{
8479 struct cfg80211_registered_device *rdev = info->user_ptr[0];
8480 struct net_device *dev = info->user_ptr[1];
29cbe68c 8481 struct wireless_dev *wdev = dev->ieee80211_ptr;
bd90fdcc
JB
8482 struct mesh_config cfg;
8483 u32 mask;
8484 int err;
8485
29cbe68c
JB
8486 if (wdev->iftype != NL80211_IFTYPE_MESH_POINT)
8487 return -EOPNOTSUPP;
8488
24bdd9f4 8489 if (!rdev->ops->update_mesh_config)
bd90fdcc
JB
8490 return -EOPNOTSUPP;
8491
24bdd9f4 8492 err = nl80211_parse_mesh_config(info, &cfg, &mask);
bd90fdcc
JB
8493 if (err)
8494 return err;
8495
29cbe68c 8496 wdev_lock(wdev);
7b0a0e3c 8497 if (!wdev->u.mesh.id_len)
29cbe68c
JB
8498 err = -ENOLINK;
8499
8500 if (!err)
e35e4d28 8501 err = rdev_update_mesh_config(rdev, dev, mask, &cfg);
29cbe68c
JB
8502
8503 wdev_unlock(wdev);
8504
8505 return err;
93da9cc1 8506}
8507
ad30ca2c
AN
8508static int nl80211_put_regdom(const struct ieee80211_regdomain *regdom,
8509 struct sk_buff *msg)
f130347c 8510{
f130347c
LR
8511 struct nlattr *nl_reg_rules;
8512 unsigned int i;
f130347c 8513
458f4f9e
JB
8514 if (nla_put_string(msg, NL80211_ATTR_REG_ALPHA2, regdom->alpha2) ||
8515 (regdom->dfs_region &&
8516 nla_put_u8(msg, NL80211_ATTR_DFS_REGION, regdom->dfs_region)))
ad30ca2c 8517 goto nla_put_failure;
458f4f9e 8518
ae0be8de 8519 nl_reg_rules = nla_nest_start_noflag(msg, NL80211_ATTR_REG_RULES);
f130347c 8520 if (!nl_reg_rules)
ad30ca2c 8521 goto nla_put_failure;
f130347c 8522
458f4f9e 8523 for (i = 0; i < regdom->n_reg_rules; i++) {
f130347c
LR
8524 struct nlattr *nl_reg_rule;
8525 const struct ieee80211_reg_rule *reg_rule;
8526 const struct ieee80211_freq_range *freq_range;
8527 const struct ieee80211_power_rule *power_rule;
97524820 8528 unsigned int max_bandwidth_khz;
f130347c 8529
458f4f9e 8530 reg_rule = &regdom->reg_rules[i];
f130347c
LR
8531 freq_range = &reg_rule->freq_range;
8532 power_rule = &reg_rule->power_rule;
8533
ae0be8de 8534 nl_reg_rule = nla_nest_start_noflag(msg, i);
f130347c 8535 if (!nl_reg_rule)
ad30ca2c 8536 goto nla_put_failure;
f130347c 8537
97524820
JD
8538 max_bandwidth_khz = freq_range->max_bandwidth_khz;
8539 if (!max_bandwidth_khz)
8540 max_bandwidth_khz = reg_get_max_bandwidth(regdom,
8541 reg_rule);
8542
9360ffd1
DM
8543 if (nla_put_u32(msg, NL80211_ATTR_REG_RULE_FLAGS,
8544 reg_rule->flags) ||
8545 nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_START,
8546 freq_range->start_freq_khz) ||
8547 nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_END,
8548 freq_range->end_freq_khz) ||
8549 nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_MAX_BW,
97524820 8550 max_bandwidth_khz) ||
9360ffd1
DM
8551 nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN,
8552 power_rule->max_antenna_gain) ||
8553 nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_EIRP,
089027e5
JD
8554 power_rule->max_eirp) ||
8555 nla_put_u32(msg, NL80211_ATTR_DFS_CAC_TIME,
8556 reg_rule->dfs_cac_ms))
ad30ca2c 8557 goto nla_put_failure;
f130347c
LR
8558
8559 nla_nest_end(msg, nl_reg_rule);
8560 }
8561
8562 nla_nest_end(msg, nl_reg_rules);
ad30ca2c
AN
8563 return 0;
8564
8565nla_put_failure:
8566 return -EMSGSIZE;
8567}
8568
8569static int nl80211_get_reg_do(struct sk_buff *skb, struct genl_info *info)
8570{
8571 const struct ieee80211_regdomain *regdom = NULL;
8572 struct cfg80211_registered_device *rdev;
8573 struct wiphy *wiphy = NULL;
8574 struct sk_buff *msg;
024fcf5e 8575 int err = -EMSGSIZE;
ad30ca2c
AN
8576 void *hdr;
8577
8578 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
8579 if (!msg)
8580 return -ENOBUFS;
8581
8582 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
8583 NL80211_CMD_GET_REG);
8584 if (!hdr)
8585 goto put_failure;
8586
a05829a7
JB
8587 rtnl_lock();
8588
ad30ca2c 8589 if (info->attrs[NL80211_ATTR_WIPHY]) {
1bdd716c
AN
8590 bool self_managed;
8591
ad30ca2c
AN
8592 rdev = cfg80211_get_dev_from_info(genl_info_net(info), info);
8593 if (IS_ERR(rdev)) {
024fcf5e
JB
8594 err = PTR_ERR(rdev);
8595 goto nla_put_failure;
ad30ca2c
AN
8596 }
8597
8598 wiphy = &rdev->wiphy;
1bdd716c
AN
8599 self_managed = wiphy->regulatory_flags &
8600 REGULATORY_WIPHY_SELF_MANAGED;
024fcf5e
JB
8601
8602 rcu_read_lock();
8603
ad30ca2c
AN
8604 regdom = get_wiphy_regdom(wiphy);
8605
1bdd716c
AN
8606 /* a self-managed-reg device must have a private regdom */
8607 if (WARN_ON(!regdom && self_managed)) {
024fcf5e
JB
8608 err = -EINVAL;
8609 goto nla_put_failure_rcu;
1bdd716c
AN
8610 }
8611
ad30ca2c
AN
8612 if (regdom &&
8613 nla_put_u32(msg, NL80211_ATTR_WIPHY, get_wiphy_idx(wiphy)))
024fcf5e
JB
8614 goto nla_put_failure_rcu;
8615 } else {
8616 rcu_read_lock();
ad30ca2c
AN
8617 }
8618
8619 if (!wiphy && reg_last_request_cell_base() &&
8620 nla_put_u32(msg, NL80211_ATTR_USER_REG_HINT_TYPE,
8621 NL80211_USER_REG_HINT_CELL_BASE))
024fcf5e 8622 goto nla_put_failure_rcu;
ad30ca2c
AN
8623
8624 if (!regdom)
8625 regdom = rcu_dereference(cfg80211_regdomain);
8626
8627 if (nl80211_put_regdom(regdom, msg))
8628 goto nla_put_failure_rcu;
8629
8630 rcu_read_unlock();
f130347c
LR
8631
8632 genlmsg_end(msg, hdr);
a05829a7 8633 rtnl_unlock();
5fe231e8 8634 return genlmsg_reply(msg, info);
f130347c 8635
458f4f9e
JB
8636nla_put_failure_rcu:
8637 rcu_read_unlock();
f130347c 8638nla_put_failure:
a05829a7 8639 rtnl_unlock();
efe1cf0c 8640put_failure:
d080e275 8641 nlmsg_free(msg);
024fcf5e 8642 return err;
f130347c
LR
8643}
8644
ad30ca2c
AN
8645static int nl80211_send_regdom(struct sk_buff *msg, struct netlink_callback *cb,
8646 u32 seq, int flags, struct wiphy *wiphy,
8647 const struct ieee80211_regdomain *regdom)
8648{
8649 void *hdr = nl80211hdr_put(msg, NETLINK_CB(cb->skb).portid, seq, flags,
8650 NL80211_CMD_GET_REG);
8651
8652 if (!hdr)
8653 return -1;
8654
0a833c29 8655 genl_dump_check_consistent(cb, hdr);
ad30ca2c
AN
8656
8657 if (nl80211_put_regdom(regdom, msg))
8658 goto nla_put_failure;
8659
8660 if (!wiphy && reg_last_request_cell_base() &&
8661 nla_put_u32(msg, NL80211_ATTR_USER_REG_HINT_TYPE,
8662 NL80211_USER_REG_HINT_CELL_BASE))
8663 goto nla_put_failure;
8664
8665 if (wiphy &&
8666 nla_put_u32(msg, NL80211_ATTR_WIPHY, get_wiphy_idx(wiphy)))
8667 goto nla_put_failure;
8668
1bdd716c
AN
8669 if (wiphy && wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED &&
8670 nla_put_flag(msg, NL80211_ATTR_WIPHY_SELF_MANAGED_REG))
8671 goto nla_put_failure;
8672
053c095a
JB
8673 genlmsg_end(msg, hdr);
8674 return 0;
ad30ca2c
AN
8675
8676nla_put_failure:
8677 genlmsg_cancel(msg, hdr);
8678 return -EMSGSIZE;
8679}
8680
8681static int nl80211_get_reg_dump(struct sk_buff *skb,
8682 struct netlink_callback *cb)
8683{
8684 const struct ieee80211_regdomain *regdom = NULL;
8685 struct cfg80211_registered_device *rdev;
8686 int err, reg_idx, start = cb->args[2];
8687
024fcf5e 8688 rcu_read_lock();
ad30ca2c
AN
8689
8690 if (cfg80211_regdomain && start == 0) {
8691 err = nl80211_send_regdom(skb, cb, cb->nlh->nlmsg_seq,
8692 NLM_F_MULTI, NULL,
024fcf5e 8693 rcu_dereference(cfg80211_regdomain));
ad30ca2c
AN
8694 if (err < 0)
8695 goto out_err;
8696 }
8697
8698 /* the global regdom is idx 0 */
8699 reg_idx = 1;
024fcf5e 8700 list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) {
ad30ca2c
AN
8701 regdom = get_wiphy_regdom(&rdev->wiphy);
8702 if (!regdom)
8703 continue;
8704
8705 if (++reg_idx <= start)
8706 continue;
8707
8708 err = nl80211_send_regdom(skb, cb, cb->nlh->nlmsg_seq,
8709 NLM_F_MULTI, &rdev->wiphy, regdom);
8710 if (err < 0) {
8711 reg_idx--;
8712 break;
8713 }
8714 }
8715
8716 cb->args[2] = reg_idx;
8717 err = skb->len;
8718out_err:
024fcf5e 8719 rcu_read_unlock();
ad30ca2c
AN
8720 return err;
8721}
8722
b6863036
JB
8723#ifdef CONFIG_CFG80211_CRDA_SUPPORT
8724static const struct nla_policy reg_rule_policy[NL80211_REG_RULE_ATTR_MAX + 1] = {
8725 [NL80211_ATTR_REG_RULE_FLAGS] = { .type = NLA_U32 },
8726 [NL80211_ATTR_FREQ_RANGE_START] = { .type = NLA_U32 },
8727 [NL80211_ATTR_FREQ_RANGE_END] = { .type = NLA_U32 },
8728 [NL80211_ATTR_FREQ_RANGE_MAX_BW] = { .type = NLA_U32 },
8729 [NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN] = { .type = NLA_U32 },
8730 [NL80211_ATTR_POWER_RULE_MAX_EIRP] = { .type = NLA_U32 },
8731 [NL80211_ATTR_DFS_CAC_TIME] = { .type = NLA_U32 },
8732};
8733
8734static int parse_reg_rule(struct nlattr *tb[],
8735 struct ieee80211_reg_rule *reg_rule)
8736{
8737 struct ieee80211_freq_range *freq_range = &reg_rule->freq_range;
8738 struct ieee80211_power_rule *power_rule = &reg_rule->power_rule;
8739
8740 if (!tb[NL80211_ATTR_REG_RULE_FLAGS])
8741 return -EINVAL;
8742 if (!tb[NL80211_ATTR_FREQ_RANGE_START])
8743 return -EINVAL;
8744 if (!tb[NL80211_ATTR_FREQ_RANGE_END])
8745 return -EINVAL;
8746 if (!tb[NL80211_ATTR_FREQ_RANGE_MAX_BW])
8747 return -EINVAL;
8748 if (!tb[NL80211_ATTR_POWER_RULE_MAX_EIRP])
8749 return -EINVAL;
8750
8751 reg_rule->flags = nla_get_u32(tb[NL80211_ATTR_REG_RULE_FLAGS]);
8752
8753 freq_range->start_freq_khz =
8754 nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]);
8755 freq_range->end_freq_khz =
8756 nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]);
8757 freq_range->max_bandwidth_khz =
8758 nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]);
8759
8760 power_rule->max_eirp =
8761 nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_EIRP]);
8762
8763 if (tb[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN])
8764 power_rule->max_antenna_gain =
8765 nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN]);
8766
8767 if (tb[NL80211_ATTR_DFS_CAC_TIME])
8768 reg_rule->dfs_cac_ms =
8769 nla_get_u32(tb[NL80211_ATTR_DFS_CAC_TIME]);
8770
8771 return 0;
8772}
8773
b2e1b302
LR
8774static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
8775{
8776 struct nlattr *tb[NL80211_REG_RULE_ATTR_MAX + 1];
8777 struct nlattr *nl_reg_rule;
ea372c54
JB
8778 char *alpha2;
8779 int rem_reg_rules, r;
391d132c 8780 u32 num_rules = 0, rule_idx = 0;
4c7d3982 8781 enum nl80211_dfs_regions dfs_region = NL80211_DFS_UNSET;
ea372c54 8782 struct ieee80211_regdomain *rd;
b2e1b302
LR
8783
8784 if (!info->attrs[NL80211_ATTR_REG_ALPHA2])
8785 return -EINVAL;
8786
8787 if (!info->attrs[NL80211_ATTR_REG_RULES])
8788 return -EINVAL;
8789
8790 alpha2 = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]);
8791
8b60b078
LR
8792 if (info->attrs[NL80211_ATTR_DFS_REGION])
8793 dfs_region = nla_get_u8(info->attrs[NL80211_ATTR_DFS_REGION]);
8794
b2e1b302 8795 nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES],
1a919318 8796 rem_reg_rules) {
b2e1b302
LR
8797 num_rules++;
8798 if (num_rules > NL80211_MAX_SUPP_REG_RULES)
4776c6e7 8799 return -EINVAL;
b2e1b302
LR
8800 }
8801
a05829a7
JB
8802 rtnl_lock();
8803 if (!reg_is_valid_request(alpha2)) {
8804 r = -EINVAL;
8805 goto out;
8806 }
e438768f 8807
391d132c 8808 rd = kzalloc(struct_size(rd, reg_rules, num_rules), GFP_KERNEL);
a05829a7
JB
8809 if (!rd) {
8810 r = -ENOMEM;
8811 goto out;
8812 }
b2e1b302
LR
8813
8814 rd->n_reg_rules = num_rules;
8815 rd->alpha2[0] = alpha2[0];
8816 rd->alpha2[1] = alpha2[1];
8817
8b60b078
LR
8818 /*
8819 * Disable DFS master mode if the DFS region was
8820 * not supported or known on this kernel.
8821 */
8822 if (reg_supported_dfs_region(dfs_region))
8823 rd->dfs_region = dfs_region;
8824
b2e1b302 8825 nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES],
1a919318 8826 rem_reg_rules) {
8cb08174
JB
8827 r = nla_parse_nested_deprecated(tb, NL80211_REG_RULE_ATTR_MAX,
8828 nl_reg_rule, reg_rule_policy,
8829 info->extack);
ae811e21
JB
8830 if (r)
8831 goto bad_reg;
b2e1b302
LR
8832 r = parse_reg_rule(tb, &rd->reg_rules[rule_idx]);
8833 if (r)
8834 goto bad_reg;
8835
8836 rule_idx++;
8837
d0e18f83
LR
8838 if (rule_idx > NL80211_MAX_SUPP_REG_RULES) {
8839 r = -EINVAL;
b2e1b302 8840 goto bad_reg;
d0e18f83 8841 }
b2e1b302
LR
8842 }
8843
a05829a7 8844 r = set_regdom(rd, REGD_SOURCE_CRDA);
06627990 8845 /* set_regdom takes ownership of rd */
a05829a7 8846 rd = NULL;
d2372b31 8847 bad_reg:
b2e1b302 8848 kfree(rd);
a05829a7
JB
8849 out:
8850 rtnl_unlock();
d0e18f83 8851 return r;
b2e1b302 8852}
b6863036 8853#endif /* CONFIG_CFG80211_CRDA_SUPPORT */
b2e1b302 8854
83f5e2cf
JB
8855static int validate_scan_freqs(struct nlattr *freqs)
8856{
8857 struct nlattr *attr1, *attr2;
8858 int n_channels = 0, tmp1, tmp2;
8859
d7f13f74
SD
8860 nla_for_each_nested(attr1, freqs, tmp1)
8861 if (nla_len(attr1) != sizeof(u32))
8862 return 0;
8863
83f5e2cf
JB
8864 nla_for_each_nested(attr1, freqs, tmp1) {
8865 n_channels++;
8866 /*
8867 * Some hardware has a limited channel list for
8868 * scanning, and it is pretty much nonsensical
8869 * to scan for a channel twice, so disallow that
8870 * and don't require drivers to check that the
8871 * channel list they get isn't longer than what
8872 * they can scan, as long as they can scan all
8873 * the channels they registered at once.
8874 */
8875 nla_for_each_nested(attr2, freqs, tmp2)
8876 if (attr1 != attr2 &&
8877 nla_get_u32(attr1) == nla_get_u32(attr2))
8878 return 0;
8879 }
8880
8881 return n_channels;
8882}
8883
57fbcce3 8884static bool is_band_valid(struct wiphy *wiphy, enum nl80211_band b)
38de03d2 8885{
57fbcce3 8886 return b < NUM_NL80211_BANDS && wiphy->bands[b];
38de03d2
AS
8887}
8888
8889static int parse_bss_select(struct nlattr *nla, struct wiphy *wiphy,
8890 struct cfg80211_bss_selection *bss_select)
8891{
8892 struct nlattr *attr[NL80211_BSS_SELECT_ATTR_MAX + 1];
8893 struct nlattr *nest;
8894 int err;
8895 bool found = false;
8896 int i;
8897
8898 /* only process one nested attribute */
8899 nest = nla_data(nla);
8900 if (!nla_ok(nest, nla_len(nest)))
8901 return -EINVAL;
8902
8cb08174
JB
8903 err = nla_parse_nested_deprecated(attr, NL80211_BSS_SELECT_ATTR_MAX,
8904 nest, nl80211_bss_select_policy,
8905 NULL);
38de03d2
AS
8906 if (err)
8907 return err;
8908
8909 /* only one attribute may be given */
8910 for (i = 0; i <= NL80211_BSS_SELECT_ATTR_MAX; i++) {
8911 if (attr[i]) {
8912 if (found)
8913 return -EINVAL;
8914 found = true;
8915 }
8916 }
8917
8918 bss_select->behaviour = __NL80211_BSS_SELECT_ATTR_INVALID;
8919
8920 if (attr[NL80211_BSS_SELECT_ATTR_RSSI])
8921 bss_select->behaviour = NL80211_BSS_SELECT_ATTR_RSSI;
8922
8923 if (attr[NL80211_BSS_SELECT_ATTR_BAND_PREF]) {
8924 bss_select->behaviour = NL80211_BSS_SELECT_ATTR_BAND_PREF;
8925 bss_select->param.band_pref =
8926 nla_get_u32(attr[NL80211_BSS_SELECT_ATTR_BAND_PREF]);
8927 if (!is_band_valid(wiphy, bss_select->param.band_pref))
8928 return -EINVAL;
8929 }
8930
8931 if (attr[NL80211_BSS_SELECT_ATTR_RSSI_ADJUST]) {
8932 struct nl80211_bss_select_rssi_adjust *adj_param;
8933
8934 adj_param = nla_data(attr[NL80211_BSS_SELECT_ATTR_RSSI_ADJUST]);
8935 bss_select->behaviour = NL80211_BSS_SELECT_ATTR_RSSI_ADJUST;
8936 bss_select->param.adjust.band = adj_param->band;
8937 bss_select->param.adjust.delta = adj_param->delta;
8938 if (!is_band_valid(wiphy, bss_select->param.adjust.band))
8939 return -EINVAL;
8940 }
8941
8942 /* user-space did not provide behaviour attribute */
8943 if (bss_select->behaviour == __NL80211_BSS_SELECT_ATTR_INVALID)
8944 return -EINVAL;
8945
8946 if (!(wiphy->bss_select_support & BIT(bss_select->behaviour)))
8947 return -EINVAL;
8948
8949 return 0;
8950}
8951
9bb7e0f2
JB
8952int nl80211_parse_random_mac(struct nlattr **attrs,
8953 u8 *mac_addr, u8 *mac_addr_mask)
ad2b26ab
JB
8954{
8955 int i;
8956
8957 if (!attrs[NL80211_ATTR_MAC] && !attrs[NL80211_ATTR_MAC_MASK]) {
d2beae10
JP
8958 eth_zero_addr(mac_addr);
8959 eth_zero_addr(mac_addr_mask);
ad2b26ab
JB
8960 mac_addr[0] = 0x2;
8961 mac_addr_mask[0] = 0x3;
8962
8963 return 0;
8964 }
8965
8966 /* need both or none */
8967 if (!attrs[NL80211_ATTR_MAC] || !attrs[NL80211_ATTR_MAC_MASK])
8968 return -EINVAL;
8969
8970 memcpy(mac_addr, nla_data(attrs[NL80211_ATTR_MAC]), ETH_ALEN);
8971 memcpy(mac_addr_mask, nla_data(attrs[NL80211_ATTR_MAC_MASK]), ETH_ALEN);
8972
8973 /* don't allow or configure an mcast address */
8974 if (!is_multicast_ether_addr(mac_addr_mask) ||
8975 is_multicast_ether_addr(mac_addr))
8976 return -EINVAL;
8977
8978 /*
8979 * allow users to pass a MAC address that has bits set outside
8980 * of the mask, but don't bother drivers with having to deal
8981 * with such bits
8982 */
8983 for (i = 0; i < ETH_ALEN; i++)
8984 mac_addr[i] &= mac_addr_mask[i];
8985
8986 return 0;
8987}
8988
7b0a0e3c
JB
8989static bool cfg80211_off_channel_oper_allowed(struct wireless_dev *wdev,
8990 struct ieee80211_channel *chan)
34373d12 8991{
7b0a0e3c
JB
8992 unsigned int link_id;
8993 bool all_ok = true;
8994
34373d12
VT
8995 ASSERT_WDEV_LOCK(wdev);
8996
8997 if (!cfg80211_beaconing_iface_active(wdev))
8998 return true;
8999
7b0a0e3c
JB
9000 /*
9001 * FIXME: check if we have a free HW resource/link for chan
9002 *
9003 * This, as well as the FIXME below, requires knowing the link
9004 * capabilities of the hardware.
9005 */
9006
9007 /* we cannot leave radar channels */
9008 for_each_valid_link(wdev, link_id) {
9009 struct cfg80211_chan_def *chandef;
9010
9011 chandef = wdev_chandef(wdev, link_id);
f624bb6f 9012 if (!chandef || !chandef->chan)
7b0a0e3c
JB
9013 continue;
9014
9015 /*
9016 * FIXME: don't require all_ok, but rather check only the
9017 * correct HW resource/link onto which 'chan' falls,
9018 * as only that link leaves the channel for doing
9019 * the off-channel operation.
9020 */
9021
9022 if (chandef->chan->flags & IEEE80211_CHAN_RADAR)
9023 all_ok = false;
9024 }
9025
9026 if (all_ok)
34373d12
VT
9027 return true;
9028
9029 return regulatory_pre_cac_allowed(wdev->wiphy);
9030}
9031
db0a4ad8
JB
9032static bool nl80211_check_scan_feat(struct wiphy *wiphy, u32 flags, u32 flag,
9033 enum nl80211_ext_feature_index feat)
9034{
9035 if (!(flags & flag))
9036 return true;
9037 if (wiphy_ext_feature_isset(wiphy, feat))
9038 return true;
9039 return false;
9040}
9041
2d23d073
RZ
9042static int
9043nl80211_check_scan_flags(struct wiphy *wiphy, struct wireless_dev *wdev,
9044 void *request, struct nlattr **attrs,
9045 bool is_sched_scan)
9046{
9047 u8 *mac_addr, *mac_addr_mask;
9048 u32 *flags;
9049 enum nl80211_feature_flags randomness_flag;
9050
9051 if (!attrs[NL80211_ATTR_SCAN_FLAGS])
9052 return 0;
9053
9054 if (is_sched_scan) {
9055 struct cfg80211_sched_scan_request *req = request;
9056
9057 randomness_flag = wdev ?
9058 NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR :
9059 NL80211_FEATURE_ND_RANDOM_MAC_ADDR;
9060 flags = &req->flags;
9061 mac_addr = req->mac_addr;
9062 mac_addr_mask = req->mac_addr_mask;
9063 } else {
9064 struct cfg80211_scan_request *req = request;
9065
9066 randomness_flag = NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
9067 flags = &req->flags;
9068 mac_addr = req->mac_addr;
9069 mac_addr_mask = req->mac_addr_mask;
9070 }
9071
9072 *flags = nla_get_u32(attrs[NL80211_ATTR_SCAN_FLAGS]);
9073
5037a009
SD
9074 if (((*flags & NL80211_SCAN_FLAG_LOW_PRIORITY) &&
9075 !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) ||
db0a4ad8
JB
9076 !nl80211_check_scan_feat(wiphy, *flags,
9077 NL80211_SCAN_FLAG_LOW_SPAN,
9078 NL80211_EXT_FEATURE_LOW_SPAN_SCAN) ||
9079 !nl80211_check_scan_feat(wiphy, *flags,
9080 NL80211_SCAN_FLAG_LOW_POWER,
9081 NL80211_EXT_FEATURE_LOW_POWER_SCAN) ||
9082 !nl80211_check_scan_feat(wiphy, *flags,
9083 NL80211_SCAN_FLAG_HIGH_ACCURACY,
9084 NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN) ||
9085 !nl80211_check_scan_feat(wiphy, *flags,
9086 NL80211_SCAN_FLAG_FILS_MAX_CHANNEL_TIME,
9087 NL80211_EXT_FEATURE_FILS_MAX_CHANNEL_TIME) ||
9088 !nl80211_check_scan_feat(wiphy, *flags,
9089 NL80211_SCAN_FLAG_ACCEPT_BCAST_PROBE_RESP,
9090 NL80211_EXT_FEATURE_ACCEPT_BCAST_PROBE_RESP) ||
9091 !nl80211_check_scan_feat(wiphy, *flags,
9092 NL80211_SCAN_FLAG_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION,
9093 NL80211_EXT_FEATURE_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION) ||
9094 !nl80211_check_scan_feat(wiphy, *flags,
9095 NL80211_SCAN_FLAG_OCE_PROBE_REQ_HIGH_TX_RATE,
2e076f19
JB
9096 NL80211_EXT_FEATURE_OCE_PROBE_REQ_HIGH_TX_RATE) ||
9097 !nl80211_check_scan_feat(wiphy, *flags,
9098 NL80211_SCAN_FLAG_RANDOM_SN,
9099 NL80211_EXT_FEATURE_SCAN_RANDOM_SN) ||
9100 !nl80211_check_scan_feat(wiphy, *flags,
9101 NL80211_SCAN_FLAG_MIN_PREQ_CONTENT,
9102 NL80211_EXT_FEATURE_SCAN_MIN_PREQ_CONTENT))
2d23d073
RZ
9103 return -EOPNOTSUPP;
9104
9105 if (*flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
9106 int err;
9107
9108 if (!(wiphy->features & randomness_flag) ||
7b0a0e3c 9109 (wdev && wdev->connected))
2d23d073
RZ
9110 return -EOPNOTSUPP;
9111
9112 err = nl80211_parse_random_mac(attrs, mac_addr, mac_addr_mask);
9113 if (err)
9114 return err;
9115 }
9116
2d23d073
RZ
9117 return 0;
9118}
9119
2a519311
JB
9120static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
9121{
4c476991 9122 struct cfg80211_registered_device *rdev = info->user_ptr[0];
fd014284 9123 struct wireless_dev *wdev = info->user_ptr[1];
2a519311 9124 struct cfg80211_scan_request *request;
2032f3b2
TP
9125 struct nlattr *scan_freqs = NULL;
9126 bool scan_freqs_khz = false;
2a519311
JB
9127 struct nlattr *attr;
9128 struct wiphy *wiphy;
83f5e2cf 9129 int err, tmp, n_ssids = 0, n_channels, i;
14e05beb 9130 size_t ie_len, size;
2a519311 9131
79c97e97 9132 wiphy = &rdev->wiphy;
2a519311 9133
cb3b7d87
AB
9134 if (wdev->iftype == NL80211_IFTYPE_NAN)
9135 return -EOPNOTSUPP;
9136
4c476991
JB
9137 if (!rdev->ops->scan)
9138 return -EOPNOTSUPP;
2a519311 9139
83286856
CJ
9140 if (rdev->scan_req || rdev->scan_msg)
9141 return -EBUSY;
2a519311 9142
2032f3b2
TP
9143 if (info->attrs[NL80211_ATTR_SCAN_FREQ_KHZ]) {
9144 if (!wiphy_ext_feature_isset(wiphy,
9145 NL80211_EXT_FEATURE_SCAN_FREQ_KHZ))
9146 return -EOPNOTSUPP;
9147 scan_freqs = info->attrs[NL80211_ATTR_SCAN_FREQ_KHZ];
9148 scan_freqs_khz = true;
9149 } else if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES])
9150 scan_freqs = info->attrs[NL80211_ATTR_SCAN_FREQUENCIES];
9151
9152 if (scan_freqs) {
9153 n_channels = validate_scan_freqs(scan_freqs);
83286856
CJ
9154 if (!n_channels)
9155 return -EINVAL;
2a519311 9156 } else {
bdfbec2d 9157 n_channels = ieee80211_get_num_supported_channels(wiphy);
2a519311
JB
9158 }
9159
9160 if (info->attrs[NL80211_ATTR_SCAN_SSIDS])
9161 nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp)
9162 n_ssids++;
9163
83286856
CJ
9164 if (n_ssids > wiphy->max_scan_ssids)
9165 return -EINVAL;
2a519311 9166
70692ad2
JM
9167 if (info->attrs[NL80211_ATTR_IE])
9168 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
9169 else
9170 ie_len = 0;
9171
83286856
CJ
9172 if (ie_len > wiphy->max_scan_ie_len)
9173 return -EINVAL;
18a83659 9174
14e05beb
JK
9175 size = struct_size(request, channels, n_channels);
9176 size = size_add(size, array_size(sizeof(*request->ssids), n_ssids));
9177 size = size_add(size, ie_len);
9178 request = kzalloc(size, GFP_KERNEL);
83286856
CJ
9179 if (!request)
9180 return -ENOMEM;
2a519311 9181
2a519311 9182 if (n_ssids)
5ba63533 9183 request->ssids = (void *)&request->channels[n_channels];
2a519311 9184 request->n_ssids = n_ssids;
70692ad2 9185 if (ie_len) {
13874e4b 9186 if (n_ssids)
70692ad2
JM
9187 request->ie = (void *)(request->ssids + n_ssids);
9188 else
9189 request->ie = (void *)(request->channels + n_channels);
9190 }
2a519311 9191
584991dc 9192 i = 0;
2032f3b2 9193 if (scan_freqs) {
2a519311 9194 /* user specified, bail out if channel not found */
2032f3b2 9195 nla_for_each_nested(attr, scan_freqs, tmp) {
584991dc 9196 struct ieee80211_channel *chan;
2032f3b2 9197 int freq = nla_get_u32(attr);
584991dc 9198
2032f3b2
TP
9199 if (!scan_freqs_khz)
9200 freq = MHZ_TO_KHZ(freq);
584991dc 9201
2032f3b2 9202 chan = ieee80211_get_channel_khz(wiphy, freq);
584991dc 9203 if (!chan) {
2a519311
JB
9204 err = -EINVAL;
9205 goto out_free;
9206 }
584991dc
JB
9207
9208 /* ignore disabled channels */
9209 if (chan->flags & IEEE80211_CHAN_DISABLED)
9210 continue;
9211
9212 request->channels[i] = chan;
2a519311
JB
9213 i++;
9214 }
9215 } else {
57fbcce3 9216 enum nl80211_band band;
34850ab2 9217
2a519311 9218 /* all channels */
57fbcce3 9219 for (band = 0; band < NUM_NL80211_BANDS; band++) {
2a519311 9220 int j;
7a087e74 9221
2a519311
JB
9222 if (!wiphy->bands[band])
9223 continue;
9224 for (j = 0; j < wiphy->bands[band]->n_channels; j++) {
584991dc
JB
9225 struct ieee80211_channel *chan;
9226
9227 chan = &wiphy->bands[band]->channels[j];
9228
9229 if (chan->flags & IEEE80211_CHAN_DISABLED)
9230 continue;
9231
9232 request->channels[i] = chan;
2a519311
JB
9233 i++;
9234 }
9235 }
9236 }
9237
584991dc
JB
9238 if (!i) {
9239 err = -EINVAL;
9240 goto out_free;
9241 }
9242
9243 request->n_channels = i;
9244
34373d12 9245 wdev_lock(wdev);
7b0a0e3c
JB
9246 for (i = 0; i < request->n_channels; i++) {
9247 struct ieee80211_channel *chan = request->channels[i];
34373d12 9248
7b0a0e3c
JB
9249 /* if we can go off-channel to the target channel we're good */
9250 if (cfg80211_off_channel_oper_allowed(wdev, chan))
9251 continue;
34373d12 9252
7b0a0e3c 9253 if (!cfg80211_wdev_on_sub_chan(wdev, chan, true)) {
34373d12
VT
9254 wdev_unlock(wdev);
9255 err = -EBUSY;
9256 goto out_free;
9257 }
9258 }
9259 wdev_unlock(wdev);
9260
2a519311 9261 i = 0;
13874e4b 9262 if (n_ssids) {
2a519311 9263 nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) {
57a27e1d 9264 if (nla_len(attr) > IEEE80211_MAX_SSID_LEN) {
2a519311
JB
9265 err = -EINVAL;
9266 goto out_free;
9267 }
57a27e1d 9268 request->ssids[i].ssid_len = nla_len(attr);
2a519311 9269 memcpy(request->ssids[i].ssid, nla_data(attr), nla_len(attr));
2a519311
JB
9270 i++;
9271 }
9272 }
9273
70692ad2
JM
9274 if (info->attrs[NL80211_ATTR_IE]) {
9275 request->ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
de95a54b
JB
9276 memcpy((void *)request->ie,
9277 nla_data(info->attrs[NL80211_ATTR_IE]),
70692ad2
JM
9278 request->ie_len);
9279 }
9280
57fbcce3 9281 for (i = 0; i < NUM_NL80211_BANDS; i++)
a401d2bb
JB
9282 if (wiphy->bands[i])
9283 request->rates[i] =
9284 (1 << wiphy->bands[i]->n_bitrates) - 1;
34850ab2
JB
9285
9286 if (info->attrs[NL80211_ATTR_SCAN_SUPP_RATES]) {
9287 nla_for_each_nested(attr,
9288 info->attrs[NL80211_ATTR_SCAN_SUPP_RATES],
9289 tmp) {
57fbcce3 9290 enum nl80211_band band = nla_type(attr);
34850ab2 9291
57fbcce3 9292 if (band < 0 || band >= NUM_NL80211_BANDS) {
34850ab2
JB
9293 err = -EINVAL;
9294 goto out_free;
9295 }
1b09cd82
FF
9296
9297 if (!wiphy->bands[band])
9298 continue;
9299
34850ab2
JB
9300 err = ieee80211_get_ratemask(wiphy->bands[band],
9301 nla_data(attr),
9302 nla_len(attr),
9303 &request->rates[band]);
9304 if (err)
9305 goto out_free;
9306 }
9307 }
9308
1d76250b 9309 if (info->attrs[NL80211_ATTR_MEASUREMENT_DURATION]) {
1d76250b
AS
9310 request->duration =
9311 nla_get_u16(info->attrs[NL80211_ATTR_MEASUREMENT_DURATION]);
9312 request->duration_mandatory =
9313 nla_get_flag(info->attrs[NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY]);
9314 }
9315
2d23d073
RZ
9316 err = nl80211_check_scan_flags(wiphy, wdev, request, info->attrs,
9317 false);
9318 if (err)
9319 goto out_free;
ed473771 9320
e9f935e3
RM
9321 request->no_cck =
9322 nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]);
9323
2fa436b3
VK
9324 /* Initial implementation used NL80211_ATTR_MAC to set the specific
9325 * BSSID to scan for. This was problematic because that same attribute
9326 * was already used for another purpose (local random MAC address). The
9327 * NL80211_ATTR_BSSID attribute was added to fix this. For backwards
9328 * compatibility with older userspace components, also use the
9329 * NL80211_ATTR_MAC value here if it can be determined to be used for
9330 * the specific BSSID use case instead of the random MAC address
9331 * (NL80211_ATTR_SCAN_FLAGS is used to enable random MAC address use).
9332 */
9333 if (info->attrs[NL80211_ATTR_BSSID])
9334 memcpy(request->bssid,
9335 nla_data(info->attrs[NL80211_ATTR_BSSID]), ETH_ALEN);
9336 else if (!(request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) &&
9337 info->attrs[NL80211_ATTR_MAC])
818965d3
JM
9338 memcpy(request->bssid, nla_data(info->attrs[NL80211_ATTR_MAC]),
9339 ETH_ALEN);
9340 else
9341 eth_broadcast_addr(request->bssid);
9342
fd014284 9343 request->wdev = wdev;
79c97e97 9344 request->wiphy = &rdev->wiphy;
15d6030b 9345 request->scan_start = jiffies;
2a519311 9346
79c97e97 9347 rdev->scan_req = request;
c8cb5b85 9348 err = cfg80211_scan(rdev);
2a519311 9349
504776be
CJ
9350 if (err)
9351 goto out_free;
9352
9353 nl80211_send_scan_start(rdev, wdev);
1160dfa1 9354 dev_hold(wdev->netdev);
504776be
CJ
9355
9356 return 0;
9357
2a519311 9358 out_free:
504776be
CJ
9359 rdev->scan_req = NULL;
9360 kfree(request);
3b85875a 9361
2a519311
JB
9362 return err;
9363}
9364
91d3ab46
VK
9365static int nl80211_abort_scan(struct sk_buff *skb, struct genl_info *info)
9366{
9367 struct cfg80211_registered_device *rdev = info->user_ptr[0];
9368 struct wireless_dev *wdev = info->user_ptr[1];
9369
9370 if (!rdev->ops->abort_scan)
9371 return -EOPNOTSUPP;
9372
9373 if (rdev->scan_msg)
9374 return 0;
9375
9376 if (!rdev->scan_req)
9377 return -ENOENT;
9378
9379 rdev_abort_scan(rdev, wdev);
9380 return 0;
9381}
9382
3b06d277
AS
9383static int
9384nl80211_parse_sched_scan_plans(struct wiphy *wiphy, int n_plans,
9385 struct cfg80211_sched_scan_request *request,
9386 struct nlattr **attrs)
9387{
9388 int tmp, err, i = 0;
9389 struct nlattr *attr;
9390
9391 if (!attrs[NL80211_ATTR_SCHED_SCAN_PLANS]) {
9392 u32 interval;
9393
9394 /*
9395 * If scan plans are not specified,
5a88de53 9396 * %NL80211_ATTR_SCHED_SCAN_INTERVAL will be specified. In this
3b06d277
AS
9397 * case one scan plan will be set with the specified scan
9398 * interval and infinite number of iterations.
9399 */
3b06d277
AS
9400 interval = nla_get_u32(attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL]);
9401 if (!interval)
9402 return -EINVAL;
9403
9404 request->scan_plans[0].interval =
9405 DIV_ROUND_UP(interval, MSEC_PER_SEC);
9406 if (!request->scan_plans[0].interval)
9407 return -EINVAL;
9408
9409 if (request->scan_plans[0].interval >
9410 wiphy->max_sched_scan_plan_interval)
9411 request->scan_plans[0].interval =
9412 wiphy->max_sched_scan_plan_interval;
9413
9414 return 0;
9415 }
9416
9417 nla_for_each_nested(attr, attrs[NL80211_ATTR_SCHED_SCAN_PLANS], tmp) {
9418 struct nlattr *plan[NL80211_SCHED_SCAN_PLAN_MAX + 1];
9419
9420 if (WARN_ON(i >= n_plans))
9421 return -EINVAL;
9422
8cb08174
JB
9423 err = nla_parse_nested_deprecated(plan,
9424 NL80211_SCHED_SCAN_PLAN_MAX,
9425 attr, nl80211_plan_policy,
9426 NULL);
3b06d277
AS
9427 if (err)
9428 return err;
9429
9430 if (!plan[NL80211_SCHED_SCAN_PLAN_INTERVAL])
9431 return -EINVAL;
9432
9433 request->scan_plans[i].interval =
9434 nla_get_u32(plan[NL80211_SCHED_SCAN_PLAN_INTERVAL]);
9435 if (!request->scan_plans[i].interval ||
9436 request->scan_plans[i].interval >
9437 wiphy->max_sched_scan_plan_interval)
9438 return -EINVAL;
9439
9440 if (plan[NL80211_SCHED_SCAN_PLAN_ITERATIONS]) {
9441 request->scan_plans[i].iterations =
9442 nla_get_u32(plan[NL80211_SCHED_SCAN_PLAN_ITERATIONS]);
9443 if (!request->scan_plans[i].iterations ||
9444 (request->scan_plans[i].iterations >
9445 wiphy->max_sched_scan_plan_iterations))
9446 return -EINVAL;
9447 } else if (i < n_plans - 1) {
9448 /*
9449 * All scan plans but the last one must specify
9450 * a finite number of iterations
9451 */
9452 return -EINVAL;
9453 }
9454
9455 i++;
9456 }
9457
9458 /*
9459 * The last scan plan must not specify the number of
9460 * iterations, it is supposed to run infinitely
9461 */
9462 if (request->scan_plans[n_plans - 1].iterations)
9463 return -EINVAL;
9464
9465 return 0;
9466}
9467
1e1b11b6 9468static int
9469nl80211_parse_sched_scan_per_band_rssi(struct wiphy *wiphy,
9470 struct cfg80211_match_set *match_sets,
9471 struct nlattr *tb_band_rssi,
9472 s32 rssi_thold)
9473{
9474 struct nlattr *attr;
9475 int i, tmp, ret = 0;
9476
9477 if (!wiphy_ext_feature_isset(wiphy,
9478 NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD)) {
9479 if (tb_band_rssi)
9480 ret = -EOPNOTSUPP;
9481 else
9482 for (i = 0; i < NUM_NL80211_BANDS; i++)
9483 match_sets->per_band_rssi_thold[i] =
9484 NL80211_SCAN_RSSI_THOLD_OFF;
9485 return ret;
9486 }
9487
9488 for (i = 0; i < NUM_NL80211_BANDS; i++)
9489 match_sets->per_band_rssi_thold[i] = rssi_thold;
9490
9491 nla_for_each_nested(attr, tb_band_rssi, tmp) {
9492 enum nl80211_band band = nla_type(attr);
9493
9494 if (band < 0 || band >= NUM_NL80211_BANDS)
9495 return -EINVAL;
9496
9497 match_sets->per_band_rssi_thold[band] = nla_get_s32(attr);
9498 }
9499
9500 return 0;
9501}
9502
256da02d 9503static struct cfg80211_sched_scan_request *
ad2b26ab 9504nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev,
aad1e812 9505 struct nlattr **attrs, int max_match_sets)
807f8a8c
LC
9506{
9507 struct cfg80211_sched_scan_request *request;
807f8a8c 9508 struct nlattr *attr;
3b06d277 9509 int err, tmp, n_ssids = 0, n_match_sets = 0, n_channels, i, n_plans = 0;
57fbcce3 9510 enum nl80211_band band;
14e05beb 9511 size_t ie_len, size;
a1f1c21c 9512 struct nlattr *tb[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1];
ea73cbce 9513 s32 default_match_rssi = NL80211_SCAN_RSSI_THOLD_OFF;
807f8a8c 9514
256da02d 9515 if (attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
807f8a8c 9516 n_channels = validate_scan_freqs(
256da02d 9517 attrs[NL80211_ATTR_SCAN_FREQUENCIES]);
807f8a8c 9518 if (!n_channels)
256da02d 9519 return ERR_PTR(-EINVAL);
807f8a8c 9520 } else {
bdfbec2d 9521 n_channels = ieee80211_get_num_supported_channels(wiphy);
807f8a8c
LC
9522 }
9523
256da02d
LC
9524 if (attrs[NL80211_ATTR_SCAN_SSIDS])
9525 nla_for_each_nested(attr, attrs[NL80211_ATTR_SCAN_SSIDS],
807f8a8c
LC
9526 tmp)
9527 n_ssids++;
9528
93b6aa69 9529 if (n_ssids > wiphy->max_sched_scan_ssids)
256da02d 9530 return ERR_PTR(-EINVAL);
807f8a8c 9531
ea73cbce
JB
9532 /*
9533 * First, count the number of 'real' matchsets. Due to an issue with
9534 * the old implementation, matchsets containing only the RSSI attribute
9535 * (NL80211_SCHED_SCAN_MATCH_ATTR_RSSI) are considered as the 'default'
9536 * RSSI for all matchsets, rather than their own matchset for reporting
9537 * all APs with a strong RSSI. This is needed to be compatible with
9538 * older userspace that treated a matchset with only the RSSI as the
9539 * global RSSI for all other matchsets - if there are other matchsets.
9540 */
256da02d 9541 if (attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) {
a1f1c21c 9542 nla_for_each_nested(attr,
256da02d 9543 attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
ea73cbce
JB
9544 tmp) {
9545 struct nlattr *rssi;
9546
8cb08174
JB
9547 err = nla_parse_nested_deprecated(tb,
9548 NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
9549 attr,
9550 nl80211_match_policy,
9551 NULL);
ea73cbce 9552 if (err)
256da02d 9553 return ERR_PTR(err);
3007e352
AVS
9554
9555 /* SSID and BSSID are mutually exclusive */
9556 if (tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID] &&
9557 tb[NL80211_SCHED_SCAN_MATCH_ATTR_BSSID])
9558 return ERR_PTR(-EINVAL);
9559
ea73cbce 9560 /* add other standalone attributes here */
3007e352
AVS
9561 if (tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID] ||
9562 tb[NL80211_SCHED_SCAN_MATCH_ATTR_BSSID]) {
ea73cbce
JB
9563 n_match_sets++;
9564 continue;
9565 }
9566 rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI];
9567 if (rssi)
9568 default_match_rssi = nla_get_s32(rssi);
9569 }
9570 }
9571
9572 /* However, if there's no other matchset, add the RSSI one */
9573 if (!n_match_sets && default_match_rssi != NL80211_SCAN_RSSI_THOLD_OFF)
9574 n_match_sets = 1;
a1f1c21c 9575
aad1e812 9576 if (n_match_sets > max_match_sets)
256da02d 9577 return ERR_PTR(-EINVAL);
a1f1c21c 9578
256da02d
LC
9579 if (attrs[NL80211_ATTR_IE])
9580 ie_len = nla_len(attrs[NL80211_ATTR_IE]);
807f8a8c
LC
9581 else
9582 ie_len = 0;
9583
5a865bad 9584 if (ie_len > wiphy->max_sched_scan_ie_len)
256da02d 9585 return ERR_PTR(-EINVAL);
c10841ca 9586
3b06d277
AS
9587 if (attrs[NL80211_ATTR_SCHED_SCAN_PLANS]) {
9588 /*
9589 * NL80211_ATTR_SCHED_SCAN_INTERVAL must not be specified since
9590 * each scan plan already specifies its own interval
9591 */
9592 if (attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL])
9593 return ERR_PTR(-EINVAL);
9594
9595 nla_for_each_nested(attr,
9596 attrs[NL80211_ATTR_SCHED_SCAN_PLANS], tmp)
9597 n_plans++;
9598 } else {
9599 /*
9600 * The scan interval attribute is kept for backward
9601 * compatibility. If no scan plans are specified and sched scan
9602 * interval is specified, one scan plan will be set with this
9603 * scan interval and infinite number of iterations.
9604 */
9605 if (!attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL])
9606 return ERR_PTR(-EINVAL);
9607
9608 n_plans = 1;
9609 }
9610
9611 if (!n_plans || n_plans > wiphy->max_sched_scan_plans)
9612 return ERR_PTR(-EINVAL);
9613
bf95ecdb 9614 if (!wiphy_ext_feature_isset(
9615 wiphy, NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI) &&
9616 (attrs[NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI] ||
9617 attrs[NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST]))
9618 return ERR_PTR(-EINVAL);
9619
14e05beb
JK
9620 size = struct_size(request, channels, n_channels);
9621 size = size_add(size, array_size(sizeof(*request->ssids), n_ssids));
9622 size = size_add(size, array_size(sizeof(*request->match_sets),
9623 n_match_sets));
9624 size = size_add(size, array_size(sizeof(*request->scan_plans),
9625 n_plans));
9626 size = size_add(size, ie_len);
9627 request = kzalloc(size, GFP_KERNEL);
256da02d
LC
9628 if (!request)
9629 return ERR_PTR(-ENOMEM);
807f8a8c
LC
9630
9631 if (n_ssids)
9632 request->ssids = (void *)&request->channels[n_channels];
9633 request->n_ssids = n_ssids;
9634 if (ie_len) {
13874e4b 9635 if (n_ssids)
807f8a8c
LC
9636 request->ie = (void *)(request->ssids + n_ssids);
9637 else
9638 request->ie = (void *)(request->channels + n_channels);
9639 }
9640
a1f1c21c
LC
9641 if (n_match_sets) {
9642 if (request->ie)
9643 request->match_sets = (void *)(request->ie + ie_len);
13874e4b 9644 else if (n_ssids)
a1f1c21c
LC
9645 request->match_sets =
9646 (void *)(request->ssids + n_ssids);
9647 else
9648 request->match_sets =
9649 (void *)(request->channels + n_channels);
9650 }
9651 request->n_match_sets = n_match_sets;
9652
3b06d277
AS
9653 if (n_match_sets)
9654 request->scan_plans = (void *)(request->match_sets +
9655 n_match_sets);
9656 else if (request->ie)
9657 request->scan_plans = (void *)(request->ie + ie_len);
9658 else if (n_ssids)
9659 request->scan_plans = (void *)(request->ssids + n_ssids);
9660 else
9661 request->scan_plans = (void *)(request->channels + n_channels);
9662
9663 request->n_scan_plans = n_plans;
9664
807f8a8c 9665 i = 0;
256da02d 9666 if (attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
807f8a8c
LC
9667 /* user specified, bail out if channel not found */
9668 nla_for_each_nested(attr,
256da02d 9669 attrs[NL80211_ATTR_SCAN_FREQUENCIES],
807f8a8c
LC
9670 tmp) {
9671 struct ieee80211_channel *chan;
9672
9673 chan = ieee80211_get_channel(wiphy, nla_get_u32(attr));
9674
9675 if (!chan) {
9676 err = -EINVAL;
9677 goto out_free;
9678 }
9679
9680 /* ignore disabled channels */
9681 if (chan->flags & IEEE80211_CHAN_DISABLED)
9682 continue;
9683
9684 request->channels[i] = chan;
9685 i++;
9686 }
9687 } else {
9688 /* all channels */
57fbcce3 9689 for (band = 0; band < NUM_NL80211_BANDS; band++) {
807f8a8c 9690 int j;
7a087e74 9691
807f8a8c
LC
9692 if (!wiphy->bands[band])
9693 continue;
9694 for (j = 0; j < wiphy->bands[band]->n_channels; j++) {
9695 struct ieee80211_channel *chan;
9696
9697 chan = &wiphy->bands[band]->channels[j];
9698
9699 if (chan->flags & IEEE80211_CHAN_DISABLED)
9700 continue;
9701
9702 request->channels[i] = chan;
9703 i++;
9704 }
9705 }
9706 }
9707
9708 if (!i) {
9709 err = -EINVAL;
9710 goto out_free;
9711 }
9712
9713 request->n_channels = i;
9714
9715 i = 0;
13874e4b 9716 if (n_ssids) {
256da02d 9717 nla_for_each_nested(attr, attrs[NL80211_ATTR_SCAN_SSIDS],
807f8a8c 9718 tmp) {
57a27e1d 9719 if (nla_len(attr) > IEEE80211_MAX_SSID_LEN) {
807f8a8c
LC
9720 err = -EINVAL;
9721 goto out_free;
9722 }
57a27e1d 9723 request->ssids[i].ssid_len = nla_len(attr);
807f8a8c
LC
9724 memcpy(request->ssids[i].ssid, nla_data(attr),
9725 nla_len(attr));
807f8a8c
LC
9726 i++;
9727 }
9728 }
9729
a1f1c21c 9730 i = 0;
256da02d 9731 if (attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) {
a1f1c21c 9732 nla_for_each_nested(attr,
256da02d 9733 attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
a1f1c21c 9734 tmp) {
3007e352 9735 struct nlattr *ssid, *bssid, *rssi;
a1f1c21c 9736
8cb08174
JB
9737 err = nla_parse_nested_deprecated(tb,
9738 NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
9739 attr,
9740 nl80211_match_policy,
9741 NULL);
ae811e21
JB
9742 if (err)
9743 goto out_free;
4a4ab0d7 9744 ssid = tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID];
3007e352 9745 bssid = tb[NL80211_SCHED_SCAN_MATCH_ATTR_BSSID];
d39f3b4f
JB
9746
9747 if (!ssid && !bssid) {
9748 i++;
9749 continue;
9750 }
9751
9752 if (WARN_ON(i >= n_match_sets)) {
9753 /* this indicates a programming error,
9754 * the loop above should have verified
9755 * things properly
9756 */
9757 err = -EINVAL;
9758 goto out_free;
9759 }
9760
9761 if (ssid) {
d39f3b4f
JB
9762 memcpy(request->match_sets[i].ssid.ssid,
9763 nla_data(ssid), nla_len(ssid));
9764 request->match_sets[i].ssid.ssid_len =
9765 nla_len(ssid);
9766 }
cb9abd48 9767 if (bssid)
d39f3b4f
JB
9768 memcpy(request->match_sets[i].bssid,
9769 nla_data(bssid), ETH_ALEN);
3007e352 9770
d39f3b4f
JB
9771 /* special attribute - old implementation w/a */
9772 request->match_sets[i].rssi_thold = default_match_rssi;
9773 rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI];
9774 if (rssi)
ea73cbce 9775 request->match_sets[i].rssi_thold =
d39f3b4f 9776 nla_get_s32(rssi);
1e1b11b6 9777
9778 /* Parse per band RSSI attribute */
9779 err = nl80211_parse_sched_scan_per_band_rssi(wiphy,
9780 &request->match_sets[i],
9781 tb[NL80211_SCHED_SCAN_MATCH_PER_BAND_RSSI],
9782 request->match_sets[i].rssi_thold);
9783 if (err)
9784 goto out_free;
9785
a1f1c21c
LC
9786 i++;
9787 }
ea73cbce
JB
9788
9789 /* there was no other matchset, so the RSSI one is alone */
f89f46cf 9790 if (i == 0 && n_match_sets)
ea73cbce
JB
9791 request->match_sets[0].rssi_thold = default_match_rssi;
9792
9793 request->min_rssi_thold = INT_MAX;
9794 for (i = 0; i < n_match_sets; i++)
9795 request->min_rssi_thold =
9796 min(request->match_sets[i].rssi_thold,
9797 request->min_rssi_thold);
9798 } else {
9799 request->min_rssi_thold = NL80211_SCAN_RSSI_THOLD_OFF;
a1f1c21c
LC
9800 }
9801
9900e484
JB
9802 if (ie_len) {
9803 request->ie_len = ie_len;
807f8a8c 9804 memcpy((void *)request->ie,
256da02d 9805 nla_data(attrs[NL80211_ATTR_IE]),
807f8a8c
LC
9806 request->ie_len);
9807 }
9808
2d23d073
RZ
9809 err = nl80211_check_scan_flags(wiphy, wdev, request, attrs, true);
9810 if (err)
9811 goto out_free;
ed473771 9812
9c748934
LC
9813 if (attrs[NL80211_ATTR_SCHED_SCAN_DELAY])
9814 request->delay =
9815 nla_get_u32(attrs[NL80211_ATTR_SCHED_SCAN_DELAY]);
9816
bf95ecdb 9817 if (attrs[NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI]) {
9818 request->relative_rssi = nla_get_s8(
9819 attrs[NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI]);
9820 request->relative_rssi_set = true;
9821 }
9822
9823 if (request->relative_rssi_set &&
9824 attrs[NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST]) {
9825 struct nl80211_bss_select_rssi_adjust *rssi_adjust;
9826
9827 rssi_adjust = nla_data(
9828 attrs[NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST]);
9829 request->rssi_adjust.band = rssi_adjust->band;
9830 request->rssi_adjust.delta = rssi_adjust->delta;
9831 if (!is_band_valid(wiphy, request->rssi_adjust.band)) {
9832 err = -EINVAL;
9833 goto out_free;
9834 }
9835 }
9836
3b06d277
AS
9837 err = nl80211_parse_sched_scan_plans(wiphy, n_plans, request, attrs);
9838 if (err)
9839 goto out_free;
9840
15d6030b 9841 request->scan_start = jiffies;
807f8a8c 9842
256da02d 9843 return request;
807f8a8c
LC
9844
9845out_free:
9846 kfree(request);
256da02d
LC
9847 return ERR_PTR(err);
9848}
9849
9850static int nl80211_start_sched_scan(struct sk_buff *skb,
9851 struct genl_info *info)
9852{
9853 struct cfg80211_registered_device *rdev = info->user_ptr[0];
9854 struct net_device *dev = info->user_ptr[1];
ad2b26ab 9855 struct wireless_dev *wdev = dev->ieee80211_ptr;
31a60ed1 9856 struct cfg80211_sched_scan_request *sched_scan_req;
ca986ad9 9857 bool want_multi;
256da02d
LC
9858 int err;
9859
ca986ad9 9860 if (!rdev->wiphy.max_sched_scan_reqs || !rdev->ops->sched_scan_start)
256da02d
LC
9861 return -EOPNOTSUPP;
9862
ca986ad9
AVS
9863 want_multi = info->attrs[NL80211_ATTR_SCHED_SCAN_MULTI];
9864 err = cfg80211_sched_scan_req_possible(rdev, want_multi);
9865 if (err)
9866 return err;
256da02d 9867
31a60ed1 9868 sched_scan_req = nl80211_parse_sched_scan(&rdev->wiphy, wdev,
aad1e812
AVS
9869 info->attrs,
9870 rdev->wiphy.max_match_sets);
31a60ed1
JR
9871
9872 err = PTR_ERR_OR_ZERO(sched_scan_req);
256da02d
LC
9873 if (err)
9874 goto out_err;
9875
ca986ad9
AVS
9876 /* leave request id zero for legacy request
9877 * or if driver does not support multi-scheduled scan
9878 */
2fd351a8
DK
9879 if (want_multi && rdev->wiphy.max_sched_scan_reqs > 1)
9880 sched_scan_req->reqid = cfg80211_assign_cookie(rdev);
ca986ad9 9881
31a60ed1 9882 err = rdev_sched_scan_start(rdev, dev, sched_scan_req);
256da02d
LC
9883 if (err)
9884 goto out_free;
9885
31a60ed1
JR
9886 sched_scan_req->dev = dev;
9887 sched_scan_req->wiphy = &rdev->wiphy;
9888
93a1e86c
JR
9889 if (info->attrs[NL80211_ATTR_SOCKET_OWNER])
9890 sched_scan_req->owner_nlportid = info->snd_portid;
9891
ca986ad9 9892 cfg80211_add_sched_scan_req(rdev, sched_scan_req);
256da02d 9893
96b08fd6 9894 nl80211_send_sched_scan(sched_scan_req, NL80211_CMD_START_SCHED_SCAN);
256da02d
LC
9895 return 0;
9896
9897out_free:
31a60ed1 9898 kfree(sched_scan_req);
256da02d 9899out_err:
807f8a8c
LC
9900 return err;
9901}
9902
9903static int nl80211_stop_sched_scan(struct sk_buff *skb,
9904 struct genl_info *info)
9905{
ca986ad9 9906 struct cfg80211_sched_scan_request *req;
807f8a8c 9907 struct cfg80211_registered_device *rdev = info->user_ptr[0];
ca986ad9 9908 u64 cookie;
807f8a8c 9909
ca986ad9 9910 if (!rdev->wiphy.max_sched_scan_reqs || !rdev->ops->sched_scan_stop)
807f8a8c
LC
9911 return -EOPNOTSUPP;
9912
ca986ad9
AVS
9913 if (info->attrs[NL80211_ATTR_COOKIE]) {
9914 cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);
9915 return __cfg80211_stop_sched_scan(rdev, cookie, false);
9916 }
9917
9918 req = list_first_or_null_rcu(&rdev->sched_scan_req_list,
9919 struct cfg80211_sched_scan_request,
9920 list);
9921 if (!req || req->reqid ||
9922 (req->owner_nlportid &&
9923 req->owner_nlportid != info->snd_portid))
9924 return -ENOENT;
9925
9926 return cfg80211_stop_sched_scan_req(rdev, req, false);
807f8a8c
LC
9927}
9928
04f39047
SW
9929static int nl80211_start_radar_detection(struct sk_buff *skb,
9930 struct genl_info *info)
9931{
9932 struct cfg80211_registered_device *rdev = info->user_ptr[0];
9933 struct net_device *dev = info->user_ptr[1];
9934 struct wireless_dev *wdev = dev->ieee80211_ptr;
13cf6dec 9935 struct wiphy *wiphy = wdev->wiphy;
04f39047 9936 struct cfg80211_chan_def chandef;
55f7435c 9937 enum nl80211_dfs_regions dfs_region;
31559f35 9938 unsigned int cac_time_ms;
84158164
LB
9939 int err = -EINVAL;
9940
9941 flush_delayed_work(&rdev->dfs_update_channels_wk);
9942
9943 wiphy_lock(wiphy);
04f39047 9944
13cf6dec 9945 dfs_region = reg_get_dfs_region(wiphy);
55f7435c 9946 if (dfs_region == NL80211_DFS_UNSET)
84158164 9947 goto unlock;
55f7435c 9948
04f39047
SW
9949 err = nl80211_parse_chandef(rdev, info, &chandef);
9950 if (err)
84158164 9951 goto unlock;
04f39047 9952
13cf6dec 9953 err = cfg80211_chandef_dfs_required(wiphy, &chandef, wdev->iftype);
04f39047 9954 if (err < 0)
84158164 9955 goto unlock;
04f39047 9956
84158164
LB
9957 if (err == 0) {
9958 err = -EINVAL;
9959 goto unlock;
9960 }
04f39047 9961
84158164
LB
9962 if (!cfg80211_chandef_dfs_usable(wiphy, &chandef)) {
9963 err = -EINVAL;
9964 goto unlock;
9965 }
04f39047 9966
a95bfb87
LB
9967 if (nla_get_flag(info->attrs[NL80211_ATTR_RADAR_BACKGROUND])) {
9968 err = cfg80211_start_background_radar_detection(rdev, wdev,
9969 &chandef);
84158164
LB
9970 goto unlock;
9971 }
bc2dfc02 9972
84158164
LB
9973 if (netif_carrier_ok(dev)) {
9974 err = -EBUSY;
9975 goto unlock;
9976 }
bc2dfc02 9977
84158164
LB
9978 if (wdev->cac_started) {
9979 err = -EBUSY;
9980 goto unlock;
9981 }
bc2dfc02 9982
13cf6dec 9983 /* CAC start is offloaded to HW and can't be started manually */
84158164
LB
9984 if (wiphy_ext_feature_isset(wiphy, NL80211_EXT_FEATURE_DFS_OFFLOAD)) {
9985 err = -EOPNOTSUPP;
9986 goto unlock;
9987 }
13cf6dec 9988
84158164
LB
9989 if (!rdev->ops->start_radar_detection) {
9990 err = -EOPNOTSUPP;
9991 goto unlock;
9992 }
04f39047 9993
31559f35
JD
9994 cac_time_ms = cfg80211_chandef_dfs_cac_time(&rdev->wiphy, &chandef);
9995 if (WARN_ON(!cac_time_ms))
9996 cac_time_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
9997
a1056b1b 9998 err = rdev_start_radar_detection(rdev, dev, &chandef, cac_time_ms);
04f39047 9999 if (!err) {
7b0a0e3c 10000 wdev->links[0].ap.chandef = chandef;
04f39047
SW
10001 wdev->cac_started = true;
10002 wdev->cac_start_time = jiffies;
31559f35 10003 wdev->cac_time_ms = cac_time_ms;
04f39047 10004 }
84158164
LB
10005unlock:
10006 wiphy_unlock(wiphy);
10007
04f39047
SW
10008 return err;
10009}
10010
30c63115
S
10011static int nl80211_notify_radar_detection(struct sk_buff *skb,
10012 struct genl_info *info)
10013{
10014 struct cfg80211_registered_device *rdev = info->user_ptr[0];
10015 struct net_device *dev = info->user_ptr[1];
10016 struct wireless_dev *wdev = dev->ieee80211_ptr;
10017 struct wiphy *wiphy = wdev->wiphy;
10018 struct cfg80211_chan_def chandef;
10019 enum nl80211_dfs_regions dfs_region;
10020 int err;
10021
10022 dfs_region = reg_get_dfs_region(wiphy);
10023 if (dfs_region == NL80211_DFS_UNSET) {
10024 GENL_SET_ERR_MSG(info,
10025 "DFS Region is not set. Unexpected Radar indication");
10026 return -EINVAL;
10027 }
10028
10029 err = nl80211_parse_chandef(rdev, info, &chandef);
10030 if (err) {
10031 GENL_SET_ERR_MSG(info, "Unable to extract chandef info");
10032 return err;
10033 }
10034
10035 err = cfg80211_chandef_dfs_required(wiphy, &chandef, wdev->iftype);
10036 if (err < 0) {
10037 GENL_SET_ERR_MSG(info, "chandef is invalid");
10038 return err;
10039 }
10040
10041 if (err == 0) {
10042 GENL_SET_ERR_MSG(info,
10043 "Unexpected Radar indication for chandef/iftype");
10044 return -EINVAL;
10045 }
10046
10047 /* Do not process this notification if radar is already detected
10048 * by kernel on this channel, and return success.
10049 */
10050 if (chandef.chan->dfs_state == NL80211_DFS_UNAVAILABLE)
10051 return 0;
10052
10053 cfg80211_set_dfs_state(wiphy, &chandef, NL80211_DFS_UNAVAILABLE);
10054
10055 cfg80211_sched_dfs_chan_update(rdev);
10056
a680fe46 10057 rdev->radar_chandef = chandef;
30c63115
S
10058
10059 /* Propagate this notification to other radios as well */
10060 queue_work(cfg80211_wq, &rdev->propagate_radar_detect_wk);
10061
10062 return 0;
10063}
10064
16ef1fe2
SW
10065static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
10066{
10067 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7b0a0e3c 10068 unsigned int link_id = nl80211_link_id(info->attrs);
16ef1fe2
SW
10069 struct net_device *dev = info->user_ptr[1];
10070 struct wireless_dev *wdev = dev->ieee80211_ptr;
10071 struct cfg80211_csa_settings params;
a05829a7 10072 struct nlattr **csa_attrs = NULL;
16ef1fe2 10073 int err;
ee4bc9e7 10074 bool need_new_beacon = false;
8d9de16f 10075 bool need_handle_dfs_flag = true;
9a774c78 10076 int len, i;
252e07ca 10077 u32 cs_count;
16ef1fe2
SW
10078
10079 if (!rdev->ops->channel_switch ||
10080 !(rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH))
10081 return -EOPNOTSUPP;
10082
ee4bc9e7
SW
10083 switch (dev->ieee80211_ptr->iftype) {
10084 case NL80211_IFTYPE_AP:
10085 case NL80211_IFTYPE_P2P_GO:
10086 need_new_beacon = true;
8d9de16f
BB
10087 /* For all modes except AP the handle_dfs flag needs to be
10088 * supplied to tell the kernel that userspace will handle radar
10089 * events when they happen. Otherwise a switch to a channel
10090 * requiring DFS will be rejected.
10091 */
10092 need_handle_dfs_flag = false;
ee4bc9e7
SW
10093
10094 /* useless if AP is not running */
7b0a0e3c 10095 if (!wdev->links[link_id].ap.beacon_interval)
1ff79dfa 10096 return -ENOTCONN;
ee4bc9e7
SW
10097 break;
10098 case NL80211_IFTYPE_ADHOC:
7b0a0e3c 10099 if (!wdev->u.ibss.ssid_len)
1ff79dfa
JB
10100 return -ENOTCONN;
10101 break;
c6da674a 10102 case NL80211_IFTYPE_MESH_POINT:
7b0a0e3c 10103 if (!wdev->u.mesh.id_len)
1ff79dfa 10104 return -ENOTCONN;
ee4bc9e7
SW
10105 break;
10106 default:
16ef1fe2 10107 return -EOPNOTSUPP;
ee4bc9e7 10108 }
16ef1fe2
SW
10109
10110 memset(&params, 0, sizeof(params));
c177db2d 10111 params.beacon_csa.ftm_responder = -1;
16ef1fe2
SW
10112
10113 if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] ||
10114 !info->attrs[NL80211_ATTR_CH_SWITCH_COUNT])
10115 return -EINVAL;
10116
10117 /* only important for AP, IBSS and mesh create IEs internally */
d0a361a5 10118 if (need_new_beacon && !info->attrs[NL80211_ATTR_CSA_IES])
16ef1fe2
SW
10119 return -EINVAL;
10120
252e07ca
LC
10121 /* Even though the attribute is u32, the specification says
10122 * u8, so let's make sure we don't overflow.
10123 */
10124 cs_count = nla_get_u32(info->attrs[NL80211_ATTR_CH_SWITCH_COUNT]);
10125 if (cs_count > 255)
10126 return -EINVAL;
10127
10128 params.count = cs_count;
16ef1fe2 10129
ee4bc9e7
SW
10130 if (!need_new_beacon)
10131 goto skip_beacons;
10132
dbbb27e1
AD
10133 err = nl80211_parse_beacon(rdev, info->attrs, &params.beacon_after,
10134 info->extack);
16ef1fe2 10135 if (err)
dc1e3cb8 10136 goto free;
16ef1fe2 10137
a05829a7
JB
10138 csa_attrs = kcalloc(NL80211_ATTR_MAX + 1, sizeof(*csa_attrs),
10139 GFP_KERNEL);
dc1e3cb8
JC
10140 if (!csa_attrs) {
10141 err = -ENOMEM;
10142 goto free;
10143 }
a05829a7 10144
8cb08174
JB
10145 err = nla_parse_nested_deprecated(csa_attrs, NL80211_ATTR_MAX,
10146 info->attrs[NL80211_ATTR_CSA_IES],
10147 nl80211_policy, info->extack);
16ef1fe2 10148 if (err)
a05829a7 10149 goto free;
16ef1fe2 10150
dbbb27e1
AD
10151 err = nl80211_parse_beacon(rdev, csa_attrs, &params.beacon_csa,
10152 info->extack);
16ef1fe2 10153 if (err)
a05829a7 10154 goto free;
16ef1fe2 10155
a05829a7
JB
10156 if (!csa_attrs[NL80211_ATTR_CNTDWN_OFFS_BEACON]) {
10157 err = -EINVAL;
10158 goto free;
10159 }
16ef1fe2 10160
00c207ed 10161 len = nla_len(csa_attrs[NL80211_ATTR_CNTDWN_OFFS_BEACON]);
a05829a7
JB
10162 if (!len || (len % sizeof(u16))) {
10163 err = -EINVAL;
10164 goto free;
10165 }
16ef1fe2 10166
9a774c78
AO
10167 params.n_counter_offsets_beacon = len / sizeof(u16);
10168 if (rdev->wiphy.max_num_csa_counters &&
10169 (params.n_counter_offsets_beacon >
a05829a7
JB
10170 rdev->wiphy.max_num_csa_counters)) {
10171 err = -EINVAL;
10172 goto free;
10173 }
16ef1fe2 10174
9a774c78 10175 params.counter_offsets_beacon =
00c207ed 10176 nla_data(csa_attrs[NL80211_ATTR_CNTDWN_OFFS_BEACON]);
9a774c78
AO
10177
10178 /* sanity checks - counters should fit and be the same */
10179 for (i = 0; i < params.n_counter_offsets_beacon; i++) {
10180 u16 offset = params.counter_offsets_beacon[i];
10181
a05829a7
JB
10182 if (offset >= params.beacon_csa.tail_len) {
10183 err = -EINVAL;
10184 goto free;
10185 }
9a774c78 10186
a05829a7
JB
10187 if (params.beacon_csa.tail[offset] != params.count) {
10188 err = -EINVAL;
10189 goto free;
10190 }
9a774c78
AO
10191 }
10192
00c207ed
JC
10193 if (csa_attrs[NL80211_ATTR_CNTDWN_OFFS_PRESP]) {
10194 len = nla_len(csa_attrs[NL80211_ATTR_CNTDWN_OFFS_PRESP]);
a05829a7
JB
10195 if (!len || (len % sizeof(u16))) {
10196 err = -EINVAL;
10197 goto free;
10198 }
16ef1fe2 10199
9a774c78
AO
10200 params.n_counter_offsets_presp = len / sizeof(u16);
10201 if (rdev->wiphy.max_num_csa_counters &&
ad5987b4 10202 (params.n_counter_offsets_presp >
a05829a7
JB
10203 rdev->wiphy.max_num_csa_counters)) {
10204 err = -EINVAL;
10205 goto free;
10206 }
9a774c78
AO
10207
10208 params.counter_offsets_presp =
00c207ed 10209 nla_data(csa_attrs[NL80211_ATTR_CNTDWN_OFFS_PRESP]);
9a774c78
AO
10210
10211 /* sanity checks - counters should fit and be the same */
10212 for (i = 0; i < params.n_counter_offsets_presp; i++) {
10213 u16 offset = params.counter_offsets_presp[i];
10214
a05829a7
JB
10215 if (offset >= params.beacon_csa.probe_resp_len) {
10216 err = -EINVAL;
10217 goto free;
10218 }
9a774c78
AO
10219
10220 if (params.beacon_csa.probe_resp[offset] !=
a05829a7
JB
10221 params.count) {
10222 err = -EINVAL;
10223 goto free;
10224 }
9a774c78 10225 }
16ef1fe2
SW
10226 }
10227
ee4bc9e7 10228skip_beacons:
16ef1fe2
SW
10229 err = nl80211_parse_chandef(rdev, info, &params.chandef);
10230 if (err)
a05829a7 10231 goto free;
16ef1fe2 10232
923b352f 10233 if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &params.chandef,
a05829a7
JB
10234 wdev->iftype)) {
10235 err = -EINVAL;
10236 goto free;
10237 }
16ef1fe2 10238
2beb6dab
LC
10239 err = cfg80211_chandef_dfs_required(wdev->wiphy,
10240 &params.chandef,
10241 wdev->iftype);
10242 if (err < 0)
a05829a7 10243 goto free;
2beb6dab 10244
8d9de16f 10245 if (err > 0) {
2beb6dab 10246 params.radar_required = true;
8d9de16f
BB
10247 if (need_handle_dfs_flag &&
10248 !nla_get_flag(info->attrs[NL80211_ATTR_HANDLE_DFS])) {
a05829a7
JB
10249 err = -EINVAL;
10250 goto free;
8d9de16f
BB
10251 }
10252 }
16ef1fe2 10253
16ef1fe2
SW
10254 if (info->attrs[NL80211_ATTR_CH_SWITCH_BLOCK_TX])
10255 params.block_tx = true;
10256
d7c1a9a0
AD
10257 if (info->attrs[NL80211_ATTR_PUNCT_BITMAP]) {
10258 err = nl80211_parse_punct_bitmap(rdev, info,
10259 &params.chandef,
10260 &params.punct_bitmap);
10261 if (err)
10262 goto free;
10263 }
10264
c56589ed
SW
10265 wdev_lock(wdev);
10266 err = rdev_channel_switch(rdev, dev, &params);
10267 wdev_unlock(wdev);
10268
a05829a7 10269free:
dc1e3cb8
JC
10270 kfree(params.beacon_after.mbssid_ies);
10271 kfree(params.beacon_csa.mbssid_ies);
dbbb27e1
AD
10272 kfree(params.beacon_after.rnr_ies);
10273 kfree(params.beacon_csa.rnr_ies);
a05829a7 10274 kfree(csa_attrs);
c56589ed 10275 return err;
16ef1fe2
SW
10276}
10277
9720bb3a
JB
10278static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
10279 u32 seq, int flags,
2a519311 10280 struct cfg80211_registered_device *rdev,
48ab905d
JB
10281 struct wireless_dev *wdev,
10282 struct cfg80211_internal_bss *intbss)
2a519311 10283{
48ab905d 10284 struct cfg80211_bss *res = &intbss->pub;
9caf0364 10285 const struct cfg80211_bss_ies *ies;
7b0a0e3c 10286 unsigned int link_id;
2a519311
JB
10287 void *hdr;
10288 struct nlattr *bss;
48ab905d
JB
10289
10290 ASSERT_WDEV_LOCK(wdev);
2a519311 10291
15e47304 10292 hdr = nl80211hdr_put(msg, NETLINK_CB(cb->skb).portid, seq, flags,
2a519311
JB
10293 NL80211_CMD_NEW_SCAN_RESULTS);
10294 if (!hdr)
10295 return -1;
10296
0a833c29 10297 genl_dump_check_consistent(cb, hdr);
9720bb3a 10298
97990a06
JB
10299 if (nla_put_u32(msg, NL80211_ATTR_GENERATION, rdev->bss_generation))
10300 goto nla_put_failure;
10301 if (wdev->netdev &&
9360ffd1
DM
10302 nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex))
10303 goto nla_put_failure;
2dad624e
ND
10304 if (nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
10305 NL80211_ATTR_PAD))
97990a06 10306 goto nla_put_failure;
2a519311 10307
ae0be8de 10308 bss = nla_nest_start_noflag(msg, NL80211_ATTR_BSS);
2a519311
JB
10309 if (!bss)
10310 goto nla_put_failure;
9360ffd1 10311 if ((!is_zero_ether_addr(res->bssid) &&
9caf0364 10312 nla_put(msg, NL80211_BSS_BSSID, ETH_ALEN, res->bssid)))
9360ffd1 10313 goto nla_put_failure;
9caf0364
JB
10314
10315 rcu_read_lock();
0e227084
JB
10316 /* indicate whether we have probe response data or not */
10317 if (rcu_access_pointer(res->proberesp_ies) &&
10318 nla_put_flag(msg, NL80211_BSS_PRESP_DATA))
10319 goto fail_unlock_rcu;
10320
10321 /* this pointer prefers to be pointed to probe response data
10322 * but is always valid
10323 */
9caf0364 10324 ies = rcu_dereference(res->ies);
8cef2c9d 10325 if (ies) {
2dad624e
ND
10326 if (nla_put_u64_64bit(msg, NL80211_BSS_TSF, ies->tsf,
10327 NL80211_BSS_PAD))
8cef2c9d 10328 goto fail_unlock_rcu;
8cef2c9d
JB
10329 if (ies->len && nla_put(msg, NL80211_BSS_INFORMATION_ELEMENTS,
10330 ies->len, ies->data))
10331 goto fail_unlock_rcu;
9caf0364 10332 }
0e227084
JB
10333
10334 /* and this pointer is always (unless driver didn't know) beacon data */
9caf0364 10335 ies = rcu_dereference(res->beacon_ies);
0e227084 10336 if (ies && ies->from_beacon) {
2dad624e
ND
10337 if (nla_put_u64_64bit(msg, NL80211_BSS_BEACON_TSF, ies->tsf,
10338 NL80211_BSS_PAD))
8cef2c9d
JB
10339 goto fail_unlock_rcu;
10340 if (ies->len && nla_put(msg, NL80211_BSS_BEACON_IES,
10341 ies->len, ies->data))
10342 goto fail_unlock_rcu;
9caf0364
JB
10343 }
10344 rcu_read_unlock();
10345
9360ffd1
DM
10346 if (res->beacon_interval &&
10347 nla_put_u16(msg, NL80211_BSS_BEACON_INTERVAL, res->beacon_interval))
10348 goto nla_put_failure;
10349 if (nla_put_u16(msg, NL80211_BSS_CAPABILITY, res->capability) ||
10350 nla_put_u32(msg, NL80211_BSS_FREQUENCY, res->channel->center_freq) ||
942ba88b
TP
10351 nla_put_u32(msg, NL80211_BSS_FREQUENCY_OFFSET,
10352 res->channel->freq_offset) ||
dcd6eac1 10353 nla_put_u32(msg, NL80211_BSS_CHAN_WIDTH, res->scan_width) ||
9360ffd1
DM
10354 nla_put_u32(msg, NL80211_BSS_SEEN_MS_AGO,
10355 jiffies_to_msecs(jiffies - intbss->ts)))
10356 goto nla_put_failure;
2a519311 10357
1d76250b
AS
10358 if (intbss->parent_tsf &&
10359 (nla_put_u64_64bit(msg, NL80211_BSS_PARENT_TSF,
10360 intbss->parent_tsf, NL80211_BSS_PAD) ||
10361 nla_put(msg, NL80211_BSS_PARENT_BSSID, ETH_ALEN,
10362 intbss->parent_bssid)))
10363 goto nla_put_failure;
10364
6e19bc4b 10365 if (intbss->ts_boottime &&
2dad624e
ND
10366 nla_put_u64_64bit(msg, NL80211_BSS_LAST_SEEN_BOOTTIME,
10367 intbss->ts_boottime, NL80211_BSS_PAD))
6e19bc4b
DS
10368 goto nla_put_failure;
10369
983dafaa
SD
10370 if (!nl80211_put_signal(msg, intbss->pub.chains,
10371 intbss->pub.chain_signal,
10372 NL80211_BSS_CHAIN_SIGNAL))
10373 goto nla_put_failure;
10374
77965c97 10375 switch (rdev->wiphy.signal_type) {
2a519311 10376 case CFG80211_SIGNAL_TYPE_MBM:
9360ffd1
DM
10377 if (nla_put_u32(msg, NL80211_BSS_SIGNAL_MBM, res->signal))
10378 goto nla_put_failure;
2a519311
JB
10379 break;
10380 case CFG80211_SIGNAL_TYPE_UNSPEC:
9360ffd1
DM
10381 if (nla_put_u8(msg, NL80211_BSS_SIGNAL_UNSPEC, res->signal))
10382 goto nla_put_failure;
2a519311
JB
10383 break;
10384 default:
10385 break;
10386 }
10387
48ab905d 10388 switch (wdev->iftype) {
074ac8df 10389 case NL80211_IFTYPE_P2P_CLIENT:
48ab905d 10390 case NL80211_IFTYPE_STATION:
7b0a0e3c
JB
10391 for_each_valid_link(wdev, link_id) {
10392 if (intbss == wdev->links[link_id].client.current_bss &&
dd374f84
JB
10393 (nla_put_u32(msg, NL80211_BSS_STATUS,
10394 NL80211_BSS_STATUS_ASSOCIATED) ||
10395 (wdev->valid_links &&
6522047c
JB
10396 (nla_put_u8(msg, NL80211_BSS_MLO_LINK_ID,
10397 link_id) ||
10398 nla_put(msg, NL80211_BSS_MLD_ADDR, ETH_ALEN,
10399 wdev->u.client.connected_addr)))))
7b0a0e3c
JB
10400 goto nla_put_failure;
10401 }
48ab905d
JB
10402 break;
10403 case NL80211_IFTYPE_ADHOC:
7b0a0e3c 10404 if (intbss == wdev->u.ibss.current_bss &&
9360ffd1
DM
10405 nla_put_u32(msg, NL80211_BSS_STATUS,
10406 NL80211_BSS_STATUS_IBSS_JOINED))
10407 goto nla_put_failure;
48ab905d
JB
10408 break;
10409 default:
10410 break;
10411 }
10412
2a519311
JB
10413 nla_nest_end(msg, bss);
10414
053c095a
JB
10415 genlmsg_end(msg, hdr);
10416 return 0;
2a519311 10417
8cef2c9d
JB
10418 fail_unlock_rcu:
10419 rcu_read_unlock();
2a519311
JB
10420 nla_put_failure:
10421 genlmsg_cancel(msg, hdr);
10422 return -EMSGSIZE;
10423}
10424
97990a06 10425static int nl80211_dump_scan(struct sk_buff *skb, struct netlink_callback *cb)
2a519311 10426{
48ab905d 10427 struct cfg80211_registered_device *rdev;
2a519311 10428 struct cfg80211_internal_bss *scan;
48ab905d 10429 struct wireless_dev *wdev;
97990a06 10430 int start = cb->args[2], idx = 0;
2a519311
JB
10431 int err;
10432
ce6b6974 10433 err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev, NULL);
a05829a7 10434 if (err)
67748893 10435 return err;
a05829a7
JB
10436 /* nl80211_prepare_wdev_dump acquired it in the successful case */
10437 __acquire(&rdev->wiphy.mtx);
2a519311 10438
48ab905d
JB
10439 wdev_lock(wdev);
10440 spin_lock_bh(&rdev->bss_lock);
d1e23c94
DK
10441
10442 /*
10443 * dump_scan will be called multiple times to break up the scan results
10444 * into multiple messages. It is unlikely that any more bss-es will be
10445 * expired after the first call, so only call only call this on the
10446 * first dump_scan invocation.
10447 */
10448 if (start == 0)
10449 cfg80211_bss_expire(rdev);
48ab905d 10450
9720bb3a
JB
10451 cb->seq = rdev->bss_generation;
10452
48ab905d 10453 list_for_each_entry(scan, &rdev->bss_list, list) {
2a519311
JB
10454 if (++idx <= start)
10455 continue;
9720bb3a 10456 if (nl80211_send_bss(skb, cb,
2a519311 10457 cb->nlh->nlmsg_seq, NLM_F_MULTI,
48ab905d 10458 rdev, wdev, scan) < 0) {
2a519311 10459 idx--;
67748893 10460 break;
2a519311
JB
10461 }
10462 }
10463
48ab905d
JB
10464 spin_unlock_bh(&rdev->bss_lock);
10465 wdev_unlock(wdev);
2a519311 10466
97990a06 10467 cb->args[2] = idx;
a05829a7 10468 wiphy_unlock(&rdev->wiphy);
2a519311 10469
67748893 10470 return skb->len;
2a519311
JB
10471}
10472
15e47304 10473static int nl80211_send_survey(struct sk_buff *msg, u32 portid, u32 seq,
11f78ac3
JB
10474 int flags, struct net_device *dev,
10475 bool allow_radio_stats,
10476 struct survey_info *survey)
61fa713c
HS
10477{
10478 void *hdr;
10479 struct nlattr *infoattr;
10480
11f78ac3
JB
10481 /* skip radio stats if userspace didn't request them */
10482 if (!survey->channel && !allow_radio_stats)
10483 return 0;
10484
15e47304 10485 hdr = nl80211hdr_put(msg, portid, seq, flags,
61fa713c
HS
10486 NL80211_CMD_NEW_SURVEY_RESULTS);
10487 if (!hdr)
10488 return -ENOMEM;
10489
9360ffd1
DM
10490 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
10491 goto nla_put_failure;
61fa713c 10492
ae0be8de 10493 infoattr = nla_nest_start_noflag(msg, NL80211_ATTR_SURVEY_INFO);
61fa713c
HS
10494 if (!infoattr)
10495 goto nla_put_failure;
10496
11f78ac3
JB
10497 if (survey->channel &&
10498 nla_put_u32(msg, NL80211_SURVEY_INFO_FREQUENCY,
9360ffd1
DM
10499 survey->channel->center_freq))
10500 goto nla_put_failure;
58ef7c1b
TP
10501
10502 if (survey->channel && survey->channel->freq_offset &&
10503 nla_put_u32(msg, NL80211_SURVEY_INFO_FREQUENCY_OFFSET,
10504 survey->channel->freq_offset))
10505 goto nla_put_failure;
9360ffd1
DM
10506
10507 if ((survey->filled & SURVEY_INFO_NOISE_DBM) &&
10508 nla_put_u8(msg, NL80211_SURVEY_INFO_NOISE, survey->noise))
10509 goto nla_put_failure;
10510 if ((survey->filled & SURVEY_INFO_IN_USE) &&
10511 nla_put_flag(msg, NL80211_SURVEY_INFO_IN_USE))
10512 goto nla_put_failure;
4ed20beb 10513 if ((survey->filled & SURVEY_INFO_TIME) &&
2dad624e
ND
10514 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME,
10515 survey->time, NL80211_SURVEY_INFO_PAD))
9360ffd1 10516 goto nla_put_failure;
4ed20beb 10517 if ((survey->filled & SURVEY_INFO_TIME_BUSY) &&
2dad624e
ND
10518 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_BUSY,
10519 survey->time_busy, NL80211_SURVEY_INFO_PAD))
9360ffd1 10520 goto nla_put_failure;
4ed20beb 10521 if ((survey->filled & SURVEY_INFO_TIME_EXT_BUSY) &&
2dad624e
ND
10522 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_EXT_BUSY,
10523 survey->time_ext_busy, NL80211_SURVEY_INFO_PAD))
9360ffd1 10524 goto nla_put_failure;
4ed20beb 10525 if ((survey->filled & SURVEY_INFO_TIME_RX) &&
2dad624e
ND
10526 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_RX,
10527 survey->time_rx, NL80211_SURVEY_INFO_PAD))
9360ffd1 10528 goto nla_put_failure;
4ed20beb 10529 if ((survey->filled & SURVEY_INFO_TIME_TX) &&
2dad624e
ND
10530 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_TX,
10531 survey->time_tx, NL80211_SURVEY_INFO_PAD))
9360ffd1 10532 goto nla_put_failure;
052536ab 10533 if ((survey->filled & SURVEY_INFO_TIME_SCAN) &&
2dad624e
ND
10534 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_SCAN,
10535 survey->time_scan, NL80211_SURVEY_INFO_PAD))
052536ab 10536 goto nla_put_failure;
c8cd6e7f
FF
10537 if ((survey->filled & SURVEY_INFO_TIME_BSS_RX) &&
10538 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_BSS_RX,
10539 survey->time_bss_rx, NL80211_SURVEY_INFO_PAD))
10540 goto nla_put_failure;
61fa713c
HS
10541
10542 nla_nest_end(msg, infoattr);
10543
053c095a
JB
10544 genlmsg_end(msg, hdr);
10545 return 0;
61fa713c
HS
10546
10547 nla_put_failure:
10548 genlmsg_cancel(msg, hdr);
10549 return -EMSGSIZE;
10550}
10551
11f78ac3 10552static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb)
61fa713c 10553{
50508d94 10554 struct nlattr **attrbuf;
61fa713c 10555 struct survey_info survey;
1b8ec87a 10556 struct cfg80211_registered_device *rdev;
97990a06
JB
10557 struct wireless_dev *wdev;
10558 int survey_idx = cb->args[2];
61fa713c 10559 int res;
11f78ac3 10560 bool radio_stats;
61fa713c 10561
50508d94
JB
10562 attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf), GFP_KERNEL);
10563 if (!attrbuf)
10564 return -ENOMEM;
10565
ce6b6974 10566 res = nl80211_prepare_wdev_dump(cb, &rdev, &wdev, attrbuf);
a05829a7
JB
10567 if (res) {
10568 kfree(attrbuf);
10569 return res;
10570 }
10571 /* nl80211_prepare_wdev_dump acquired it in the successful case */
10572 __acquire(&rdev->wiphy.mtx);
61fa713c 10573
11f78ac3 10574 /* prepare_wdev_dump parsed the attributes */
c90c39da 10575 radio_stats = attrbuf[NL80211_ATTR_SURVEY_RADIO_STATS];
11f78ac3 10576
97990a06
JB
10577 if (!wdev->netdev) {
10578 res = -EINVAL;
10579 goto out_err;
10580 }
10581
1b8ec87a 10582 if (!rdev->ops->dump_survey) {
61fa713c
HS
10583 res = -EOPNOTSUPP;
10584 goto out_err;
10585 }
10586
10587 while (1) {
284b38b6 10588 wdev_lock(wdev);
1b8ec87a 10589 res = rdev_dump_survey(rdev, wdev->netdev, survey_idx, &survey);
284b38b6 10590 wdev_unlock(wdev);
61fa713c
HS
10591 if (res == -ENOENT)
10592 break;
10593 if (res)
10594 goto out_err;
10595
11f78ac3
JB
10596 /* don't send disabled channels, but do send non-channel data */
10597 if (survey.channel &&
10598 survey.channel->flags & IEEE80211_CHAN_DISABLED) {
180cdc79
LR
10599 survey_idx++;
10600 continue;
10601 }
10602
61fa713c 10603 if (nl80211_send_survey(skb,
15e47304 10604 NETLINK_CB(cb->skb).portid,
61fa713c 10605 cb->nlh->nlmsg_seq, NLM_F_MULTI,
11f78ac3 10606 wdev->netdev, radio_stats, &survey) < 0)
61fa713c
HS
10607 goto out;
10608 survey_idx++;
10609 }
10610
10611 out:
97990a06 10612 cb->args[2] = survey_idx;
61fa713c
HS
10613 res = skb->len;
10614 out_err:
50508d94 10615 kfree(attrbuf);
a05829a7 10616 wiphy_unlock(&rdev->wiphy);
61fa713c
HS
10617 return res;
10618}
10619
b23aa676
SO
10620static bool nl80211_valid_wpa_versions(u32 wpa_versions)
10621{
10622 return !(wpa_versions & ~(NL80211_WPA_VERSION_1 |
cc3e14c2
CHH
10623 NL80211_WPA_VERSION_2 |
10624 NL80211_WPA_VERSION_3));
b23aa676
SO
10625}
10626
636a5d36
JM
10627static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
10628{
4c476991
JB
10629 struct cfg80211_registered_device *rdev = info->user_ptr[0];
10630 struct net_device *dev = info->user_ptr[1];
19957bb3 10631 struct ieee80211_channel *chan;
325839da
JB
10632 const u8 *bssid, *ssid;
10633 int err, ssid_len;
19957bb3 10634 enum nl80211_auth_type auth_type;
fffd0934 10635 struct key_parse key;
d5cdfacb 10636 bool local_state_change;
325839da 10637 struct cfg80211_auth_request req = {};
942ba88b 10638 u32 freq;
636a5d36 10639
f4a11bb0
JB
10640 if (!info->attrs[NL80211_ATTR_MAC])
10641 return -EINVAL;
10642
1778092e
JM
10643 if (!info->attrs[NL80211_ATTR_AUTH_TYPE])
10644 return -EINVAL;
10645
19957bb3
JB
10646 if (!info->attrs[NL80211_ATTR_SSID])
10647 return -EINVAL;
10648
10649 if (!info->attrs[NL80211_ATTR_WIPHY_FREQ])
10650 return -EINVAL;
10651
fffd0934
JB
10652 err = nl80211_parse_key(info, &key);
10653 if (err)
10654 return err;
10655
10656 if (key.idx >= 0) {
e31b8213
JB
10657 if (key.type != -1 && key.type != NL80211_KEYTYPE_GROUP)
10658 return -EINVAL;
fffd0934
JB
10659 if (!key.p.key || !key.p.key_len)
10660 return -EINVAL;
10661 if ((key.p.cipher != WLAN_CIPHER_SUITE_WEP40 ||
10662 key.p.key_len != WLAN_KEY_LEN_WEP40) &&
10663 (key.p.cipher != WLAN_CIPHER_SUITE_WEP104 ||
10664 key.p.key_len != WLAN_KEY_LEN_WEP104))
10665 return -EINVAL;
b6b5555b 10666 if (key.idx > 3)
fffd0934
JB
10667 return -EINVAL;
10668 } else {
10669 key.p.key_len = 0;
10670 key.p.key = NULL;
10671 }
10672
afea0b7a
JB
10673 if (key.idx >= 0) {
10674 int i;
10675 bool ok = false;
7a087e74 10676
afea0b7a
JB
10677 for (i = 0; i < rdev->wiphy.n_cipher_suites; i++) {
10678 if (key.p.cipher == rdev->wiphy.cipher_suites[i]) {
10679 ok = true;
10680 break;
10681 }
10682 }
4c476991
JB
10683 if (!ok)
10684 return -EINVAL;
afea0b7a
JB
10685 }
10686
4c476991
JB
10687 if (!rdev->ops->auth)
10688 return -EOPNOTSUPP;
636a5d36 10689
074ac8df 10690 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
10691 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
10692 return -EOPNOTSUPP;
eec60b03 10693
19957bb3 10694 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
942ba88b
TP
10695 freq = MHZ_TO_KHZ(nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
10696 if (info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET])
10697 freq +=
10698 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET]);
10699
10700 chan = nl80211_get_valid_chan(&rdev->wiphy, freq);
664834de 10701 if (!chan)
4c476991 10702 return -EINVAL;
636a5d36 10703
19957bb3
JB
10704 ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
10705 ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
636a5d36
JM
10706
10707 if (info->attrs[NL80211_ATTR_IE]) {
325839da
JB
10708 req.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
10709 req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
636a5d36
JM
10710 }
10711
19957bb3 10712 auth_type = nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
e39e5b5e 10713 if (!nl80211_valid_auth_type(rdev, auth_type, NL80211_CMD_AUTHENTICATE))
4c476991 10714 return -EINVAL;
636a5d36 10715
63181060
JM
10716 if ((auth_type == NL80211_AUTHTYPE_SAE ||
10717 auth_type == NL80211_AUTHTYPE_FILS_SK ||
10718 auth_type == NL80211_AUTHTYPE_FILS_SK_PFS ||
10719 auth_type == NL80211_AUTHTYPE_FILS_PK) &&
11b6b5a4 10720 !info->attrs[NL80211_ATTR_AUTH_DATA])
e39e5b5e
JM
10721 return -EINVAL;
10722
11b6b5a4 10723 if (info->attrs[NL80211_ATTR_AUTH_DATA]) {
63181060
JM
10724 if (auth_type != NL80211_AUTHTYPE_SAE &&
10725 auth_type != NL80211_AUTHTYPE_FILS_SK &&
10726 auth_type != NL80211_AUTHTYPE_FILS_SK_PFS &&
10727 auth_type != NL80211_AUTHTYPE_FILS_PK)
e39e5b5e 10728 return -EINVAL;
325839da
JB
10729 req.auth_data = nla_data(info->attrs[NL80211_ATTR_AUTH_DATA]);
10730 req.auth_data_len = nla_len(info->attrs[NL80211_ATTR_AUTH_DATA]);
e39e5b5e
JM
10731 }
10732
d5cdfacb
JM
10733 local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
10734
95de817b
JB
10735 /*
10736 * Since we no longer track auth state, ignore
10737 * requests to only change local state.
10738 */
10739 if (local_state_change)
10740 return 0;
10741
325839da
JB
10742 req.auth_type = auth_type;
10743 req.key = key.p.key;
10744 req.key_len = key.p.key_len;
10745 req.key_idx = key.idx;
d648c230
JB
10746 req.link_id = nl80211_link_id_or_invalid(info->attrs);
10747 if (req.link_id >= 0) {
45aaf17c
JB
10748 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_MLO))
10749 return -EINVAL;
d648c230
JB
10750 if (!info->attrs[NL80211_ATTR_MLD_ADDR])
10751 return -EINVAL;
10752 req.ap_mld_addr = nla_data(info->attrs[NL80211_ATTR_MLD_ADDR]);
727073ca
JB
10753 if (!is_valid_ether_addr(req.ap_mld_addr))
10754 return -EINVAL;
d648c230 10755 }
325839da
JB
10756
10757 req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
10758 IEEE80211_BSS_TYPE_ESS,
10759 IEEE80211_PRIVACY_ANY);
10760 if (!req.bss)
10761 return -ENOENT;
10762
91bf9b26 10763 wdev_lock(dev->ieee80211_ptr);
325839da 10764 err = cfg80211_mlme_auth(rdev, dev, &req);
91bf9b26 10765 wdev_unlock(dev->ieee80211_ptr);
325839da
JB
10766
10767 cfg80211_put_bss(&rdev->wiphy, req.bss);
10768
91bf9b26 10769 return err;
636a5d36
JM
10770}
10771
64bf3d4b
DK
10772static int validate_pae_over_nl80211(struct cfg80211_registered_device *rdev,
10773 struct genl_info *info)
10774{
10775 if (!info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
10776 GENL_SET_ERR_MSG(info, "SOCKET_OWNER not set");
10777 return -EINVAL;
10778 }
10779
10780 if (!rdev->ops->tx_control_port ||
10781 !wiphy_ext_feature_isset(&rdev->wiphy,
10782 NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211))
10783 return -EOPNOTSUPP;
10784
10785 return 0;
10786}
10787
c0692b8f
JB
10788static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev,
10789 struct genl_info *info,
3dc27d25
JB
10790 struct cfg80211_crypto_settings *settings,
10791 int cipher_limit)
b23aa676 10792{
c0b2bbd8
JB
10793 memset(settings, 0, sizeof(*settings));
10794
b23aa676
SO
10795 settings->control_port = info->attrs[NL80211_ATTR_CONTROL_PORT];
10796
c0692b8f
JB
10797 if (info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]) {
10798 u16 proto;
7a087e74 10799
c0692b8f
JB
10800 proto = nla_get_u16(
10801 info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]);
10802 settings->control_port_ethertype = cpu_to_be16(proto);
10803 if (!(rdev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) &&
10804 proto != ETH_P_PAE)
10805 return -EINVAL;
10806 if (info->attrs[NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT])
10807 settings->control_port_no_encrypt = true;
10808 } else
10809 settings->control_port_ethertype = cpu_to_be16(ETH_P_PAE);
10810
64bf3d4b
DK
10811 if (info->attrs[NL80211_ATTR_CONTROL_PORT_OVER_NL80211]) {
10812 int r = validate_pae_over_nl80211(rdev, info);
10813
10814 if (r < 0)
10815 return r;
10816
10817 settings->control_port_over_nl80211 = true;
7f3f96ce
MT
10818
10819 if (info->attrs[NL80211_ATTR_CONTROL_PORT_NO_PREAUTH])
10820 settings->control_port_no_preauth = true;
64bf3d4b
DK
10821 }
10822
b23aa676
SO
10823 if (info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE]) {
10824 void *data;
10825 int len, i;
10826
10827 data = nla_data(info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE]);
10828 len = nla_len(info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE]);
10829 settings->n_ciphers_pairwise = len / sizeof(u32);
10830
10831 if (len % sizeof(u32))
10832 return -EINVAL;
10833
3dc27d25 10834 if (settings->n_ciphers_pairwise > cipher_limit)
b23aa676
SO
10835 return -EINVAL;
10836
10837 memcpy(settings->ciphers_pairwise, data, len);
10838
10839 for (i = 0; i < settings->n_ciphers_pairwise; i++)
38ba3c57
JM
10840 if (!cfg80211_supported_cipher_suite(
10841 &rdev->wiphy,
b23aa676
SO
10842 settings->ciphers_pairwise[i]))
10843 return -EINVAL;
10844 }
10845
10846 if (info->attrs[NL80211_ATTR_CIPHER_SUITE_GROUP]) {
10847 settings->cipher_group =
10848 nla_get_u32(info->attrs[NL80211_ATTR_CIPHER_SUITE_GROUP]);
38ba3c57
JM
10849 if (!cfg80211_supported_cipher_suite(&rdev->wiphy,
10850 settings->cipher_group))
b23aa676
SO
10851 return -EINVAL;
10852 }
10853
10854 if (info->attrs[NL80211_ATTR_WPA_VERSIONS]) {
10855 settings->wpa_versions =
10856 nla_get_u32(info->attrs[NL80211_ATTR_WPA_VERSIONS]);
10857 if (!nl80211_valid_wpa_versions(settings->wpa_versions))
10858 return -EINVAL;
10859 }
10860
10861 if (info->attrs[NL80211_ATTR_AKM_SUITES]) {
10862 void *data;
6d30240e 10863 int len;
b23aa676
SO
10864
10865 data = nla_data(info->attrs[NL80211_ATTR_AKM_SUITES]);
10866 len = nla_len(info->attrs[NL80211_ATTR_AKM_SUITES]);
10867 settings->n_akm_suites = len / sizeof(u32);
10868
10869 if (len % sizeof(u32))
10870 return -EINVAL;
10871
ecad3b0b 10872 if (settings->n_akm_suites > rdev->wiphy.max_num_akm_suites)
1b9ca027
JM
10873 return -EINVAL;
10874
b23aa676 10875 memcpy(settings->akm_suites, data, len);
b23aa676
SO
10876 }
10877
91b5ab62
EP
10878 if (info->attrs[NL80211_ATTR_PMK]) {
10879 if (nla_len(info->attrs[NL80211_ATTR_PMK]) != WLAN_PMK_LEN)
10880 return -EINVAL;
10881 if (!wiphy_ext_feature_isset(&rdev->wiphy,
f9662274
CHH
10882 NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK) &&
10883 !wiphy_ext_feature_isset(&rdev->wiphy,
10884 NL80211_EXT_FEATURE_4WAY_HANDSHAKE_AP_PSK))
91b5ab62
EP
10885 return -EINVAL;
10886 settings->psk = nla_data(info->attrs[NL80211_ATTR_PMK]);
10887 }
10888
26f7044e
CHH
10889 if (info->attrs[NL80211_ATTR_SAE_PASSWORD]) {
10890 if (!wiphy_ext_feature_isset(&rdev->wiphy,
2831a631
CHH
10891 NL80211_EXT_FEATURE_SAE_OFFLOAD) &&
10892 !wiphy_ext_feature_isset(&rdev->wiphy,
10893 NL80211_EXT_FEATURE_SAE_OFFLOAD_AP))
26f7044e
CHH
10894 return -EINVAL;
10895 settings->sae_pwd =
10896 nla_data(info->attrs[NL80211_ATTR_SAE_PASSWORD]);
10897 settings->sae_pwd_len =
10898 nla_len(info->attrs[NL80211_ATTR_SAE_PASSWORD]);
10899 }
10900
9f0ffa41
RD
10901 if (info->attrs[NL80211_ATTR_SAE_PWE])
10902 settings->sae_pwe =
10903 nla_get_u8(info->attrs[NL80211_ATTR_SAE_PWE]);
10904 else
10905 settings->sae_pwe = NL80211_SAE_PWE_UNSPECIFIED;
10906
b23aa676
SO
10907 return 0;
10908}
10909
9ecff10e
JB
10910static struct cfg80211_bss *nl80211_assoc_bss(struct cfg80211_registered_device *rdev,
10911 const u8 *ssid, int ssid_len,
96c06950 10912 struct nlattr **attrs)
9ecff10e
JB
10913{
10914 struct ieee80211_channel *chan;
10915 struct cfg80211_bss *bss;
10916 const u8 *bssid;
10917 u32 freq;
10918
10919 if (!attrs[NL80211_ATTR_MAC] || !attrs[NL80211_ATTR_WIPHY_FREQ])
10920 return ERR_PTR(-EINVAL);
10921
10922 bssid = nla_data(attrs[NL80211_ATTR_MAC]);
10923
10924 freq = MHZ_TO_KHZ(nla_get_u32(attrs[NL80211_ATTR_WIPHY_FREQ]));
10925 if (attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET])
10926 freq += nla_get_u32(attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET]);
10927
10928 chan = nl80211_get_valid_chan(&rdev->wiphy, freq);
10929 if (!chan)
10930 return ERR_PTR(-EINVAL);
10931
10932 bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid,
10933 ssid, ssid_len,
10934 IEEE80211_BSS_TYPE_ESS,
10935 IEEE80211_PRIVACY_ANY);
10936 if (!bss)
10937 return ERR_PTR(-ENOENT);
10938
9ecff10e
JB
10939 return bss;
10940}
10941
636a5d36
JM
10942static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
10943{
4c476991
JB
10944 struct cfg80211_registered_device *rdev = info->user_ptr[0];
10945 struct net_device *dev = info->user_ptr[1];
f62fab73 10946 struct cfg80211_assoc_request req = {};
d648c230 10947 struct nlattr **attrs = NULL;
96c06950 10948 const u8 *ap_addr, *ssid;
d648c230 10949 unsigned int link_id;
0f759448 10950 int err, ssid_len;
636a5d36 10951
bad29297
AZ
10952 if (dev->ieee80211_ptr->conn_owner_nlportid &&
10953 dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)
10954 return -EPERM;
10955
9ecff10e 10956 if (!info->attrs[NL80211_ATTR_SSID])
f4a11bb0
JB
10957 return -EINVAL;
10958
4c476991
JB
10959 if (!rdev->ops->assoc)
10960 return -EOPNOTSUPP;
636a5d36 10961
074ac8df 10962 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
10963 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
10964 return -EOPNOTSUPP;
eec60b03 10965
19957bb3
JB
10966 ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
10967 ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
636a5d36
JM
10968
10969 if (info->attrs[NL80211_ATTR_IE]) {
f62fab73
JB
10970 req.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
10971 req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
df35f316
JB
10972
10973 if (cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE,
10974 req.ie, req.ie_len)) {
10975 GENL_SET_ERR_MSG(info,
10976 "non-inheritance makes no sense");
10977 return -EINVAL;
10978 }
636a5d36
JM
10979 }
10980
dc6382ce 10981 if (info->attrs[NL80211_ATTR_USE_MFP]) {
4f5dadce 10982 enum nl80211_mfp mfp =
dc6382ce 10983 nla_get_u32(info->attrs[NL80211_ATTR_USE_MFP]);
4f5dadce 10984 if (mfp == NL80211_MFP_REQUIRED)
f62fab73 10985 req.use_mfp = true;
4c476991
JB
10986 else if (mfp != NL80211_MFP_NO)
10987 return -EINVAL;
dc6382ce
JM
10988 }
10989
3e5d7649 10990 if (info->attrs[NL80211_ATTR_PREV_BSSID])
f62fab73 10991 req.prev_bssid = nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]);
3e5d7649 10992
7e7c8926 10993 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HT]))
f62fab73 10994 req.flags |= ASSOC_REQ_DISABLE_HT;
7e7c8926
BG
10995
10996 if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
f62fab73
JB
10997 memcpy(&req.ht_capa_mask,
10998 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]),
10999 sizeof(req.ht_capa_mask));
7e7c8926
BG
11000
11001 if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
f62fab73 11002 if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
7e7c8926 11003 return -EINVAL;
f62fab73
JB
11004 memcpy(&req.ht_capa,
11005 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]),
11006 sizeof(req.ht_capa));
7e7c8926
BG
11007 }
11008
ee2aca34 11009 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_VHT]))
f62fab73 11010 req.flags |= ASSOC_REQ_DISABLE_VHT;
ee2aca34 11011
b6db0f89
BG
11012 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HE]))
11013 req.flags |= ASSOC_REQ_DISABLE_HE;
11014
36f84235
MS
11015 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_EHT]))
11016 req.flags |= ASSOC_REQ_DISABLE_EHT;
11017
ee2aca34 11018 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK])
f62fab73
JB
11019 memcpy(&req.vht_capa_mask,
11020 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]),
11021 sizeof(req.vht_capa_mask));
ee2aca34
JB
11022
11023 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY]) {
f62fab73 11024 if (!info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK])
ee2aca34 11025 return -EINVAL;
f62fab73
JB
11026 memcpy(&req.vht_capa,
11027 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]),
11028 sizeof(req.vht_capa));
ee2aca34
JB
11029 }
11030
bab5ab7d 11031 if (nla_get_flag(info->attrs[NL80211_ATTR_USE_RRM])) {
0c9ca11b
BL
11032 if (!((rdev->wiphy.features &
11033 NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES) &&
11034 (rdev->wiphy.features & NL80211_FEATURE_QUIET)) &&
11035 !wiphy_ext_feature_isset(&rdev->wiphy,
11036 NL80211_EXT_FEATURE_RRM))
bab5ab7d
AK
11037 return -EINVAL;
11038 req.flags |= ASSOC_REQ_USE_RRM;
11039 }
11040
348bd456
JM
11041 if (info->attrs[NL80211_ATTR_FILS_KEK]) {
11042 req.fils_kek = nla_data(info->attrs[NL80211_ATTR_FILS_KEK]);
11043 req.fils_kek_len = nla_len(info->attrs[NL80211_ATTR_FILS_KEK]);
11044 if (!info->attrs[NL80211_ATTR_FILS_NONCES])
11045 return -EINVAL;
11046 req.fils_nonces =
11047 nla_data(info->attrs[NL80211_ATTR_FILS_NONCES]);
11048 }
11049
d2b7588a
TP
11050 if (info->attrs[NL80211_ATTR_S1G_CAPABILITY_MASK]) {
11051 if (!info->attrs[NL80211_ATTR_S1G_CAPABILITY])
11052 return -EINVAL;
11053 memcpy(&req.s1g_capa_mask,
11054 nla_data(info->attrs[NL80211_ATTR_S1G_CAPABILITY_MASK]),
11055 sizeof(req.s1g_capa_mask));
11056 }
11057
11058 if (info->attrs[NL80211_ATTR_S1G_CAPABILITY]) {
11059 if (!info->attrs[NL80211_ATTR_S1G_CAPABILITY_MASK])
11060 return -EINVAL;
11061 memcpy(&req.s1g_capa,
11062 nla_data(info->attrs[NL80211_ATTR_S1G_CAPABILITY]),
11063 sizeof(req.s1g_capa));
11064 }
11065
d648c230
JB
11066 req.link_id = nl80211_link_id_or_invalid(info->attrs);
11067
11068 if (info->attrs[NL80211_ATTR_MLO_LINKS]) {
11069 unsigned int attrsize = NUM_NL80211_ATTR * sizeof(*attrs);
11070 struct nlattr *link;
11071 int rem = 0;
11072
11073 if (req.link_id < 0)
11074 return -EINVAL;
11075
11076 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_MLO))
11077 return -EINVAL;
11078
11079 if (info->attrs[NL80211_ATTR_MAC] ||
11080 info->attrs[NL80211_ATTR_WIPHY_FREQ] ||
11081 !info->attrs[NL80211_ATTR_MLD_ADDR])
11082 return -EINVAL;
11083
11084 req.ap_mld_addr = nla_data(info->attrs[NL80211_ATTR_MLD_ADDR]);
96c06950 11085 ap_addr = req.ap_mld_addr;
d648c230
JB
11086
11087 attrs = kzalloc(attrsize, GFP_KERNEL);
11088 if (!attrs)
11089 return -ENOMEM;
11090
11091 nla_for_each_nested(link,
11092 info->attrs[NL80211_ATTR_MLO_LINKS],
11093 rem) {
11094 memset(attrs, 0, attrsize);
11095
11096 nla_parse_nested(attrs, NL80211_ATTR_MAX,
11097 link, NULL, NULL);
11098
11099 if (!attrs[NL80211_ATTR_MLO_LINK_ID]) {
11100 err = -EINVAL;
11101 goto free;
11102 }
11103
11104 link_id = nla_get_u8(attrs[NL80211_ATTR_MLO_LINK_ID]);
11105 /* cannot use the same link ID again */
11106 if (req.links[link_id].bss) {
11107 err = -EINVAL;
11108 goto free;
11109 }
11110 req.links[link_id].bss =
96c06950 11111 nl80211_assoc_bss(rdev, ssid, ssid_len, attrs);
d648c230
JB
11112 if (IS_ERR(req.links[link_id].bss)) {
11113 err = PTR_ERR(req.links[link_id].bss);
9b6bf4d6 11114 req.links[link_id].bss = NULL;
d648c230
JB
11115 goto free;
11116 }
11117
11118 if (attrs[NL80211_ATTR_IE]) {
11119 req.links[link_id].elems =
11120 nla_data(attrs[NL80211_ATTR_IE]);
11121 req.links[link_id].elems_len =
11122 nla_len(attrs[NL80211_ATTR_IE]);
df35f316
JB
11123
11124 if (cfg80211_find_elem(WLAN_EID_FRAGMENT,
11125 req.links[link_id].elems,
11126 req.links[link_id].elems_len)) {
11127 GENL_SET_ERR_MSG(info,
11128 "cannot deal with fragmentation");
11129 err = -EINVAL;
11130 goto free;
11131 }
11132
11133 if (cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE,
11134 req.links[link_id].elems,
11135 req.links[link_id].elems_len)) {
11136 GENL_SET_ERR_MSG(info,
11137 "cannot deal with non-inheritance");
11138 err = -EINVAL;
11139 goto free;
11140 }
d648c230 11141 }
6cf963ed
IP
11142
11143 req.links[link_id].disabled =
11144 nla_get_flag(attrs[NL80211_ATTR_MLO_LINK_DISABLED]);
d648c230
JB
11145 }
11146
11147 if (!req.links[req.link_id].bss) {
11148 err = -EINVAL;
11149 goto free;
11150 }
11151
34d76a14
JB
11152 if (req.links[req.link_id].elems_len) {
11153 GENL_SET_ERR_MSG(info,
11154 "cannot have per-link elems on assoc link");
11155 err = -EINVAL;
11156 goto free;
11157 }
11158
6cf963ed
IP
11159 if (req.links[req.link_id].disabled) {
11160 GENL_SET_ERR_MSG(info,
11161 "cannot have assoc link disabled");
11162 err = -EINVAL;
11163 goto free;
11164 }
11165
d648c230
JB
11166 kfree(attrs);
11167 attrs = NULL;
11168 } else {
11169 if (req.link_id >= 0)
11170 return -EINVAL;
11171
96c06950 11172 req.bss = nl80211_assoc_bss(rdev, ssid, ssid_len, info->attrs);
d648c230
JB
11173 if (IS_ERR(req.bss))
11174 return PTR_ERR(req.bss);
96c06950 11175 ap_addr = req.bss->bssid;
d648c230 11176 }
0f759448 11177
f62fab73 11178 err = nl80211_crypto_settings(rdev, info, &req.crypto, 1);
91bf9b26
JB
11179 if (!err) {
11180 wdev_lock(dev->ieee80211_ptr);
bd2522b1 11181
0f759448 11182 err = cfg80211_mlme_assoc(rdev, dev, &req);
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
AZ
11189 }
11190
91bf9b26
JB
11191 wdev_unlock(dev->ieee80211_ptr);
11192 }
636a5d36 11193
d648c230
JB
11194free:
11195 for (link_id = 0; link_id < ARRAY_SIZE(req.links); link_id++)
11196 cfg80211_put_bss(&rdev->wiphy, req.links[link_id].bss);
0f759448 11197 cfg80211_put_bss(&rdev->wiphy, req.bss);
d648c230 11198 kfree(attrs);
0f759448 11199
636a5d36
JM
11200 return err;
11201}
11202
11203static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info)
11204{
4c476991
JB
11205 struct cfg80211_registered_device *rdev = info->user_ptr[0];
11206 struct net_device *dev = info->user_ptr[1];
19957bb3 11207 const u8 *ie = NULL, *bssid;
91bf9b26 11208 int ie_len = 0, err;
19957bb3 11209 u16 reason_code;
d5cdfacb 11210 bool local_state_change;
636a5d36 11211
bad29297
AZ
11212 if (dev->ieee80211_ptr->conn_owner_nlportid &&
11213 dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)
11214 return -EPERM;
11215
f4a11bb0
JB
11216 if (!info->attrs[NL80211_ATTR_MAC])
11217 return -EINVAL;
11218
11219 if (!info->attrs[NL80211_ATTR_REASON_CODE])
11220 return -EINVAL;
11221
4c476991
JB
11222 if (!rdev->ops->deauth)
11223 return -EOPNOTSUPP;
636a5d36 11224
074ac8df 11225 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
11226 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
11227 return -EOPNOTSUPP;
eec60b03 11228
19957bb3 11229 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
636a5d36 11230
19957bb3
JB
11231 reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
11232 if (reason_code == 0) {
f4a11bb0 11233 /* Reason Code 0 is reserved */
4c476991 11234 return -EINVAL;
255e737e 11235 }
636a5d36
JM
11236
11237 if (info->attrs[NL80211_ATTR_IE]) {
19957bb3
JB
11238 ie = nla_data(info->attrs[NL80211_ATTR_IE]);
11239 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
636a5d36
JM
11240 }
11241
d5cdfacb
JM
11242 local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
11243
91bf9b26
JB
11244 wdev_lock(dev->ieee80211_ptr);
11245 err = cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code,
11246 local_state_change);
11247 wdev_unlock(dev->ieee80211_ptr);
11248 return err;
636a5d36
JM
11249}
11250
11251static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info)
11252{
4c476991
JB
11253 struct cfg80211_registered_device *rdev = info->user_ptr[0];
11254 struct net_device *dev = info->user_ptr[1];
19957bb3 11255 const u8 *ie = NULL, *bssid;
91bf9b26 11256 int ie_len = 0, err;
19957bb3 11257 u16 reason_code;
d5cdfacb 11258 bool local_state_change;
636a5d36 11259
bad29297
AZ
11260 if (dev->ieee80211_ptr->conn_owner_nlportid &&
11261 dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)
11262 return -EPERM;
11263
f4a11bb0
JB
11264 if (!info->attrs[NL80211_ATTR_MAC])
11265 return -EINVAL;
11266
11267 if (!info->attrs[NL80211_ATTR_REASON_CODE])
11268 return -EINVAL;
11269
4c476991
JB
11270 if (!rdev->ops->disassoc)
11271 return -EOPNOTSUPP;
636a5d36 11272
074ac8df 11273 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
11274 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
11275 return -EOPNOTSUPP;
eec60b03 11276
19957bb3 11277 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
636a5d36 11278
19957bb3
JB
11279 reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
11280 if (reason_code == 0) {
f4a11bb0 11281 /* Reason Code 0 is reserved */
4c476991 11282 return -EINVAL;
255e737e 11283 }
636a5d36
JM
11284
11285 if (info->attrs[NL80211_ATTR_IE]) {
19957bb3
JB
11286 ie = nla_data(info->attrs[NL80211_ATTR_IE]);
11287 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
636a5d36
JM
11288 }
11289
d5cdfacb
JM
11290 local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
11291
91bf9b26
JB
11292 wdev_lock(dev->ieee80211_ptr);
11293 err = cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code,
11294 local_state_change);
11295 wdev_unlock(dev->ieee80211_ptr);
11296 return err;
636a5d36
JM
11297}
11298
dd5b4cc7
FF
11299static bool
11300nl80211_parse_mcast_rate(struct cfg80211_registered_device *rdev,
57fbcce3 11301 int mcast_rate[NUM_NL80211_BANDS],
dd5b4cc7
FF
11302 int rateval)
11303{
11304 struct wiphy *wiphy = &rdev->wiphy;
11305 bool found = false;
11306 int band, i;
11307
57fbcce3 11308 for (band = 0; band < NUM_NL80211_BANDS; band++) {
dd5b4cc7
FF
11309 struct ieee80211_supported_band *sband;
11310
11311 sband = wiphy->bands[band];
11312 if (!sband)
11313 continue;
11314
11315 for (i = 0; i < sband->n_bitrates; i++) {
11316 if (sband->bitrates[i].bitrate == rateval) {
11317 mcast_rate[band] = i + 1;
11318 found = true;
11319 break;
11320 }
11321 }
11322 }
11323
11324 return found;
11325}
11326
04a773ad
JB
11327static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
11328{
4c476991
JB
11329 struct cfg80211_registered_device *rdev = info->user_ptr[0];
11330 struct net_device *dev = info->user_ptr[1];
04a773ad
JB
11331 struct cfg80211_ibss_params ibss;
11332 struct wiphy *wiphy;
fffd0934 11333 struct cfg80211_cached_keys *connkeys = NULL;
04a773ad
JB
11334 int err;
11335
8e30bc55
JB
11336 memset(&ibss, 0, sizeof(ibss));
11337
683b6d3b 11338 if (!info->attrs[NL80211_ATTR_SSID] ||
04a773ad
JB
11339 !nla_len(info->attrs[NL80211_ATTR_SSID]))
11340 return -EINVAL;
11341
8e30bc55
JB
11342 ibss.beacon_interval = 100;
11343
12d20fc9 11344 if (info->attrs[NL80211_ATTR_BEACON_INTERVAL])
8e30bc55
JB
11345 ibss.beacon_interval =
11346 nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
12d20fc9 11347
0c317a02
PK
11348 err = cfg80211_validate_beacon_int(rdev, NL80211_IFTYPE_ADHOC,
11349 ibss.beacon_interval);
12d20fc9
PK
11350 if (err)
11351 return err;
8e30bc55 11352
4c476991
JB
11353 if (!rdev->ops->join_ibss)
11354 return -EOPNOTSUPP;
04a773ad 11355
4c476991
JB
11356 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC)
11357 return -EOPNOTSUPP;
04a773ad 11358
79c97e97 11359 wiphy = &rdev->wiphy;
04a773ad 11360
39193498 11361 if (info->attrs[NL80211_ATTR_MAC]) {
04a773ad 11362 ibss.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
39193498
JB
11363
11364 if (!is_valid_ether_addr(ibss.bssid))
11365 return -EINVAL;
11366 }
04a773ad
JB
11367 ibss.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
11368 ibss.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
11369
11370 if (info->attrs[NL80211_ATTR_IE]) {
11371 ibss.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
11372 ibss.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
11373 }
11374
683b6d3b
JB
11375 err = nl80211_parse_chandef(rdev, info, &ibss.chandef);
11376 if (err)
11377 return err;
04a773ad 11378
174e0cd2
IP
11379 if (!cfg80211_reg_can_beacon(&rdev->wiphy, &ibss.chandef,
11380 NL80211_IFTYPE_ADHOC))
54858ee5
AS
11381 return -EINVAL;
11382
2f301ab2 11383 switch (ibss.chandef.width) {
bf372645
SW
11384 case NL80211_CHAN_WIDTH_5:
11385 case NL80211_CHAN_WIDTH_10:
2f301ab2
SW
11386 case NL80211_CHAN_WIDTH_20_NOHT:
11387 break;
11388 case NL80211_CHAN_WIDTH_20:
11389 case NL80211_CHAN_WIDTH_40:
ffc11991
JD
11390 if (!(rdev->wiphy.features & NL80211_FEATURE_HT_IBSS))
11391 return -EINVAL;
11392 break;
11393 case NL80211_CHAN_WIDTH_80:
11394 case NL80211_CHAN_WIDTH_80P80:
11395 case NL80211_CHAN_WIDTH_160:
11396 if (!(rdev->wiphy.features & NL80211_FEATURE_HT_IBSS))
11397 return -EINVAL;
11398 if (!wiphy_ext_feature_isset(&rdev->wiphy,
11399 NL80211_EXT_FEATURE_VHT_IBSS))
11400 return -EINVAL;
11401 break;
3743bec6
JD
11402 case NL80211_CHAN_WIDTH_320:
11403 return -EINVAL;
2f301ab2 11404 default:
c04d6150 11405 return -EINVAL;
2f301ab2 11406 }
db9c64cf 11407
04a773ad 11408 ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED];
fffd0934
JB
11409 ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY];
11410
fbd2c8dc
TP
11411 if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) {
11412 u8 *rates =
11413 nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
11414 int n_rates =
11415 nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
11416 struct ieee80211_supported_band *sband =
683b6d3b 11417 wiphy->bands[ibss.chandef.chan->band];
fbd2c8dc 11418
34850ab2
JB
11419 err = ieee80211_get_ratemask(sband, rates, n_rates,
11420 &ibss.basic_rates);
11421 if (err)
11422 return err;
fbd2c8dc 11423 }
dd5b4cc7 11424
803768f5
SW
11425 if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
11426 memcpy(&ibss.ht_capa_mask,
11427 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]),
11428 sizeof(ibss.ht_capa_mask));
11429
11430 if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
11431 if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
11432 return -EINVAL;
11433 memcpy(&ibss.ht_capa,
11434 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]),
11435 sizeof(ibss.ht_capa));
11436 }
11437
dd5b4cc7
FF
11438 if (info->attrs[NL80211_ATTR_MCAST_RATE] &&
11439 !nl80211_parse_mcast_rate(rdev, ibss.mcast_rate,
11440 nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE])))
11441 return -EINVAL;
fbd2c8dc 11442
4c476991 11443 if (ibss.privacy && info->attrs[NL80211_ATTR_KEYS]) {
de7044ee
SM
11444 bool no_ht = false;
11445
768075eb 11446 connkeys = nl80211_parse_connkeys(rdev, info, &no_ht);
4c476991
JB
11447 if (IS_ERR(connkeys))
11448 return PTR_ERR(connkeys);
de7044ee 11449
3d9d1d66
JB
11450 if ((ibss.chandef.width != NL80211_CHAN_WIDTH_20_NOHT) &&
11451 no_ht) {
453431a5 11452 kfree_sensitive(connkeys);
de7044ee
SM
11453 return -EINVAL;
11454 }
4c476991 11455 }
04a773ad 11456
267335d6
AQ
11457 ibss.control_port =
11458 nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT]);
11459
c3bfe1f6
DK
11460 if (info->attrs[NL80211_ATTR_CONTROL_PORT_OVER_NL80211]) {
11461 int r = validate_pae_over_nl80211(rdev, info);
11462
d350a0f4 11463 if (r < 0) {
453431a5 11464 kfree_sensitive(connkeys);
c3bfe1f6 11465 return r;
d350a0f4 11466 }
c3bfe1f6
DK
11467
11468 ibss.control_port_over_nl80211 = true;
11469 }
11470
5336fa88
SW
11471 ibss.userspace_handles_dfs =
11472 nla_get_flag(info->attrs[NL80211_ATTR_HANDLE_DFS]);
11473
f8d16d3e
DK
11474 wdev_lock(dev->ieee80211_ptr);
11475 err = __cfg80211_join_ibss(rdev, dev, &ibss, connkeys);
fffd0934 11476 if (err)
453431a5 11477 kfree_sensitive(connkeys);
f8d16d3e
DK
11478 else if (info->attrs[NL80211_ATTR_SOCKET_OWNER])
11479 dev->ieee80211_ptr->conn_owner_nlportid = info->snd_portid;
11480 wdev_unlock(dev->ieee80211_ptr);
11481
04a773ad
JB
11482 return err;
11483}
11484
11485static int nl80211_leave_ibss(struct sk_buff *skb, struct genl_info *info)
11486{
4c476991
JB
11487 struct cfg80211_registered_device *rdev = info->user_ptr[0];
11488 struct net_device *dev = info->user_ptr[1];
04a773ad 11489
4c476991
JB
11490 if (!rdev->ops->leave_ibss)
11491 return -EOPNOTSUPP;
04a773ad 11492
4c476991
JB
11493 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC)
11494 return -EOPNOTSUPP;
04a773ad 11495
4c476991 11496 return cfg80211_leave_ibss(rdev, dev, false);
04a773ad
JB
11497}
11498
f4e583c8
AQ
11499static int nl80211_set_mcast_rate(struct sk_buff *skb, struct genl_info *info)
11500{
11501 struct cfg80211_registered_device *rdev = info->user_ptr[0];
11502 struct net_device *dev = info->user_ptr[1];
57fbcce3 11503 int mcast_rate[NUM_NL80211_BANDS];
f4e583c8 11504 u32 nla_rate;
f4e583c8
AQ
11505
11506 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC &&
876dc930
BVB
11507 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT &&
11508 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_OCB)
f4e583c8
AQ
11509 return -EOPNOTSUPP;
11510
11511 if (!rdev->ops->set_mcast_rate)
11512 return -EOPNOTSUPP;
11513
11514 memset(mcast_rate, 0, sizeof(mcast_rate));
11515
11516 if (!info->attrs[NL80211_ATTR_MCAST_RATE])
11517 return -EINVAL;
11518
11519 nla_rate = nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE]);
11520 if (!nl80211_parse_mcast_rate(rdev, mcast_rate, nla_rate))
11521 return -EINVAL;
11522
a21cd7d6 11523 return rdev_set_mcast_rate(rdev, dev, mcast_rate);
f4e583c8
AQ
11524}
11525
ad7e718c
JB
11526static struct sk_buff *
11527__cfg80211_alloc_vendor_skb(struct cfg80211_registered_device *rdev,
6c09e791
AK
11528 struct wireless_dev *wdev, int approxlen,
11529 u32 portid, u32 seq, enum nl80211_commands cmd,
567ffc35
JB
11530 enum nl80211_attrs attr,
11531 const struct nl80211_vendor_cmd_info *info,
11532 gfp_t gfp)
ad7e718c
JB
11533{
11534 struct sk_buff *skb;
11535 void *hdr;
11536 struct nlattr *data;
11537
11538 skb = nlmsg_new(approxlen + 100, gfp);
11539 if (!skb)
11540 return NULL;
11541
11542 hdr = nl80211hdr_put(skb, portid, seq, 0, cmd);
11543 if (!hdr) {
11544 kfree_skb(skb);
11545 return NULL;
11546 }
11547
11548 if (nla_put_u32(skb, NL80211_ATTR_WIPHY, rdev->wiphy_idx))
11549 goto nla_put_failure;
567ffc35
JB
11550
11551 if (info) {
11552 if (nla_put_u32(skb, NL80211_ATTR_VENDOR_ID,
11553 info->vendor_id))
11554 goto nla_put_failure;
11555 if (nla_put_u32(skb, NL80211_ATTR_VENDOR_SUBCMD,
11556 info->subcmd))
11557 goto nla_put_failure;
11558 }
11559
6c09e791 11560 if (wdev) {
2dad624e
ND
11561 if (nla_put_u64_64bit(skb, NL80211_ATTR_WDEV,
11562 wdev_id(wdev), NL80211_ATTR_PAD))
6c09e791
AK
11563 goto nla_put_failure;
11564 if (wdev->netdev &&
11565 nla_put_u32(skb, NL80211_ATTR_IFINDEX,
11566 wdev->netdev->ifindex))
11567 goto nla_put_failure;
11568 }
11569
ae0be8de 11570 data = nla_nest_start_noflag(skb, attr);
76e1fb4b
JB
11571 if (!data)
11572 goto nla_put_failure;
ad7e718c
JB
11573
11574 ((void **)skb->cb)[0] = rdev;
11575 ((void **)skb->cb)[1] = hdr;
11576 ((void **)skb->cb)[2] = data;
11577
11578 return skb;
11579
11580 nla_put_failure:
11581 kfree_skb(skb);
11582 return NULL;
11583}
f4e583c8 11584
e03ad6ea 11585struct sk_buff *__cfg80211_alloc_event_skb(struct wiphy *wiphy,
6c09e791 11586 struct wireless_dev *wdev,
e03ad6ea
JB
11587 enum nl80211_commands cmd,
11588 enum nl80211_attrs attr,
55c1fdf0 11589 unsigned int portid,
e03ad6ea
JB
11590 int vendor_event_idx,
11591 int approxlen, gfp_t gfp)
11592{
f26cbf40 11593 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
e03ad6ea
JB
11594 const struct nl80211_vendor_cmd_info *info;
11595
11596 switch (cmd) {
11597 case NL80211_CMD_TESTMODE:
11598 if (WARN_ON(vendor_event_idx != -1))
11599 return NULL;
11600 info = NULL;
11601 break;
11602 case NL80211_CMD_VENDOR:
11603 if (WARN_ON(vendor_event_idx < 0 ||
11604 vendor_event_idx >= wiphy->n_vendor_events))
11605 return NULL;
11606 info = &wiphy->vendor_events[vendor_event_idx];
11607 break;
11608 default:
11609 WARN_ON(1);
11610 return NULL;
11611 }
11612
55c1fdf0 11613 return __cfg80211_alloc_vendor_skb(rdev, wdev, approxlen, portid, 0,
e03ad6ea
JB
11614 cmd, attr, info, gfp);
11615}
11616EXPORT_SYMBOL(__cfg80211_alloc_event_skb);
11617
11618void __cfg80211_send_event_skb(struct sk_buff *skb, gfp_t gfp)
11619{
11620 struct cfg80211_registered_device *rdev = ((void **)skb->cb)[0];
11621 void *hdr = ((void **)skb->cb)[1];
55c1fdf0 11622 struct nlmsghdr *nlhdr = nlmsg_hdr(skb);
e03ad6ea
JB
11623 struct nlattr *data = ((void **)skb->cb)[2];
11624 enum nl80211_multicast_groups mcgrp = NL80211_MCGRP_TESTMODE;
11625
bd8c78e7
JB
11626 /* clear CB data for netlink core to own from now on */
11627 memset(skb->cb, 0, sizeof(skb->cb));
11628
e03ad6ea
JB
11629 nla_nest_end(skb, data);
11630 genlmsg_end(skb, hdr);
11631
55c1fdf0
JB
11632 if (nlhdr->nlmsg_pid) {
11633 genlmsg_unicast(wiphy_net(&rdev->wiphy), skb,
11634 nlhdr->nlmsg_pid);
11635 } else {
11636 if (data->nla_type == NL80211_ATTR_VENDOR_DATA)
11637 mcgrp = NL80211_MCGRP_VENDOR;
e03ad6ea 11638
55c1fdf0
JB
11639 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
11640 skb, 0, mcgrp, gfp);
11641 }
e03ad6ea
JB
11642}
11643EXPORT_SYMBOL(__cfg80211_send_event_skb);
11644
aff89a9b 11645#ifdef CONFIG_NL80211_TESTMODE
aff89a9b
JB
11646static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info)
11647{
4c476991 11648 struct cfg80211_registered_device *rdev = info->user_ptr[0];
a05829a7 11649 struct wireless_dev *wdev;
aff89a9b
JB
11650 int err;
11651
a05829a7
JB
11652 lockdep_assert_held(&rdev->wiphy.mtx);
11653
11654 wdev = __cfg80211_wdev_from_attrs(rdev, genl_info_net(info),
11655 info->attrs);
11656
fc73f11f
DS
11657 if (!rdev->ops->testmode_cmd)
11658 return -EOPNOTSUPP;
11659
11660 if (IS_ERR(wdev)) {
11661 err = PTR_ERR(wdev);
11662 if (err != -EINVAL)
11663 return err;
11664 wdev = NULL;
11665 } else if (wdev->wiphy != &rdev->wiphy) {
11666 return -EINVAL;
11667 }
11668
aff89a9b
JB
11669 if (!info->attrs[NL80211_ATTR_TESTDATA])
11670 return -EINVAL;
11671
ad7e718c 11672 rdev->cur_cmd_info = info;
fc73f11f 11673 err = rdev_testmode_cmd(rdev, wdev,
aff89a9b
JB
11674 nla_data(info->attrs[NL80211_ATTR_TESTDATA]),
11675 nla_len(info->attrs[NL80211_ATTR_TESTDATA]));
ad7e718c 11676 rdev->cur_cmd_info = NULL;
aff89a9b 11677
aff89a9b
JB
11678 return err;
11679}
11680
71063f0e
WYG
11681static int nl80211_testmode_dump(struct sk_buff *skb,
11682 struct netlink_callback *cb)
11683{
00918d33 11684 struct cfg80211_registered_device *rdev;
50508d94 11685 struct nlattr **attrbuf = NULL;
71063f0e
WYG
11686 int err;
11687 long phy_idx;
11688 void *data = NULL;
11689 int data_len = 0;
11690
5fe231e8
JB
11691 rtnl_lock();
11692
71063f0e
WYG
11693 if (cb->args[0]) {
11694 /*
11695 * 0 is a valid index, but not valid for args[0],
11696 * so we need to offset by 1.
11697 */
11698 phy_idx = cb->args[0] - 1;
a4956dca
LC
11699
11700 rdev = cfg80211_rdev_by_wiphy_idx(phy_idx);
11701 if (!rdev) {
11702 err = -ENOENT;
11703 goto out_err;
11704 }
71063f0e 11705 } else {
50508d94
JB
11706 attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf),
11707 GFP_KERNEL);
11708 if (!attrbuf) {
11709 err = -ENOMEM;
11710 goto out_err;
11711 }
c90c39da 11712
8cb08174
JB
11713 err = nlmsg_parse_deprecated(cb->nlh,
11714 GENL_HDRLEN + nl80211_fam.hdrsize,
11715 attrbuf, nl80211_fam.maxattr,
11716 nl80211_policy, NULL);
71063f0e 11717 if (err)
5fe231e8 11718 goto out_err;
00918d33 11719
c90c39da 11720 rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk), attrbuf);
2bd7e35d 11721 if (IS_ERR(rdev)) {
5fe231e8
JB
11722 err = PTR_ERR(rdev);
11723 goto out_err;
00918d33 11724 }
2bd7e35d 11725 phy_idx = rdev->wiphy_idx;
2bd7e35d 11726
c90c39da
JB
11727 if (attrbuf[NL80211_ATTR_TESTDATA])
11728 cb->args[1] = (long)attrbuf[NL80211_ATTR_TESTDATA];
71063f0e
WYG
11729 }
11730
11731 if (cb->args[1]) {
11732 data = nla_data((void *)cb->args[1]);
11733 data_len = nla_len((void *)cb->args[1]);
11734 }
11735
00918d33 11736 if (!rdev->ops->testmode_dump) {
71063f0e
WYG
11737 err = -EOPNOTSUPP;
11738 goto out_err;
11739 }
11740
11741 while (1) {
15e47304 11742 void *hdr = nl80211hdr_put(skb, NETLINK_CB(cb->skb).portid,
71063f0e
WYG
11743 cb->nlh->nlmsg_seq, NLM_F_MULTI,
11744 NL80211_CMD_TESTMODE);
11745 struct nlattr *tmdata;
11746
cb35fba3
DC
11747 if (!hdr)
11748 break;
11749
9360ffd1 11750 if (nla_put_u32(skb, NL80211_ATTR_WIPHY, phy_idx)) {
71063f0e
WYG
11751 genlmsg_cancel(skb, hdr);
11752 break;
11753 }
11754
ae0be8de 11755 tmdata = nla_nest_start_noflag(skb, NL80211_ATTR_TESTDATA);
71063f0e
WYG
11756 if (!tmdata) {
11757 genlmsg_cancel(skb, hdr);
11758 break;
11759 }
e35e4d28 11760 err = rdev_testmode_dump(rdev, skb, cb, data, data_len);
71063f0e
WYG
11761 nla_nest_end(skb, tmdata);
11762
11763 if (err == -ENOBUFS || err == -ENOENT) {
11764 genlmsg_cancel(skb, hdr);
11765 break;
11766 } else if (err) {
11767 genlmsg_cancel(skb, hdr);
11768 goto out_err;
11769 }
11770
11771 genlmsg_end(skb, hdr);
11772 }
11773
11774 err = skb->len;
11775 /* see above */
11776 cb->args[0] = phy_idx + 1;
11777 out_err:
50508d94 11778 kfree(attrbuf);
5fe231e8 11779 rtnl_unlock();
71063f0e
WYG
11780 return err;
11781}
aff89a9b
JB
11782#endif
11783
b23aa676
SO
11784static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
11785{
4c476991
JB
11786 struct cfg80211_registered_device *rdev = info->user_ptr[0];
11787 struct net_device *dev = info->user_ptr[1];
b23aa676
SO
11788 struct cfg80211_connect_params connect;
11789 struct wiphy *wiphy;
fffd0934 11790 struct cfg80211_cached_keys *connkeys = NULL;
942ba88b 11791 u32 freq = 0;
b23aa676
SO
11792 int err;
11793
11794 memset(&connect, 0, sizeof(connect));
11795
b23aa676
SO
11796 if (!info->attrs[NL80211_ATTR_SSID] ||
11797 !nla_len(info->attrs[NL80211_ATTR_SSID]))
11798 return -EINVAL;
11799
11800 if (info->attrs[NL80211_ATTR_AUTH_TYPE]) {
11801 connect.auth_type =
11802 nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
e39e5b5e
JM
11803 if (!nl80211_valid_auth_type(rdev, connect.auth_type,
11804 NL80211_CMD_CONNECT))
b23aa676
SO
11805 return -EINVAL;
11806 } else
11807 connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
11808
11809 connect.privacy = info->attrs[NL80211_ATTR_PRIVACY];
11810
3a00df57
AS
11811 if (info->attrs[NL80211_ATTR_WANT_1X_4WAY_HS] &&
11812 !wiphy_ext_feature_isset(&rdev->wiphy,
11813 NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X))
11814 return -EINVAL;
11815 connect.want_1x = info->attrs[NL80211_ATTR_WANT_1X_4WAY_HS];
11816
c0692b8f 11817 err = nl80211_crypto_settings(rdev, info, &connect.crypto,
3dc27d25 11818 NL80211_MAX_NR_CIPHER_SUITES);
b23aa676
SO
11819 if (err)
11820 return err;
b23aa676 11821
074ac8df 11822 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
11823 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
11824 return -EOPNOTSUPP;
b23aa676 11825
79c97e97 11826 wiphy = &rdev->wiphy;
b23aa676 11827
4486ea98
BS
11828 connect.bg_scan_period = -1;
11829 if (info->attrs[NL80211_ATTR_BG_SCAN_PERIOD] &&
11830 (wiphy->flags & WIPHY_FLAG_SUPPORTS_FW_ROAM)) {
11831 connect.bg_scan_period =
11832 nla_get_u16(info->attrs[NL80211_ATTR_BG_SCAN_PERIOD]);
11833 }
11834
b23aa676
SO
11835 if (info->attrs[NL80211_ATTR_MAC])
11836 connect.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
1df4a510
JM
11837 else if (info->attrs[NL80211_ATTR_MAC_HINT])
11838 connect.bssid_hint =
11839 nla_data(info->attrs[NL80211_ATTR_MAC_HINT]);
b23aa676
SO
11840 connect.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
11841 connect.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
11842
11843 if (info->attrs[NL80211_ATTR_IE]) {
11844 connect.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
11845 connect.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
11846 }
11847
cee00a95
JM
11848 if (info->attrs[NL80211_ATTR_USE_MFP]) {
11849 connect.mfp = nla_get_u32(info->attrs[NL80211_ATTR_USE_MFP]);
65026002
EG
11850 if (connect.mfp == NL80211_MFP_OPTIONAL &&
11851 !wiphy_ext_feature_isset(&rdev->wiphy,
11852 NL80211_EXT_FEATURE_MFP_OPTIONAL))
11853 return -EOPNOTSUPP;
cee00a95
JM
11854 } else {
11855 connect.mfp = NL80211_MFP_NO;
11856 }
11857
ba6fbacf
JM
11858 if (info->attrs[NL80211_ATTR_PREV_BSSID])
11859 connect.prev_bssid =
11860 nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]);
11861
942ba88b
TP
11862 if (info->attrs[NL80211_ATTR_WIPHY_FREQ])
11863 freq = MHZ_TO_KHZ(nla_get_u32(
11864 info->attrs[NL80211_ATTR_WIPHY_FREQ]));
11865 if (info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET])
11866 freq +=
11867 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET]);
11868
11869 if (freq) {
11870 connect.channel = nl80211_get_valid_chan(wiphy, freq);
664834de 11871 if (!connect.channel)
1df4a510
JM
11872 return -EINVAL;
11873 } else if (info->attrs[NL80211_ATTR_WIPHY_FREQ_HINT]) {
942ba88b
TP
11874 freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ_HINT]);
11875 freq = MHZ_TO_KHZ(freq);
11876 connect.channel_hint = nl80211_get_valid_chan(wiphy, freq);
664834de 11877 if (!connect.channel_hint)
4c476991 11878 return -EINVAL;
b23aa676
SO
11879 }
11880
2a38075c
AAL
11881 if (info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]) {
11882 connect.edmg.channels =
11883 nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]);
11884
11885 if (info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG])
11886 connect.edmg.bw_config =
11887 nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG]);
11888 }
11889
fffd0934 11890 if (connect.privacy && info->attrs[NL80211_ATTR_KEYS]) {
768075eb 11891 connkeys = nl80211_parse_connkeys(rdev, info, NULL);
4c476991
JB
11892 if (IS_ERR(connkeys))
11893 return PTR_ERR(connkeys);
fffd0934
JB
11894 }
11895
7e7c8926
BG
11896 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HT]))
11897 connect.flags |= ASSOC_REQ_DISABLE_HT;
11898
11899 if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
11900 memcpy(&connect.ht_capa_mask,
11901 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]),
11902 sizeof(connect.ht_capa_mask));
11903
11904 if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
b4e4f47e 11905 if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]) {
453431a5 11906 kfree_sensitive(connkeys);
7e7c8926 11907 return -EINVAL;
b4e4f47e 11908 }
7e7c8926
BG
11909 memcpy(&connect.ht_capa,
11910 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]),
11911 sizeof(connect.ht_capa));
11912 }
11913
ee2aca34
JB
11914 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_VHT]))
11915 connect.flags |= ASSOC_REQ_DISABLE_VHT;
11916
b6db0f89
BG
11917 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HE]))
11918 connect.flags |= ASSOC_REQ_DISABLE_HE;
11919
36f84235
MS
11920 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_EHT]))
11921 connect.flags |= ASSOC_REQ_DISABLE_EHT;
11922
ee2aca34
JB
11923 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK])
11924 memcpy(&connect.vht_capa_mask,
11925 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]),
11926 sizeof(connect.vht_capa_mask));
11927
11928 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY]) {
11929 if (!info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]) {
453431a5 11930 kfree_sensitive(connkeys);
ee2aca34
JB
11931 return -EINVAL;
11932 }
11933 memcpy(&connect.vht_capa,
11934 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]),
11935 sizeof(connect.vht_capa));
11936 }
11937
bab5ab7d 11938 if (nla_get_flag(info->attrs[NL80211_ATTR_USE_RRM])) {
0c9ca11b
BL
11939 if (!((rdev->wiphy.features &
11940 NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES) &&
11941 (rdev->wiphy.features & NL80211_FEATURE_QUIET)) &&
11942 !wiphy_ext_feature_isset(&rdev->wiphy,
11943 NL80211_EXT_FEATURE_RRM)) {
453431a5 11944 kfree_sensitive(connkeys);
bab5ab7d 11945 return -EINVAL;
707554b4 11946 }
bab5ab7d
AK
11947 connect.flags |= ASSOC_REQ_USE_RRM;
11948 }
11949
34d50519 11950 connect.pbss = nla_get_flag(info->attrs[NL80211_ATTR_PBSS]);
57fbcce3 11951 if (connect.pbss && !rdev->wiphy.bands[NL80211_BAND_60GHZ]) {
453431a5 11952 kfree_sensitive(connkeys);
34d50519
LD
11953 return -EOPNOTSUPP;
11954 }
11955
38de03d2
AS
11956 if (info->attrs[NL80211_ATTR_BSS_SELECT]) {
11957 /* bss selection makes no sense if bssid is set */
11958 if (connect.bssid) {
453431a5 11959 kfree_sensitive(connkeys);
38de03d2
AS
11960 return -EINVAL;
11961 }
11962
11963 err = parse_bss_select(info->attrs[NL80211_ATTR_BSS_SELECT],
11964 wiphy, &connect.bss_select);
11965 if (err) {
453431a5 11966 kfree_sensitive(connkeys);
38de03d2
AS
11967 return err;
11968 }
11969 }
11970
a3caf744
VK
11971 if (wiphy_ext_feature_isset(&rdev->wiphy,
11972 NL80211_EXT_FEATURE_FILS_SK_OFFLOAD) &&
11973 info->attrs[NL80211_ATTR_FILS_ERP_USERNAME] &&
11974 info->attrs[NL80211_ATTR_FILS_ERP_REALM] &&
11975 info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] &&
11976 info->attrs[NL80211_ATTR_FILS_ERP_RRK]) {
11977 connect.fils_erp_username =
11978 nla_data(info->attrs[NL80211_ATTR_FILS_ERP_USERNAME]);
11979 connect.fils_erp_username_len =
11980 nla_len(info->attrs[NL80211_ATTR_FILS_ERP_USERNAME]);
11981 connect.fils_erp_realm =
11982 nla_data(info->attrs[NL80211_ATTR_FILS_ERP_REALM]);
11983 connect.fils_erp_realm_len =
11984 nla_len(info->attrs[NL80211_ATTR_FILS_ERP_REALM]);
11985 connect.fils_erp_next_seq_num =
11986 nla_get_u16(
11987 info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM]);
11988 connect.fils_erp_rrk =
11989 nla_data(info->attrs[NL80211_ATTR_FILS_ERP_RRK]);
11990 connect.fils_erp_rrk_len =
11991 nla_len(info->attrs[NL80211_ATTR_FILS_ERP_RRK]);
11992 } else if (info->attrs[NL80211_ATTR_FILS_ERP_USERNAME] ||
11993 info->attrs[NL80211_ATTR_FILS_ERP_REALM] ||
11994 info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] ||
11995 info->attrs[NL80211_ATTR_FILS_ERP_RRK]) {
453431a5 11996 kfree_sensitive(connkeys);
a3caf744
VK
11997 return -EINVAL;
11998 }
11999
40cbfa90
SD
12000 if (nla_get_flag(info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])) {
12001 if (!info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
453431a5 12002 kfree_sensitive(connkeys);
40cbfa90
SD
12003 GENL_SET_ERR_MSG(info,
12004 "external auth requires connection ownership");
12005 return -EINVAL;
12006 }
12007 connect.flags |= CONNECT_REQ_EXTERNAL_AUTH_SUPPORT;
12008 }
12009
efbabc11
VJ
12010 if (nla_get_flag(info->attrs[NL80211_ATTR_MLO_SUPPORT]))
12011 connect.flags |= CONNECT_REQ_MLO_SUPPORT;
12012
83739b03 12013 wdev_lock(dev->ieee80211_ptr);
bd2522b1 12014
4ce2bd9c
JM
12015 err = cfg80211_connect(rdev, dev, &connect, connkeys,
12016 connect.prev_bssid);
fffd0934 12017 if (err)
453431a5 12018 kfree_sensitive(connkeys);
bd2522b1
AZ
12019
12020 if (!err && info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
12021 dev->ieee80211_ptr->conn_owner_nlportid = info->snd_portid;
12022 if (connect.bssid)
12023 memcpy(dev->ieee80211_ptr->disconnect_bssid,
12024 connect.bssid, ETH_ALEN);
12025 else
3b1648f1 12026 eth_zero_addr(dev->ieee80211_ptr->disconnect_bssid);
bd2522b1
AZ
12027 }
12028
12029 wdev_unlock(dev->ieee80211_ptr);
12030
b23aa676
SO
12031 return err;
12032}
12033
088e8df8 12034static int nl80211_update_connect_params(struct sk_buff *skb,
12035 struct genl_info *info)
12036{
12037 struct cfg80211_connect_params connect = {};
12038 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12039 struct net_device *dev = info->user_ptr[1];
12040 struct wireless_dev *wdev = dev->ieee80211_ptr;
7f9a3e15
VK
12041 bool fils_sk_offload;
12042 u32 auth_type;
088e8df8 12043 u32 changed = 0;
12044 int ret;
12045
12046 if (!rdev->ops->update_connect_params)
12047 return -EOPNOTSUPP;
12048
12049 if (info->attrs[NL80211_ATTR_IE]) {
088e8df8 12050 connect.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
12051 connect.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
12052 changed |= UPDATE_ASSOC_IES;
12053 }
12054
7f9a3e15
VK
12055 fils_sk_offload = wiphy_ext_feature_isset(&rdev->wiphy,
12056 NL80211_EXT_FEATURE_FILS_SK_OFFLOAD);
12057
12058 /*
12059 * when driver supports fils-sk offload all attributes must be
12060 * provided. So the else covers "fils-sk-not-all" and
12061 * "no-fils-sk-any".
12062 */
12063 if (fils_sk_offload &&
12064 info->attrs[NL80211_ATTR_FILS_ERP_USERNAME] &&
12065 info->attrs[NL80211_ATTR_FILS_ERP_REALM] &&
12066 info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] &&
12067 info->attrs[NL80211_ATTR_FILS_ERP_RRK]) {
12068 connect.fils_erp_username =
12069 nla_data(info->attrs[NL80211_ATTR_FILS_ERP_USERNAME]);
12070 connect.fils_erp_username_len =
12071 nla_len(info->attrs[NL80211_ATTR_FILS_ERP_USERNAME]);
12072 connect.fils_erp_realm =
12073 nla_data(info->attrs[NL80211_ATTR_FILS_ERP_REALM]);
12074 connect.fils_erp_realm_len =
12075 nla_len(info->attrs[NL80211_ATTR_FILS_ERP_REALM]);
12076 connect.fils_erp_next_seq_num =
12077 nla_get_u16(
12078 info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM]);
12079 connect.fils_erp_rrk =
12080 nla_data(info->attrs[NL80211_ATTR_FILS_ERP_RRK]);
12081 connect.fils_erp_rrk_len =
12082 nla_len(info->attrs[NL80211_ATTR_FILS_ERP_RRK]);
12083 changed |= UPDATE_FILS_ERP_INFO;
12084 } else if (info->attrs[NL80211_ATTR_FILS_ERP_USERNAME] ||
12085 info->attrs[NL80211_ATTR_FILS_ERP_REALM] ||
12086 info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] ||
12087 info->attrs[NL80211_ATTR_FILS_ERP_RRK]) {
12088 return -EINVAL;
12089 }
12090
12091 if (info->attrs[NL80211_ATTR_AUTH_TYPE]) {
12092 auth_type = nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
12093 if (!nl80211_valid_auth_type(rdev, auth_type,
12094 NL80211_CMD_CONNECT))
12095 return -EINVAL;
12096
12097 if (auth_type == NL80211_AUTHTYPE_FILS_SK &&
12098 fils_sk_offload && !(changed & UPDATE_FILS_ERP_INFO))
12099 return -EINVAL;
12100
12101 connect.auth_type = auth_type;
12102 changed |= UPDATE_AUTH_TYPE;
12103 }
12104
088e8df8 12105 wdev_lock(dev->ieee80211_ptr);
7b0a0e3c 12106 if (!wdev->connected)
088e8df8 12107 ret = -ENOLINK;
12108 else
12109 ret = rdev_update_connect_params(rdev, dev, &connect, changed);
12110 wdev_unlock(dev->ieee80211_ptr);
12111
12112 return ret;
12113}
12114
b23aa676
SO
12115static int nl80211_disconnect(struct sk_buff *skb, struct genl_info *info)
12116{
4c476991
JB
12117 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12118 struct net_device *dev = info->user_ptr[1];
b23aa676 12119 u16 reason;
83739b03 12120 int ret;
b23aa676 12121
bad29297
AZ
12122 if (dev->ieee80211_ptr->conn_owner_nlportid &&
12123 dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)
12124 return -EPERM;
12125
b23aa676
SO
12126 if (!info->attrs[NL80211_ATTR_REASON_CODE])
12127 reason = WLAN_REASON_DEAUTH_LEAVING;
12128 else
12129 reason = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
12130
12131 if (reason == 0)
12132 return -EINVAL;
12133
074ac8df 12134 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
12135 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
12136 return -EOPNOTSUPP;
b23aa676 12137
83739b03
JB
12138 wdev_lock(dev->ieee80211_ptr);
12139 ret = cfg80211_disconnect(rdev, dev, reason, true);
12140 wdev_unlock(dev->ieee80211_ptr);
12141 return ret;
b23aa676
SO
12142}
12143
463d0183
JB
12144static int nl80211_wiphy_netns(struct sk_buff *skb, struct genl_info *info)
12145{
4c476991 12146 struct cfg80211_registered_device *rdev = info->user_ptr[0];
463d0183
JB
12147 struct net *net;
12148 int err;
463d0183 12149
4b681c82
VK
12150 if (info->attrs[NL80211_ATTR_PID]) {
12151 u32 pid = nla_get_u32(info->attrs[NL80211_ATTR_PID]);
12152
12153 net = get_net_ns_by_pid(pid);
12154 } else if (info->attrs[NL80211_ATTR_NETNS_FD]) {
12155 u32 fd = nla_get_u32(info->attrs[NL80211_ATTR_NETNS_FD]);
463d0183 12156
4b681c82
VK
12157 net = get_net_ns_by_fd(fd);
12158 } else {
12159 return -EINVAL;
12160 }
463d0183 12161
4c476991
JB
12162 if (IS_ERR(net))
12163 return PTR_ERR(net);
463d0183
JB
12164
12165 err = 0;
12166
12167 /* check if anything to do */
4c476991
JB
12168 if (!net_eq(wiphy_net(&rdev->wiphy), net))
12169 err = cfg80211_switch_netns(rdev, net);
463d0183 12170
463d0183 12171 put_net(net);
463d0183
JB
12172 return err;
12173}
12174
67fbb16b
SO
12175static int nl80211_setdel_pmksa(struct sk_buff *skb, struct genl_info *info)
12176{
4c476991 12177 struct cfg80211_registered_device *rdev = info->user_ptr[0];
67fbb16b
SO
12178 int (*rdev_ops)(struct wiphy *wiphy, struct net_device *dev,
12179 struct cfg80211_pmksa *pmksa) = NULL;
4c476991 12180 struct net_device *dev = info->user_ptr[1];
67fbb16b
SO
12181 struct cfg80211_pmksa pmksa;
12182
12183 memset(&pmksa, 0, sizeof(struct cfg80211_pmksa));
12184
67fbb16b
SO
12185 if (!info->attrs[NL80211_ATTR_PMKID])
12186 return -EINVAL;
12187
67fbb16b 12188 pmksa.pmkid = nla_data(info->attrs[NL80211_ATTR_PMKID]);
a3caf744
VK
12189
12190 if (info->attrs[NL80211_ATTR_MAC]) {
12191 pmksa.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
12192 } else if (info->attrs[NL80211_ATTR_SSID] &&
12193 info->attrs[NL80211_ATTR_FILS_CACHE_ID] &&
12194 (info->genlhdr->cmd == NL80211_CMD_DEL_PMKSA ||
12195 info->attrs[NL80211_ATTR_PMK])) {
12196 pmksa.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
12197 pmksa.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
12198 pmksa.cache_id =
12199 nla_data(info->attrs[NL80211_ATTR_FILS_CACHE_ID]);
12200 } else {
12201 return -EINVAL;
12202 }
12203 if (info->attrs[NL80211_ATTR_PMK]) {
12204 pmksa.pmk = nla_data(info->attrs[NL80211_ATTR_PMK]);
12205 pmksa.pmk_len = nla_len(info->attrs[NL80211_ATTR_PMK]);
12206 }
67fbb16b 12207
7fc82af8
VJ
12208 if (info->attrs[NL80211_ATTR_PMK_LIFETIME])
12209 pmksa.pmk_lifetime =
12210 nla_get_u32(info->attrs[NL80211_ATTR_PMK_LIFETIME]);
12211
12212 if (info->attrs[NL80211_ATTR_PMK_REAUTH_THRESHOLD])
12213 pmksa.pmk_reauth_threshold =
12214 nla_get_u8(
12215 info->attrs[NL80211_ATTR_PMK_REAUTH_THRESHOLD]);
12216
074ac8df 12217 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
6c900360
LD
12218 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT &&
12219 !(dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP &&
12220 wiphy_ext_feature_isset(&rdev->wiphy,
12221 NL80211_EXT_FEATURE_AP_PMKSA_CACHING)))
4c476991 12222 return -EOPNOTSUPP;
67fbb16b
SO
12223
12224 switch (info->genlhdr->cmd) {
12225 case NL80211_CMD_SET_PMKSA:
12226 rdev_ops = rdev->ops->set_pmksa;
12227 break;
12228 case NL80211_CMD_DEL_PMKSA:
12229 rdev_ops = rdev->ops->del_pmksa;
12230 break;
12231 default:
12232 WARN_ON(1);
12233 break;
12234 }
12235
4c476991
JB
12236 if (!rdev_ops)
12237 return -EOPNOTSUPP;
67fbb16b 12238
4c476991 12239 return rdev_ops(&rdev->wiphy, dev, &pmksa);
67fbb16b
SO
12240}
12241
12242static int nl80211_flush_pmksa(struct sk_buff *skb, struct genl_info *info)
12243{
4c476991
JB
12244 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12245 struct net_device *dev = info->user_ptr[1];
67fbb16b 12246
074ac8df 12247 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
12248 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
12249 return -EOPNOTSUPP;
67fbb16b 12250
4c476991
JB
12251 if (!rdev->ops->flush_pmksa)
12252 return -EOPNOTSUPP;
67fbb16b 12253
e35e4d28 12254 return rdev_flush_pmksa(rdev, dev);
67fbb16b
SO
12255}
12256
109086ce
AN
12257static int nl80211_tdls_mgmt(struct sk_buff *skb, struct genl_info *info)
12258{
12259 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12260 struct net_device *dev = info->user_ptr[1];
12261 u8 action_code, dialog_token;
df942e7b 12262 u32 peer_capability = 0;
109086ce
AN
12263 u16 status_code;
12264 u8 *peer;
c6112046 12265 int link_id;
31fa97c5 12266 bool initiator;
109086ce
AN
12267
12268 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) ||
12269 !rdev->ops->tdls_mgmt)
12270 return -EOPNOTSUPP;
12271
12272 if (!info->attrs[NL80211_ATTR_TDLS_ACTION] ||
12273 !info->attrs[NL80211_ATTR_STATUS_CODE] ||
12274 !info->attrs[NL80211_ATTR_TDLS_DIALOG_TOKEN] ||
12275 !info->attrs[NL80211_ATTR_IE] ||
12276 !info->attrs[NL80211_ATTR_MAC])
12277 return -EINVAL;
12278
12279 peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
12280 action_code = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_ACTION]);
12281 status_code = nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]);
12282 dialog_token = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_DIALOG_TOKEN]);
31fa97c5 12283 initiator = nla_get_flag(info->attrs[NL80211_ATTR_TDLS_INITIATOR]);
df942e7b
SDU
12284 if (info->attrs[NL80211_ATTR_TDLS_PEER_CAPABILITY])
12285 peer_capability =
12286 nla_get_u32(info->attrs[NL80211_ATTR_TDLS_PEER_CAPABILITY]);
c6112046 12287 link_id = nl80211_link_id_or_invalid(info->attrs);
109086ce 12288
c6112046 12289 return rdev_tdls_mgmt(rdev, dev, peer, link_id, action_code,
df942e7b 12290 dialog_token, status_code, peer_capability,
31fa97c5 12291 initiator,
e35e4d28
HG
12292 nla_data(info->attrs[NL80211_ATTR_IE]),
12293 nla_len(info->attrs[NL80211_ATTR_IE]));
109086ce
AN
12294}
12295
12296static int nl80211_tdls_oper(struct sk_buff *skb, struct genl_info *info)
12297{
12298 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12299 struct net_device *dev = info->user_ptr[1];
12300 enum nl80211_tdls_operation operation;
12301 u8 *peer;
12302
12303 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) ||
12304 !rdev->ops->tdls_oper)
12305 return -EOPNOTSUPP;
12306
12307 if (!info->attrs[NL80211_ATTR_TDLS_OPERATION] ||
12308 !info->attrs[NL80211_ATTR_MAC])
12309 return -EINVAL;
12310
12311 operation = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_OPERATION]);
12312 peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
12313
e35e4d28 12314 return rdev_tdls_oper(rdev, dev, peer, operation);
109086ce
AN
12315}
12316
9588bbd5
JM
12317static int nl80211_remain_on_channel(struct sk_buff *skb,
12318 struct genl_info *info)
12319{
4c476991 12320 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7b0a0e3c 12321 unsigned int link_id = nl80211_link_id(info->attrs);
71bbc994 12322 struct wireless_dev *wdev = info->user_ptr[1];
683b6d3b 12323 struct cfg80211_chan_def chandef;
9588bbd5
JM
12324 struct sk_buff *msg;
12325 void *hdr;
12326 u64 cookie;
683b6d3b 12327 u32 duration;
9588bbd5
JM
12328 int err;
12329
12330 if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] ||
12331 !info->attrs[NL80211_ATTR_DURATION])
12332 return -EINVAL;
12333
12334 duration = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]);
12335
ebf348fc
JB
12336 if (!rdev->ops->remain_on_channel ||
12337 !(rdev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL))
12338 return -EOPNOTSUPP;
12339
9588bbd5 12340 /*
ebf348fc
JB
12341 * We should be on that channel for at least a minimum amount of
12342 * time (10ms) but no longer than the driver supports.
9588bbd5 12343 */
ebf348fc 12344 if (duration < NL80211_MIN_REMAIN_ON_CHANNEL_TIME ||
a293911d 12345 duration > rdev->wiphy.max_remain_on_channel_duration)
9588bbd5
JM
12346 return -EINVAL;
12347
683b6d3b
JB
12348 err = nl80211_parse_chandef(rdev, info, &chandef);
12349 if (err)
12350 return err;
9588bbd5 12351
34373d12 12352 wdev_lock(wdev);
7b0a0e3c
JB
12353 if (!cfg80211_off_channel_oper_allowed(wdev, chandef.chan)) {
12354 const struct cfg80211_chan_def *oper_chandef, *compat_chandef;
12355
12356 oper_chandef = wdev_chandef(wdev, link_id);
12357
12358 if (WARN_ON(!oper_chandef)) {
12359 /* cannot happen since we must beacon to get here */
12360 WARN_ON(1);
12361 wdev_unlock(wdev);
12362 return -EBUSY;
12363 }
12364
12365 /* note: returns first one if identical chandefs */
12366 compat_chandef = cfg80211_chandef_compatible(&chandef,
12367 oper_chandef);
12368
34373d12
VT
12369 if (compat_chandef != &chandef) {
12370 wdev_unlock(wdev);
12371 return -EBUSY;
12372 }
12373 }
12374 wdev_unlock(wdev);
12375
9588bbd5 12376 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4c476991
JB
12377 if (!msg)
12378 return -ENOMEM;
9588bbd5 12379
15e47304 12380 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
9588bbd5 12381 NL80211_CMD_REMAIN_ON_CHANNEL);
cb35fba3
DC
12382 if (!hdr) {
12383 err = -ENOBUFS;
9588bbd5
JM
12384 goto free_msg;
12385 }
12386
683b6d3b
JB
12387 err = rdev_remain_on_channel(rdev, wdev, chandef.chan,
12388 duration, &cookie);
9588bbd5
JM
12389
12390 if (err)
12391 goto free_msg;
12392
2dad624e
ND
12393 if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
12394 NL80211_ATTR_PAD))
9360ffd1 12395 goto nla_put_failure;
9588bbd5
JM
12396
12397 genlmsg_end(msg, hdr);
4c476991
JB
12398
12399 return genlmsg_reply(msg, info);
9588bbd5
JM
12400
12401 nla_put_failure:
12402 err = -ENOBUFS;
12403 free_msg:
12404 nlmsg_free(msg);
9588bbd5
JM
12405 return err;
12406}
12407
12408static int nl80211_cancel_remain_on_channel(struct sk_buff *skb,
12409 struct genl_info *info)
12410{
4c476991 12411 struct cfg80211_registered_device *rdev = info->user_ptr[0];
71bbc994 12412 struct wireless_dev *wdev = info->user_ptr[1];
9588bbd5 12413 u64 cookie;
9588bbd5
JM
12414
12415 if (!info->attrs[NL80211_ATTR_COOKIE])
12416 return -EINVAL;
12417
4c476991
JB
12418 if (!rdev->ops->cancel_remain_on_channel)
12419 return -EOPNOTSUPP;
9588bbd5 12420
9588bbd5
JM
12421 cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);
12422
e35e4d28 12423 return rdev_cancel_remain_on_channel(rdev, wdev, cookie);
9588bbd5
JM
12424}
12425
13ae75b1
JM
12426static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
12427 struct genl_info *info)
12428{
13ae75b1 12429 struct cfg80211_bitrate_mask mask;
7b0a0e3c 12430 unsigned int link_id = nl80211_link_id(info->attrs);
a7c7fbff 12431 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4c476991 12432 struct net_device *dev = info->user_ptr[1];
f971e188 12433 struct wireless_dev *wdev = dev->ieee80211_ptr;
a7c7fbff 12434 int err;
13ae75b1 12435
4c476991
JB
12436 if (!rdev->ops->set_bitrate_mask)
12437 return -EOPNOTSUPP;
13ae75b1 12438
f971e188 12439 wdev_lock(wdev);
9a5f6488 12440 err = nl80211_parse_tx_bitrate_mask(info, info->attrs,
eb89a6a6 12441 NL80211_ATTR_TX_RATES, &mask,
7b0a0e3c 12442 dev, true, link_id);
a7c7fbff 12443 if (err)
f971e188 12444 goto out;
13ae75b1 12445
7b0a0e3c 12446 err = rdev_set_bitrate_mask(rdev, dev, link_id, NULL, &mask);
f971e188
JB
12447out:
12448 wdev_unlock(wdev);
12449 return err;
13ae75b1
JM
12450}
12451
2e161f78 12452static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info)
026331c4 12453{
4c476991 12454 struct cfg80211_registered_device *rdev = info->user_ptr[0];
71bbc994 12455 struct wireless_dev *wdev = info->user_ptr[1];
2e161f78 12456 u16 frame_type = IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION;
026331c4
JM
12457
12458 if (!info->attrs[NL80211_ATTR_FRAME_MATCH])
12459 return -EINVAL;
12460
2e161f78
JB
12461 if (info->attrs[NL80211_ATTR_FRAME_TYPE])
12462 frame_type = nla_get_u16(info->attrs[NL80211_ATTR_FRAME_TYPE]);
026331c4 12463
71bbc994
JB
12464 switch (wdev->iftype) {
12465 case NL80211_IFTYPE_STATION:
12466 case NL80211_IFTYPE_ADHOC:
12467 case NL80211_IFTYPE_P2P_CLIENT:
12468 case NL80211_IFTYPE_AP:
12469 case NL80211_IFTYPE_AP_VLAN:
12470 case NL80211_IFTYPE_MESH_POINT:
12471 case NL80211_IFTYPE_P2P_GO:
98104fde 12472 case NL80211_IFTYPE_P2P_DEVICE:
71bbc994 12473 break;
cb3b7d87 12474 case NL80211_IFTYPE_NAN:
9b89495e
VG
12475 if (!wiphy_ext_feature_isset(wdev->wiphy,
12476 NL80211_EXT_FEATURE_SECURE_NAN))
12477 return -EOPNOTSUPP;
12478 break;
71bbc994 12479 default:
4c476991 12480 return -EOPNOTSUPP;
71bbc994 12481 }
026331c4
JM
12482
12483 /* not much point in registering if we can't reply */
4c476991
JB
12484 if (!rdev->ops->mgmt_tx)
12485 return -EOPNOTSUPP;
026331c4 12486
9dba48a6
JB
12487 if (info->attrs[NL80211_ATTR_RECEIVE_MULTICAST] &&
12488 !wiphy_ext_feature_isset(&rdev->wiphy,
12489 NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS)) {
12490 GENL_SET_ERR_MSG(info,
12491 "multicast RX registrations are not supported");
12492 return -EOPNOTSUPP;
12493 }
12494
15e47304 12495 return cfg80211_mlme_register_mgmt(wdev, info->snd_portid, frame_type,
ff74c51e
IP
12496 nla_data(info->attrs[NL80211_ATTR_FRAME_MATCH]),
12497 nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH]),
9dba48a6 12498 info->attrs[NL80211_ATTR_RECEIVE_MULTICAST],
ff74c51e 12499 info->extack);
026331c4
JM
12500}
12501
2e161f78 12502static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
026331c4 12503{
4c476991 12504 struct cfg80211_registered_device *rdev = info->user_ptr[0];
71bbc994 12505 struct wireless_dev *wdev = info->user_ptr[1];
683b6d3b 12506 struct cfg80211_chan_def chandef;
026331c4 12507 int err;
d64d373f 12508 void *hdr = NULL;
026331c4 12509 u64 cookie;
e247bd90 12510 struct sk_buff *msg = NULL;
b176e629
AO
12511 struct cfg80211_mgmt_tx_params params = {
12512 .dont_wait_for_ack =
12513 info->attrs[NL80211_ATTR_DONT_WAIT_FOR_ACK],
12514 };
026331c4 12515
683b6d3b 12516 if (!info->attrs[NL80211_ATTR_FRAME])
026331c4
JM
12517 return -EINVAL;
12518
4c476991
JB
12519 if (!rdev->ops->mgmt_tx)
12520 return -EOPNOTSUPP;
026331c4 12521
71bbc994 12522 switch (wdev->iftype) {
ea141b75
AQ
12523 case NL80211_IFTYPE_P2P_DEVICE:
12524 if (!info->attrs[NL80211_ATTR_WIPHY_FREQ])
12525 return -EINVAL;
d7832c71 12526 break;
71bbc994
JB
12527 case NL80211_IFTYPE_STATION:
12528 case NL80211_IFTYPE_ADHOC:
12529 case NL80211_IFTYPE_P2P_CLIENT:
12530 case NL80211_IFTYPE_AP:
12531 case NL80211_IFTYPE_AP_VLAN:
12532 case NL80211_IFTYPE_MESH_POINT:
12533 case NL80211_IFTYPE_P2P_GO:
12534 break;
cb3b7d87 12535 case NL80211_IFTYPE_NAN:
9b89495e
VG
12536 if (!wiphy_ext_feature_isset(wdev->wiphy,
12537 NL80211_EXT_FEATURE_SECURE_NAN))
12538 return -EOPNOTSUPP;
12539 break;
71bbc994 12540 default:
4c476991 12541 return -EOPNOTSUPP;
71bbc994 12542 }
026331c4 12543
f7ca38df 12544 if (info->attrs[NL80211_ATTR_DURATION]) {
7c4ef712 12545 if (!(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX))
f7ca38df 12546 return -EINVAL;
b176e629 12547 params.wait = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]);
ebf348fc
JB
12548
12549 /*
12550 * We should wait on the channel for at least a minimum amount
12551 * of time (10ms) but no longer than the driver supports.
12552 */
b176e629
AO
12553 if (params.wait < NL80211_MIN_REMAIN_ON_CHANNEL_TIME ||
12554 params.wait > rdev->wiphy.max_remain_on_channel_duration)
ebf348fc 12555 return -EINVAL;
f7ca38df
JB
12556 }
12557
b176e629 12558 params.offchan = info->attrs[NL80211_ATTR_OFFCHANNEL_TX_OK];
f7ca38df 12559
b176e629 12560 if (params.offchan && !(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX))
7c4ef712
JB
12561 return -EINVAL;
12562
b176e629 12563 params.no_cck = nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]);
e9f935e3 12564
ea141b75
AQ
12565 /* get the channel if any has been specified, otherwise pass NULL to
12566 * the driver. The latter will use the current one
12567 */
12568 chandef.chan = NULL;
12569 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
12570 err = nl80211_parse_chandef(rdev, info, &chandef);
12571 if (err)
12572 return err;
12573 }
12574
b176e629 12575 if (!chandef.chan && params.offchan)
ea141b75 12576 return -EINVAL;
026331c4 12577
34373d12 12578 wdev_lock(wdev);
7b0a0e3c
JB
12579 if (params.offchan &&
12580 !cfg80211_off_channel_oper_allowed(wdev, chandef.chan)) {
34373d12
VT
12581 wdev_unlock(wdev);
12582 return -EBUSY;
12583 }
95f498bb
JB
12584
12585 params.link_id = nl80211_link_id_or_invalid(info->attrs);
12586 /*
12587 * This now races due to the unlock, but we cannot check
12588 * the valid links for the _station_ anyway, so that's up
12589 * to the driver.
12590 */
12591 if (params.link_id >= 0 &&
12592 !(wdev->valid_links & BIT(params.link_id))) {
12593 wdev_unlock(wdev);
12594 return -EINVAL;
12595 }
34373d12
VT
12596 wdev_unlock(wdev);
12597
34d22ce2
AO
12598 params.buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
12599 params.len = nla_len(info->attrs[NL80211_ATTR_FRAME]);
12600
12601 if (info->attrs[NL80211_ATTR_CSA_C_OFFSETS_TX]) {
12602 int len = nla_len(info->attrs[NL80211_ATTR_CSA_C_OFFSETS_TX]);
12603 int i;
12604
12605 if (len % sizeof(u16))
12606 return -EINVAL;
12607
12608 params.n_csa_offsets = len / sizeof(u16);
12609 params.csa_offsets =
12610 nla_data(info->attrs[NL80211_ATTR_CSA_C_OFFSETS_TX]);
12611
12612 /* check that all the offsets fit the frame */
12613 for (i = 0; i < params.n_csa_offsets; i++) {
12614 if (params.csa_offsets[i] >= params.len)
12615 return -EINVAL;
12616 }
12617 }
12618
b176e629 12619 if (!params.dont_wait_for_ack) {
e247bd90
JB
12620 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
12621 if (!msg)
12622 return -ENOMEM;
026331c4 12623
15e47304 12624 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
e247bd90 12625 NL80211_CMD_FRAME);
cb35fba3
DC
12626 if (!hdr) {
12627 err = -ENOBUFS;
e247bd90
JB
12628 goto free_msg;
12629 }
026331c4 12630 }
e247bd90 12631
b176e629
AO
12632 params.chan = chandef.chan;
12633 err = cfg80211_mlme_mgmt_tx(rdev, wdev, &params, &cookie);
026331c4
JM
12634 if (err)
12635 goto free_msg;
12636
e247bd90 12637 if (msg) {
2dad624e
ND
12638 if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
12639 NL80211_ATTR_PAD))
9360ffd1 12640 goto nla_put_failure;
026331c4 12641
e247bd90
JB
12642 genlmsg_end(msg, hdr);
12643 return genlmsg_reply(msg, info);
12644 }
12645
12646 return 0;
026331c4
JM
12647
12648 nla_put_failure:
12649 err = -ENOBUFS;
12650 free_msg:
12651 nlmsg_free(msg);
026331c4
JM
12652 return err;
12653}
12654
f7ca38df
JB
12655static int nl80211_tx_mgmt_cancel_wait(struct sk_buff *skb, struct genl_info *info)
12656{
12657 struct cfg80211_registered_device *rdev = info->user_ptr[0];
71bbc994 12658 struct wireless_dev *wdev = info->user_ptr[1];
f7ca38df
JB
12659 u64 cookie;
12660
12661 if (!info->attrs[NL80211_ATTR_COOKIE])
12662 return -EINVAL;
12663
12664 if (!rdev->ops->mgmt_tx_cancel_wait)
12665 return -EOPNOTSUPP;
12666
71bbc994
JB
12667 switch (wdev->iftype) {
12668 case NL80211_IFTYPE_STATION:
12669 case NL80211_IFTYPE_ADHOC:
12670 case NL80211_IFTYPE_P2P_CLIENT:
12671 case NL80211_IFTYPE_AP:
12672 case NL80211_IFTYPE_AP_VLAN:
12673 case NL80211_IFTYPE_P2P_GO:
98104fde 12674 case NL80211_IFTYPE_P2P_DEVICE:
71bbc994 12675 break;
cb3b7d87 12676 case NL80211_IFTYPE_NAN:
9b89495e
VG
12677 if (!wiphy_ext_feature_isset(wdev->wiphy,
12678 NL80211_EXT_FEATURE_SECURE_NAN))
12679 return -EOPNOTSUPP;
12680 break;
71bbc994 12681 default:
f7ca38df 12682 return -EOPNOTSUPP;
71bbc994 12683 }
f7ca38df
JB
12684
12685 cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);
12686
e35e4d28 12687 return rdev_mgmt_tx_cancel_wait(rdev, wdev, cookie);
f7ca38df
JB
12688}
12689
ffb9eb3d
KV
12690static int nl80211_set_power_save(struct sk_buff *skb, struct genl_info *info)
12691{
4c476991 12692 struct cfg80211_registered_device *rdev = info->user_ptr[0];
ffb9eb3d 12693 struct wireless_dev *wdev;
4c476991 12694 struct net_device *dev = info->user_ptr[1];
ffb9eb3d
KV
12695 u8 ps_state;
12696 bool state;
12697 int err;
12698
4c476991
JB
12699 if (!info->attrs[NL80211_ATTR_PS_STATE])
12700 return -EINVAL;
ffb9eb3d
KV
12701
12702 ps_state = nla_get_u32(info->attrs[NL80211_ATTR_PS_STATE]);
12703
ffb9eb3d
KV
12704 wdev = dev->ieee80211_ptr;
12705
4c476991
JB
12706 if (!rdev->ops->set_power_mgmt)
12707 return -EOPNOTSUPP;
ffb9eb3d
KV
12708
12709 state = (ps_state == NL80211_PS_ENABLED) ? true : false;
12710
12711 if (state == wdev->ps)
4c476991 12712 return 0;
ffb9eb3d 12713
e35e4d28 12714 err = rdev_set_power_mgmt(rdev, dev, state, wdev->ps_timeout);
4c476991
JB
12715 if (!err)
12716 wdev->ps = state;
ffb9eb3d
KV
12717 return err;
12718}
12719
12720static int nl80211_get_power_save(struct sk_buff *skb, struct genl_info *info)
12721{
4c476991 12722 struct cfg80211_registered_device *rdev = info->user_ptr[0];
ffb9eb3d
KV
12723 enum nl80211_ps_state ps_state;
12724 struct wireless_dev *wdev;
4c476991 12725 struct net_device *dev = info->user_ptr[1];
ffb9eb3d
KV
12726 struct sk_buff *msg;
12727 void *hdr;
12728 int err;
12729
ffb9eb3d
KV
12730 wdev = dev->ieee80211_ptr;
12731
4c476991
JB
12732 if (!rdev->ops->set_power_mgmt)
12733 return -EOPNOTSUPP;
ffb9eb3d
KV
12734
12735 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4c476991
JB
12736 if (!msg)
12737 return -ENOMEM;
ffb9eb3d 12738
15e47304 12739 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
ffb9eb3d
KV
12740 NL80211_CMD_GET_POWER_SAVE);
12741 if (!hdr) {
4c476991 12742 err = -ENOBUFS;
ffb9eb3d
KV
12743 goto free_msg;
12744 }
12745
12746 if (wdev->ps)
12747 ps_state = NL80211_PS_ENABLED;
12748 else
12749 ps_state = NL80211_PS_DISABLED;
12750
9360ffd1
DM
12751 if (nla_put_u32(msg, NL80211_ATTR_PS_STATE, ps_state))
12752 goto nla_put_failure;
ffb9eb3d
KV
12753
12754 genlmsg_end(msg, hdr);
4c476991 12755 return genlmsg_reply(msg, info);
ffb9eb3d 12756
4c476991 12757 nla_put_failure:
ffb9eb3d 12758 err = -ENOBUFS;
4c476991 12759 free_msg:
ffb9eb3d 12760 nlmsg_free(msg);
ffb9eb3d
KV
12761 return err;
12762}
12763
94e860f1
JB
12764static const struct nla_policy
12765nl80211_attr_cqm_policy[NL80211_ATTR_CQM_MAX + 1] = {
4a4b8169 12766 [NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_BINARY },
d6dc1a38
JO
12767 [NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U32 },
12768 [NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 },
84f10708
TP
12769 [NL80211_ATTR_CQM_TXE_RATE] = { .type = NLA_U32 },
12770 [NL80211_ATTR_CQM_TXE_PKTS] = { .type = NLA_U32 },
12771 [NL80211_ATTR_CQM_TXE_INTVL] = { .type = NLA_U32 },
bee427b8 12772 [NL80211_ATTR_CQM_RSSI_LEVEL] = { .type = NLA_S32 },
d6dc1a38
JO
12773};
12774
84f10708 12775static int nl80211_set_cqm_txe(struct genl_info *info,
d9d8b019 12776 u32 rate, u32 pkts, u32 intvl)
84f10708
TP
12777{
12778 struct cfg80211_registered_device *rdev = info->user_ptr[0];
84f10708 12779 struct net_device *dev = info->user_ptr[1];
1da5fcc8 12780 struct wireless_dev *wdev = dev->ieee80211_ptr;
84f10708 12781
d9d8b019 12782 if (rate > 100 || intvl > NL80211_CQM_TXE_MAX_INTVL)
84f10708
TP
12783 return -EINVAL;
12784
84f10708
TP
12785 if (!rdev->ops->set_cqm_txe_config)
12786 return -EOPNOTSUPP;
12787
12788 if (wdev->iftype != NL80211_IFTYPE_STATION &&
12789 wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
12790 return -EOPNOTSUPP;
12791
e35e4d28 12792 return rdev_set_cqm_txe_config(rdev, dev, rate, pkts, intvl);
84f10708
TP
12793}
12794
4a4b8169
AZ
12795static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev,
12796 struct net_device *dev)
12797{
12798 struct wireless_dev *wdev = dev->ieee80211_ptr;
12799 s32 last, low, high;
12800 u32 hyst;
1222a160 12801 int i, n, low_index;
4a4b8169
AZ
12802 int err;
12803
12804 /* RSSI reporting disabled? */
12805 if (!wdev->cqm_config)
12806 return rdev_set_cqm_rssi_range_config(rdev, dev, 0, 0);
12807
12808 /*
12809 * Obtain current RSSI value if possible, if not and no RSSI threshold
12810 * event has been received yet, we should receive an event after a
12811 * connection is established and enough beacons received to calculate
12812 * the average.
12813 */
7b0a0e3c
JB
12814 if (!wdev->cqm_config->last_rssi_event_value &&
12815 wdev->links[0].client.current_bss &&
4a4b8169 12816 rdev->ops->get_station) {
73887fd9 12817 struct station_info sinfo = {};
4a4b8169
AZ
12818 u8 *mac_addr;
12819
7b0a0e3c 12820 mac_addr = wdev->links[0].client.current_bss->pub.bssid;
4a4b8169 12821
73887fd9
JB
12822 err = rdev_get_station(rdev, dev, mac_addr, &sinfo);
12823 if (err)
4a4b8169
AZ
12824 return err;
12825
df16737d 12826 cfg80211_sinfo_release_content(&sinfo);
397c657a 12827 if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_BEACON_SIGNAL_AVG))
4a4b8169 12828 wdev->cqm_config->last_rssi_event_value =
73887fd9 12829 (s8) sinfo.rx_beacon_signal_avg;
4a4b8169
AZ
12830 }
12831
12832 last = wdev->cqm_config->last_rssi_event_value;
12833 hyst = wdev->cqm_config->rssi_hyst;
12834 n = wdev->cqm_config->n_rssi_thresholds;
12835
4b2c5a14
MH
12836 for (i = 0; i < n; i++) {
12837 i = array_index_nospec(i, n);
4a4b8169
AZ
12838 if (last < wdev->cqm_config->rssi_thresholds[i])
12839 break;
4b2c5a14 12840 }
4a4b8169 12841
1222a160
MH
12842 low_index = i - 1;
12843 if (low_index >= 0) {
12844 low_index = array_index_nospec(low_index, n);
12845 low = wdev->cqm_config->rssi_thresholds[low_index] - hyst;
12846 } else {
12847 low = S32_MIN;
12848 }
12849 if (i < n) {
12850 i = array_index_nospec(i, n);
12851 high = wdev->cqm_config->rssi_thresholds[i] + hyst - 1;
12852 } else {
12853 high = S32_MAX;
12854 }
4a4b8169
AZ
12855
12856 return rdev_set_cqm_rssi_range_config(rdev, dev, low, high);
12857}
12858
d6dc1a38 12859static int nl80211_set_cqm_rssi(struct genl_info *info,
4a4b8169
AZ
12860 const s32 *thresholds, int n_thresholds,
12861 u32 hysteresis)
d6dc1a38 12862{
4c476991 12863 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4c476991 12864 struct net_device *dev = info->user_ptr[1];
1da5fcc8 12865 struct wireless_dev *wdev = dev->ieee80211_ptr;
4a4b8169
AZ
12866 int i, err;
12867 s32 prev = S32_MIN;
d6dc1a38 12868
4a4b8169
AZ
12869 /* Check all values negative and sorted */
12870 for (i = 0; i < n_thresholds; i++) {
12871 if (thresholds[i] > 0 || thresholds[i] <= prev)
12872 return -EINVAL;
d6dc1a38 12873
4a4b8169
AZ
12874 prev = thresholds[i];
12875 }
d6dc1a38 12876
074ac8df 12877 if (wdev->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
12878 wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
12879 return -EOPNOTSUPP;
d6dc1a38 12880
4a4b8169
AZ
12881 wdev_lock(wdev);
12882 cfg80211_cqm_config_free(wdev);
12883 wdev_unlock(wdev);
12884
12885 if (n_thresholds <= 1 && rdev->ops->set_cqm_rssi_config) {
12886 if (n_thresholds == 0 || thresholds[0] == 0) /* Disabling */
12887 return rdev_set_cqm_rssi_config(rdev, dev, 0, 0);
12888
12889 return rdev_set_cqm_rssi_config(rdev, dev,
12890 thresholds[0], hysteresis);
12891 }
12892
12893 if (!wiphy_ext_feature_isset(&rdev->wiphy,
12894 NL80211_EXT_FEATURE_CQM_RSSI_LIST))
12895 return -EOPNOTSUPP;
12896
12897 if (n_thresholds == 1 && thresholds[0] == 0) /* Disabling */
12898 n_thresholds = 0;
12899
12900 wdev_lock(wdev);
12901 if (n_thresholds) {
12902 struct cfg80211_cqm_config *cqm_config;
12903
40f231e7
LB
12904 cqm_config = kzalloc(struct_size(cqm_config, rssi_thresholds,
12905 n_thresholds),
12906 GFP_KERNEL);
4a4b8169
AZ
12907 if (!cqm_config) {
12908 err = -ENOMEM;
12909 goto unlock;
12910 }
12911
12912 cqm_config->rssi_hyst = hysteresis;
12913 cqm_config->n_rssi_thresholds = n_thresholds;
12914 memcpy(cqm_config->rssi_thresholds, thresholds,
40f231e7
LB
12915 flex_array_size(cqm_config, rssi_thresholds,
12916 n_thresholds));
4a4b8169
AZ
12917
12918 wdev->cqm_config = cqm_config;
12919 }
12920
12921 err = cfg80211_cqm_rssi_update(rdev, dev);
12922
12923unlock:
12924 wdev_unlock(wdev);
12925
12926 return err;
d6dc1a38
JO
12927}
12928
12929static int nl80211_set_cqm(struct sk_buff *skb, struct genl_info *info)
12930{
12931 struct nlattr *attrs[NL80211_ATTR_CQM_MAX + 1];
12932 struct nlattr *cqm;
12933 int err;
12934
12935 cqm = info->attrs[NL80211_ATTR_CQM];
1da5fcc8
JB
12936 if (!cqm)
12937 return -EINVAL;
d6dc1a38 12938
8cb08174
JB
12939 err = nla_parse_nested_deprecated(attrs, NL80211_ATTR_CQM_MAX, cqm,
12940 nl80211_attr_cqm_policy,
12941 info->extack);
d6dc1a38 12942 if (err)
1da5fcc8 12943 return err;
d6dc1a38
JO
12944
12945 if (attrs[NL80211_ATTR_CQM_RSSI_THOLD] &&
12946 attrs[NL80211_ATTR_CQM_RSSI_HYST]) {
4a4b8169
AZ
12947 const s32 *thresholds =
12948 nla_data(attrs[NL80211_ATTR_CQM_RSSI_THOLD]);
12949 int len = nla_len(attrs[NL80211_ATTR_CQM_RSSI_THOLD]);
1da5fcc8 12950 u32 hysteresis = nla_get_u32(attrs[NL80211_ATTR_CQM_RSSI_HYST]);
d6dc1a38 12951
4a4b8169
AZ
12952 if (len % 4)
12953 return -EINVAL;
12954
12955 return nl80211_set_cqm_rssi(info, thresholds, len / 4,
12956 hysteresis);
1da5fcc8
JB
12957 }
12958
12959 if (attrs[NL80211_ATTR_CQM_TXE_RATE] &&
12960 attrs[NL80211_ATTR_CQM_TXE_PKTS] &&
12961 attrs[NL80211_ATTR_CQM_TXE_INTVL]) {
12962 u32 rate = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_RATE]);
12963 u32 pkts = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_PKTS]);
12964 u32 intvl = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_INTVL]);
12965
12966 return nl80211_set_cqm_txe(info, rate, pkts, intvl);
12967 }
12968
12969 return -EINVAL;
d6dc1a38
JO
12970}
12971
6e0bd6c3
RL
12972static int nl80211_join_ocb(struct sk_buff *skb, struct genl_info *info)
12973{
12974 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12975 struct net_device *dev = info->user_ptr[1];
12976 struct ocb_setup setup = {};
12977 int err;
12978
12979 err = nl80211_parse_chandef(rdev, info, &setup.chandef);
12980 if (err)
12981 return err;
12982
12983 return cfg80211_join_ocb(rdev, dev, &setup);
12984}
12985
12986static int nl80211_leave_ocb(struct sk_buff *skb, struct genl_info *info)
12987{
12988 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12989 struct net_device *dev = info->user_ptr[1];
12990
12991 return cfg80211_leave_ocb(rdev, dev);
12992}
12993
29cbe68c
JB
12994static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info)
12995{
12996 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12997 struct net_device *dev = info->user_ptr[1];
12998 struct mesh_config cfg;
c80d545d 12999 struct mesh_setup setup;
29cbe68c
JB
13000 int err;
13001
13002 /* start with default */
13003 memcpy(&cfg, &default_mesh_config, sizeof(cfg));
c80d545d 13004 memcpy(&setup, &default_mesh_setup, sizeof(setup));
29cbe68c 13005
24bdd9f4 13006 if (info->attrs[NL80211_ATTR_MESH_CONFIG]) {
29cbe68c 13007 /* and parse parameters if given */
24bdd9f4 13008 err = nl80211_parse_mesh_config(info, &cfg, NULL);
29cbe68c
JB
13009 if (err)
13010 return err;
13011 }
13012
13013 if (!info->attrs[NL80211_ATTR_MESH_ID] ||
13014 !nla_len(info->attrs[NL80211_ATTR_MESH_ID]))
13015 return -EINVAL;
13016
c80d545d
JC
13017 setup.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]);
13018 setup.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
13019
4bb62344
CYY
13020 if (info->attrs[NL80211_ATTR_MCAST_RATE] &&
13021 !nl80211_parse_mcast_rate(rdev, setup.mcast_rate,
13022 nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE])))
13023 return -EINVAL;
13024
9bdbf04d
MP
13025 if (info->attrs[NL80211_ATTR_BEACON_INTERVAL]) {
13026 setup.beacon_interval =
13027 nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
12d20fc9 13028
0c317a02
PK
13029 err = cfg80211_validate_beacon_int(rdev,
13030 NL80211_IFTYPE_MESH_POINT,
13031 setup.beacon_interval);
12d20fc9
PK
13032 if (err)
13033 return err;
9bdbf04d
MP
13034 }
13035
13036 if (info->attrs[NL80211_ATTR_DTIM_PERIOD]) {
13037 setup.dtim_period =
13038 nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);
13039 if (setup.dtim_period < 1 || setup.dtim_period > 100)
13040 return -EINVAL;
13041 }
13042
c80d545d
JC
13043 if (info->attrs[NL80211_ATTR_MESH_SETUP]) {
13044 /* parse additional setup parameters if given */
13045 err = nl80211_parse_mesh_setup(info, &setup);
13046 if (err)
13047 return err;
13048 }
13049
d37bb18a
TP
13050 if (setup.user_mpm)
13051 cfg.auto_open_plinks = false;
13052
cc1d2806 13053 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
683b6d3b
JB
13054 err = nl80211_parse_chandef(rdev, info, &setup.chandef);
13055 if (err)
13056 return err;
cc1d2806 13057 } else {
188c1b3c 13058 /* __cfg80211_join_mesh() will sort it out */
683b6d3b 13059 setup.chandef.chan = NULL;
cc1d2806
JB
13060 }
13061
ffb3cf30
AN
13062 if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) {
13063 u8 *rates = nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
13064 int n_rates =
13065 nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
13066 struct ieee80211_supported_band *sband;
13067
13068 if (!setup.chandef.chan)
13069 return -EINVAL;
13070
13071 sband = rdev->wiphy.bands[setup.chandef.chan->band];
13072
13073 err = ieee80211_get_ratemask(sband, rates, n_rates,
13074 &setup.basic_rates);
13075 if (err)
13076 return err;
13077 }
13078
8564e382 13079 if (info->attrs[NL80211_ATTR_TX_RATES]) {
9a5f6488
TC
13080 err = nl80211_parse_tx_bitrate_mask(info, info->attrs,
13081 NL80211_ATTR_TX_RATES,
eb89a6a6 13082 &setup.beacon_rate,
7b0a0e3c 13083 dev, false, 0);
8564e382
JB
13084 if (err)
13085 return err;
13086
265698d7
JB
13087 if (!setup.chandef.chan)
13088 return -EINVAL;
13089
8564e382
JB
13090 err = validate_beacon_tx_rate(rdev, setup.chandef.chan->band,
13091 &setup.beacon_rate);
13092 if (err)
13093 return err;
13094 }
13095
d37d49c2
BB
13096 setup.userspace_handles_dfs =
13097 nla_get_flag(info->attrs[NL80211_ATTR_HANDLE_DFS]);
13098
1224f583
DK
13099 if (info->attrs[NL80211_ATTR_CONTROL_PORT_OVER_NL80211]) {
13100 int r = validate_pae_over_nl80211(rdev, info);
13101
13102 if (r < 0)
13103 return r;
13104
13105 setup.control_port_over_nl80211 = true;
13106 }
13107
188c1b3c
DK
13108 wdev_lock(dev->ieee80211_ptr);
13109 err = __cfg80211_join_mesh(rdev, dev, &setup, &cfg);
13110 if (!err && info->attrs[NL80211_ATTR_SOCKET_OWNER])
13111 dev->ieee80211_ptr->conn_owner_nlportid = info->snd_portid;
13112 wdev_unlock(dev->ieee80211_ptr);
13113
13114 return err;
29cbe68c
JB
13115}
13116
13117static int nl80211_leave_mesh(struct sk_buff *skb, struct genl_info *info)
13118{
13119 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13120 struct net_device *dev = info->user_ptr[1];
13121
13122 return cfg80211_leave_mesh(rdev, dev);
13123}
13124
dfb89c56 13125#ifdef CONFIG_PM
bb92d199
AK
13126static int nl80211_send_wowlan_patterns(struct sk_buff *msg,
13127 struct cfg80211_registered_device *rdev)
13128{
6abb9cb9 13129 struct cfg80211_wowlan *wowlan = rdev->wiphy.wowlan_config;
bb92d199
AK
13130 struct nlattr *nl_pats, *nl_pat;
13131 int i, pat_len;
13132
6abb9cb9 13133 if (!wowlan->n_patterns)
bb92d199
AK
13134 return 0;
13135
ae0be8de 13136 nl_pats = nla_nest_start_noflag(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN);
bb92d199
AK
13137 if (!nl_pats)
13138 return -ENOBUFS;
13139
6abb9cb9 13140 for (i = 0; i < wowlan->n_patterns; i++) {
ae0be8de 13141 nl_pat = nla_nest_start_noflag(msg, i + 1);
bb92d199
AK
13142 if (!nl_pat)
13143 return -ENOBUFS;
6abb9cb9 13144 pat_len = wowlan->patterns[i].pattern_len;
50ac6607 13145 if (nla_put(msg, NL80211_PKTPAT_MASK, DIV_ROUND_UP(pat_len, 8),
6abb9cb9 13146 wowlan->patterns[i].mask) ||
50ac6607
AK
13147 nla_put(msg, NL80211_PKTPAT_PATTERN, pat_len,
13148 wowlan->patterns[i].pattern) ||
13149 nla_put_u32(msg, NL80211_PKTPAT_OFFSET,
6abb9cb9 13150 wowlan->patterns[i].pkt_offset))
bb92d199
AK
13151 return -ENOBUFS;
13152 nla_nest_end(msg, nl_pat);
13153 }
13154 nla_nest_end(msg, nl_pats);
13155
13156 return 0;
13157}
13158
2a0e047e
JB
13159static int nl80211_send_wowlan_tcp(struct sk_buff *msg,
13160 struct cfg80211_wowlan_tcp *tcp)
13161{
13162 struct nlattr *nl_tcp;
13163
13164 if (!tcp)
13165 return 0;
13166
ae0be8de
MK
13167 nl_tcp = nla_nest_start_noflag(msg,
13168 NL80211_WOWLAN_TRIG_TCP_CONNECTION);
2a0e047e
JB
13169 if (!nl_tcp)
13170 return -ENOBUFS;
13171
930345ea
JB
13172 if (nla_put_in_addr(msg, NL80211_WOWLAN_TCP_SRC_IPV4, tcp->src) ||
13173 nla_put_in_addr(msg, NL80211_WOWLAN_TCP_DST_IPV4, tcp->dst) ||
2a0e047e
JB
13174 nla_put(msg, NL80211_WOWLAN_TCP_DST_MAC, ETH_ALEN, tcp->dst_mac) ||
13175 nla_put_u16(msg, NL80211_WOWLAN_TCP_SRC_PORT, tcp->src_port) ||
13176 nla_put_u16(msg, NL80211_WOWLAN_TCP_DST_PORT, tcp->dst_port) ||
13177 nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD,
13178 tcp->payload_len, tcp->payload) ||
13179 nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_INTERVAL,
13180 tcp->data_interval) ||
13181 nla_put(msg, NL80211_WOWLAN_TCP_WAKE_PAYLOAD,
13182 tcp->wake_len, tcp->wake_data) ||
13183 nla_put(msg, NL80211_WOWLAN_TCP_WAKE_MASK,
13184 DIV_ROUND_UP(tcp->wake_len, 8), tcp->wake_mask))
13185 return -ENOBUFS;
13186
13187 if (tcp->payload_seq.len &&
13188 nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ,
13189 sizeof(tcp->payload_seq), &tcp->payload_seq))
13190 return -ENOBUFS;
13191
13192 if (tcp->payload_tok.len &&
13193 nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN,
13194 sizeof(tcp->payload_tok) + tcp->tokens_size,
13195 &tcp->payload_tok))
13196 return -ENOBUFS;
13197
e248ad30
JB
13198 nla_nest_end(msg, nl_tcp);
13199
2a0e047e
JB
13200 return 0;
13201}
13202
75453ccb
LC
13203static int nl80211_send_wowlan_nd(struct sk_buff *msg,
13204 struct cfg80211_sched_scan_request *req)
13205{
3b06d277 13206 struct nlattr *nd, *freqs, *matches, *match, *scan_plans, *scan_plan;
75453ccb
LC
13207 int i;
13208
13209 if (!req)
13210 return 0;
13211
ae0be8de 13212 nd = nla_nest_start_noflag(msg, NL80211_WOWLAN_TRIG_NET_DETECT);
75453ccb
LC
13213 if (!nd)
13214 return -ENOBUFS;
13215
3b06d277
AS
13216 if (req->n_scan_plans == 1 &&
13217 nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_INTERVAL,
13218 req->scan_plans[0].interval * 1000))
75453ccb
LC
13219 return -ENOBUFS;
13220
21fea567
LC
13221 if (nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_DELAY, req->delay))
13222 return -ENOBUFS;
13223
bf95ecdb 13224 if (req->relative_rssi_set) {
13225 struct nl80211_bss_select_rssi_adjust rssi_adjust;
13226
13227 if (nla_put_s8(msg, NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI,
13228 req->relative_rssi))
13229 return -ENOBUFS;
13230
13231 rssi_adjust.band = req->rssi_adjust.band;
13232 rssi_adjust.delta = req->rssi_adjust.delta;
13233 if (nla_put(msg, NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST,
13234 sizeof(rssi_adjust), &rssi_adjust))
13235 return -ENOBUFS;
13236 }
13237
ae0be8de 13238 freqs = nla_nest_start_noflag(msg, NL80211_ATTR_SCAN_FREQUENCIES);
75453ccb
LC
13239 if (!freqs)
13240 return -ENOBUFS;
13241
53b18980
JB
13242 for (i = 0; i < req->n_channels; i++) {
13243 if (nla_put_u32(msg, i, req->channels[i]->center_freq))
13244 return -ENOBUFS;
13245 }
75453ccb
LC
13246
13247 nla_nest_end(msg, freqs);
13248
13249 if (req->n_match_sets) {
ae0be8de
MK
13250 matches = nla_nest_start_noflag(msg,
13251 NL80211_ATTR_SCHED_SCAN_MATCH);
76e1fb4b
JB
13252 if (!matches)
13253 return -ENOBUFS;
13254
75453ccb 13255 for (i = 0; i < req->n_match_sets; i++) {
ae0be8de 13256 match = nla_nest_start_noflag(msg, i);
76e1fb4b
JB
13257 if (!match)
13258 return -ENOBUFS;
13259
53b18980
JB
13260 if (nla_put(msg, NL80211_SCHED_SCAN_MATCH_ATTR_SSID,
13261 req->match_sets[i].ssid.ssid_len,
13262 req->match_sets[i].ssid.ssid))
13263 return -ENOBUFS;
75453ccb
LC
13264 nla_nest_end(msg, match);
13265 }
13266 nla_nest_end(msg, matches);
13267 }
13268
ae0be8de 13269 scan_plans = nla_nest_start_noflag(msg, NL80211_ATTR_SCHED_SCAN_PLANS);
3b06d277
AS
13270 if (!scan_plans)
13271 return -ENOBUFS;
13272
13273 for (i = 0; i < req->n_scan_plans; i++) {
ae0be8de 13274 scan_plan = nla_nest_start_noflag(msg, i + 1);
76e1fb4b
JB
13275 if (!scan_plan)
13276 return -ENOBUFS;
13277
67626964 13278 if (nla_put_u32(msg, NL80211_SCHED_SCAN_PLAN_INTERVAL,
3b06d277
AS
13279 req->scan_plans[i].interval) ||
13280 (req->scan_plans[i].iterations &&
13281 nla_put_u32(msg, NL80211_SCHED_SCAN_PLAN_ITERATIONS,
13282 req->scan_plans[i].iterations)))
13283 return -ENOBUFS;
13284 nla_nest_end(msg, scan_plan);
13285 }
13286 nla_nest_end(msg, scan_plans);
13287
75453ccb
LC
13288 nla_nest_end(msg, nd);
13289
13290 return 0;
13291}
13292
ff1b6e69
JB
13293static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info)
13294{
13295 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13296 struct sk_buff *msg;
13297 void *hdr;
2a0e047e 13298 u32 size = NLMSG_DEFAULT_SIZE;
ff1b6e69 13299
964dc9e2 13300 if (!rdev->wiphy.wowlan)
ff1b6e69
JB
13301 return -EOPNOTSUPP;
13302
6abb9cb9 13303 if (rdev->wiphy.wowlan_config && rdev->wiphy.wowlan_config->tcp) {
2a0e047e 13304 /* adjust size to have room for all the data */
6abb9cb9
JB
13305 size += rdev->wiphy.wowlan_config->tcp->tokens_size +
13306 rdev->wiphy.wowlan_config->tcp->payload_len +
13307 rdev->wiphy.wowlan_config->tcp->wake_len +
13308 rdev->wiphy.wowlan_config->tcp->wake_len / 8;
2a0e047e
JB
13309 }
13310
13311 msg = nlmsg_new(size, GFP_KERNEL);
ff1b6e69
JB
13312 if (!msg)
13313 return -ENOMEM;
13314
15e47304 13315 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
ff1b6e69
JB
13316 NL80211_CMD_GET_WOWLAN);
13317 if (!hdr)
13318 goto nla_put_failure;
13319
6abb9cb9 13320 if (rdev->wiphy.wowlan_config) {
ff1b6e69
JB
13321 struct nlattr *nl_wowlan;
13322
ae0be8de
MK
13323 nl_wowlan = nla_nest_start_noflag(msg,
13324 NL80211_ATTR_WOWLAN_TRIGGERS);
ff1b6e69
JB
13325 if (!nl_wowlan)
13326 goto nla_put_failure;
13327
6abb9cb9 13328 if ((rdev->wiphy.wowlan_config->any &&
9360ffd1 13329 nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) ||
6abb9cb9 13330 (rdev->wiphy.wowlan_config->disconnect &&
9360ffd1 13331 nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) ||
6abb9cb9 13332 (rdev->wiphy.wowlan_config->magic_pkt &&
9360ffd1 13333 nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) ||
6abb9cb9 13334 (rdev->wiphy.wowlan_config->gtk_rekey_failure &&
9360ffd1 13335 nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) ||
6abb9cb9 13336 (rdev->wiphy.wowlan_config->eap_identity_req &&
9360ffd1 13337 nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) ||
6abb9cb9 13338 (rdev->wiphy.wowlan_config->four_way_handshake &&
9360ffd1 13339 nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) ||
6abb9cb9 13340 (rdev->wiphy.wowlan_config->rfkill_release &&
9360ffd1
DM
13341 nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE)))
13342 goto nla_put_failure;
2a0e047e 13343
bb92d199
AK
13344 if (nl80211_send_wowlan_patterns(msg, rdev))
13345 goto nla_put_failure;
2a0e047e 13346
6abb9cb9
JB
13347 if (nl80211_send_wowlan_tcp(msg,
13348 rdev->wiphy.wowlan_config->tcp))
2a0e047e 13349 goto nla_put_failure;
75453ccb
LC
13350
13351 if (nl80211_send_wowlan_nd(
13352 msg,
13353 rdev->wiphy.wowlan_config->nd_config))
13354 goto nla_put_failure;
2a0e047e 13355
ff1b6e69
JB
13356 nla_nest_end(msg, nl_wowlan);
13357 }
13358
13359 genlmsg_end(msg, hdr);
13360 return genlmsg_reply(msg, info);
13361
13362nla_put_failure:
13363 nlmsg_free(msg);
13364 return -ENOBUFS;
13365}
13366
2a0e047e
JB
13367static int nl80211_parse_wowlan_tcp(struct cfg80211_registered_device *rdev,
13368 struct nlattr *attr,
13369 struct cfg80211_wowlan *trig)
13370{
13371 struct nlattr *tb[NUM_NL80211_WOWLAN_TCP];
13372 struct cfg80211_wowlan_tcp *cfg;
13373 struct nl80211_wowlan_tcp_data_token *tok = NULL;
13374 struct nl80211_wowlan_tcp_data_seq *seq = NULL;
13375 u32 size;
13376 u32 data_size, wake_size, tokens_size = 0, wake_mask_size;
13377 int err, port;
13378
964dc9e2 13379 if (!rdev->wiphy.wowlan->tcp)
2a0e047e
JB
13380 return -EINVAL;
13381
8cb08174
JB
13382 err = nla_parse_nested_deprecated(tb, MAX_NL80211_WOWLAN_TCP, attr,
13383 nl80211_wowlan_tcp_policy, NULL);
2a0e047e
JB
13384 if (err)
13385 return err;
13386
13387 if (!tb[NL80211_WOWLAN_TCP_SRC_IPV4] ||
13388 !tb[NL80211_WOWLAN_TCP_DST_IPV4] ||
13389 !tb[NL80211_WOWLAN_TCP_DST_MAC] ||
13390 !tb[NL80211_WOWLAN_TCP_DST_PORT] ||
13391 !tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD] ||
13392 !tb[NL80211_WOWLAN_TCP_DATA_INTERVAL] ||
13393 !tb[NL80211_WOWLAN_TCP_WAKE_PAYLOAD] ||
13394 !tb[NL80211_WOWLAN_TCP_WAKE_MASK])
13395 return -EINVAL;
13396
13397 data_size = nla_len(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD]);
964dc9e2 13398 if (data_size > rdev->wiphy.wowlan->tcp->data_payload_max)
2a0e047e
JB
13399 return -EINVAL;
13400
13401 if (nla_get_u32(tb[NL80211_WOWLAN_TCP_DATA_INTERVAL]) >
964dc9e2 13402 rdev->wiphy.wowlan->tcp->data_interval_max ||
723d568a 13403 nla_get_u32(tb[NL80211_WOWLAN_TCP_DATA_INTERVAL]) == 0)
2a0e047e
JB
13404 return -EINVAL;
13405
13406 wake_size = nla_len(tb[NL80211_WOWLAN_TCP_WAKE_PAYLOAD]);
964dc9e2 13407 if (wake_size > rdev->wiphy.wowlan->tcp->wake_payload_max)
2a0e047e
JB
13408 return -EINVAL;
13409
13410 wake_mask_size = nla_len(tb[NL80211_WOWLAN_TCP_WAKE_MASK]);
13411 if (wake_mask_size != DIV_ROUND_UP(wake_size, 8))
13412 return -EINVAL;
13413
13414 if (tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN]) {
13415 u32 tokln = nla_len(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN]);
13416
13417 tok = nla_data(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN]);
13418 tokens_size = tokln - sizeof(*tok);
13419
13420 if (!tok->len || tokens_size % tok->len)
13421 return -EINVAL;
964dc9e2 13422 if (!rdev->wiphy.wowlan->tcp->tok)
2a0e047e 13423 return -EINVAL;
964dc9e2 13424 if (tok->len > rdev->wiphy.wowlan->tcp->tok->max_len)
2a0e047e 13425 return -EINVAL;
964dc9e2 13426 if (tok->len < rdev->wiphy.wowlan->tcp->tok->min_len)
2a0e047e 13427 return -EINVAL;
964dc9e2 13428 if (tokens_size > rdev->wiphy.wowlan->tcp->tok->bufsize)
2a0e047e
JB
13429 return -EINVAL;
13430 if (tok->offset + tok->len > data_size)
13431 return -EINVAL;
13432 }
13433
13434 if (tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ]) {
13435 seq = nla_data(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ]);
964dc9e2 13436 if (!rdev->wiphy.wowlan->tcp->seq)
2a0e047e
JB
13437 return -EINVAL;
13438 if (seq->len == 0 || seq->len > 4)
13439 return -EINVAL;
13440 if (seq->len + seq->offset > data_size)
13441 return -EINVAL;
13442 }
13443
13444 size = sizeof(*cfg);
13445 size += data_size;
13446 size += wake_size + wake_mask_size;
13447 size += tokens_size;
13448
13449 cfg = kzalloc(size, GFP_KERNEL);
13450 if (!cfg)
13451 return -ENOMEM;
67b61f6c
JB
13452 cfg->src = nla_get_in_addr(tb[NL80211_WOWLAN_TCP_SRC_IPV4]);
13453 cfg->dst = nla_get_in_addr(tb[NL80211_WOWLAN_TCP_DST_IPV4]);
2a0e047e
JB
13454 memcpy(cfg->dst_mac, nla_data(tb[NL80211_WOWLAN_TCP_DST_MAC]),
13455 ETH_ALEN);
13456 if (tb[NL80211_WOWLAN_TCP_SRC_PORT])
13457 port = nla_get_u16(tb[NL80211_WOWLAN_TCP_SRC_PORT]);
13458 else
13459 port = 0;
13460#ifdef CONFIG_INET
13461 /* allocate a socket and port for it and use it */
13462 err = __sock_create(wiphy_net(&rdev->wiphy), PF_INET, SOCK_STREAM,
13463 IPPROTO_TCP, &cfg->sock, 1);
13464 if (err) {
13465 kfree(cfg);
13466 return err;
13467 }
13468 if (inet_csk_get_port(cfg->sock->sk, port)) {
13469 sock_release(cfg->sock);
13470 kfree(cfg);
13471 return -EADDRINUSE;
13472 }
13473 cfg->src_port = inet_sk(cfg->sock->sk)->inet_num;
13474#else
13475 if (!port) {
13476 kfree(cfg);
13477 return -EINVAL;
13478 }
13479 cfg->src_port = port;
13480#endif
13481
13482 cfg->dst_port = nla_get_u16(tb[NL80211_WOWLAN_TCP_DST_PORT]);
13483 cfg->payload_len = data_size;
13484 cfg->payload = (u8 *)cfg + sizeof(*cfg) + tokens_size;
13485 memcpy((void *)cfg->payload,
13486 nla_data(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD]),
13487 data_size);
13488 if (seq)
13489 cfg->payload_seq = *seq;
13490 cfg->data_interval = nla_get_u32(tb[NL80211_WOWLAN_TCP_DATA_INTERVAL]);
13491 cfg->wake_len = wake_size;
13492 cfg->wake_data = (u8 *)cfg + sizeof(*cfg) + tokens_size + data_size;
13493 memcpy((void *)cfg->wake_data,
13494 nla_data(tb[NL80211_WOWLAN_TCP_WAKE_PAYLOAD]),
13495 wake_size);
13496 cfg->wake_mask = (u8 *)cfg + sizeof(*cfg) + tokens_size +
13497 data_size + wake_size;
13498 memcpy((void *)cfg->wake_mask,
13499 nla_data(tb[NL80211_WOWLAN_TCP_WAKE_MASK]),
13500 wake_mask_size);
13501 if (tok) {
13502 cfg->tokens_size = tokens_size;
10d5ea5a
KC
13503 cfg->payload_tok = *tok;
13504 memcpy(cfg->payload_tok.token_stream, tok->token_stream,
13505 tokens_size);
2a0e047e
JB
13506 }
13507
13508 trig->tcp = cfg;
13509
13510 return 0;
13511}
13512
8cd4d456
LC
13513static int nl80211_parse_wowlan_nd(struct cfg80211_registered_device *rdev,
13514 const struct wiphy_wowlan_support *wowlan,
13515 struct nlattr *attr,
13516 struct cfg80211_wowlan *trig)
13517{
13518 struct nlattr **tb;
13519 int err;
13520
6396bb22 13521 tb = kcalloc(NUM_NL80211_ATTR, sizeof(*tb), GFP_KERNEL);
8cd4d456
LC
13522 if (!tb)
13523 return -ENOMEM;
13524
13525 if (!(wowlan->flags & WIPHY_WOWLAN_NET_DETECT)) {
13526 err = -EOPNOTSUPP;
13527 goto out;
13528 }
13529
8cb08174
JB
13530 err = nla_parse_nested_deprecated(tb, NL80211_ATTR_MAX, attr,
13531 nl80211_policy, NULL);
8cd4d456
LC
13532 if (err)
13533 goto out;
13534
aad1e812
AVS
13535 trig->nd_config = nl80211_parse_sched_scan(&rdev->wiphy, NULL, tb,
13536 wowlan->max_nd_match_sets);
8cd4d456
LC
13537 err = PTR_ERR_OR_ZERO(trig->nd_config);
13538 if (err)
13539 trig->nd_config = NULL;
13540
13541out:
13542 kfree(tb);
13543 return err;
13544}
13545
ff1b6e69
JB
13546static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
13547{
13548 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13549 struct nlattr *tb[NUM_NL80211_WOWLAN_TRIG];
ff1b6e69 13550 struct cfg80211_wowlan new_triggers = {};
ae33bd81 13551 struct cfg80211_wowlan *ntrig;
964dc9e2 13552 const struct wiphy_wowlan_support *wowlan = rdev->wiphy.wowlan;
ff1b6e69 13553 int err, i;
6abb9cb9 13554 bool prev_enabled = rdev->wiphy.wowlan_config;
98fc4386 13555 bool regular = false;
ff1b6e69 13556
964dc9e2 13557 if (!wowlan)
ff1b6e69
JB
13558 return -EOPNOTSUPP;
13559
ae33bd81
JB
13560 if (!info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS]) {
13561 cfg80211_rdev_free_wowlan(rdev);
6abb9cb9 13562 rdev->wiphy.wowlan_config = NULL;
ae33bd81
JB
13563 goto set_wakeup;
13564 }
ff1b6e69 13565
8cb08174
JB
13566 err = nla_parse_nested_deprecated(tb, MAX_NL80211_WOWLAN_TRIG,
13567 info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS],
13568 nl80211_wowlan_policy, info->extack);
ff1b6e69
JB
13569 if (err)
13570 return err;
13571
13572 if (tb[NL80211_WOWLAN_TRIG_ANY]) {
13573 if (!(wowlan->flags & WIPHY_WOWLAN_ANY))
13574 return -EINVAL;
13575 new_triggers.any = true;
13576 }
13577
13578 if (tb[NL80211_WOWLAN_TRIG_DISCONNECT]) {
13579 if (!(wowlan->flags & WIPHY_WOWLAN_DISCONNECT))
13580 return -EINVAL;
13581 new_triggers.disconnect = true;
98fc4386 13582 regular = true;
ff1b6e69
JB
13583 }
13584
13585 if (tb[NL80211_WOWLAN_TRIG_MAGIC_PKT]) {
13586 if (!(wowlan->flags & WIPHY_WOWLAN_MAGIC_PKT))
13587 return -EINVAL;
13588 new_triggers.magic_pkt = true;
98fc4386 13589 regular = true;
ff1b6e69
JB
13590 }
13591
77dbbb13
JB
13592 if (tb[NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED])
13593 return -EINVAL;
13594
13595 if (tb[NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE]) {
13596 if (!(wowlan->flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE))
13597 return -EINVAL;
13598 new_triggers.gtk_rekey_failure = true;
98fc4386 13599 regular = true;
77dbbb13
JB
13600 }
13601
13602 if (tb[NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST]) {
13603 if (!(wowlan->flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ))
13604 return -EINVAL;
13605 new_triggers.eap_identity_req = true;
98fc4386 13606 regular = true;
77dbbb13
JB
13607 }
13608
13609 if (tb[NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE]) {
13610 if (!(wowlan->flags & WIPHY_WOWLAN_4WAY_HANDSHAKE))
13611 return -EINVAL;
13612 new_triggers.four_way_handshake = true;
98fc4386 13613 regular = true;
77dbbb13
JB
13614 }
13615
13616 if (tb[NL80211_WOWLAN_TRIG_RFKILL_RELEASE]) {
13617 if (!(wowlan->flags & WIPHY_WOWLAN_RFKILL_RELEASE))
13618 return -EINVAL;
13619 new_triggers.rfkill_release = true;
98fc4386 13620 regular = true;
77dbbb13
JB
13621 }
13622
ff1b6e69
JB
13623 if (tb[NL80211_WOWLAN_TRIG_PKT_PATTERN]) {
13624 struct nlattr *pat;
13625 int n_patterns = 0;
bb92d199 13626 int rem, pat_len, mask_len, pkt_offset;
50ac6607 13627 struct nlattr *pat_tb[NUM_NL80211_PKTPAT];
ff1b6e69 13628
98fc4386
JB
13629 regular = true;
13630
ff1b6e69
JB
13631 nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN],
13632 rem)
13633 n_patterns++;
13634 if (n_patterns > wowlan->n_patterns)
13635 return -EINVAL;
13636
13637 new_triggers.patterns = kcalloc(n_patterns,
13638 sizeof(new_triggers.patterns[0]),
13639 GFP_KERNEL);
13640 if (!new_triggers.patterns)
13641 return -ENOMEM;
13642
13643 new_triggers.n_patterns = n_patterns;
13644 i = 0;
13645
13646 nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN],
13647 rem) {
922bd80f
JB
13648 u8 *mask_pat;
13649
8cb08174
JB
13650 err = nla_parse_nested_deprecated(pat_tb,
13651 MAX_NL80211_PKTPAT,
13652 pat,
13653 nl80211_packet_pattern_policy,
13654 info->extack);
95bca62f
JB
13655 if (err)
13656 goto error;
13657
ff1b6e69 13658 err = -EINVAL;
50ac6607
AK
13659 if (!pat_tb[NL80211_PKTPAT_MASK] ||
13660 !pat_tb[NL80211_PKTPAT_PATTERN])
ff1b6e69 13661 goto error;
50ac6607 13662 pat_len = nla_len(pat_tb[NL80211_PKTPAT_PATTERN]);
ff1b6e69 13663 mask_len = DIV_ROUND_UP(pat_len, 8);
50ac6607 13664 if (nla_len(pat_tb[NL80211_PKTPAT_MASK]) != mask_len)
ff1b6e69
JB
13665 goto error;
13666 if (pat_len > wowlan->pattern_max_len ||
13667 pat_len < wowlan->pattern_min_len)
13668 goto error;
13669
50ac6607 13670 if (!pat_tb[NL80211_PKTPAT_OFFSET])
bb92d199
AK
13671 pkt_offset = 0;
13672 else
13673 pkt_offset = nla_get_u32(
50ac6607 13674 pat_tb[NL80211_PKTPAT_OFFSET]);
bb92d199
AK
13675 if (pkt_offset > wowlan->max_pkt_offset)
13676 goto error;
13677 new_triggers.patterns[i].pkt_offset = pkt_offset;
13678
922bd80f
JB
13679 mask_pat = kmalloc(mask_len + pat_len, GFP_KERNEL);
13680 if (!mask_pat) {
ff1b6e69
JB
13681 err = -ENOMEM;
13682 goto error;
13683 }
922bd80f
JB
13684 new_triggers.patterns[i].mask = mask_pat;
13685 memcpy(mask_pat, nla_data(pat_tb[NL80211_PKTPAT_MASK]),
ff1b6e69 13686 mask_len);
922bd80f
JB
13687 mask_pat += mask_len;
13688 new_triggers.patterns[i].pattern = mask_pat;
ff1b6e69 13689 new_triggers.patterns[i].pattern_len = pat_len;
922bd80f 13690 memcpy(mask_pat,
50ac6607 13691 nla_data(pat_tb[NL80211_PKTPAT_PATTERN]),
ff1b6e69
JB
13692 pat_len);
13693 i++;
13694 }
13695 }
13696
2a0e047e 13697 if (tb[NL80211_WOWLAN_TRIG_TCP_CONNECTION]) {
98fc4386 13698 regular = true;
2a0e047e
JB
13699 err = nl80211_parse_wowlan_tcp(
13700 rdev, tb[NL80211_WOWLAN_TRIG_TCP_CONNECTION],
13701 &new_triggers);
13702 if (err)
13703 goto error;
13704 }
13705
8cd4d456 13706 if (tb[NL80211_WOWLAN_TRIG_NET_DETECT]) {
98fc4386 13707 regular = true;
8cd4d456
LC
13708 err = nl80211_parse_wowlan_nd(
13709 rdev, wowlan, tb[NL80211_WOWLAN_TRIG_NET_DETECT],
13710 &new_triggers);
13711 if (err)
13712 goto error;
13713 }
13714
98fc4386
JB
13715 /* The 'any' trigger means the device continues operating more or less
13716 * as in its normal operation mode and wakes up the host on most of the
13717 * normal interrupts (like packet RX, ...)
13718 * It therefore makes little sense to combine with the more constrained
13719 * wakeup trigger modes.
13720 */
13721 if (new_triggers.any && regular) {
13722 err = -EINVAL;
13723 goto error;
13724 }
13725
ae33bd81
JB
13726 ntrig = kmemdup(&new_triggers, sizeof(new_triggers), GFP_KERNEL);
13727 if (!ntrig) {
13728 err = -ENOMEM;
13729 goto error;
ff1b6e69 13730 }
ae33bd81 13731 cfg80211_rdev_free_wowlan(rdev);
6abb9cb9 13732 rdev->wiphy.wowlan_config = ntrig;
ff1b6e69 13733
ae33bd81 13734 set_wakeup:
6abb9cb9
JB
13735 if (rdev->ops->set_wakeup &&
13736 prev_enabled != !!rdev->wiphy.wowlan_config)
13737 rdev_set_wakeup(rdev, rdev->wiphy.wowlan_config);
6d52563f 13738
ff1b6e69
JB
13739 return 0;
13740 error:
13741 for (i = 0; i < new_triggers.n_patterns; i++)
13742 kfree(new_triggers.patterns[i].mask);
13743 kfree(new_triggers.patterns);
2a0e047e
JB
13744 if (new_triggers.tcp && new_triggers.tcp->sock)
13745 sock_release(new_triggers.tcp->sock);
13746 kfree(new_triggers.tcp);
e5dbe070 13747 kfree(new_triggers.nd_config);
ff1b6e69
JB
13748 return err;
13749}
dfb89c56 13750#endif
ff1b6e69 13751
be29b99a
AK
13752static int nl80211_send_coalesce_rules(struct sk_buff *msg,
13753 struct cfg80211_registered_device *rdev)
13754{
13755 struct nlattr *nl_pats, *nl_pat, *nl_rule, *nl_rules;
13756 int i, j, pat_len;
13757 struct cfg80211_coalesce_rules *rule;
13758
13759 if (!rdev->coalesce->n_rules)
13760 return 0;
13761
ae0be8de 13762 nl_rules = nla_nest_start_noflag(msg, NL80211_ATTR_COALESCE_RULE);
be29b99a
AK
13763 if (!nl_rules)
13764 return -ENOBUFS;
13765
13766 for (i = 0; i < rdev->coalesce->n_rules; i++) {
ae0be8de 13767 nl_rule = nla_nest_start_noflag(msg, i + 1);
be29b99a
AK
13768 if (!nl_rule)
13769 return -ENOBUFS;
13770
13771 rule = &rdev->coalesce->rules[i];
13772 if (nla_put_u32(msg, NL80211_ATTR_COALESCE_RULE_DELAY,
13773 rule->delay))
13774 return -ENOBUFS;
13775
13776 if (nla_put_u32(msg, NL80211_ATTR_COALESCE_RULE_CONDITION,
13777 rule->condition))
13778 return -ENOBUFS;
13779
ae0be8de
MK
13780 nl_pats = nla_nest_start_noflag(msg,
13781 NL80211_ATTR_COALESCE_RULE_PKT_PATTERN);
be29b99a
AK
13782 if (!nl_pats)
13783 return -ENOBUFS;
13784
13785 for (j = 0; j < rule->n_patterns; j++) {
ae0be8de 13786 nl_pat = nla_nest_start_noflag(msg, j + 1);
be29b99a
AK
13787 if (!nl_pat)
13788 return -ENOBUFS;
13789 pat_len = rule->patterns[j].pattern_len;
13790 if (nla_put(msg, NL80211_PKTPAT_MASK,
13791 DIV_ROUND_UP(pat_len, 8),
13792 rule->patterns[j].mask) ||
13793 nla_put(msg, NL80211_PKTPAT_PATTERN, pat_len,
13794 rule->patterns[j].pattern) ||
13795 nla_put_u32(msg, NL80211_PKTPAT_OFFSET,
13796 rule->patterns[j].pkt_offset))
13797 return -ENOBUFS;
13798 nla_nest_end(msg, nl_pat);
13799 }
13800 nla_nest_end(msg, nl_pats);
13801 nla_nest_end(msg, nl_rule);
13802 }
13803 nla_nest_end(msg, nl_rules);
13804
13805 return 0;
13806}
13807
13808static int nl80211_get_coalesce(struct sk_buff *skb, struct genl_info *info)
13809{
13810 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13811 struct sk_buff *msg;
13812 void *hdr;
13813
13814 if (!rdev->wiphy.coalesce)
13815 return -EOPNOTSUPP;
13816
13817 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
13818 if (!msg)
13819 return -ENOMEM;
13820
13821 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
13822 NL80211_CMD_GET_COALESCE);
13823 if (!hdr)
13824 goto nla_put_failure;
13825
13826 if (rdev->coalesce && nl80211_send_coalesce_rules(msg, rdev))
13827 goto nla_put_failure;
13828
13829 genlmsg_end(msg, hdr);
13830 return genlmsg_reply(msg, info);
13831
13832nla_put_failure:
13833 nlmsg_free(msg);
13834 return -ENOBUFS;
13835}
13836
13837void cfg80211_rdev_free_coalesce(struct cfg80211_registered_device *rdev)
13838{
13839 struct cfg80211_coalesce *coalesce = rdev->coalesce;
13840 int i, j;
13841 struct cfg80211_coalesce_rules *rule;
13842
13843 if (!coalesce)
13844 return;
13845
13846 for (i = 0; i < coalesce->n_rules; i++) {
13847 rule = &coalesce->rules[i];
13848 for (j = 0; j < rule->n_patterns; j++)
13849 kfree(rule->patterns[j].mask);
13850 kfree(rule->patterns);
13851 }
13852 kfree(coalesce->rules);
13853 kfree(coalesce);
13854 rdev->coalesce = NULL;
13855}
13856
13857static int nl80211_parse_coalesce_rule(struct cfg80211_registered_device *rdev,
13858 struct nlattr *rule,
13859 struct cfg80211_coalesce_rules *new_rule)
13860{
13861 int err, i;
13862 const struct wiphy_coalesce_support *coalesce = rdev->wiphy.coalesce;
13863 struct nlattr *tb[NUM_NL80211_ATTR_COALESCE_RULE], *pat;
13864 int rem, pat_len, mask_len, pkt_offset, n_patterns = 0;
13865 struct nlattr *pat_tb[NUM_NL80211_PKTPAT];
13866
8cb08174
JB
13867 err = nla_parse_nested_deprecated(tb, NL80211_ATTR_COALESCE_RULE_MAX,
13868 rule, nl80211_coalesce_policy, NULL);
be29b99a
AK
13869 if (err)
13870 return err;
13871
13872 if (tb[NL80211_ATTR_COALESCE_RULE_DELAY])
13873 new_rule->delay =
13874 nla_get_u32(tb[NL80211_ATTR_COALESCE_RULE_DELAY]);
13875 if (new_rule->delay > coalesce->max_delay)
13876 return -EINVAL;
13877
13878 if (tb[NL80211_ATTR_COALESCE_RULE_CONDITION])
13879 new_rule->condition =
13880 nla_get_u32(tb[NL80211_ATTR_COALESCE_RULE_CONDITION]);
be29b99a
AK
13881
13882 if (!tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN])
13883 return -EINVAL;
13884
13885 nla_for_each_nested(pat, tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN],
13886 rem)
13887 n_patterns++;
13888 if (n_patterns > coalesce->n_patterns)
13889 return -EINVAL;
13890
13891 new_rule->patterns = kcalloc(n_patterns, sizeof(new_rule->patterns[0]),
13892 GFP_KERNEL);
13893 if (!new_rule->patterns)
13894 return -ENOMEM;
13895
13896 new_rule->n_patterns = n_patterns;
13897 i = 0;
13898
13899 nla_for_each_nested(pat, tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN],
13900 rem) {
922bd80f
JB
13901 u8 *mask_pat;
13902
8cb08174
JB
13903 err = nla_parse_nested_deprecated(pat_tb, MAX_NL80211_PKTPAT,
13904 pat,
13905 nl80211_packet_pattern_policy,
13906 NULL);
95bca62f
JB
13907 if (err)
13908 return err;
13909
be29b99a
AK
13910 if (!pat_tb[NL80211_PKTPAT_MASK] ||
13911 !pat_tb[NL80211_PKTPAT_PATTERN])
13912 return -EINVAL;
13913 pat_len = nla_len(pat_tb[NL80211_PKTPAT_PATTERN]);
13914 mask_len = DIV_ROUND_UP(pat_len, 8);
13915 if (nla_len(pat_tb[NL80211_PKTPAT_MASK]) != mask_len)
13916 return -EINVAL;
13917 if (pat_len > coalesce->pattern_max_len ||
13918 pat_len < coalesce->pattern_min_len)
13919 return -EINVAL;
13920
13921 if (!pat_tb[NL80211_PKTPAT_OFFSET])
13922 pkt_offset = 0;
13923 else
13924 pkt_offset = nla_get_u32(pat_tb[NL80211_PKTPAT_OFFSET]);
13925 if (pkt_offset > coalesce->max_pkt_offset)
13926 return -EINVAL;
13927 new_rule->patterns[i].pkt_offset = pkt_offset;
13928
922bd80f
JB
13929 mask_pat = kmalloc(mask_len + pat_len, GFP_KERNEL);
13930 if (!mask_pat)
be29b99a 13931 return -ENOMEM;
922bd80f
JB
13932
13933 new_rule->patterns[i].mask = mask_pat;
13934 memcpy(mask_pat, nla_data(pat_tb[NL80211_PKTPAT_MASK]),
13935 mask_len);
13936
13937 mask_pat += mask_len;
13938 new_rule->patterns[i].pattern = mask_pat;
be29b99a 13939 new_rule->patterns[i].pattern_len = pat_len;
922bd80f
JB
13940 memcpy(mask_pat, nla_data(pat_tb[NL80211_PKTPAT_PATTERN]),
13941 pat_len);
be29b99a
AK
13942 i++;
13943 }
13944
13945 return 0;
13946}
13947
13948static int nl80211_set_coalesce(struct sk_buff *skb, struct genl_info *info)
13949{
13950 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13951 const struct wiphy_coalesce_support *coalesce = rdev->wiphy.coalesce;
13952 struct cfg80211_coalesce new_coalesce = {};
13953 struct cfg80211_coalesce *n_coalesce;
13954 int err, rem_rule, n_rules = 0, i, j;
13955 struct nlattr *rule;
13956 struct cfg80211_coalesce_rules *tmp_rule;
13957
13958 if (!rdev->wiphy.coalesce || !rdev->ops->set_coalesce)
13959 return -EOPNOTSUPP;
13960
13961 if (!info->attrs[NL80211_ATTR_COALESCE_RULE]) {
13962 cfg80211_rdev_free_coalesce(rdev);
a1056b1b 13963 rdev_set_coalesce(rdev, NULL);
be29b99a
AK
13964 return 0;
13965 }
13966
13967 nla_for_each_nested(rule, info->attrs[NL80211_ATTR_COALESCE_RULE],
13968 rem_rule)
13969 n_rules++;
13970 if (n_rules > coalesce->n_rules)
13971 return -EINVAL;
13972
13973 new_coalesce.rules = kcalloc(n_rules, sizeof(new_coalesce.rules[0]),
13974 GFP_KERNEL);
13975 if (!new_coalesce.rules)
13976 return -ENOMEM;
13977
13978 new_coalesce.n_rules = n_rules;
13979 i = 0;
13980
13981 nla_for_each_nested(rule, info->attrs[NL80211_ATTR_COALESCE_RULE],
13982 rem_rule) {
13983 err = nl80211_parse_coalesce_rule(rdev, rule,
13984 &new_coalesce.rules[i]);
13985 if (err)
13986 goto error;
13987
13988 i++;
13989 }
13990
a1056b1b 13991 err = rdev_set_coalesce(rdev, &new_coalesce);
be29b99a
AK
13992 if (err)
13993 goto error;
13994
13995 n_coalesce = kmemdup(&new_coalesce, sizeof(new_coalesce), GFP_KERNEL);
13996 if (!n_coalesce) {
13997 err = -ENOMEM;
13998 goto error;
13999 }
14000 cfg80211_rdev_free_coalesce(rdev);
14001 rdev->coalesce = n_coalesce;
14002
14003 return 0;
14004error:
14005 for (i = 0; i < new_coalesce.n_rules; i++) {
14006 tmp_rule = &new_coalesce.rules[i];
14007 for (j = 0; j < tmp_rule->n_patterns; j++)
14008 kfree(tmp_rule->patterns[j].mask);
14009 kfree(tmp_rule->patterns);
14010 }
14011 kfree(new_coalesce.rules);
14012
14013 return err;
14014}
14015
e5497d76
JB
14016static int nl80211_set_rekey_data(struct sk_buff *skb, struct genl_info *info)
14017{
14018 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14019 struct net_device *dev = info->user_ptr[1];
14020 struct wireless_dev *wdev = dev->ieee80211_ptr;
14021 struct nlattr *tb[NUM_NL80211_REKEY_DATA];
f495acd8 14022 struct cfg80211_gtk_rekey_data rekey_data = {};
e5497d76
JB
14023 int err;
14024
14025 if (!info->attrs[NL80211_ATTR_REKEY_DATA])
14026 return -EINVAL;
14027
8cb08174
JB
14028 err = nla_parse_nested_deprecated(tb, MAX_NL80211_REKEY_DATA,
14029 info->attrs[NL80211_ATTR_REKEY_DATA],
14030 nl80211_rekey_policy, info->extack);
e5497d76
JB
14031 if (err)
14032 return err;
14033
e785fa0a
VD
14034 if (!tb[NL80211_REKEY_DATA_REPLAY_CTR] || !tb[NL80211_REKEY_DATA_KEK] ||
14035 !tb[NL80211_REKEY_DATA_KCK])
14036 return -EINVAL;
093a48d2
NE
14037 if (nla_len(tb[NL80211_REKEY_DATA_KEK]) != NL80211_KEK_LEN &&
14038 !(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_EXT_KEK_KCK &&
14039 nla_len(tb[NL80211_REKEY_DATA_KEK]) == NL80211_KEK_EXT_LEN))
e5497d76 14040 return -ERANGE;
093a48d2
NE
14041 if (nla_len(tb[NL80211_REKEY_DATA_KCK]) != NL80211_KCK_LEN &&
14042 !(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_EXT_KEK_KCK &&
648fba79
SB
14043 nla_len(tb[NL80211_REKEY_DATA_KCK]) == NL80211_KCK_EXT_LEN) &&
14044 !(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_EXT_KCK_32 &&
14045 nla_len(tb[NL80211_REKEY_DATA_KCK]) == NL80211_KCK_EXT_LEN_32))
e5497d76
JB
14046 return -ERANGE;
14047
78f686ca
JB
14048 rekey_data.kek = nla_data(tb[NL80211_REKEY_DATA_KEK]);
14049 rekey_data.kck = nla_data(tb[NL80211_REKEY_DATA_KCK]);
14050 rekey_data.replay_ctr = nla_data(tb[NL80211_REKEY_DATA_REPLAY_CTR]);
093a48d2
NE
14051 rekey_data.kek_len = nla_len(tb[NL80211_REKEY_DATA_KEK]);
14052 rekey_data.kck_len = nla_len(tb[NL80211_REKEY_DATA_KCK]);
14053 if (tb[NL80211_REKEY_DATA_AKM])
14054 rekey_data.akm = nla_get_u32(tb[NL80211_REKEY_DATA_AKM]);
e5497d76
JB
14055
14056 wdev_lock(wdev);
7b0a0e3c 14057 if (!wdev->connected) {
e5497d76
JB
14058 err = -ENOTCONN;
14059 goto out;
14060 }
14061
14062 if (!rdev->ops->set_rekey_data) {
14063 err = -EOPNOTSUPP;
14064 goto out;
14065 }
14066
e35e4d28 14067 err = rdev_set_rekey_data(rdev, dev, &rekey_data);
e5497d76
JB
14068 out:
14069 wdev_unlock(wdev);
14070 return err;
14071}
14072
28946da7
JB
14073static int nl80211_register_unexpected_frame(struct sk_buff *skb,
14074 struct genl_info *info)
14075{
14076 struct net_device *dev = info->user_ptr[1];
14077 struct wireless_dev *wdev = dev->ieee80211_ptr;
14078
14079 if (wdev->iftype != NL80211_IFTYPE_AP &&
14080 wdev->iftype != NL80211_IFTYPE_P2P_GO)
14081 return -EINVAL;
14082
15e47304 14083 if (wdev->ap_unexpected_nlportid)
28946da7
JB
14084 return -EBUSY;
14085
15e47304 14086 wdev->ap_unexpected_nlportid = info->snd_portid;
28946da7
JB
14087 return 0;
14088}
14089
7f6cf311
JB
14090static int nl80211_probe_client(struct sk_buff *skb,
14091 struct genl_info *info)
14092{
14093 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14094 struct net_device *dev = info->user_ptr[1];
14095 struct wireless_dev *wdev = dev->ieee80211_ptr;
14096 struct sk_buff *msg;
14097 void *hdr;
14098 const u8 *addr;
14099 u64 cookie;
14100 int err;
14101
14102 if (wdev->iftype != NL80211_IFTYPE_AP &&
14103 wdev->iftype != NL80211_IFTYPE_P2P_GO)
14104 return -EOPNOTSUPP;
14105
14106 if (!info->attrs[NL80211_ATTR_MAC])
14107 return -EINVAL;
14108
14109 if (!rdev->ops->probe_client)
14110 return -EOPNOTSUPP;
14111
14112 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
14113 if (!msg)
14114 return -ENOMEM;
14115
15e47304 14116 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
7f6cf311 14117 NL80211_CMD_PROBE_CLIENT);
cb35fba3
DC
14118 if (!hdr) {
14119 err = -ENOBUFS;
7f6cf311
JB
14120 goto free_msg;
14121 }
14122
14123 addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
14124
e35e4d28 14125 err = rdev_probe_client(rdev, dev, addr, &cookie);
7f6cf311
JB
14126 if (err)
14127 goto free_msg;
14128
2dad624e
ND
14129 if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
14130 NL80211_ATTR_PAD))
9360ffd1 14131 goto nla_put_failure;
7f6cf311
JB
14132
14133 genlmsg_end(msg, hdr);
14134
14135 return genlmsg_reply(msg, info);
14136
14137 nla_put_failure:
14138 err = -ENOBUFS;
14139 free_msg:
14140 nlmsg_free(msg);
14141 return err;
14142}
14143
5e760230
JB
14144static int nl80211_register_beacons(struct sk_buff *skb, struct genl_info *info)
14145{
14146 struct cfg80211_registered_device *rdev = info->user_ptr[0];
37c73b5f
BG
14147 struct cfg80211_beacon_registration *reg, *nreg;
14148 int rv;
5e760230
JB
14149
14150 if (!(rdev->wiphy.flags & WIPHY_FLAG_REPORTS_OBSS))
14151 return -EOPNOTSUPP;
14152
37c73b5f
BG
14153 nreg = kzalloc(sizeof(*nreg), GFP_KERNEL);
14154 if (!nreg)
14155 return -ENOMEM;
14156
14157 /* First, check if already registered. */
14158 spin_lock_bh(&rdev->beacon_registrations_lock);
14159 list_for_each_entry(reg, &rdev->beacon_registrations, list) {
14160 if (reg->nlportid == info->snd_portid) {
14161 rv = -EALREADY;
14162 goto out_err;
14163 }
14164 }
14165 /* Add it to the list */
14166 nreg->nlportid = info->snd_portid;
14167 list_add(&nreg->list, &rdev->beacon_registrations);
5e760230 14168
37c73b5f 14169 spin_unlock_bh(&rdev->beacon_registrations_lock);
5e760230
JB
14170
14171 return 0;
37c73b5f
BG
14172out_err:
14173 spin_unlock_bh(&rdev->beacon_registrations_lock);
14174 kfree(nreg);
14175 return rv;
5e760230
JB
14176}
14177
98104fde
JB
14178static int nl80211_start_p2p_device(struct sk_buff *skb, struct genl_info *info)
14179{
14180 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14181 struct wireless_dev *wdev = info->user_ptr[1];
14182 int err;
14183
14184 if (!rdev->ops->start_p2p_device)
14185 return -EOPNOTSUPP;
14186
14187 if (wdev->iftype != NL80211_IFTYPE_P2P_DEVICE)
14188 return -EOPNOTSUPP;
14189
73c7da3d 14190 if (wdev_running(wdev))
98104fde
JB
14191 return 0;
14192
358ae888 14193 if (rfkill_blocked(rdev->wiphy.rfkill))
b6a55015 14194 return -ERFKILL;
98104fde 14195
eeb126e9 14196 err = rdev_start_p2p_device(rdev, wdev);
98104fde
JB
14197 if (err)
14198 return err;
14199
73c7da3d 14200 wdev->is_running = true;
98104fde 14201 rdev->opencount++;
98104fde
JB
14202
14203 return 0;
14204}
14205
14206static int nl80211_stop_p2p_device(struct sk_buff *skb, struct genl_info *info)
14207{
14208 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14209 struct wireless_dev *wdev = info->user_ptr[1];
14210
14211 if (wdev->iftype != NL80211_IFTYPE_P2P_DEVICE)
14212 return -EOPNOTSUPP;
14213
14214 if (!rdev->ops->stop_p2p_device)
14215 return -EOPNOTSUPP;
14216
f9f47529 14217 cfg80211_stop_p2p_device(rdev, wdev);
98104fde
JB
14218
14219 return 0;
14220}
14221
cb3b7d87
AB
14222static int nl80211_start_nan(struct sk_buff *skb, struct genl_info *info)
14223{
14224 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14225 struct wireless_dev *wdev = info->user_ptr[1];
14226 struct cfg80211_nan_conf conf = {};
14227 int err;
14228
14229 if (wdev->iftype != NL80211_IFTYPE_NAN)
14230 return -EOPNOTSUPP;
14231
eeb04a96 14232 if (wdev_running(wdev))
cb3b7d87
AB
14233 return -EEXIST;
14234
358ae888 14235 if (rfkill_blocked(rdev->wiphy.rfkill))
cb3b7d87
AB
14236 return -ERFKILL;
14237
14238 if (!info->attrs[NL80211_ATTR_NAN_MASTER_PREF])
14239 return -EINVAL;
14240
cb3b7d87
AB
14241 conf.master_pref =
14242 nla_get_u8(info->attrs[NL80211_ATTR_NAN_MASTER_PREF]);
cb3b7d87 14243
8585989d
LC
14244 if (info->attrs[NL80211_ATTR_BANDS]) {
14245 u32 bands = nla_get_u32(info->attrs[NL80211_ATTR_BANDS]);
14246
14247 if (bands & ~(u32)wdev->wiphy->nan_supported_bands)
14248 return -EOPNOTSUPP;
14249
14250 if (bands && !(bands & BIT(NL80211_BAND_2GHZ)))
14251 return -EINVAL;
14252
14253 conf.bands = bands;
14254 }
cb3b7d87
AB
14255
14256 err = rdev_start_nan(rdev, wdev, &conf);
14257 if (err)
14258 return err;
14259
73c7da3d 14260 wdev->is_running = true;
cb3b7d87
AB
14261 rdev->opencount++;
14262
14263 return 0;
14264}
14265
14266static int nl80211_stop_nan(struct sk_buff *skb, struct genl_info *info)
14267{
14268 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14269 struct wireless_dev *wdev = info->user_ptr[1];
14270
14271 if (wdev->iftype != NL80211_IFTYPE_NAN)
14272 return -EOPNOTSUPP;
14273
14274 cfg80211_stop_nan(rdev, wdev);
14275
14276 return 0;
14277}
14278
a442b761
AB
14279static int validate_nan_filter(struct nlattr *filter_attr)
14280{
14281 struct nlattr *attr;
14282 int len = 0, n_entries = 0, rem;
14283
14284 nla_for_each_nested(attr, filter_attr, rem) {
14285 len += nla_len(attr);
14286 n_entries++;
14287 }
14288
14289 if (len >= U8_MAX)
14290 return -EINVAL;
14291
14292 return n_entries;
14293}
14294
14295static int handle_nan_filter(struct nlattr *attr_filter,
14296 struct cfg80211_nan_func *func,
14297 bool tx)
14298{
14299 struct nlattr *attr;
14300 int n_entries, rem, i;
14301 struct cfg80211_nan_func_filter *filter;
14302
14303 n_entries = validate_nan_filter(attr_filter);
14304 if (n_entries < 0)
14305 return n_entries;
14306
14307 BUILD_BUG_ON(sizeof(*func->rx_filters) != sizeof(*func->tx_filters));
14308
14309 filter = kcalloc(n_entries, sizeof(*func->rx_filters), GFP_KERNEL);
14310 if (!filter)
14311 return -ENOMEM;
14312
14313 i = 0;
14314 nla_for_each_nested(attr, attr_filter, rem) {
b15ca182 14315 filter[i].filter = nla_memdup(attr, GFP_KERNEL);
6ad27f52
JJ
14316 if (!filter[i].filter)
14317 goto err;
14318
a442b761
AB
14319 filter[i].len = nla_len(attr);
14320 i++;
14321 }
14322 if (tx) {
14323 func->num_tx_filters = n_entries;
14324 func->tx_filters = filter;
14325 } else {
14326 func->num_rx_filters = n_entries;
14327 func->rx_filters = filter;
14328 }
14329
14330 return 0;
6ad27f52
JJ
14331
14332err:
14333 i = 0;
14334 nla_for_each_nested(attr, attr_filter, rem) {
14335 kfree(filter[i].filter);
14336 i++;
14337 }
14338 kfree(filter);
14339 return -ENOMEM;
a442b761
AB
14340}
14341
14342static int nl80211_nan_add_func(struct sk_buff *skb,
14343 struct genl_info *info)
14344{
14345 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14346 struct wireless_dev *wdev = info->user_ptr[1];
14347 struct nlattr *tb[NUM_NL80211_NAN_FUNC_ATTR], *func_attr;
14348 struct cfg80211_nan_func *func;
14349 struct sk_buff *msg = NULL;
14350 void *hdr = NULL;
14351 int err = 0;
14352
14353 if (wdev->iftype != NL80211_IFTYPE_NAN)
14354 return -EOPNOTSUPP;
14355
73c7da3d 14356 if (!wdev_running(wdev))
a442b761
AB
14357 return -ENOTCONN;
14358
14359 if (!info->attrs[NL80211_ATTR_NAN_FUNC])
14360 return -EINVAL;
14361
8cb08174
JB
14362 err = nla_parse_nested_deprecated(tb, NL80211_NAN_FUNC_ATTR_MAX,
14363 info->attrs[NL80211_ATTR_NAN_FUNC],
14364 nl80211_nan_func_policy,
14365 info->extack);
a442b761
AB
14366 if (err)
14367 return err;
14368
14369 func = kzalloc(sizeof(*func), GFP_KERNEL);
14370 if (!func)
14371 return -ENOMEM;
14372
b60ad348 14373 func->cookie = cfg80211_assign_cookie(rdev);
a442b761 14374
cb9abd48 14375 if (!tb[NL80211_NAN_FUNC_TYPE]) {
a442b761
AB
14376 err = -EINVAL;
14377 goto out;
14378 }
14379
14380
14381 func->type = nla_get_u8(tb[NL80211_NAN_FUNC_TYPE]);
14382
14383 if (!tb[NL80211_NAN_FUNC_SERVICE_ID]) {
14384 err = -EINVAL;
14385 goto out;
14386 }
14387
14388 memcpy(func->service_id, nla_data(tb[NL80211_NAN_FUNC_SERVICE_ID]),
14389 sizeof(func->service_id));
14390
14391 func->close_range =
14392 nla_get_flag(tb[NL80211_NAN_FUNC_CLOSE_RANGE]);
14393
14394 if (tb[NL80211_NAN_FUNC_SERVICE_INFO]) {
14395 func->serv_spec_info_len =
14396 nla_len(tb[NL80211_NAN_FUNC_SERVICE_INFO]);
14397 func->serv_spec_info =
14398 kmemdup(nla_data(tb[NL80211_NAN_FUNC_SERVICE_INFO]),
14399 func->serv_spec_info_len,
14400 GFP_KERNEL);
14401 if (!func->serv_spec_info) {
14402 err = -ENOMEM;
14403 goto out;
14404 }
14405 }
14406
14407 if (tb[NL80211_NAN_FUNC_TTL])
14408 func->ttl = nla_get_u32(tb[NL80211_NAN_FUNC_TTL]);
14409
14410 switch (func->type) {
14411 case NL80211_NAN_FUNC_PUBLISH:
14412 if (!tb[NL80211_NAN_FUNC_PUBLISH_TYPE]) {
14413 err = -EINVAL;
14414 goto out;
14415 }
14416
14417 func->publish_type =
14418 nla_get_u8(tb[NL80211_NAN_FUNC_PUBLISH_TYPE]);
14419 func->publish_bcast =
14420 nla_get_flag(tb[NL80211_NAN_FUNC_PUBLISH_BCAST]);
14421
14422 if ((!(func->publish_type & NL80211_NAN_SOLICITED_PUBLISH)) &&
14423 func->publish_bcast) {
14424 err = -EINVAL;
14425 goto out;
14426 }
14427 break;
14428 case NL80211_NAN_FUNC_SUBSCRIBE:
14429 func->subscribe_active =
14430 nla_get_flag(tb[NL80211_NAN_FUNC_SUBSCRIBE_ACTIVE]);
14431 break;
14432 case NL80211_NAN_FUNC_FOLLOW_UP:
14433 if (!tb[NL80211_NAN_FUNC_FOLLOW_UP_ID] ||
3ea15452
HC
14434 !tb[NL80211_NAN_FUNC_FOLLOW_UP_REQ_ID] ||
14435 !tb[NL80211_NAN_FUNC_FOLLOW_UP_DEST]) {
a442b761
AB
14436 err = -EINVAL;
14437 goto out;
14438 }
14439
14440 func->followup_id =
14441 nla_get_u8(tb[NL80211_NAN_FUNC_FOLLOW_UP_ID]);
14442 func->followup_reqid =
14443 nla_get_u8(tb[NL80211_NAN_FUNC_FOLLOW_UP_REQ_ID]);
14444 memcpy(func->followup_dest.addr,
14445 nla_data(tb[NL80211_NAN_FUNC_FOLLOW_UP_DEST]),
14446 sizeof(func->followup_dest.addr));
14447 if (func->ttl) {
14448 err = -EINVAL;
14449 goto out;
14450 }
14451 break;
14452 default:
14453 err = -EINVAL;
14454 goto out;
14455 }
14456
14457 if (tb[NL80211_NAN_FUNC_SRF]) {
14458 struct nlattr *srf_tb[NUM_NL80211_NAN_SRF_ATTR];
14459
8cb08174
JB
14460 err = nla_parse_nested_deprecated(srf_tb,
14461 NL80211_NAN_SRF_ATTR_MAX,
14462 tb[NL80211_NAN_FUNC_SRF],
14463 nl80211_nan_srf_policy,
14464 info->extack);
a442b761
AB
14465 if (err)
14466 goto out;
14467
14468 func->srf_include =
14469 nla_get_flag(srf_tb[NL80211_NAN_SRF_INCLUDE]);
14470
14471 if (srf_tb[NL80211_NAN_SRF_BF]) {
14472 if (srf_tb[NL80211_NAN_SRF_MAC_ADDRS] ||
14473 !srf_tb[NL80211_NAN_SRF_BF_IDX]) {
14474 err = -EINVAL;
14475 goto out;
14476 }
14477
14478 func->srf_bf_len =
14479 nla_len(srf_tb[NL80211_NAN_SRF_BF]);
14480 func->srf_bf =
14481 kmemdup(nla_data(srf_tb[NL80211_NAN_SRF_BF]),
14482 func->srf_bf_len, GFP_KERNEL);
14483 if (!func->srf_bf) {
14484 err = -ENOMEM;
14485 goto out;
14486 }
14487
14488 func->srf_bf_idx =
14489 nla_get_u8(srf_tb[NL80211_NAN_SRF_BF_IDX]);
14490 } else {
14491 struct nlattr *attr, *mac_attr =
14492 srf_tb[NL80211_NAN_SRF_MAC_ADDRS];
14493 int n_entries, rem, i = 0;
14494
14495 if (!mac_attr) {
14496 err = -EINVAL;
14497 goto out;
14498 }
14499
14500 n_entries = validate_acl_mac_addrs(mac_attr);
14501 if (n_entries <= 0) {
14502 err = -EINVAL;
14503 goto out;
14504 }
14505
14506 func->srf_num_macs = n_entries;
14507 func->srf_macs =
6396bb22 14508 kcalloc(n_entries, sizeof(*func->srf_macs),
a442b761
AB
14509 GFP_KERNEL);
14510 if (!func->srf_macs) {
14511 err = -ENOMEM;
14512 goto out;
14513 }
14514
14515 nla_for_each_nested(attr, mac_attr, rem)
14516 memcpy(func->srf_macs[i++].addr, nla_data(attr),
14517 sizeof(*func->srf_macs));
14518 }
14519 }
14520
14521 if (tb[NL80211_NAN_FUNC_TX_MATCH_FILTER]) {
14522 err = handle_nan_filter(tb[NL80211_NAN_FUNC_TX_MATCH_FILTER],
14523 func, true);
14524 if (err)
14525 goto out;
14526 }
14527
14528 if (tb[NL80211_NAN_FUNC_RX_MATCH_FILTER]) {
14529 err = handle_nan_filter(tb[NL80211_NAN_FUNC_RX_MATCH_FILTER],
14530 func, false);
14531 if (err)
14532 goto out;
14533 }
14534
14535 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
14536 if (!msg) {
14537 err = -ENOMEM;
14538 goto out;
14539 }
14540
14541 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
14542 NL80211_CMD_ADD_NAN_FUNCTION);
14543 /* This can't really happen - we just allocated 4KB */
14544 if (WARN_ON(!hdr)) {
14545 err = -ENOMEM;
14546 goto out;
14547 }
14548
14549 err = rdev_add_nan_func(rdev, wdev, func);
14550out:
14551 if (err < 0) {
14552 cfg80211_free_nan_func(func);
14553 nlmsg_free(msg);
14554 return err;
14555 }
14556
14557 /* propagate the instance id and cookie to userspace */
14558 if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, func->cookie,
14559 NL80211_ATTR_PAD))
14560 goto nla_put_failure;
14561
ae0be8de 14562 func_attr = nla_nest_start_noflag(msg, NL80211_ATTR_NAN_FUNC);
a442b761
AB
14563 if (!func_attr)
14564 goto nla_put_failure;
14565
14566 if (nla_put_u8(msg, NL80211_NAN_FUNC_INSTANCE_ID,
14567 func->instance_id))
14568 goto nla_put_failure;
14569
14570 nla_nest_end(msg, func_attr);
14571
14572 genlmsg_end(msg, hdr);
14573 return genlmsg_reply(msg, info);
14574
14575nla_put_failure:
14576 nlmsg_free(msg);
14577 return -ENOBUFS;
14578}
14579
14580static int nl80211_nan_del_func(struct sk_buff *skb,
14581 struct genl_info *info)
14582{
14583 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14584 struct wireless_dev *wdev = info->user_ptr[1];
14585 u64 cookie;
14586
14587 if (wdev->iftype != NL80211_IFTYPE_NAN)
14588 return -EOPNOTSUPP;
14589
73c7da3d 14590 if (!wdev_running(wdev))
a442b761
AB
14591 return -ENOTCONN;
14592
14593 if (!info->attrs[NL80211_ATTR_COOKIE])
14594 return -EINVAL;
14595
a442b761
AB
14596 cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);
14597
14598 rdev_del_nan_func(rdev, wdev, cookie);
14599
14600 return 0;
14601}
14602
a5a9dcf2
AB
14603static int nl80211_nan_change_config(struct sk_buff *skb,
14604 struct genl_info *info)
14605{
14606 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14607 struct wireless_dev *wdev = info->user_ptr[1];
14608 struct cfg80211_nan_conf conf = {};
14609 u32 changed = 0;
14610
14611 if (wdev->iftype != NL80211_IFTYPE_NAN)
14612 return -EOPNOTSUPP;
14613
73c7da3d 14614 if (!wdev_running(wdev))
a5a9dcf2
AB
14615 return -ENOTCONN;
14616
14617 if (info->attrs[NL80211_ATTR_NAN_MASTER_PREF]) {
14618 conf.master_pref =
14619 nla_get_u8(info->attrs[NL80211_ATTR_NAN_MASTER_PREF]);
14620 if (conf.master_pref <= 1 || conf.master_pref == 255)
14621 return -EINVAL;
14622
14623 changed |= CFG80211_NAN_CONF_CHANGED_PREF;
14624 }
14625
8585989d
LC
14626 if (info->attrs[NL80211_ATTR_BANDS]) {
14627 u32 bands = nla_get_u32(info->attrs[NL80211_ATTR_BANDS]);
14628
14629 if (bands & ~(u32)wdev->wiphy->nan_supported_bands)
14630 return -EOPNOTSUPP;
14631
14632 if (bands && !(bands & BIT(NL80211_BAND_2GHZ)))
14633 return -EINVAL;
14634
14635 conf.bands = bands;
14636 changed |= CFG80211_NAN_CONF_CHANGED_BANDS;
a5a9dcf2
AB
14637 }
14638
14639 if (!changed)
14640 return -EINVAL;
14641
14642 return rdev_nan_change_conf(rdev, wdev, &conf, changed);
14643}
14644
50bcd31d
AB
14645void cfg80211_nan_match(struct wireless_dev *wdev,
14646 struct cfg80211_nan_match_params *match, gfp_t gfp)
14647{
14648 struct wiphy *wiphy = wdev->wiphy;
14649 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
14650 struct nlattr *match_attr, *local_func_attr, *peer_func_attr;
14651 struct sk_buff *msg;
14652 void *hdr;
14653
14654 if (WARN_ON(!match->inst_id || !match->peer_inst_id || !match->addr))
14655 return;
14656
14657 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
14658 if (!msg)
14659 return;
14660
14661 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NAN_MATCH);
14662 if (!hdr) {
14663 nlmsg_free(msg);
14664 return;
14665 }
14666
14667 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
14668 (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
14669 wdev->netdev->ifindex)) ||
14670 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
14671 NL80211_ATTR_PAD))
14672 goto nla_put_failure;
14673
14674 if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, match->cookie,
14675 NL80211_ATTR_PAD) ||
14676 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, match->addr))
14677 goto nla_put_failure;
14678
ae0be8de 14679 match_attr = nla_nest_start_noflag(msg, NL80211_ATTR_NAN_MATCH);
50bcd31d
AB
14680 if (!match_attr)
14681 goto nla_put_failure;
14682
ae0be8de
MK
14683 local_func_attr = nla_nest_start_noflag(msg,
14684 NL80211_NAN_MATCH_FUNC_LOCAL);
50bcd31d
AB
14685 if (!local_func_attr)
14686 goto nla_put_failure;
14687
14688 if (nla_put_u8(msg, NL80211_NAN_FUNC_INSTANCE_ID, match->inst_id))
14689 goto nla_put_failure;
14690
14691 nla_nest_end(msg, local_func_attr);
14692
ae0be8de
MK
14693 peer_func_attr = nla_nest_start_noflag(msg,
14694 NL80211_NAN_MATCH_FUNC_PEER);
50bcd31d
AB
14695 if (!peer_func_attr)
14696 goto nla_put_failure;
14697
14698 if (nla_put_u8(msg, NL80211_NAN_FUNC_TYPE, match->type) ||
14699 nla_put_u8(msg, NL80211_NAN_FUNC_INSTANCE_ID, match->peer_inst_id))
14700 goto nla_put_failure;
14701
14702 if (match->info && match->info_len &&
14703 nla_put(msg, NL80211_NAN_FUNC_SERVICE_INFO, match->info_len,
14704 match->info))
14705 goto nla_put_failure;
14706
14707 nla_nest_end(msg, peer_func_attr);
14708 nla_nest_end(msg, match_attr);
14709 genlmsg_end(msg, hdr);
14710
14711 if (!wdev->owner_nlportid)
14712 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
14713 msg, 0, NL80211_MCGRP_NAN, gfp);
14714 else
14715 genlmsg_unicast(wiphy_net(&rdev->wiphy), msg,
14716 wdev->owner_nlportid);
14717
14718 return;
14719
14720nla_put_failure:
14721 nlmsg_free(msg);
14722}
14723EXPORT_SYMBOL(cfg80211_nan_match);
14724
368e5a7b
AB
14725void cfg80211_nan_func_terminated(struct wireless_dev *wdev,
14726 u8 inst_id,
14727 enum nl80211_nan_func_term_reason reason,
14728 u64 cookie, gfp_t gfp)
14729{
14730 struct wiphy *wiphy = wdev->wiphy;
14731 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
14732 struct sk_buff *msg;
14733 struct nlattr *func_attr;
14734 void *hdr;
14735
14736 if (WARN_ON(!inst_id))
14737 return;
14738
14739 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
14740 if (!msg)
14741 return;
14742
14743 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_DEL_NAN_FUNCTION);
14744 if (!hdr) {
14745 nlmsg_free(msg);
14746 return;
14747 }
14748
14749 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
14750 (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
14751 wdev->netdev->ifindex)) ||
14752 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
14753 NL80211_ATTR_PAD))
14754 goto nla_put_failure;
14755
14756 if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
14757 NL80211_ATTR_PAD))
14758 goto nla_put_failure;
14759
ae0be8de 14760 func_attr = nla_nest_start_noflag(msg, NL80211_ATTR_NAN_FUNC);
368e5a7b
AB
14761 if (!func_attr)
14762 goto nla_put_failure;
14763
14764 if (nla_put_u8(msg, NL80211_NAN_FUNC_INSTANCE_ID, inst_id) ||
14765 nla_put_u8(msg, NL80211_NAN_FUNC_TERM_REASON, reason))
14766 goto nla_put_failure;
14767
14768 nla_nest_end(msg, func_attr);
14769 genlmsg_end(msg, hdr);
14770
14771 if (!wdev->owner_nlportid)
14772 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
14773 msg, 0, NL80211_MCGRP_NAN, gfp);
14774 else
14775 genlmsg_unicast(wiphy_net(&rdev->wiphy), msg,
14776 wdev->owner_nlportid);
14777
14778 return;
14779
14780nla_put_failure:
14781 nlmsg_free(msg);
14782}
14783EXPORT_SYMBOL(cfg80211_nan_func_terminated);
14784
3713b4e3
JB
14785static int nl80211_get_protocol_features(struct sk_buff *skb,
14786 struct genl_info *info)
14787{
14788 void *hdr;
14789 struct sk_buff *msg;
14790
14791 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
14792 if (!msg)
14793 return -ENOMEM;
14794
14795 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
14796 NL80211_CMD_GET_PROTOCOL_FEATURES);
14797 if (!hdr)
14798 goto nla_put_failure;
14799
14800 if (nla_put_u32(msg, NL80211_ATTR_PROTOCOL_FEATURES,
14801 NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP))
14802 goto nla_put_failure;
14803
14804 genlmsg_end(msg, hdr);
14805 return genlmsg_reply(msg, info);
14806
14807 nla_put_failure:
14808 kfree_skb(msg);
14809 return -ENOBUFS;
14810}
14811
355199e0
JM
14812static int nl80211_update_ft_ies(struct sk_buff *skb, struct genl_info *info)
14813{
14814 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14815 struct cfg80211_update_ft_ies_params ft_params;
14816 struct net_device *dev = info->user_ptr[1];
14817
14818 if (!rdev->ops->update_ft_ies)
14819 return -EOPNOTSUPP;
14820
14821 if (!info->attrs[NL80211_ATTR_MDID] ||
3d7af878 14822 !info->attrs[NL80211_ATTR_IE])
355199e0
JM
14823 return -EINVAL;
14824
14825 memset(&ft_params, 0, sizeof(ft_params));
14826 ft_params.md = nla_get_u16(info->attrs[NL80211_ATTR_MDID]);
14827 ft_params.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
14828 ft_params.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
14829
14830 return rdev_update_ft_ies(rdev, dev, &ft_params);
14831}
14832
5de17984
AS
14833static int nl80211_crit_protocol_start(struct sk_buff *skb,
14834 struct genl_info *info)
14835{
14836 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14837 struct wireless_dev *wdev = info->user_ptr[1];
14838 enum nl80211_crit_proto_id proto = NL80211_CRIT_PROTO_UNSPEC;
14839 u16 duration;
14840 int ret;
14841
14842 if (!rdev->ops->crit_proto_start)
14843 return -EOPNOTSUPP;
14844
14845 if (WARN_ON(!rdev->ops->crit_proto_stop))
14846 return -EINVAL;
14847
14848 if (rdev->crit_proto_nlportid)
14849 return -EBUSY;
14850
14851 /* determine protocol if provided */
14852 if (info->attrs[NL80211_ATTR_CRIT_PROT_ID])
14853 proto = nla_get_u16(info->attrs[NL80211_ATTR_CRIT_PROT_ID]);
14854
14855 if (proto >= NUM_NL80211_CRIT_PROTO)
14856 return -EINVAL;
14857
14858 /* timeout must be provided */
14859 if (!info->attrs[NL80211_ATTR_MAX_CRIT_PROT_DURATION])
14860 return -EINVAL;
14861
14862 duration =
14863 nla_get_u16(info->attrs[NL80211_ATTR_MAX_CRIT_PROT_DURATION]);
14864
5de17984
AS
14865 ret = rdev_crit_proto_start(rdev, wdev, proto, duration);
14866 if (!ret)
14867 rdev->crit_proto_nlportid = info->snd_portid;
14868
14869 return ret;
14870}
14871
14872static int nl80211_crit_protocol_stop(struct sk_buff *skb,
14873 struct genl_info *info)
14874{
14875 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14876 struct wireless_dev *wdev = info->user_ptr[1];
14877
14878 if (!rdev->ops->crit_proto_stop)
14879 return -EOPNOTSUPP;
14880
14881 if (rdev->crit_proto_nlportid) {
14882 rdev->crit_proto_nlportid = 0;
14883 rdev_crit_proto_stop(rdev, wdev);
14884 }
14885 return 0;
14886}
14887
901bb989
JB
14888static int nl80211_vendor_check_policy(const struct wiphy_vendor_command *vcmd,
14889 struct nlattr *attr,
14890 struct netlink_ext_ack *extack)
14891{
14892 if (vcmd->policy == VENDOR_CMD_RAW_DATA) {
14893 if (attr->nla_type & NLA_F_NESTED) {
14894 NL_SET_ERR_MSG_ATTR(extack, attr,
14895 "unexpected nested data");
14896 return -EINVAL;
14897 }
14898
14899 return 0;
14900 }
14901
14902 if (!(attr->nla_type & NLA_F_NESTED)) {
14903 NL_SET_ERR_MSG_ATTR(extack, attr, "expected nested data");
14904 return -EINVAL;
14905 }
14906
32d5109a 14907 return nla_validate_nested(attr, vcmd->maxattr, vcmd->policy, extack);
901bb989
JB
14908}
14909
ad7e718c
JB
14910static int nl80211_vendor_cmd(struct sk_buff *skb, struct genl_info *info)
14911{
14912 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14913 struct wireless_dev *wdev =
a05829a7
JB
14914 __cfg80211_wdev_from_attrs(rdev, genl_info_net(info),
14915 info->attrs);
ad7e718c
JB
14916 int i, err;
14917 u32 vid, subcmd;
14918
14919 if (!rdev->wiphy.vendor_commands)
14920 return -EOPNOTSUPP;
14921
14922 if (IS_ERR(wdev)) {
14923 err = PTR_ERR(wdev);
14924 if (err != -EINVAL)
14925 return err;
14926 wdev = NULL;
14927 } else if (wdev->wiphy != &rdev->wiphy) {
14928 return -EINVAL;
14929 }
14930
14931 if (!info->attrs[NL80211_ATTR_VENDOR_ID] ||
14932 !info->attrs[NL80211_ATTR_VENDOR_SUBCMD])
14933 return -EINVAL;
14934
14935 vid = nla_get_u32(info->attrs[NL80211_ATTR_VENDOR_ID]);
14936 subcmd = nla_get_u32(info->attrs[NL80211_ATTR_VENDOR_SUBCMD]);
14937 for (i = 0; i < rdev->wiphy.n_vendor_commands; i++) {
14938 const struct wiphy_vendor_command *vcmd;
14939 void *data = NULL;
14940 int len = 0;
14941
14942 vcmd = &rdev->wiphy.vendor_commands[i];
14943
14944 if (vcmd->info.vendor_id != vid || vcmd->info.subcmd != subcmd)
14945 continue;
14946
14947 if (vcmd->flags & (WIPHY_VENDOR_CMD_NEED_WDEV |
14948 WIPHY_VENDOR_CMD_NEED_NETDEV)) {
14949 if (!wdev)
14950 return -EINVAL;
14951 if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_NETDEV &&
14952 !wdev->netdev)
14953 return -EINVAL;
14954
14955 if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_RUNNING) {
73c7da3d 14956 if (!wdev_running(wdev))
ad7e718c
JB
14957 return -ENETDOWN;
14958 }
14959 } else {
14960 wdev = NULL;
14961 }
14962
4052d3d2
JS
14963 if (!vcmd->doit)
14964 return -EOPNOTSUPP;
14965
ad7e718c
JB
14966 if (info->attrs[NL80211_ATTR_VENDOR_DATA]) {
14967 data = nla_data(info->attrs[NL80211_ATTR_VENDOR_DATA]);
14968 len = nla_len(info->attrs[NL80211_ATTR_VENDOR_DATA]);
901bb989
JB
14969
14970 err = nl80211_vendor_check_policy(vcmd,
14971 info->attrs[NL80211_ATTR_VENDOR_DATA],
14972 info->extack);
14973 if (err)
14974 return err;
ad7e718c
JB
14975 }
14976
14977 rdev->cur_cmd_info = info;
901bb989 14978 err = vcmd->doit(&rdev->wiphy, wdev, data, len);
ad7e718c
JB
14979 rdev->cur_cmd_info = NULL;
14980 return err;
14981 }
14982
14983 return -EOPNOTSUPP;
14984}
14985
7bdbe400
JB
14986static int nl80211_prepare_vendor_dump(struct sk_buff *skb,
14987 struct netlink_callback *cb,
14988 struct cfg80211_registered_device **rdev,
14989 struct wireless_dev **wdev)
14990{
50508d94 14991 struct nlattr **attrbuf;
7bdbe400
JB
14992 u32 vid, subcmd;
14993 unsigned int i;
14994 int vcmd_idx = -1;
14995 int err;
14996 void *data = NULL;
14997 unsigned int data_len = 0;
14998
7bdbe400
JB
14999 if (cb->args[0]) {
15000 /* subtract the 1 again here */
15001 struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0] - 1);
15002 struct wireless_dev *tmp;
15003
ea90e0dc
JB
15004 if (!wiphy)
15005 return -ENODEV;
7bdbe400
JB
15006 *rdev = wiphy_to_rdev(wiphy);
15007 *wdev = NULL;
15008
15009 if (cb->args[1]) {
53873f13 15010 list_for_each_entry(tmp, &wiphy->wdev_list, list) {
7bdbe400
JB
15011 if (tmp->identifier == cb->args[1] - 1) {
15012 *wdev = tmp;
15013 break;
15014 }
15015 }
15016 }
15017
15018 /* keep rtnl locked in successful case */
15019 return 0;
15020 }
15021
50508d94
JB
15022 attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf), GFP_KERNEL);
15023 if (!attrbuf)
15024 return -ENOMEM;
15025
8cb08174
JB
15026 err = nlmsg_parse_deprecated(cb->nlh,
15027 GENL_HDRLEN + nl80211_fam.hdrsize,
15028 attrbuf, nl80211_fam.maxattr,
15029 nl80211_policy, NULL);
7bdbe400 15030 if (err)
50508d94 15031 goto out;
7bdbe400 15032
c90c39da 15033 if (!attrbuf[NL80211_ATTR_VENDOR_ID] ||
50508d94
JB
15034 !attrbuf[NL80211_ATTR_VENDOR_SUBCMD]) {
15035 err = -EINVAL;
15036 goto out;
15037 }
7bdbe400 15038
a05829a7 15039 *wdev = __cfg80211_wdev_from_attrs(NULL, sock_net(skb->sk), attrbuf);
7bdbe400
JB
15040 if (IS_ERR(*wdev))
15041 *wdev = NULL;
15042
c90c39da 15043 *rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk), attrbuf);
50508d94
JB
15044 if (IS_ERR(*rdev)) {
15045 err = PTR_ERR(*rdev);
15046 goto out;
15047 }
7bdbe400 15048
c90c39da
JB
15049 vid = nla_get_u32(attrbuf[NL80211_ATTR_VENDOR_ID]);
15050 subcmd = nla_get_u32(attrbuf[NL80211_ATTR_VENDOR_SUBCMD]);
7bdbe400
JB
15051
15052 for (i = 0; i < (*rdev)->wiphy.n_vendor_commands; i++) {
15053 const struct wiphy_vendor_command *vcmd;
15054
15055 vcmd = &(*rdev)->wiphy.vendor_commands[i];
15056
15057 if (vcmd->info.vendor_id != vid || vcmd->info.subcmd != subcmd)
15058 continue;
15059
50508d94
JB
15060 if (!vcmd->dumpit) {
15061 err = -EOPNOTSUPP;
15062 goto out;
15063 }
7bdbe400
JB
15064
15065 vcmd_idx = i;
15066 break;
15067 }
15068
50508d94
JB
15069 if (vcmd_idx < 0) {
15070 err = -EOPNOTSUPP;
15071 goto out;
15072 }
7bdbe400 15073
c90c39da
JB
15074 if (attrbuf[NL80211_ATTR_VENDOR_DATA]) {
15075 data = nla_data(attrbuf[NL80211_ATTR_VENDOR_DATA]);
15076 data_len = nla_len(attrbuf[NL80211_ATTR_VENDOR_DATA]);
901bb989
JB
15077
15078 err = nl80211_vendor_check_policy(
15079 &(*rdev)->wiphy.vendor_commands[vcmd_idx],
15080 attrbuf[NL80211_ATTR_VENDOR_DATA],
15081 cb->extack);
15082 if (err)
50508d94 15083 goto out;
7bdbe400
JB
15084 }
15085
15086 /* 0 is the first index - add 1 to parse only once */
15087 cb->args[0] = (*rdev)->wiphy_idx + 1;
15088 /* add 1 to know if it was NULL */
15089 cb->args[1] = *wdev ? (*wdev)->identifier + 1 : 0;
15090 cb->args[2] = vcmd_idx;
15091 cb->args[3] = (unsigned long)data;
15092 cb->args[4] = data_len;
15093
15094 /* keep rtnl locked in successful case */
50508d94
JB
15095 err = 0;
15096out:
15097 kfree(attrbuf);
15098 return err;
7bdbe400
JB
15099}
15100
15101static int nl80211_vendor_cmd_dump(struct sk_buff *skb,
15102 struct netlink_callback *cb)
15103{
15104 struct cfg80211_registered_device *rdev;
15105 struct wireless_dev *wdev;
15106 unsigned int vcmd_idx;
15107 const struct wiphy_vendor_command *vcmd;
15108 void *data;
15109 int data_len;
15110 int err;
15111 struct nlattr *vendor_data;
15112
ea90e0dc 15113 rtnl_lock();
7bdbe400
JB
15114 err = nl80211_prepare_vendor_dump(skb, cb, &rdev, &wdev);
15115 if (err)
ea90e0dc 15116 goto out;
7bdbe400
JB
15117
15118 vcmd_idx = cb->args[2];
15119 data = (void *)cb->args[3];
15120 data_len = cb->args[4];
15121 vcmd = &rdev->wiphy.vendor_commands[vcmd_idx];
15122
15123 if (vcmd->flags & (WIPHY_VENDOR_CMD_NEED_WDEV |
15124 WIPHY_VENDOR_CMD_NEED_NETDEV)) {
ea90e0dc
JB
15125 if (!wdev) {
15126 err = -EINVAL;
15127 goto out;
15128 }
7bdbe400 15129 if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_NETDEV &&
ea90e0dc
JB
15130 !wdev->netdev) {
15131 err = -EINVAL;
15132 goto out;
15133 }
7bdbe400
JB
15134
15135 if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_RUNNING) {
ea90e0dc
JB
15136 if (!wdev_running(wdev)) {
15137 err = -ENETDOWN;
15138 goto out;
15139 }
7bdbe400
JB
15140 }
15141 }
15142
15143 while (1) {
15144 void *hdr = nl80211hdr_put(skb, NETLINK_CB(cb->skb).portid,
15145 cb->nlh->nlmsg_seq, NLM_F_MULTI,
15146 NL80211_CMD_VENDOR);
15147 if (!hdr)
15148 break;
15149
15150 if (nla_put_u32(skb, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
2dad624e
ND
15151 (wdev && nla_put_u64_64bit(skb, NL80211_ATTR_WDEV,
15152 wdev_id(wdev),
15153 NL80211_ATTR_PAD))) {
7bdbe400
JB
15154 genlmsg_cancel(skb, hdr);
15155 break;
15156 }
15157
ae0be8de
MK
15158 vendor_data = nla_nest_start_noflag(skb,
15159 NL80211_ATTR_VENDOR_DATA);
7bdbe400
JB
15160 if (!vendor_data) {
15161 genlmsg_cancel(skb, hdr);
15162 break;
15163 }
15164
15165 err = vcmd->dumpit(&rdev->wiphy, wdev, skb, data, data_len,
15166 (unsigned long *)&cb->args[5]);
15167 nla_nest_end(skb, vendor_data);
15168
15169 if (err == -ENOBUFS || err == -ENOENT) {
15170 genlmsg_cancel(skb, hdr);
15171 break;
9c167b2d 15172 } else if (err <= 0) {
7bdbe400
JB
15173 genlmsg_cancel(skb, hdr);
15174 goto out;
15175 }
15176
15177 genlmsg_end(skb, hdr);
15178 }
15179
15180 err = skb->len;
15181 out:
15182 rtnl_unlock();
15183 return err;
15184}
15185
ad7e718c
JB
15186struct sk_buff *__cfg80211_alloc_reply_skb(struct wiphy *wiphy,
15187 enum nl80211_commands cmd,
15188 enum nl80211_attrs attr,
15189 int approxlen)
15190{
f26cbf40 15191 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
ad7e718c
JB
15192
15193 if (WARN_ON(!rdev->cur_cmd_info))
15194 return NULL;
15195
6c09e791 15196 return __cfg80211_alloc_vendor_skb(rdev, NULL, approxlen,
ad7e718c
JB
15197 rdev->cur_cmd_info->snd_portid,
15198 rdev->cur_cmd_info->snd_seq,
567ffc35 15199 cmd, attr, NULL, GFP_KERNEL);
ad7e718c
JB
15200}
15201EXPORT_SYMBOL(__cfg80211_alloc_reply_skb);
15202
15203int cfg80211_vendor_cmd_reply(struct sk_buff *skb)
15204{
15205 struct cfg80211_registered_device *rdev = ((void **)skb->cb)[0];
15206 void *hdr = ((void **)skb->cb)[1];
15207 struct nlattr *data = ((void **)skb->cb)[2];
15208
bd8c78e7
JB
15209 /* clear CB data for netlink core to own from now on */
15210 memset(skb->cb, 0, sizeof(skb->cb));
15211
ad7e718c
JB
15212 if (WARN_ON(!rdev->cur_cmd_info)) {
15213 kfree_skb(skb);
15214 return -EINVAL;
15215 }
15216
15217 nla_nest_end(skb, data);
15218 genlmsg_end(skb, hdr);
15219 return genlmsg_reply(skb, rdev->cur_cmd_info);
15220}
15221EXPORT_SYMBOL_GPL(cfg80211_vendor_cmd_reply);
15222
55c1fdf0
JB
15223unsigned int cfg80211_vendor_cmd_get_sender(struct wiphy *wiphy)
15224{
15225 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
15226
15227 if (WARN_ON(!rdev->cur_cmd_info))
15228 return 0;
15229
15230 return rdev->cur_cmd_info->snd_portid;
15231}
15232EXPORT_SYMBOL_GPL(cfg80211_vendor_cmd_get_sender);
15233
fa9ffc74
KP
15234static int nl80211_set_qos_map(struct sk_buff *skb,
15235 struct genl_info *info)
15236{
15237 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15238 struct cfg80211_qos_map *qos_map = NULL;
15239 struct net_device *dev = info->user_ptr[1];
15240 u8 *pos, len, num_des, des_len, des;
15241 int ret;
15242
15243 if (!rdev->ops->set_qos_map)
15244 return -EOPNOTSUPP;
15245
15246 if (info->attrs[NL80211_ATTR_QOS_MAP]) {
15247 pos = nla_data(info->attrs[NL80211_ATTR_QOS_MAP]);
15248 len = nla_len(info->attrs[NL80211_ATTR_QOS_MAP]);
15249
c8b82802 15250 if (len % 2)
fa9ffc74
KP
15251 return -EINVAL;
15252
15253 qos_map = kzalloc(sizeof(struct cfg80211_qos_map), GFP_KERNEL);
15254 if (!qos_map)
15255 return -ENOMEM;
15256
15257 num_des = (len - IEEE80211_QOS_MAP_LEN_MIN) >> 1;
15258 if (num_des) {
15259 des_len = num_des *
15260 sizeof(struct cfg80211_dscp_exception);
15261 memcpy(qos_map->dscp_exception, pos, des_len);
15262 qos_map->num_des = num_des;
15263 for (des = 0; des < num_des; des++) {
15264 if (qos_map->dscp_exception[des].up > 7) {
15265 kfree(qos_map);
15266 return -EINVAL;
15267 }
15268 }
15269 pos += des_len;
15270 }
15271 memcpy(qos_map->up, pos, IEEE80211_QOS_MAP_LEN_MIN);
15272 }
15273
15274 wdev_lock(dev->ieee80211_ptr);
15275 ret = nl80211_key_allowed(dev->ieee80211_ptr);
15276 if (!ret)
15277 ret = rdev_set_qos_map(rdev, dev, qos_map);
15278 wdev_unlock(dev->ieee80211_ptr);
15279
15280 kfree(qos_map);
15281 return ret;
15282}
15283
960d01ac
JB
15284static int nl80211_add_tx_ts(struct sk_buff *skb, struct genl_info *info)
15285{
15286 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15287 struct net_device *dev = info->user_ptr[1];
15288 struct wireless_dev *wdev = dev->ieee80211_ptr;
15289 const u8 *peer;
15290 u8 tsid, up;
15291 u16 admitted_time = 0;
15292 int err;
15293
723e73ac 15294 if (!(rdev->wiphy.features & NL80211_FEATURE_SUPPORTS_WMM_ADMISSION))
960d01ac
JB
15295 return -EOPNOTSUPP;
15296
15297 if (!info->attrs[NL80211_ATTR_TSID] || !info->attrs[NL80211_ATTR_MAC] ||
15298 !info->attrs[NL80211_ATTR_USER_PRIO])
15299 return -EINVAL;
15300
15301 tsid = nla_get_u8(info->attrs[NL80211_ATTR_TSID]);
960d01ac 15302 up = nla_get_u8(info->attrs[NL80211_ATTR_USER_PRIO]);
960d01ac
JB
15303
15304 /* WMM uses TIDs 0-7 even for TSPEC */
723e73ac 15305 if (tsid >= IEEE80211_FIRST_TSPEC_TSID) {
960d01ac 15306 /* TODO: handle 802.11 TSPEC/admission control
723e73ac
JB
15307 * need more attributes for that (e.g. BA session requirement);
15308 * change the WMM adminssion test above to allow both then
960d01ac
JB
15309 */
15310 return -EINVAL;
15311 }
15312
15313 peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
15314
15315 if (info->attrs[NL80211_ATTR_ADMITTED_TIME]) {
15316 admitted_time =
15317 nla_get_u16(info->attrs[NL80211_ATTR_ADMITTED_TIME]);
15318 if (!admitted_time)
15319 return -EINVAL;
15320 }
15321
15322 wdev_lock(wdev);
15323 switch (wdev->iftype) {
15324 case NL80211_IFTYPE_STATION:
15325 case NL80211_IFTYPE_P2P_CLIENT:
7b0a0e3c 15326 if (wdev->connected)
960d01ac
JB
15327 break;
15328 err = -ENOTCONN;
15329 goto out;
15330 default:
15331 err = -EOPNOTSUPP;
15332 goto out;
15333 }
15334
15335 err = rdev_add_tx_ts(rdev, dev, tsid, peer, up, admitted_time);
15336
15337 out:
15338 wdev_unlock(wdev);
15339 return err;
15340}
15341
15342static int nl80211_del_tx_ts(struct sk_buff *skb, struct genl_info *info)
15343{
15344 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15345 struct net_device *dev = info->user_ptr[1];
15346 struct wireless_dev *wdev = dev->ieee80211_ptr;
15347 const u8 *peer;
15348 u8 tsid;
15349 int err;
15350
15351 if (!info->attrs[NL80211_ATTR_TSID] || !info->attrs[NL80211_ATTR_MAC])
15352 return -EINVAL;
15353
15354 tsid = nla_get_u8(info->attrs[NL80211_ATTR_TSID]);
15355 peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
15356
15357 wdev_lock(wdev);
15358 err = rdev_del_tx_ts(rdev, dev, tsid, peer);
15359 wdev_unlock(wdev);
15360
15361 return err;
15362}
15363
1057d35e
AN
15364static int nl80211_tdls_channel_switch(struct sk_buff *skb,
15365 struct genl_info *info)
15366{
15367 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15368 struct net_device *dev = info->user_ptr[1];
15369 struct wireless_dev *wdev = dev->ieee80211_ptr;
15370 struct cfg80211_chan_def chandef = {};
15371 const u8 *addr;
15372 u8 oper_class;
15373 int err;
15374
15375 if (!rdev->ops->tdls_channel_switch ||
15376 !(rdev->wiphy.features & NL80211_FEATURE_TDLS_CHANNEL_SWITCH))
15377 return -EOPNOTSUPP;
15378
15379 switch (dev->ieee80211_ptr->iftype) {
15380 case NL80211_IFTYPE_STATION:
15381 case NL80211_IFTYPE_P2P_CLIENT:
15382 break;
15383 default:
15384 return -EOPNOTSUPP;
15385 }
15386
15387 if (!info->attrs[NL80211_ATTR_MAC] ||
15388 !info->attrs[NL80211_ATTR_OPER_CLASS])
15389 return -EINVAL;
15390
15391 err = nl80211_parse_chandef(rdev, info, &chandef);
15392 if (err)
15393 return err;
15394
15395 /*
15396 * Don't allow wide channels on the 2.4Ghz band, as per IEEE802.11-2012
15397 * section 10.22.6.2.1. Disallow 5/10Mhz channels as well for now, the
15398 * specification is not defined for them.
15399 */
57fbcce3 15400 if (chandef.chan->band == NL80211_BAND_2GHZ &&
1057d35e
AN
15401 chandef.width != NL80211_CHAN_WIDTH_20_NOHT &&
15402 chandef.width != NL80211_CHAN_WIDTH_20)
15403 return -EINVAL;
15404
15405 /* we will be active on the TDLS link */
923b352f
AN
15406 if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &chandef,
15407 wdev->iftype))
1057d35e
AN
15408 return -EINVAL;
15409
15410 /* don't allow switching to DFS channels */
15411 if (cfg80211_chandef_dfs_required(wdev->wiphy, &chandef, wdev->iftype))
15412 return -EINVAL;
15413
15414 addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
15415 oper_class = nla_get_u8(info->attrs[NL80211_ATTR_OPER_CLASS]);
15416
15417 wdev_lock(wdev);
15418 err = rdev_tdls_channel_switch(rdev, dev, addr, oper_class, &chandef);
15419 wdev_unlock(wdev);
15420
15421 return err;
15422}
15423
15424static int nl80211_tdls_cancel_channel_switch(struct sk_buff *skb,
15425 struct genl_info *info)
15426{
15427 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15428 struct net_device *dev = info->user_ptr[1];
15429 struct wireless_dev *wdev = dev->ieee80211_ptr;
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
15450 wdev_lock(wdev);
15451 rdev_tdls_cancel_channel_switch(rdev, dev, addr);
15452 wdev_unlock(wdev);
15453
15454 return 0;
15455}
15456
ce0ce13a
MB
15457static int nl80211_set_multicast_to_unicast(struct sk_buff *skb,
15458 struct genl_info *info)
15459{
15460 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15461 struct net_device *dev = info->user_ptr[1];
15462 struct wireless_dev *wdev = dev->ieee80211_ptr;
15463 const struct nlattr *nla;
15464 bool enabled;
15465
ce0ce13a
MB
15466 if (!rdev->ops->set_multicast_to_unicast)
15467 return -EOPNOTSUPP;
15468
15469 if (wdev->iftype != NL80211_IFTYPE_AP &&
15470 wdev->iftype != NL80211_IFTYPE_P2P_GO)
15471 return -EOPNOTSUPP;
15472
15473 nla = info->attrs[NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED];
15474 enabled = nla_get_flag(nla);
15475
15476 return rdev_set_multicast_to_unicast(rdev, dev, enabled);
15477}
15478
3a00df57
AS
15479static int nl80211_set_pmk(struct sk_buff *skb, struct genl_info *info)
15480{
15481 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15482 struct net_device *dev = info->user_ptr[1];
15483 struct wireless_dev *wdev = dev->ieee80211_ptr;
15484 struct cfg80211_pmk_conf pmk_conf = {};
15485 int ret;
15486
15487 if (wdev->iftype != NL80211_IFTYPE_STATION &&
15488 wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
15489 return -EOPNOTSUPP;
15490
15491 if (!wiphy_ext_feature_isset(&rdev->wiphy,
15492 NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X))
15493 return -EOPNOTSUPP;
15494
15495 if (!info->attrs[NL80211_ATTR_MAC] || !info->attrs[NL80211_ATTR_PMK])
15496 return -EINVAL;
15497
15498 wdev_lock(wdev);
7b0a0e3c 15499 if (!wdev->connected) {
3a00df57
AS
15500 ret = -ENOTCONN;
15501 goto out;
15502 }
15503
15504 pmk_conf.aa = nla_data(info->attrs[NL80211_ATTR_MAC]);
7b0a0e3c 15505 if (memcmp(pmk_conf.aa, wdev->u.client.connected_addr, ETH_ALEN)) {
3a00df57
AS
15506 ret = -EINVAL;
15507 goto out;
15508 }
15509
15510 pmk_conf.pmk = nla_data(info->attrs[NL80211_ATTR_PMK]);
15511 pmk_conf.pmk_len = nla_len(info->attrs[NL80211_ATTR_PMK]);
15512 if (pmk_conf.pmk_len != WLAN_PMK_LEN &&
15513 pmk_conf.pmk_len != WLAN_PMK_LEN_SUITE_B_192) {
15514 ret = -EINVAL;
15515 goto out;
15516 }
15517
cb9abd48 15518 if (info->attrs[NL80211_ATTR_PMKR0_NAME])
3a00df57
AS
15519 pmk_conf.pmk_r0_name =
15520 nla_data(info->attrs[NL80211_ATTR_PMKR0_NAME]);
3a00df57
AS
15521
15522 ret = rdev_set_pmk(rdev, dev, &pmk_conf);
15523out:
15524 wdev_unlock(wdev);
15525 return ret;
15526}
15527
15528static int nl80211_del_pmk(struct sk_buff *skb, struct genl_info *info)
15529{
15530 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15531 struct net_device *dev = info->user_ptr[1];
15532 struct wireless_dev *wdev = dev->ieee80211_ptr;
15533 const u8 *aa;
15534 int ret;
15535
15536 if (wdev->iftype != NL80211_IFTYPE_STATION &&
15537 wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
15538 return -EOPNOTSUPP;
15539
15540 if (!wiphy_ext_feature_isset(&rdev->wiphy,
15541 NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X))
15542 return -EOPNOTSUPP;
15543
15544 if (!info->attrs[NL80211_ATTR_MAC])
15545 return -EINVAL;
15546
15547 wdev_lock(wdev);
15548 aa = nla_data(info->attrs[NL80211_ATTR_MAC]);
15549 ret = rdev_del_pmk(rdev, dev, aa);
15550 wdev_unlock(wdev);
15551
15552 return ret;
15553}
15554
40cbfa90
SD
15555static int nl80211_external_auth(struct sk_buff *skb, struct genl_info *info)
15556{
15557 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15558 struct net_device *dev = info->user_ptr[1];
15559 struct cfg80211_external_auth_params params;
15560
db8d93a7 15561 if (!rdev->ops->external_auth)
40cbfa90
SD
15562 return -EOPNOTSUPP;
15563
fe494370
SD
15564 if (!info->attrs[NL80211_ATTR_SSID] &&
15565 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
15566 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
40cbfa90
SD
15567 return -EINVAL;
15568
15569 if (!info->attrs[NL80211_ATTR_BSSID])
15570 return -EINVAL;
15571
15572 if (!info->attrs[NL80211_ATTR_STATUS_CODE])
15573 return -EINVAL;
15574
15575 memset(&params, 0, sizeof(params));
15576
fe494370
SD
15577 if (info->attrs[NL80211_ATTR_SSID]) {
15578 params.ssid.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
cb9abd48 15579 if (params.ssid.ssid_len == 0)
fe494370
SD
15580 return -EINVAL;
15581 memcpy(params.ssid.ssid,
15582 nla_data(info->attrs[NL80211_ATTR_SSID]),
15583 params.ssid.ssid_len);
15584 }
40cbfa90
SD
15585
15586 memcpy(params.bssid, nla_data(info->attrs[NL80211_ATTR_BSSID]),
15587 ETH_ALEN);
15588
15589 params.status = nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]);
15590
fe494370
SD
15591 if (info->attrs[NL80211_ATTR_PMKID])
15592 params.pmkid = nla_data(info->attrs[NL80211_ATTR_PMKID]);
15593
40cbfa90
SD
15594 return rdev_external_auth(rdev, dev, &params);
15595}
15596
2576a9ac
DK
15597static int nl80211_tx_control_port(struct sk_buff *skb, struct genl_info *info)
15598{
dca9ca2d 15599 bool dont_wait_for_ack = info->attrs[NL80211_ATTR_DONT_WAIT_FOR_ACK];
2576a9ac
DK
15600 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15601 struct net_device *dev = info->user_ptr[1];
15602 struct wireless_dev *wdev = dev->ieee80211_ptr;
15603 const u8 *buf;
15604 size_t len;
15605 u8 *dest;
15606 u16 proto;
15607 bool noencrypt;
dca9ca2d 15608 u64 cookie = 0;
67207bab 15609 int link_id;
2576a9ac
DK
15610 int err;
15611
15612 if (!wiphy_ext_feature_isset(&rdev->wiphy,
15613 NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211))
15614 return -EOPNOTSUPP;
15615
15616 if (!rdev->ops->tx_control_port)
15617 return -EOPNOTSUPP;
15618
15619 if (!info->attrs[NL80211_ATTR_FRAME] ||
15620 !info->attrs[NL80211_ATTR_MAC] ||
15621 !info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]) {
15622 GENL_SET_ERR_MSG(info, "Frame, MAC or ethertype missing");
15623 return -EINVAL;
15624 }
15625
15626 wdev_lock(wdev);
15627
15628 switch (wdev->iftype) {
15629 case NL80211_IFTYPE_AP:
15630 case NL80211_IFTYPE_P2P_GO:
15631 case NL80211_IFTYPE_MESH_POINT:
15632 break;
15633 case NL80211_IFTYPE_ADHOC:
7b0a0e3c
JB
15634 if (wdev->u.ibss.current_bss)
15635 break;
15636 err = -ENOTCONN;
15637 goto out;
2576a9ac
DK
15638 case NL80211_IFTYPE_STATION:
15639 case NL80211_IFTYPE_P2P_CLIENT:
7b0a0e3c 15640 if (wdev->connected)
2576a9ac
DK
15641 break;
15642 err = -ENOTCONN;
15643 goto out;
15644 default:
15645 err = -EOPNOTSUPP;
15646 goto out;
15647 }
15648
15649 wdev_unlock(wdev);
15650
15651 buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
15652 len = nla_len(info->attrs[NL80211_ATTR_FRAME]);
15653 dest = nla_data(info->attrs[NL80211_ATTR_MAC]);
15654 proto = nla_get_u16(info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]);
15655 noencrypt =
15656 nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT]);
15657
67207bab
AO
15658 link_id = nl80211_link_id_or_invalid(info->attrs);
15659
dca9ca2d 15660 err = rdev_tx_control_port(rdev, dev, buf, len,
67207bab 15661 dest, cpu_to_be16(proto), noencrypt, link_id,
dca9ca2d
MT
15662 dont_wait_for_ack ? NULL : &cookie);
15663 if (!err && !dont_wait_for_ack)
15664 nl_set_extack_cookie_u64(info->extack, cookie);
15665 return err;
2576a9ac
DK
15666 out:
15667 wdev_unlock(wdev);
15668 return err;
15669}
15670
81e54d08
PKC
15671static int nl80211_get_ftm_responder_stats(struct sk_buff *skb,
15672 struct genl_info *info)
15673{
15674 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15675 struct net_device *dev = info->user_ptr[1];
15676 struct wireless_dev *wdev = dev->ieee80211_ptr;
15677 struct cfg80211_ftm_responder_stats ftm_stats = {};
7b0a0e3c 15678 unsigned int link_id = nl80211_link_id(info->attrs);
81e54d08
PKC
15679 struct sk_buff *msg;
15680 void *hdr;
15681 struct nlattr *ftm_stats_attr;
15682 int err;
15683
7b0a0e3c
JB
15684 if (wdev->iftype != NL80211_IFTYPE_AP ||
15685 !wdev->links[link_id].ap.beacon_interval)
81e54d08
PKC
15686 return -EOPNOTSUPP;
15687
15688 err = rdev_get_ftm_responder_stats(rdev, dev, &ftm_stats);
15689 if (err)
15690 return err;
15691
15692 if (!ftm_stats.filled)
15693 return -ENODATA;
15694
15695 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
15696 if (!msg)
15697 return -ENOMEM;
15698
15699 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
15700 NL80211_CMD_GET_FTM_RESPONDER_STATS);
15701 if (!hdr)
1399c59f 15702 goto nla_put_failure;
81e54d08
PKC
15703
15704 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
15705 goto nla_put_failure;
15706
ae0be8de
MK
15707 ftm_stats_attr = nla_nest_start_noflag(msg,
15708 NL80211_ATTR_FTM_RESPONDER_STATS);
81e54d08
PKC
15709 if (!ftm_stats_attr)
15710 goto nla_put_failure;
15711
15712#define SET_FTM(field, name, type) \
15713 do { if ((ftm_stats.filled & BIT(NL80211_FTM_STATS_ ## name)) && \
15714 nla_put_ ## type(msg, NL80211_FTM_STATS_ ## name, \
15715 ftm_stats.field)) \
15716 goto nla_put_failure; } while (0)
15717#define SET_FTM_U64(field, name) \
15718 do { if ((ftm_stats.filled & BIT(NL80211_FTM_STATS_ ## name)) && \
15719 nla_put_u64_64bit(msg, NL80211_FTM_STATS_ ## name, \
15720 ftm_stats.field, NL80211_FTM_STATS_PAD)) \
15721 goto nla_put_failure; } while (0)
15722
15723 SET_FTM(success_num, SUCCESS_NUM, u32);
15724 SET_FTM(partial_num, PARTIAL_NUM, u32);
15725 SET_FTM(failed_num, FAILED_NUM, u32);
15726 SET_FTM(asap_num, ASAP_NUM, u32);
15727 SET_FTM(non_asap_num, NON_ASAP_NUM, u32);
15728 SET_FTM_U64(total_duration_ms, TOTAL_DURATION_MSEC);
15729 SET_FTM(unknown_triggers_num, UNKNOWN_TRIGGERS_NUM, u32);
15730 SET_FTM(reschedule_requests_num, RESCHEDULE_REQUESTS_NUM, u32);
15731 SET_FTM(out_of_window_triggers_num, OUT_OF_WINDOW_TRIGGERS_NUM, u32);
15732#undef SET_FTM
15733
15734 nla_nest_end(msg, ftm_stats_attr);
15735
15736 genlmsg_end(msg, hdr);
15737 return genlmsg_reply(msg, info);
15738
15739nla_put_failure:
15740 nlmsg_free(msg);
15741 return -ENOBUFS;
15742}
15743
cb74e977
SD
15744static int nl80211_update_owe_info(struct sk_buff *skb, struct genl_info *info)
15745{
15746 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15747 struct cfg80211_update_owe_info owe_info;
15748 struct net_device *dev = info->user_ptr[1];
15749
15750 if (!rdev->ops->update_owe_info)
15751 return -EOPNOTSUPP;
15752
15753 if (!info->attrs[NL80211_ATTR_STATUS_CODE] ||
15754 !info->attrs[NL80211_ATTR_MAC])
15755 return -EINVAL;
15756
15757 memset(&owe_info, 0, sizeof(owe_info));
15758 owe_info.status = nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]);
15759 nla_memcpy(owe_info.peer, info->attrs[NL80211_ATTR_MAC], ETH_ALEN);
15760
15761 if (info->attrs[NL80211_ATTR_IE]) {
15762 owe_info.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
15763 owe_info.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
15764 }
15765
15766 return rdev_update_owe_info(rdev, dev, &owe_info);
15767}
15768
5ab92e7f
RM
15769static int nl80211_probe_mesh_link(struct sk_buff *skb, struct genl_info *info)
15770{
15771 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15772 struct net_device *dev = info->user_ptr[1];
15773 struct wireless_dev *wdev = dev->ieee80211_ptr;
15774 struct station_info sinfo = {};
15775 const u8 *buf;
15776 size_t len;
15777 u8 *dest;
15778 int err;
15779
15780 if (!rdev->ops->probe_mesh_link || !rdev->ops->get_station)
15781 return -EOPNOTSUPP;
15782
15783 if (!info->attrs[NL80211_ATTR_MAC] ||
15784 !info->attrs[NL80211_ATTR_FRAME]) {
15785 GENL_SET_ERR_MSG(info, "Frame or MAC missing");
15786 return -EINVAL;
15787 }
15788
15789 if (wdev->iftype != NL80211_IFTYPE_MESH_POINT)
15790 return -EOPNOTSUPP;
15791
15792 dest = nla_data(info->attrs[NL80211_ATTR_MAC]);
15793 buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
15794 len = nla_len(info->attrs[NL80211_ATTR_FRAME]);
15795
15796 if (len < sizeof(struct ethhdr))
15797 return -EINVAL;
15798
15799 if (!ether_addr_equal(buf, dest) || is_multicast_ether_addr(buf) ||
15800 !ether_addr_equal(buf + ETH_ALEN, dev->dev_addr))
15801 return -EINVAL;
15802
15803 err = rdev_get_station(rdev, dev, dest, &sinfo);
15804 if (err)
15805 return err;
15806
2a279b34
FF
15807 cfg80211_sinfo_release_content(&sinfo);
15808
5ab92e7f
RM
15809 return rdev_probe_mesh_link(rdev, dev, dest, buf, len);
15810}
15811
77f576de
T
15812static int parse_tid_conf(struct cfg80211_registered_device *rdev,
15813 struct nlattr *attrs[], struct net_device *dev,
3710a8a6 15814 struct cfg80211_tid_cfg *tid_conf,
7b0a0e3c
JB
15815 struct genl_info *info, const u8 *peer,
15816 unsigned int link_id)
77f576de
T
15817{
15818 struct netlink_ext_ack *extack = info->extack;
3710a8a6 15819 u64 mask;
77f576de
T
15820 int err;
15821
15822 if (!attrs[NL80211_TID_CONFIG_ATTR_TIDS])
15823 return -EINVAL;
15824
15825 tid_conf->config_override =
15826 nla_get_flag(attrs[NL80211_TID_CONFIG_ATTR_OVERRIDE]);
3710a8a6 15827 tid_conf->tids = nla_get_u16(attrs[NL80211_TID_CONFIG_ATTR_TIDS]);
77f576de
T
15828
15829 if (tid_conf->config_override) {
15830 if (rdev->ops->reset_tid_config) {
15831 err = rdev_reset_tid_config(rdev, dev, peer,
3710a8a6 15832 tid_conf->tids);
c0336955 15833 if (err)
77f576de
T
15834 return err;
15835 } else {
15836 return -EINVAL;
15837 }
15838 }
15839
15840 if (attrs[NL80211_TID_CONFIG_ATTR_NOACK]) {
3710a8a6 15841 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_NOACK);
77f576de
T
15842 tid_conf->noack =
15843 nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_NOACK]);
15844 }
15845
6a21d16c
T
15846 if (attrs[NL80211_TID_CONFIG_ATTR_RETRY_SHORT]) {
15847 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_RETRY_SHORT);
15848 tid_conf->retry_short =
15849 nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_RETRY_SHORT]);
15850
15851 if (tid_conf->retry_short > rdev->wiphy.max_data_retry_count)
15852 return -EINVAL;
15853 }
15854
15855 if (attrs[NL80211_TID_CONFIG_ATTR_RETRY_LONG]) {
15856 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_RETRY_LONG);
15857 tid_conf->retry_long =
15858 nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_RETRY_LONG]);
15859
15860 if (tid_conf->retry_long > rdev->wiphy.max_data_retry_count)
15861 return -EINVAL;
15862 }
15863
ade274b2
T
15864 if (attrs[NL80211_TID_CONFIG_ATTR_AMPDU_CTRL]) {
15865 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_AMPDU_CTRL);
15866 tid_conf->ampdu =
15867 nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_AMPDU_CTRL]);
15868 }
15869
04f7d142
T
15870 if (attrs[NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL]) {
15871 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL);
15872 tid_conf->rtscts =
15873 nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL]);
15874 }
15875
33462e68
SM
15876 if (attrs[NL80211_TID_CONFIG_ATTR_AMSDU_CTRL]) {
15877 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_AMSDU_CTRL);
15878 tid_conf->amsdu =
15879 nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_AMSDU_CTRL]);
15880 }
15881
9a5f6488
TC
15882 if (attrs[NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE]) {
15883 u32 idx = NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE, attr;
15884
15885 tid_conf->txrate_type = nla_get_u8(attrs[idx]);
15886
15887 if (tid_conf->txrate_type != NL80211_TX_RATE_AUTOMATIC) {
15888 attr = NL80211_TID_CONFIG_ATTR_TX_RATE;
15889 err = nl80211_parse_tx_bitrate_mask(info, attrs, attr,
857b34c4 15890 &tid_conf->txrate_mask, dev,
7b0a0e3c 15891 true, link_id);
9a5f6488
TC
15892 if (err)
15893 return err;
15894
15895 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_TX_RATE);
15896 }
15897 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE);
15898 }
15899
3710a8a6
JB
15900 if (peer)
15901 mask = rdev->wiphy.tid_config_support.peer;
15902 else
15903 mask = rdev->wiphy.tid_config_support.vif;
15904
15905 if (tid_conf->mask & ~mask) {
15906 NL_SET_ERR_MSG(extack, "unsupported TID configuration");
15907 return -ENOTSUPP;
15908 }
15909
77f576de
T
15910 return 0;
15911}
15912
15913static int nl80211_set_tid_config(struct sk_buff *skb,
15914 struct genl_info *info)
15915{
15916 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15917 struct nlattr *attrs[NL80211_TID_CONFIG_ATTR_MAX + 1];
7b0a0e3c 15918 unsigned int link_id = nl80211_link_id(info->attrs);
77f576de 15919 struct net_device *dev = info->user_ptr[1];
3710a8a6 15920 struct cfg80211_tid_config *tid_config;
77f576de
T
15921 struct nlattr *tid;
15922 int conf_idx = 0, rem_conf;
15923 int ret = -EINVAL;
15924 u32 num_conf = 0;
15925
15926 if (!info->attrs[NL80211_ATTR_TID_CONFIG])
15927 return -EINVAL;
15928
15929 if (!rdev->ops->set_tid_config)
15930 return -EOPNOTSUPP;
15931
15932 nla_for_each_nested(tid, info->attrs[NL80211_ATTR_TID_CONFIG],
15933 rem_conf)
15934 num_conf++;
15935
15936 tid_config = kzalloc(struct_size(tid_config, tid_conf, num_conf),
15937 GFP_KERNEL);
15938 if (!tid_config)
15939 return -ENOMEM;
15940
15941 tid_config->n_tid_conf = num_conf;
15942
15943 if (info->attrs[NL80211_ATTR_MAC])
15944 tid_config->peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
15945
206bbcf7
JB
15946 wdev_lock(dev->ieee80211_ptr);
15947
77f576de
T
15948 nla_for_each_nested(tid, info->attrs[NL80211_ATTR_TID_CONFIG],
15949 rem_conf) {
15950 ret = nla_parse_nested(attrs, NL80211_TID_CONFIG_ATTR_MAX,
15951 tid, NULL, NULL);
15952
15953 if (ret)
15954 goto bad_tid_conf;
15955
15956 ret = parse_tid_conf(rdev, attrs, dev,
15957 &tid_config->tid_conf[conf_idx],
7b0a0e3c 15958 info, tid_config->peer, link_id);
77f576de
T
15959 if (ret)
15960 goto bad_tid_conf;
15961
15962 conf_idx++;
15963 }
15964
15965 ret = rdev_set_tid_config(rdev, dev, tid_config);
15966
15967bad_tid_conf:
15968 kfree(tid_config);
206bbcf7 15969 wdev_unlock(dev->ieee80211_ptr);
77f576de
T
15970 return ret;
15971}
15972
0d2ab3ae
JC
15973static int nl80211_color_change(struct sk_buff *skb, struct genl_info *info)
15974{
15975 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15976 struct cfg80211_color_change_settings params = {};
15977 struct net_device *dev = info->user_ptr[1];
15978 struct wireless_dev *wdev = dev->ieee80211_ptr;
15979 struct nlattr **tb;
15980 u16 offset;
15981 int err;
15982
15983 if (!rdev->ops->color_change)
15984 return -EOPNOTSUPP;
15985
15986 if (!wiphy_ext_feature_isset(&rdev->wiphy,
15987 NL80211_EXT_FEATURE_BSS_COLOR))
15988 return -EOPNOTSUPP;
15989
15990 if (wdev->iftype != NL80211_IFTYPE_AP)
15991 return -EOPNOTSUPP;
15992
15993 if (!info->attrs[NL80211_ATTR_COLOR_CHANGE_COUNT] ||
15994 !info->attrs[NL80211_ATTR_COLOR_CHANGE_COLOR] ||
15995 !info->attrs[NL80211_ATTR_COLOR_CHANGE_ELEMS])
15996 return -EINVAL;
15997
15998 params.count = nla_get_u8(info->attrs[NL80211_ATTR_COLOR_CHANGE_COUNT]);
15999 params.color = nla_get_u8(info->attrs[NL80211_ATTR_COLOR_CHANGE_COLOR]);
16000
dbbb27e1
AD
16001 err = nl80211_parse_beacon(rdev, info->attrs, &params.beacon_next,
16002 info->extack);
0d2ab3ae
JC
16003 if (err)
16004 return err;
16005
16006 tb = kcalloc(NL80211_ATTR_MAX + 1, sizeof(*tb), GFP_KERNEL);
16007 if (!tb)
16008 return -ENOMEM;
16009
16010 err = nla_parse_nested(tb, NL80211_ATTR_MAX,
16011 info->attrs[NL80211_ATTR_COLOR_CHANGE_ELEMS],
16012 nl80211_policy, info->extack);
16013 if (err)
16014 goto out;
16015
dbbb27e1
AD
16016 err = nl80211_parse_beacon(rdev, tb, &params.beacon_color_change,
16017 info->extack);
0d2ab3ae
JC
16018 if (err)
16019 goto out;
16020
16021 if (!tb[NL80211_ATTR_CNTDWN_OFFS_BEACON]) {
16022 err = -EINVAL;
16023 goto out;
16024 }
16025
16026 if (nla_len(tb[NL80211_ATTR_CNTDWN_OFFS_BEACON]) != sizeof(u16)) {
16027 err = -EINVAL;
16028 goto out;
16029 }
16030
16031 offset = nla_get_u16(tb[NL80211_ATTR_CNTDWN_OFFS_BEACON]);
16032 if (offset >= params.beacon_color_change.tail_len) {
16033 err = -EINVAL;
16034 goto out;
16035 }
16036
16037 if (params.beacon_color_change.tail[offset] != params.count) {
16038 err = -EINVAL;
16039 goto out;
16040 }
16041
16042 params.counter_offset_beacon = offset;
16043
16044 if (tb[NL80211_ATTR_CNTDWN_OFFS_PRESP]) {
16045 if (nla_len(tb[NL80211_ATTR_CNTDWN_OFFS_PRESP]) !=
16046 sizeof(u16)) {
16047 err = -EINVAL;
16048 goto out;
16049 }
16050
16051 offset = nla_get_u16(tb[NL80211_ATTR_CNTDWN_OFFS_PRESP]);
16052 if (offset >= params.beacon_color_change.probe_resp_len) {
16053 err = -EINVAL;
16054 goto out;
16055 }
16056
16057 if (params.beacon_color_change.probe_resp[offset] !=
16058 params.count) {
16059 err = -EINVAL;
16060 goto out;
16061 }
16062
16063 params.counter_offset_presp = offset;
16064 }
16065
16066 wdev_lock(wdev);
16067 err = rdev_color_change(rdev, dev, &params);
16068 wdev_unlock(wdev);
16069
16070out:
dc1e3cb8
JC
16071 kfree(params.beacon_next.mbssid_ies);
16072 kfree(params.beacon_color_change.mbssid_ies);
dbbb27e1
AD
16073 kfree(params.beacon_next.rnr_ies);
16074 kfree(params.beacon_color_change.rnr_ies);
0d2ab3ae
JC
16075 kfree(tb);
16076 return err;
16077}
16078
e306784a
SM
16079static int nl80211_set_fils_aad(struct sk_buff *skb,
16080 struct genl_info *info)
16081{
16082 struct cfg80211_registered_device *rdev = info->user_ptr[0];
16083 struct net_device *dev = info->user_ptr[1];
16084 struct cfg80211_fils_aad fils_aad = {};
16085 u8 *nonces;
16086
16087 if (!info->attrs[NL80211_ATTR_MAC] ||
16088 !info->attrs[NL80211_ATTR_FILS_KEK] ||
16089 !info->attrs[NL80211_ATTR_FILS_NONCES])
16090 return -EINVAL;
16091
16092 fils_aad.macaddr = nla_data(info->attrs[NL80211_ATTR_MAC]);
16093 fils_aad.kek_len = nla_len(info->attrs[NL80211_ATTR_FILS_KEK]);
16094 fils_aad.kek = nla_data(info->attrs[NL80211_ATTR_FILS_KEK]);
16095 nonces = nla_data(info->attrs[NL80211_ATTR_FILS_NONCES]);
16096 fils_aad.snonce = nonces;
16097 fils_aad.anonce = nonces + FILS_NONCE_LEN;
16098
16099 return rdev_set_fils_aad(rdev, dev, &fils_aad);
16100}
16101
7b0a0e3c
JB
16102static int nl80211_add_link(struct sk_buff *skb, struct genl_info *info)
16103{
f2a0290b 16104 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7b0a0e3c
JB
16105 unsigned int link_id = nl80211_link_id(info->attrs);
16106 struct net_device *dev = info->user_ptr[1];
16107 struct wireless_dev *wdev = dev->ieee80211_ptr;
f2a0290b 16108 int ret;
7b0a0e3c
JB
16109
16110 if (!(wdev->wiphy->flags & WIPHY_FLAG_SUPPORTS_MLO))
16111 return -EINVAL;
16112
16113 switch (wdev->iftype) {
16114 case NL80211_IFTYPE_AP:
16115 break;
16116 default:
16117 return -EINVAL;
16118 }
16119
16120 if (!info->attrs[NL80211_ATTR_MAC] ||
16121 !is_valid_ether_addr(nla_data(info->attrs[NL80211_ATTR_MAC])))
16122 return -EINVAL;
16123
16124 wdev_lock(wdev);
16125 wdev->valid_links |= BIT(link_id);
16126 ether_addr_copy(wdev->links[link_id].addr,
16127 nla_data(info->attrs[NL80211_ATTR_MAC]));
f2a0290b
JB
16128
16129 ret = rdev_add_intf_link(rdev, wdev, link_id);
16130 if (ret) {
16131 wdev->valid_links &= ~BIT(link_id);
16132 eth_zero_addr(wdev->links[link_id].addr);
16133 }
7b0a0e3c
JB
16134 wdev_unlock(wdev);
16135
f2a0290b 16136 return ret;
7b0a0e3c
JB
16137}
16138
16139static int nl80211_remove_link(struct sk_buff *skb, struct genl_info *info)
16140{
16141 unsigned int link_id = nl80211_link_id(info->attrs);
16142 struct net_device *dev = info->user_ptr[1];
16143 struct wireless_dev *wdev = dev->ieee80211_ptr;
16144
16145 /* cannot remove if there's no link */
16146 if (!info->attrs[NL80211_ATTR_MLO_LINK_ID])
16147 return -EINVAL;
16148
16149 switch (wdev->iftype) {
16150 case NL80211_IFTYPE_AP:
16151 break;
16152 default:
16153 return -EINVAL;
16154 }
16155
7b0a0e3c 16156 wdev_lock(wdev);
cdf0a0a8 16157 cfg80211_remove_link(wdev, link_id);
7b0a0e3c
JB
16158 wdev_unlock(wdev);
16159
16160 return 0;
16161}
16162
577e5b8c
ST
16163static int
16164nl80211_add_mod_link_station(struct sk_buff *skb, struct genl_info *info,
16165 bool add)
16166{
16167 struct link_station_parameters params = {};
16168 struct cfg80211_registered_device *rdev = info->user_ptr[0];
16169 struct net_device *dev = info->user_ptr[1];
16170 int err;
16171
16172 if ((add && !rdev->ops->add_link_station) ||
16173 (!add && !rdev->ops->mod_link_station))
16174 return -EOPNOTSUPP;
16175
16176 if (add && !info->attrs[NL80211_ATTR_MAC])
16177 return -EINVAL;
16178
8876c67e 16179 if (!info->attrs[NL80211_ATTR_MLD_ADDR])
577e5b8c
ST
16180 return -EINVAL;
16181
16182 if (add && !info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES])
16183 return -EINVAL;
16184
8876c67e 16185 params.mld_mac = nla_data(info->attrs[NL80211_ATTR_MLD_ADDR]);
577e5b8c
ST
16186
16187 if (info->attrs[NL80211_ATTR_MAC]) {
16188 params.link_mac = nla_data(info->attrs[NL80211_ATTR_MAC]);
16189 if (!is_valid_ether_addr(params.link_mac))
16190 return -EINVAL;
16191 }
16192
16193 if (!info->attrs[NL80211_ATTR_MLO_LINK_ID])
16194 return -EINVAL;
16195
16196 params.link_id = nla_get_u8(info->attrs[NL80211_ATTR_MLO_LINK_ID]);
16197
16198 if (info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]) {
16199 params.supported_rates =
16200 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
16201 params.supported_rates_len =
16202 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
16203 }
16204
16205 if (info->attrs[NL80211_ATTR_HT_CAPABILITY])
16206 params.ht_capa =
16207 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
16208
16209 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY])
16210 params.vht_capa =
16211 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);
16212
16213 if (info->attrs[NL80211_ATTR_HE_CAPABILITY]) {
16214 params.he_capa =
16215 nla_data(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
16216 params.he_capa_len =
16217 nla_len(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
16218
16219 if (info->attrs[NL80211_ATTR_EHT_CAPABILITY]) {
16220 params.eht_capa =
16221 nla_data(info->attrs[NL80211_ATTR_EHT_CAPABILITY]);
16222 params.eht_capa_len =
16223 nla_len(info->attrs[NL80211_ATTR_EHT_CAPABILITY]);
16224
16225 if (!ieee80211_eht_capa_size_ok((const u8 *)params.he_capa,
16226 (const u8 *)params.eht_capa,
ea5cba26
JB
16227 params.eht_capa_len,
16228 false))
577e5b8c
ST
16229 return -EINVAL;
16230 }
16231 }
16232
16233 if (info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY])
16234 params.he_6ghz_capa =
16235 nla_data(info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY]);
16236
16237 if (info->attrs[NL80211_ATTR_OPMODE_NOTIF]) {
16238 params.opmode_notif_used = true;
16239 params.opmode_notif =
16240 nla_get_u8(info->attrs[NL80211_ATTR_OPMODE_NOTIF]);
16241 }
16242
16243 err = nl80211_parse_sta_txpower_setting(info, &params.txpwr,
16244 &params.txpwr_set);
16245 if (err)
16246 return err;
16247
858fd188 16248 wdev_lock(dev->ieee80211_ptr);
577e5b8c 16249 if (add)
858fd188
JB
16250 err = rdev_add_link_station(rdev, dev, &params);
16251 else
16252 err = rdev_mod_link_station(rdev, dev, &params);
16253 wdev_unlock(dev->ieee80211_ptr);
16254
16255 return err;
577e5b8c
ST
16256}
16257
16258static int
16259nl80211_add_link_station(struct sk_buff *skb, struct genl_info *info)
16260{
16261 return nl80211_add_mod_link_station(skb, info, true);
16262}
16263
16264static int
16265nl80211_modify_link_station(struct sk_buff *skb, struct genl_info *info)
16266{
16267 return nl80211_add_mod_link_station(skb, info, false);
16268}
16269
16270static int
16271nl80211_remove_link_station(struct sk_buff *skb, struct genl_info *info)
16272{
16273 struct link_station_del_parameters params = {};
16274 struct cfg80211_registered_device *rdev = info->user_ptr[0];
16275 struct net_device *dev = info->user_ptr[1];
858fd188 16276 int ret;
577e5b8c
ST
16277
16278 if (!rdev->ops->del_link_station)
16279 return -EOPNOTSUPP;
16280
16281 if (!info->attrs[NL80211_ATTR_MLD_ADDR] ||
16282 !info->attrs[NL80211_ATTR_MLO_LINK_ID])
16283 return -EINVAL;
16284
16285 params.mld_mac = nla_data(info->attrs[NL80211_ATTR_MLD_ADDR]);
16286 params.link_id = nla_get_u8(info->attrs[NL80211_ATTR_MLO_LINK_ID]);
16287
858fd188
JB
16288 wdev_lock(dev->ieee80211_ptr);
16289 ret = rdev_del_link_station(rdev, dev, &params);
16290 wdev_unlock(dev->ieee80211_ptr);
16291
16292 return ret;
577e5b8c
ST
16293}
16294
cbbaf2bb
AS
16295static int nl80211_set_hw_timestamp(struct sk_buff *skb,
16296 struct genl_info *info)
16297{
16298 struct cfg80211_registered_device *rdev = info->user_ptr[0];
16299 struct net_device *dev = info->user_ptr[1];
16300 struct cfg80211_set_hw_timestamp hwts = {};
16301
16302 if (!rdev->wiphy.hw_timestamp_max_peers)
16303 return -EOPNOTSUPP;
16304
16305 if (!info->attrs[NL80211_ATTR_MAC] &&
16306 rdev->wiphy.hw_timestamp_max_peers != CFG80211_HW_TIMESTAMP_ALL_PEERS)
16307 return -EOPNOTSUPP;
16308
16309 if (info->attrs[NL80211_ATTR_MAC])
16310 hwts.macaddr = nla_data(info->attrs[NL80211_ATTR_MAC]);
16311
16312 hwts.enable =
16313 nla_get_flag(info->attrs[NL80211_ATTR_HW_TIMESTAMP_ENABLED]);
16314
16315 return rdev_set_hw_timestamp(rdev, dev, &hwts);
16316}
16317
4c476991
JB
16318#define NL80211_FLAG_NEED_WIPHY 0x01
16319#define NL80211_FLAG_NEED_NETDEV 0x02
16320#define NL80211_FLAG_NEED_RTNL 0x04
41265714
JB
16321#define NL80211_FLAG_CHECK_NETDEV_UP 0x08
16322#define NL80211_FLAG_NEED_NETDEV_UP (NL80211_FLAG_NEED_NETDEV |\
16323 NL80211_FLAG_CHECK_NETDEV_UP)
1bf614ef 16324#define NL80211_FLAG_NEED_WDEV 0x10
98104fde 16325/* If a netdev is associated, it must be UP, P2P must be started */
1bf614ef
JB
16326#define NL80211_FLAG_NEED_WDEV_UP (NL80211_FLAG_NEED_WDEV |\
16327 NL80211_FLAG_CHECK_NETDEV_UP)
5393b917 16328#define NL80211_FLAG_CLEAR_SKB 0x20
77cbf790 16329#define NL80211_FLAG_NO_WIPHY_MTX 0x40
7b0a0e3c
JB
16330#define NL80211_FLAG_MLO_VALID_LINK_ID 0x80
16331#define NL80211_FLAG_MLO_UNSUPPORTED 0x100
4c476991 16332
2182db91
JB
16333#define INTERNAL_FLAG_SELECTORS(__sel) \
16334 SELECTOR(__sel, NONE, 0) /* must be first */ \
16335 SELECTOR(__sel, WIPHY, \
16336 NL80211_FLAG_NEED_WIPHY) \
16337 SELECTOR(__sel, WDEV, \
16338 NL80211_FLAG_NEED_WDEV) \
16339 SELECTOR(__sel, NETDEV, \
16340 NL80211_FLAG_NEED_NETDEV) \
7b0a0e3c
JB
16341 SELECTOR(__sel, NETDEV_LINK, \
16342 NL80211_FLAG_NEED_NETDEV | \
16343 NL80211_FLAG_MLO_VALID_LINK_ID) \
16344 SELECTOR(__sel, NETDEV_NO_MLO, \
16345 NL80211_FLAG_NEED_NETDEV | \
16346 NL80211_FLAG_MLO_UNSUPPORTED) \
2182db91
JB
16347 SELECTOR(__sel, WIPHY_RTNL, \
16348 NL80211_FLAG_NEED_WIPHY | \
16349 NL80211_FLAG_NEED_RTNL) \
16350 SELECTOR(__sel, WIPHY_RTNL_NOMTX, \
16351 NL80211_FLAG_NEED_WIPHY | \
16352 NL80211_FLAG_NEED_RTNL | \
16353 NL80211_FLAG_NO_WIPHY_MTX) \
16354 SELECTOR(__sel, WDEV_RTNL, \
16355 NL80211_FLAG_NEED_WDEV | \
16356 NL80211_FLAG_NEED_RTNL) \
16357 SELECTOR(__sel, NETDEV_RTNL, \
16358 NL80211_FLAG_NEED_NETDEV | \
16359 NL80211_FLAG_NEED_RTNL) \
16360 SELECTOR(__sel, NETDEV_UP, \
16361 NL80211_FLAG_NEED_NETDEV_UP) \
7b0a0e3c
JB
16362 SELECTOR(__sel, NETDEV_UP_LINK, \
16363 NL80211_FLAG_NEED_NETDEV_UP | \
16364 NL80211_FLAG_MLO_VALID_LINK_ID) \
16365 SELECTOR(__sel, NETDEV_UP_NO_MLO, \
16366 NL80211_FLAG_NEED_NETDEV_UP | \
16367 NL80211_FLAG_MLO_UNSUPPORTED) \
16368 SELECTOR(__sel, NETDEV_UP_NO_MLO_CLEAR, \
16369 NL80211_FLAG_NEED_NETDEV_UP | \
16370 NL80211_FLAG_CLEAR_SKB | \
16371 NL80211_FLAG_MLO_UNSUPPORTED) \
2182db91
JB
16372 SELECTOR(__sel, NETDEV_UP_NOTMX, \
16373 NL80211_FLAG_NEED_NETDEV_UP | \
16374 NL80211_FLAG_NO_WIPHY_MTX) \
7b0a0e3c
JB
16375 SELECTOR(__sel, NETDEV_UP_NOTMX_NOMLO, \
16376 NL80211_FLAG_NEED_NETDEV_UP | \
16377 NL80211_FLAG_NO_WIPHY_MTX | \
16378 NL80211_FLAG_MLO_UNSUPPORTED) \
2182db91
JB
16379 SELECTOR(__sel, NETDEV_UP_CLEAR, \
16380 NL80211_FLAG_NEED_NETDEV_UP | \
16381 NL80211_FLAG_CLEAR_SKB) \
16382 SELECTOR(__sel, WDEV_UP, \
16383 NL80211_FLAG_NEED_WDEV_UP) \
7b0a0e3c
JB
16384 SELECTOR(__sel, WDEV_UP_LINK, \
16385 NL80211_FLAG_NEED_WDEV_UP | \
16386 NL80211_FLAG_MLO_VALID_LINK_ID) \
2182db91
JB
16387 SELECTOR(__sel, WDEV_UP_RTNL, \
16388 NL80211_FLAG_NEED_WDEV_UP | \
16389 NL80211_FLAG_NEED_RTNL) \
16390 SELECTOR(__sel, WIPHY_CLEAR, \
16391 NL80211_FLAG_NEED_WIPHY | \
16392 NL80211_FLAG_CLEAR_SKB)
16393
16394enum nl80211_internal_flags_selector {
16395#define SELECTOR(_, name, value) NL80211_IFL_SEL_##name,
16396 INTERNAL_FLAG_SELECTORS(_)
16397#undef SELECTOR
16398};
16399
16400static u32 nl80211_internal_flags[] = {
16401#define SELECTOR(_, name, value) [NL80211_IFL_SEL_##name] = value,
16402 INTERNAL_FLAG_SELECTORS(_)
16403#undef SELECTOR
16404};
16405
20b0b53a
JK
16406static int nl80211_pre_doit(const struct genl_split_ops *ops,
16407 struct sk_buff *skb,
4c476991
JB
16408 struct genl_info *info)
16409{
a05829a7 16410 struct cfg80211_registered_device *rdev = NULL;
7b0a0e3c
JB
16411 struct wireless_dev *wdev = NULL;
16412 struct net_device *dev = NULL;
2182db91 16413 u32 internal_flags;
7b0a0e3c 16414 int err;
2182db91
JB
16415
16416 if (WARN_ON(ops->internal_flags >= ARRAY_SIZE(nl80211_internal_flags)))
16417 return -EINVAL;
16418
16419 internal_flags = nl80211_internal_flags[ops->internal_flags];
4c476991 16420
a05829a7 16421 rtnl_lock();
2182db91 16422 if (internal_flags & NL80211_FLAG_NEED_WIPHY) {
4f7eff10 16423 rdev = cfg80211_get_dev_from_info(genl_info_net(info), info);
4c476991 16424 if (IS_ERR(rdev)) {
7b0a0e3c
JB
16425 err = PTR_ERR(rdev);
16426 goto out_unlock;
4c476991
JB
16427 }
16428 info->user_ptr[0] = rdev;
2182db91
JB
16429 } else if (internal_flags & NL80211_FLAG_NEED_NETDEV ||
16430 internal_flags & NL80211_FLAG_NEED_WDEV) {
a05829a7 16431 wdev = __cfg80211_wdev_from_attrs(NULL, genl_info_net(info),
89a54e48
JB
16432 info->attrs);
16433 if (IS_ERR(wdev)) {
7b0a0e3c
JB
16434 err = PTR_ERR(wdev);
16435 goto out_unlock;
4c476991 16436 }
89a54e48 16437
89a54e48 16438 dev = wdev->netdev;
7b0a0e3c 16439 dev_hold(dev);
f26cbf40 16440 rdev = wiphy_to_rdev(wdev->wiphy);
89a54e48 16441
2182db91 16442 if (internal_flags & NL80211_FLAG_NEED_NETDEV) {
1bf614ef 16443 if (!dev) {
7b0a0e3c
JB
16444 err = -EINVAL;
16445 goto out_unlock;
1bf614ef
JB
16446 }
16447
16448 info->user_ptr[1] = dev;
16449 } else {
16450 info->user_ptr[1] = wdev;
41265714 16451 }
1bf614ef 16452
2182db91 16453 if (internal_flags & NL80211_FLAG_CHECK_NETDEV_UP &&
73c7da3d 16454 !wdev_running(wdev)) {
7b0a0e3c
JB
16455 err = -ENETDOWN;
16456 goto out_unlock;
73c7da3d 16457 }
1bf614ef 16458
4c476991 16459 info->user_ptr[0] = rdev;
4c476991
JB
16460 }
16461
7b0a0e3c
JB
16462 if (internal_flags & NL80211_FLAG_MLO_VALID_LINK_ID) {
16463 struct nlattr *link_id = info->attrs[NL80211_ATTR_MLO_LINK_ID];
16464
16465 if (!wdev) {
16466 err = -EINVAL;
16467 goto out_unlock;
16468 }
16469
16470 /* MLO -> require valid link ID */
16471 if (wdev->valid_links &&
16472 (!link_id ||
ff3821bc 16473 !(wdev->valid_links & BIT(nla_get_u8(link_id))))) {
7b0a0e3c
JB
16474 err = -EINVAL;
16475 goto out_unlock;
16476 }
16477
16478 /* non-MLO -> no link ID attribute accepted */
16479 if (!wdev->valid_links && link_id) {
16480 err = -EINVAL;
16481 goto out_unlock;
16482 }
16483 }
16484
16485 if (internal_flags & NL80211_FLAG_MLO_UNSUPPORTED) {
16486 if (info->attrs[NL80211_ATTR_MLO_LINK_ID] ||
16487 (wdev && wdev->valid_links)) {
16488 err = -EINVAL;
16489 goto out_unlock;
16490 }
16491 }
16492
2182db91 16493 if (rdev && !(internal_flags & NL80211_FLAG_NO_WIPHY_MTX)) {
a05829a7
JB
16494 wiphy_lock(&rdev->wiphy);
16495 /* we keep the mutex locked until post_doit */
16496 __release(&rdev->wiphy.mtx);
16497 }
2182db91 16498 if (!(internal_flags & NL80211_FLAG_NEED_RTNL))
a05829a7
JB
16499 rtnl_unlock();
16500
4c476991 16501 return 0;
7b0a0e3c
JB
16502out_unlock:
16503 rtnl_unlock();
16504 dev_put(dev);
16505 return err;
4c476991
JB
16506}
16507
20b0b53a
JK
16508static void nl80211_post_doit(const struct genl_split_ops *ops,
16509 struct sk_buff *skb,
4c476991
JB
16510 struct genl_info *info)
16511{
2182db91
JB
16512 u32 internal_flags = nl80211_internal_flags[ops->internal_flags];
16513
1bf614ef 16514 if (info->user_ptr[1]) {
2182db91 16515 if (internal_flags & NL80211_FLAG_NEED_WDEV) {
1bf614ef
JB
16516 struct wireless_dev *wdev = info->user_ptr[1];
16517
1160dfa1 16518 dev_put(wdev->netdev);
1bf614ef
JB
16519 } else {
16520 dev_put(info->user_ptr[1]);
16521 }
16522 }
5393b917 16523
77cbf790 16524 if (info->user_ptr[0] &&
2182db91 16525 !(internal_flags & NL80211_FLAG_NO_WIPHY_MTX)) {
a05829a7
JB
16526 struct cfg80211_registered_device *rdev = info->user_ptr[0];
16527
16528 /* we kept the mutex locked since pre_doit */
16529 __acquire(&rdev->wiphy.mtx);
16530 wiphy_unlock(&rdev->wiphy);
16531 }
16532
2182db91 16533 if (internal_flags & NL80211_FLAG_NEED_RTNL)
4c476991 16534 rtnl_unlock();
5393b917
JB
16535
16536 /* If needed, clear the netlink message payload from the SKB
16537 * as it might contain key data that shouldn't stick around on
16538 * the heap after the SKB is freed. The netlink message header
16539 * is still needed for further processing, so leave it intact.
16540 */
2182db91 16541 if (internal_flags & NL80211_FLAG_CLEAR_SKB) {
5393b917
JB
16542 struct nlmsghdr *nlh = nlmsg_hdr(skb);
16543
16544 memset(nlmsg_data(nlh), 0, nlmsg_len(nlh));
16545 }
4c476991
JB
16546}
16547
6bdb68ce
CH
16548static int nl80211_set_sar_sub_specs(struct cfg80211_registered_device *rdev,
16549 struct cfg80211_sar_specs *sar_specs,
16550 struct nlattr *spec[], int index)
16551{
16552 u32 range_index, i;
16553
16554 if (!sar_specs || !spec)
16555 return -EINVAL;
16556
16557 if (!spec[NL80211_SAR_ATTR_SPECS_POWER] ||
16558 !spec[NL80211_SAR_ATTR_SPECS_RANGE_INDEX])
16559 return -EINVAL;
16560
16561 range_index = nla_get_u32(spec[NL80211_SAR_ATTR_SPECS_RANGE_INDEX]);
16562
16563 /* check if range_index exceeds num_freq_ranges */
16564 if (range_index >= rdev->wiphy.sar_capa->num_freq_ranges)
16565 return -EINVAL;
16566
16567 /* check if range_index duplicates */
16568 for (i = 0; i < index; i++) {
16569 if (sar_specs->sub_specs[i].freq_range_index == range_index)
16570 return -EINVAL;
16571 }
16572
16573 sar_specs->sub_specs[index].power =
16574 nla_get_s32(spec[NL80211_SAR_ATTR_SPECS_POWER]);
16575
16576 sar_specs->sub_specs[index].freq_range_index = range_index;
16577
16578 return 0;
16579}
16580
16581static int nl80211_set_sar_specs(struct sk_buff *skb, struct genl_info *info)
16582{
16583 struct cfg80211_registered_device *rdev = info->user_ptr[0];
16584 struct nlattr *spec[NL80211_SAR_ATTR_SPECS_MAX + 1];
16585 struct nlattr *tb[NL80211_SAR_ATTR_MAX + 1];
16586 struct cfg80211_sar_specs *sar_spec;
16587 enum nl80211_sar_type type;
16588 struct nlattr *spec_list;
16589 u32 specs;
16590 int rem, err;
16591
16592 if (!rdev->wiphy.sar_capa || !rdev->ops->set_sar_specs)
16593 return -EOPNOTSUPP;
16594
16595 if (!info->attrs[NL80211_ATTR_SAR_SPEC])
16596 return -EINVAL;
16597
16598 nla_parse_nested(tb, NL80211_SAR_ATTR_MAX,
16599 info->attrs[NL80211_ATTR_SAR_SPEC],
16600 NULL, NULL);
16601
16602 if (!tb[NL80211_SAR_ATTR_TYPE] || !tb[NL80211_SAR_ATTR_SPECS])
16603 return -EINVAL;
16604
16605 type = nla_get_u32(tb[NL80211_SAR_ATTR_TYPE]);
16606 if (type != rdev->wiphy.sar_capa->type)
16607 return -EINVAL;
16608
16609 specs = 0;
16610 nla_for_each_nested(spec_list, tb[NL80211_SAR_ATTR_SPECS], rem)
16611 specs++;
16612
16613 if (specs > rdev->wiphy.sar_capa->num_freq_ranges)
16614 return -EINVAL;
16615
40f231e7 16616 sar_spec = kzalloc(struct_size(sar_spec, sub_specs, specs), GFP_KERNEL);
6bdb68ce
CH
16617 if (!sar_spec)
16618 return -ENOMEM;
16619
16620 sar_spec->type = type;
16621 specs = 0;
16622 nla_for_each_nested(spec_list, tb[NL80211_SAR_ATTR_SPECS], rem) {
16623 nla_parse_nested(spec, NL80211_SAR_ATTR_SPECS_MAX,
16624 spec_list, NULL, NULL);
16625
16626 switch (type) {
16627 case NL80211_SAR_TYPE_POWER:
16628 if (nl80211_set_sar_sub_specs(rdev, sar_spec,
16629 spec, specs)) {
16630 err = -EINVAL;
16631 goto error;
16632 }
16633 break;
16634 default:
16635 err = -EINVAL;
16636 goto error;
16637 }
16638 specs++;
16639 }
16640
16641 sar_spec->num_sub_specs = specs;
16642
16643 rdev->cur_cmd_info = info;
16644 err = rdev_set_sar_specs(rdev, sar_spec);
16645 rdev->cur_cmd_info = NULL;
16646error:
16647 kfree(sar_spec);
16648 return err;
16649}
16650
2182db91
JB
16651#define SELECTOR(__sel, name, value) \
16652 ((__sel) == (value)) ? NL80211_IFL_SEL_##name :
16653int __missing_selector(void);
16654#define IFLAGS(__val) INTERNAL_FLAG_SELECTORS(__val) __missing_selector()
16655
4534de83 16656static const struct genl_ops nl80211_ops[] = {
55682965
JB
16657 {
16658 .cmd = NL80211_CMD_GET_WIPHY,
ef6243ac 16659 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
55682965
JB
16660 .doit = nl80211_get_wiphy,
16661 .dumpit = nl80211_dump_wiphy,
86e8cf98 16662 .done = nl80211_dump_wiphy_done,
55682965 16663 /* can be retrieved by unprivileged users */
2182db91 16664 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY),
55682965 16665 },
66a9b928
JK
16666};
16667
16668static const struct genl_small_ops nl80211_small_ops[] = {
55682965
JB
16669 {
16670 .cmd = NL80211_CMD_SET_WIPHY,
ef6243ac 16671 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
55682965 16672 .doit = nl80211_set_wiphy,
5617c6cd 16673 .flags = GENL_UNS_ADMIN_PERM,
55682965
JB
16674 },
16675 {
16676 .cmd = NL80211_CMD_GET_INTERFACE,
ef6243ac 16677 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
55682965
JB
16678 .doit = nl80211_get_interface,
16679 .dumpit = nl80211_dump_interface,
55682965 16680 /* can be retrieved by unprivileged users */
2182db91 16681 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV),
55682965
JB
16682 },
16683 {
16684 .cmd = NL80211_CMD_SET_INTERFACE,
ef6243ac 16685 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
55682965 16686 .doit = nl80211_set_interface,
5617c6cd 16687 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
16688 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV |
16689 NL80211_FLAG_NEED_RTNL),
55682965
JB
16690 },
16691 {
16692 .cmd = NL80211_CMD_NEW_INTERFACE,
ef6243ac 16693 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
55682965 16694 .doit = nl80211_new_interface,
5617c6cd 16695 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
16696 .internal_flags =
16697 IFLAGS(NL80211_FLAG_NEED_WIPHY |
16698 NL80211_FLAG_NEED_RTNL |
16699 /* we take the wiphy mutex later ourselves */
16700 NL80211_FLAG_NO_WIPHY_MTX),
55682965
JB
16701 },
16702 {
16703 .cmd = NL80211_CMD_DEL_INTERFACE,
ef6243ac 16704 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
55682965 16705 .doit = nl80211_del_interface,
5617c6cd 16706 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
16707 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV |
16708 NL80211_FLAG_NEED_RTNL),
41ade00f
JB
16709 },
16710 {
16711 .cmd = NL80211_CMD_GET_KEY,
ef6243ac 16712 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
41ade00f 16713 .doit = nl80211_get_key,
5617c6cd 16714 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16715 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
41ade00f
JB
16716 },
16717 {
16718 .cmd = NL80211_CMD_SET_KEY,
ef6243ac 16719 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
41ade00f 16720 .doit = nl80211_set_key,
5617c6cd 16721 .flags = GENL_UNS_ADMIN_PERM,
7b0a0e3c 16722 /* cannot use NL80211_FLAG_MLO_VALID_LINK_ID, depends on key */
2182db91
JB
16723 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
16724 NL80211_FLAG_CLEAR_SKB),
41ade00f
JB
16725 },
16726 {
16727 .cmd = NL80211_CMD_NEW_KEY,
ef6243ac 16728 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
41ade00f 16729 .doit = nl80211_new_key,
5617c6cd 16730 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
16731 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
16732 NL80211_FLAG_CLEAR_SKB),
41ade00f
JB
16733 },
16734 {
16735 .cmd = NL80211_CMD_DEL_KEY,
ef6243ac 16736 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
41ade00f 16737 .doit = nl80211_del_key,
5617c6cd 16738 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16739 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
55682965 16740 },
ed1b6cc7
JB
16741 {
16742 .cmd = NL80211_CMD_SET_BEACON,
ef6243ac 16743 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5617c6cd 16744 .flags = GENL_UNS_ADMIN_PERM,
8860020e 16745 .doit = nl80211_set_beacon,
7b0a0e3c
JB
16746 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
16747 NL80211_FLAG_MLO_VALID_LINK_ID),
ed1b6cc7
JB
16748 },
16749 {
8860020e 16750 .cmd = NL80211_CMD_START_AP,
ef6243ac 16751 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5617c6cd 16752 .flags = GENL_UNS_ADMIN_PERM,
8860020e 16753 .doit = nl80211_start_ap,
7b0a0e3c
JB
16754 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
16755 NL80211_FLAG_MLO_VALID_LINK_ID),
ed1b6cc7
JB
16756 },
16757 {
8860020e 16758 .cmd = NL80211_CMD_STOP_AP,
ef6243ac 16759 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5617c6cd 16760 .flags = GENL_UNS_ADMIN_PERM,
8860020e 16761 .doit = nl80211_stop_ap,
7b0a0e3c
JB
16762 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
16763 NL80211_FLAG_MLO_VALID_LINK_ID),
ed1b6cc7 16764 },
5727ef1b
JB
16765 {
16766 .cmd = NL80211_CMD_GET_STATION,
ef6243ac 16767 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5727ef1b 16768 .doit = nl80211_get_station,
2ec600d6 16769 .dumpit = nl80211_dump_station,
2182db91 16770 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
5727ef1b
JB
16771 },
16772 {
16773 .cmd = NL80211_CMD_SET_STATION,
ef6243ac 16774 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5727ef1b 16775 .doit = nl80211_set_station,
5617c6cd 16776 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16777 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
5727ef1b
JB
16778 },
16779 {
16780 .cmd = NL80211_CMD_NEW_STATION,
ef6243ac 16781 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5727ef1b 16782 .doit = nl80211_new_station,
5617c6cd 16783 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16784 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
5727ef1b
JB
16785 },
16786 {
16787 .cmd = NL80211_CMD_DEL_STATION,
ef6243ac 16788 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5727ef1b 16789 .doit = nl80211_del_station,
5617c6cd 16790 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16791 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
2ec600d6
LCC
16792 },
16793 {
16794 .cmd = NL80211_CMD_GET_MPATH,
ef6243ac 16795 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2ec600d6
LCC
16796 .doit = nl80211_get_mpath,
16797 .dumpit = nl80211_dump_mpath,
5617c6cd 16798 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16799 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
2ec600d6 16800 },
66be7d2b
HR
16801 {
16802 .cmd = NL80211_CMD_GET_MPP,
ef6243ac 16803 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
66be7d2b
HR
16804 .doit = nl80211_get_mpp,
16805 .dumpit = nl80211_dump_mpp,
5617c6cd 16806 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16807 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
66be7d2b 16808 },
2ec600d6
LCC
16809 {
16810 .cmd = NL80211_CMD_SET_MPATH,
ef6243ac 16811 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2ec600d6 16812 .doit = nl80211_set_mpath,
5617c6cd 16813 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16814 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
2ec600d6
LCC
16815 },
16816 {
16817 .cmd = NL80211_CMD_NEW_MPATH,
ef6243ac 16818 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2ec600d6 16819 .doit = nl80211_new_mpath,
5617c6cd 16820 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16821 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
2ec600d6
LCC
16822 },
16823 {
16824 .cmd = NL80211_CMD_DEL_MPATH,
ef6243ac 16825 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2ec600d6 16826 .doit = nl80211_del_mpath,
5617c6cd 16827 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16828 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
9f1ba906
JM
16829 },
16830 {
16831 .cmd = NL80211_CMD_SET_BSS,
ef6243ac 16832 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9f1ba906 16833 .doit = nl80211_set_bss,
5617c6cd 16834 .flags = GENL_UNS_ADMIN_PERM,
1e0f8cc9
JB
16835 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
16836 NL80211_FLAG_MLO_VALID_LINK_ID),
b2e1b302 16837 },
f130347c
LR
16838 {
16839 .cmd = NL80211_CMD_GET_REG,
ef6243ac 16840 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ad30ca2c
AN
16841 .doit = nl80211_get_reg_do,
16842 .dumpit = nl80211_get_reg_dump,
f130347c
LR
16843 /* can be retrieved by unprivileged users */
16844 },
b6863036 16845#ifdef CONFIG_CFG80211_CRDA_SUPPORT
b2e1b302
LR
16846 {
16847 .cmd = NL80211_CMD_SET_REG,
ef6243ac 16848 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
b2e1b302 16849 .doit = nl80211_set_reg,
b2e1b302
LR
16850 .flags = GENL_ADMIN_PERM,
16851 },
b6863036 16852#endif
b2e1b302
LR
16853 {
16854 .cmd = NL80211_CMD_REQ_SET_REG,
ef6243ac 16855 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
b2e1b302 16856 .doit = nl80211_req_set_reg,
93da9cc1 16857 .flags = GENL_ADMIN_PERM,
16858 },
1ea4ff3e
JB
16859 {
16860 .cmd = NL80211_CMD_RELOAD_REGDB,
ef6243ac 16861 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1ea4ff3e 16862 .doit = nl80211_reload_regdb,
1ea4ff3e
JB
16863 .flags = GENL_ADMIN_PERM,
16864 },
93da9cc1 16865 {
24bdd9f4 16866 .cmd = NL80211_CMD_GET_MESH_CONFIG,
ef6243ac 16867 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
24bdd9f4 16868 .doit = nl80211_get_mesh_config,
93da9cc1 16869 /* can be retrieved by unprivileged users */
2182db91 16870 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
93da9cc1 16871 },
16872 {
24bdd9f4 16873 .cmd = NL80211_CMD_SET_MESH_CONFIG,
ef6243ac 16874 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
24bdd9f4 16875 .doit = nl80211_update_mesh_config,
5617c6cd 16876 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16877 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
9aed3cc1 16878 },
2a519311
JB
16879 {
16880 .cmd = NL80211_CMD_TRIGGER_SCAN,
ef6243ac 16881 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2a519311 16882 .doit = nl80211_trigger_scan,
5617c6cd 16883 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16884 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
2a519311 16885 },
91d3ab46
VK
16886 {
16887 .cmd = NL80211_CMD_ABORT_SCAN,
ef6243ac 16888 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
91d3ab46 16889 .doit = nl80211_abort_scan,
5617c6cd 16890 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16891 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
91d3ab46 16892 },
2a519311
JB
16893 {
16894 .cmd = NL80211_CMD_GET_SCAN,
ef6243ac 16895 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2a519311
JB
16896 .dumpit = nl80211_dump_scan,
16897 },
807f8a8c
LC
16898 {
16899 .cmd = NL80211_CMD_START_SCHED_SCAN,
ef6243ac 16900 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
807f8a8c 16901 .doit = nl80211_start_sched_scan,
5617c6cd 16902 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16903 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
807f8a8c
LC
16904 },
16905 {
16906 .cmd = NL80211_CMD_STOP_SCHED_SCAN,
ef6243ac 16907 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
807f8a8c 16908 .doit = nl80211_stop_sched_scan,
5617c6cd 16909 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16910 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
807f8a8c 16911 },
636a5d36
JM
16912 {
16913 .cmd = NL80211_CMD_AUTHENTICATE,
ef6243ac 16914 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
636a5d36 16915 .doit = nl80211_authenticate,
5617c6cd 16916 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
16917 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
16918 NL80211_FLAG_CLEAR_SKB),
636a5d36
JM
16919 },
16920 {
16921 .cmd = NL80211_CMD_ASSOCIATE,
ef6243ac 16922 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
636a5d36 16923 .doit = nl80211_associate,
5617c6cd 16924 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
16925 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
16926 NL80211_FLAG_CLEAR_SKB),
636a5d36
JM
16927 },
16928 {
16929 .cmd = NL80211_CMD_DEAUTHENTICATE,
ef6243ac 16930 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
636a5d36 16931 .doit = nl80211_deauthenticate,
5617c6cd 16932 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16933 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
636a5d36
JM
16934 },
16935 {
16936 .cmd = NL80211_CMD_DISASSOCIATE,
ef6243ac 16937 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
636a5d36 16938 .doit = nl80211_disassociate,
5617c6cd 16939 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16940 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
636a5d36 16941 },
04a773ad
JB
16942 {
16943 .cmd = NL80211_CMD_JOIN_IBSS,
ef6243ac 16944 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
04a773ad 16945 .doit = nl80211_join_ibss,
5617c6cd 16946 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16947 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
04a773ad
JB
16948 },
16949 {
16950 .cmd = NL80211_CMD_LEAVE_IBSS,
ef6243ac 16951 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
04a773ad 16952 .doit = nl80211_leave_ibss,
5617c6cd 16953 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16954 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
04a773ad 16955 },
aff89a9b
JB
16956#ifdef CONFIG_NL80211_TESTMODE
16957 {
16958 .cmd = NL80211_CMD_TESTMODE,
ef6243ac 16959 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
aff89a9b 16960 .doit = nl80211_testmode_do,
71063f0e 16961 .dumpit = nl80211_testmode_dump,
5617c6cd 16962 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16963 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY),
aff89a9b
JB
16964 },
16965#endif
b23aa676
SO
16966 {
16967 .cmd = NL80211_CMD_CONNECT,
ef6243ac 16968 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
b23aa676 16969 .doit = nl80211_connect,
5617c6cd 16970 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
16971 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
16972 NL80211_FLAG_CLEAR_SKB),
b23aa676 16973 },
088e8df8 16974 {
16975 .cmd = NL80211_CMD_UPDATE_CONNECT_PARAMS,
ef6243ac 16976 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
088e8df8 16977 .doit = nl80211_update_connect_params,
088e8df8 16978 .flags = GENL_ADMIN_PERM,
2182db91
JB
16979 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
16980 NL80211_FLAG_CLEAR_SKB),
088e8df8 16981 },
b23aa676
SO
16982 {
16983 .cmd = NL80211_CMD_DISCONNECT,
ef6243ac 16984 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
b23aa676 16985 .doit = nl80211_disconnect,
5617c6cd 16986 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16987 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
b23aa676 16988 },
463d0183
JB
16989 {
16990 .cmd = NL80211_CMD_SET_WIPHY_NETNS,
ef6243ac 16991 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
463d0183 16992 .doit = nl80211_wiphy_netns,
5617c6cd 16993 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
16994 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY |
16995 NL80211_FLAG_NEED_RTNL |
16996 NL80211_FLAG_NO_WIPHY_MTX),
463d0183 16997 },
61fa713c
HS
16998 {
16999 .cmd = NL80211_CMD_GET_SURVEY,
ef6243ac 17000 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
61fa713c
HS
17001 .dumpit = nl80211_dump_survey,
17002 },
67fbb16b
SO
17003 {
17004 .cmd = NL80211_CMD_SET_PMKSA,
ef6243ac 17005 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
67fbb16b 17006 .doit = nl80211_setdel_pmksa,
5617c6cd 17007 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
17008 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
17009 NL80211_FLAG_CLEAR_SKB),
67fbb16b
SO
17010 },
17011 {
17012 .cmd = NL80211_CMD_DEL_PMKSA,
ef6243ac 17013 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
67fbb16b 17014 .doit = nl80211_setdel_pmksa,
5617c6cd 17015 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17016 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
67fbb16b
SO
17017 },
17018 {
17019 .cmd = NL80211_CMD_FLUSH_PMKSA,
ef6243ac 17020 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
67fbb16b 17021 .doit = nl80211_flush_pmksa,
5617c6cd 17022 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17023 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
67fbb16b 17024 },
9588bbd5
JM
17025 {
17026 .cmd = NL80211_CMD_REMAIN_ON_CHANNEL,
ef6243ac 17027 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9588bbd5 17028 .doit = nl80211_remain_on_channel,
5617c6cd 17029 .flags = GENL_UNS_ADMIN_PERM,
7b0a0e3c
JB
17030 /* FIXME: requiring a link ID here is probably not good */
17031 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP |
17032 NL80211_FLAG_MLO_VALID_LINK_ID),
9588bbd5
JM
17033 },
17034 {
17035 .cmd = NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL,
ef6243ac 17036 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9588bbd5 17037 .doit = nl80211_cancel_remain_on_channel,
5617c6cd 17038 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17039 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
9588bbd5 17040 },
13ae75b1
JM
17041 {
17042 .cmd = NL80211_CMD_SET_TX_BITRATE_MASK,
ef6243ac 17043 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
13ae75b1 17044 .doit = nl80211_set_tx_bitrate_mask,
5617c6cd 17045 .flags = GENL_UNS_ADMIN_PERM,
7b0a0e3c
JB
17046 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV |
17047 NL80211_FLAG_MLO_VALID_LINK_ID),
13ae75b1 17048 },
026331c4 17049 {
2e161f78 17050 .cmd = NL80211_CMD_REGISTER_FRAME,
ef6243ac 17051 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2e161f78 17052 .doit = nl80211_register_mgmt,
5617c6cd 17053 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17054 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV),
026331c4
JM
17055 },
17056 {
2e161f78 17057 .cmd = NL80211_CMD_FRAME,
ef6243ac 17058 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2e161f78 17059 .doit = nl80211_tx_mgmt,
5617c6cd 17060 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17061 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
f7ca38df
JB
17062 },
17063 {
17064 .cmd = NL80211_CMD_FRAME_WAIT_CANCEL,
ef6243ac 17065 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
f7ca38df 17066 .doit = nl80211_tx_mgmt_cancel_wait,
5617c6cd 17067 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17068 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
026331c4 17069 },
ffb9eb3d
KV
17070 {
17071 .cmd = NL80211_CMD_SET_POWER_SAVE,
ef6243ac 17072 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ffb9eb3d 17073 .doit = nl80211_set_power_save,
5617c6cd 17074 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17075 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
ffb9eb3d
KV
17076 },
17077 {
17078 .cmd = NL80211_CMD_GET_POWER_SAVE,
ef6243ac 17079 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ffb9eb3d 17080 .doit = nl80211_get_power_save,
ffb9eb3d 17081 /* can be retrieved by unprivileged users */
2182db91 17082 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
ffb9eb3d 17083 },
d6dc1a38
JO
17084 {
17085 .cmd = NL80211_CMD_SET_CQM,
ef6243ac 17086 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
d6dc1a38 17087 .doit = nl80211_set_cqm,
5617c6cd 17088 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17089 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
d6dc1a38 17090 },
f444de05
JB
17091 {
17092 .cmd = NL80211_CMD_SET_CHANNEL,
ef6243ac 17093 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
f444de05 17094 .doit = nl80211_set_channel,
5617c6cd 17095 .flags = GENL_UNS_ADMIN_PERM,
7b0a0e3c
JB
17096 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV |
17097 NL80211_FLAG_MLO_VALID_LINK_ID),
f444de05 17098 },
29cbe68c
JB
17099 {
17100 .cmd = NL80211_CMD_JOIN_MESH,
ef6243ac 17101 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
29cbe68c 17102 .doit = nl80211_join_mesh,
5617c6cd 17103 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17104 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
29cbe68c
JB
17105 },
17106 {
17107 .cmd = NL80211_CMD_LEAVE_MESH,
ef6243ac 17108 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
29cbe68c 17109 .doit = nl80211_leave_mesh,
5617c6cd 17110 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17111 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
29cbe68c 17112 },
6e0bd6c3
RL
17113 {
17114 .cmd = NL80211_CMD_JOIN_OCB,
ef6243ac 17115 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6e0bd6c3 17116 .doit = nl80211_join_ocb,
5617c6cd 17117 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17118 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
6e0bd6c3
RL
17119 },
17120 {
17121 .cmd = NL80211_CMD_LEAVE_OCB,
ef6243ac 17122 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6e0bd6c3 17123 .doit = nl80211_leave_ocb,
5617c6cd 17124 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17125 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
6e0bd6c3 17126 },
dfb89c56 17127#ifdef CONFIG_PM
ff1b6e69
JB
17128 {
17129 .cmd = NL80211_CMD_GET_WOWLAN,
ef6243ac 17130 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ff1b6e69 17131 .doit = nl80211_get_wowlan,
ff1b6e69 17132 /* can be retrieved by unprivileged users */
2182db91 17133 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY),
ff1b6e69
JB
17134 },
17135 {
17136 .cmd = NL80211_CMD_SET_WOWLAN,
ef6243ac 17137 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ff1b6e69 17138 .doit = nl80211_set_wowlan,
5617c6cd 17139 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17140 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY),
ff1b6e69 17141 },
dfb89c56 17142#endif
e5497d76
JB
17143 {
17144 .cmd = NL80211_CMD_SET_REKEY_OFFLOAD,
ef6243ac 17145 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
e5497d76 17146 .doit = nl80211_set_rekey_data,
5617c6cd 17147 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
17148 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
17149 NL80211_FLAG_CLEAR_SKB),
e5497d76 17150 },
109086ce
AN
17151 {
17152 .cmd = NL80211_CMD_TDLS_MGMT,
ef6243ac 17153 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
109086ce 17154 .doit = nl80211_tdls_mgmt,
5617c6cd 17155 .flags = GENL_UNS_ADMIN_PERM,
c6112046
MS
17156 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
17157 NL80211_FLAG_MLO_VALID_LINK_ID),
109086ce
AN
17158 },
17159 {
17160 .cmd = NL80211_CMD_TDLS_OPER,
ef6243ac 17161 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
109086ce 17162 .doit = nl80211_tdls_oper,
5617c6cd 17163 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17164 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
109086ce 17165 },
28946da7
JB
17166 {
17167 .cmd = NL80211_CMD_UNEXPECTED_FRAME,
ef6243ac 17168 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
28946da7 17169 .doit = nl80211_register_unexpected_frame,
5617c6cd 17170 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17171 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
28946da7 17172 },
7f6cf311
JB
17173 {
17174 .cmd = NL80211_CMD_PROBE_CLIENT,
ef6243ac 17175 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
7f6cf311 17176 .doit = nl80211_probe_client,
5617c6cd 17177 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17178 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
7f6cf311 17179 },
5e760230
JB
17180 {
17181 .cmd = NL80211_CMD_REGISTER_BEACONS,
ef6243ac 17182 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5e760230 17183 .doit = nl80211_register_beacons,
5617c6cd 17184 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17185 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY),
5e760230 17186 },
1d9d9213
SW
17187 {
17188 .cmd = NL80211_CMD_SET_NOACK_MAP,
ef6243ac 17189 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1d9d9213 17190 .doit = nl80211_set_noack_map,
5617c6cd 17191 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17192 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
1d9d9213 17193 },
98104fde
JB
17194 {
17195 .cmd = NL80211_CMD_START_P2P_DEVICE,
ef6243ac 17196 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
98104fde 17197 .doit = nl80211_start_p2p_device,
5617c6cd 17198 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
17199 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV |
17200 NL80211_FLAG_NEED_RTNL),
98104fde
JB
17201 },
17202 {
17203 .cmd = NL80211_CMD_STOP_P2P_DEVICE,
ef6243ac 17204 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
98104fde 17205 .doit = nl80211_stop_p2p_device,
5617c6cd 17206 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
17207 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP |
17208 NL80211_FLAG_NEED_RTNL),
cb3b7d87
AB
17209 },
17210 {
17211 .cmd = NL80211_CMD_START_NAN,
ef6243ac 17212 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
cb3b7d87 17213 .doit = nl80211_start_nan,
cb3b7d87 17214 .flags = GENL_ADMIN_PERM,
2182db91
JB
17215 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV |
17216 NL80211_FLAG_NEED_RTNL),
cb3b7d87
AB
17217 },
17218 {
17219 .cmd = NL80211_CMD_STOP_NAN,
ef6243ac 17220 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
cb3b7d87 17221 .doit = nl80211_stop_nan,
cb3b7d87 17222 .flags = GENL_ADMIN_PERM,
2182db91
JB
17223 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP |
17224 NL80211_FLAG_NEED_RTNL),
a442b761
AB
17225 },
17226 {
17227 .cmd = NL80211_CMD_ADD_NAN_FUNCTION,
ef6243ac 17228 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
a442b761 17229 .doit = nl80211_nan_add_func,
a442b761 17230 .flags = GENL_ADMIN_PERM,
2182db91 17231 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
a442b761
AB
17232 },
17233 {
17234 .cmd = NL80211_CMD_DEL_NAN_FUNCTION,
ef6243ac 17235 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
a442b761 17236 .doit = nl80211_nan_del_func,
a442b761 17237 .flags = GENL_ADMIN_PERM,
2182db91 17238 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
a5a9dcf2
AB
17239 },
17240 {
17241 .cmd = NL80211_CMD_CHANGE_NAN_CONFIG,
ef6243ac 17242 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
a5a9dcf2 17243 .doit = nl80211_nan_change_config,
a5a9dcf2 17244 .flags = GENL_ADMIN_PERM,
2182db91 17245 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
98104fde 17246 },
f4e583c8
AQ
17247 {
17248 .cmd = NL80211_CMD_SET_MCAST_RATE,
ef6243ac 17249 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
f4e583c8 17250 .doit = nl80211_set_mcast_rate,
5617c6cd 17251 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17252 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
77765eaf
VT
17253 },
17254 {
17255 .cmd = NL80211_CMD_SET_MAC_ACL,
ef6243ac 17256 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
77765eaf 17257 .doit = nl80211_set_mac_acl,
5617c6cd 17258 .flags = GENL_UNS_ADMIN_PERM,
7b0a0e3c
JB
17259 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV |
17260 NL80211_FLAG_MLO_UNSUPPORTED),
f4e583c8 17261 },
04f39047
SW
17262 {
17263 .cmd = NL80211_CMD_RADAR_DETECT,
ef6243ac 17264 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
04f39047 17265 .doit = nl80211_start_radar_detection,
5617c6cd 17266 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17267 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
7b0a0e3c
JB
17268 NL80211_FLAG_NO_WIPHY_MTX |
17269 NL80211_FLAG_MLO_UNSUPPORTED),
04f39047 17270 },
3713b4e3
JB
17271 {
17272 .cmd = NL80211_CMD_GET_PROTOCOL_FEATURES,
ef6243ac 17273 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
3713b4e3 17274 .doit = nl80211_get_protocol_features,
3713b4e3 17275 },
355199e0
JM
17276 {
17277 .cmd = NL80211_CMD_UPDATE_FT_IES,
ef6243ac 17278 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
355199e0 17279 .doit = nl80211_update_ft_ies,
5617c6cd 17280 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17281 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
355199e0 17282 },
5de17984
AS
17283 {
17284 .cmd = NL80211_CMD_CRIT_PROTOCOL_START,
ef6243ac 17285 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5de17984 17286 .doit = nl80211_crit_protocol_start,
5617c6cd 17287 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17288 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
5de17984
AS
17289 },
17290 {
17291 .cmd = NL80211_CMD_CRIT_PROTOCOL_STOP,
ef6243ac 17292 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5de17984 17293 .doit = nl80211_crit_protocol_stop,
5617c6cd 17294 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17295 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
be29b99a
AK
17296 },
17297 {
17298 .cmd = NL80211_CMD_GET_COALESCE,
ef6243ac 17299 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
be29b99a 17300 .doit = nl80211_get_coalesce,
2182db91 17301 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY),
be29b99a
AK
17302 },
17303 {
17304 .cmd = NL80211_CMD_SET_COALESCE,
ef6243ac 17305 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
be29b99a 17306 .doit = nl80211_set_coalesce,
5617c6cd 17307 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17308 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY),
16ef1fe2
SW
17309 },
17310 {
17311 .cmd = NL80211_CMD_CHANNEL_SWITCH,
ef6243ac 17312 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
16ef1fe2 17313 .doit = nl80211_channel_switch,
5617c6cd 17314 .flags = GENL_UNS_ADMIN_PERM,
7b0a0e3c
JB
17315 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
17316 NL80211_FLAG_MLO_VALID_LINK_ID),
16ef1fe2 17317 },
ad7e718c
JB
17318 {
17319 .cmd = NL80211_CMD_VENDOR,
ef6243ac 17320 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ad7e718c 17321 .doit = nl80211_vendor_cmd,
7bdbe400 17322 .dumpit = nl80211_vendor_cmd_dump,
5617c6cd 17323 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
17324 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY |
17325 NL80211_FLAG_CLEAR_SKB),
ad7e718c 17326 },
fa9ffc74
KP
17327 {
17328 .cmd = NL80211_CMD_SET_QOS_MAP,
ef6243ac 17329 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
fa9ffc74 17330 .doit = nl80211_set_qos_map,
5617c6cd 17331 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17332 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
fa9ffc74 17333 },
960d01ac
JB
17334 {
17335 .cmd = NL80211_CMD_ADD_TX_TS,
ef6243ac 17336 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
960d01ac 17337 .doit = nl80211_add_tx_ts,
5617c6cd 17338 .flags = GENL_UNS_ADMIN_PERM,
7b0a0e3c
JB
17339 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
17340 NL80211_FLAG_MLO_UNSUPPORTED),
960d01ac
JB
17341 },
17342 {
17343 .cmd = NL80211_CMD_DEL_TX_TS,
ef6243ac 17344 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
960d01ac 17345 .doit = nl80211_del_tx_ts,
5617c6cd 17346 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17347 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
960d01ac 17348 },
1057d35e
AN
17349 {
17350 .cmd = NL80211_CMD_TDLS_CHANNEL_SWITCH,
ef6243ac 17351 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1057d35e 17352 .doit = nl80211_tdls_channel_switch,
5617c6cd 17353 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17354 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
1057d35e
AN
17355 },
17356 {
17357 .cmd = NL80211_CMD_TDLS_CANCEL_CHANNEL_SWITCH,
ef6243ac 17358 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1057d35e 17359 .doit = nl80211_tdls_cancel_channel_switch,
5617c6cd 17360 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17361 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
1057d35e 17362 },
ce0ce13a
MB
17363 {
17364 .cmd = NL80211_CMD_SET_MULTICAST_TO_UNICAST,
ef6243ac 17365 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ce0ce13a 17366 .doit = nl80211_set_multicast_to_unicast,
ce0ce13a 17367 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17368 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
ce0ce13a 17369 },
3a00df57
AS
17370 {
17371 .cmd = NL80211_CMD_SET_PMK,
ef6243ac 17372 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
3a00df57 17373 .doit = nl80211_set_pmk,
2182db91
JB
17374 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
17375 NL80211_FLAG_CLEAR_SKB),
3a00df57
AS
17376 },
17377 {
17378 .cmd = NL80211_CMD_DEL_PMK,
ef6243ac 17379 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
3a00df57 17380 .doit = nl80211_del_pmk,
2182db91 17381 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
3a00df57 17382 },
40cbfa90
SD
17383 {
17384 .cmd = NL80211_CMD_EXTERNAL_AUTH,
ef6243ac 17385 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
40cbfa90 17386 .doit = nl80211_external_auth,
40cbfa90 17387 .flags = GENL_ADMIN_PERM,
2182db91 17388 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
40cbfa90 17389 },
2576a9ac
DK
17390 {
17391 .cmd = NL80211_CMD_CONTROL_PORT_FRAME,
ef6243ac 17392 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2576a9ac 17393 .doit = nl80211_tx_control_port,
2576a9ac 17394 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17395 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
2576a9ac 17396 },
81e54d08
PKC
17397 {
17398 .cmd = NL80211_CMD_GET_FTM_RESPONDER_STATS,
ef6243ac 17399 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
81e54d08 17400 .doit = nl80211_get_ftm_responder_stats,
7b0a0e3c
JB
17401 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV |
17402 NL80211_FLAG_MLO_VALID_LINK_ID),
81e54d08 17403 },
9bb7e0f2
JB
17404 {
17405 .cmd = NL80211_CMD_PEER_MEASUREMENT_START,
ef6243ac 17406 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9bb7e0f2 17407 .doit = nl80211_pmsr_start,
9bb7e0f2 17408 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17409 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
9bb7e0f2 17410 },
30c63115
S
17411 {
17412 .cmd = NL80211_CMD_NOTIFY_RADAR,
ef6243ac 17413 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
30c63115 17414 .doit = nl80211_notify_radar_detection,
30c63115 17415 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17416 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
30c63115 17417 },
cb74e977
SD
17418 {
17419 .cmd = NL80211_CMD_UPDATE_OWE_INFO,
17420 .doit = nl80211_update_owe_info,
17421 .flags = GENL_ADMIN_PERM,
2182db91 17422 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
5ab92e7f
RM
17423 },
17424 {
17425 .cmd = NL80211_CMD_PROBE_MESH_LINK,
17426 .doit = nl80211_probe_mesh_link,
17427 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17428 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
cb74e977 17429 },
77f576de
T
17430 {
17431 .cmd = NL80211_CMD_SET_TID_CONFIG,
17432 .doit = nl80211_set_tid_config,
17433 .flags = GENL_UNS_ADMIN_PERM,
7b0a0e3c
JB
17434 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV |
17435 NL80211_FLAG_MLO_VALID_LINK_ID),
77f576de 17436 },
6bdb68ce
CH
17437 {
17438 .cmd = NL80211_CMD_SET_SAR_SPECS,
17439 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
17440 .doit = nl80211_set_sar_specs,
17441 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
17442 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY |
17443 NL80211_FLAG_NEED_RTNL),
6bdb68ce 17444 },
0d2ab3ae
JC
17445 {
17446 .cmd = NL80211_CMD_COLOR_CHANGE_REQUEST,
17447 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
17448 .doit = nl80211_color_change,
17449 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17450 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
0d2ab3ae 17451 },
e306784a
SM
17452 {
17453 .cmd = NL80211_CMD_SET_FILS_AAD,
17454 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
17455 .doit = nl80211_set_fils_aad,
17456 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17457 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
e306784a 17458 },
7b0a0e3c
JB
17459 {
17460 .cmd = NL80211_CMD_ADD_LINK,
17461 .doit = nl80211_add_link,
17462 .flags = GENL_UNS_ADMIN_PERM,
17463 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
17464 },
17465 {
17466 .cmd = NL80211_CMD_REMOVE_LINK,
17467 .doit = nl80211_remove_link,
17468 .flags = GENL_UNS_ADMIN_PERM,
577e5b8c
ST
17469 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
17470 NL80211_FLAG_MLO_VALID_LINK_ID),
17471 },
17472 {
17473 .cmd = NL80211_CMD_ADD_LINK_STA,
17474 .doit = nl80211_add_link_station,
17475 .flags = GENL_UNS_ADMIN_PERM,
17476 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
17477 NL80211_FLAG_MLO_VALID_LINK_ID),
17478 },
17479 {
17480 .cmd = NL80211_CMD_MODIFY_LINK_STA,
17481 .doit = nl80211_modify_link_station,
17482 .flags = GENL_UNS_ADMIN_PERM,
17483 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
17484 NL80211_FLAG_MLO_VALID_LINK_ID),
17485 },
17486 {
17487 .cmd = NL80211_CMD_REMOVE_LINK_STA,
17488 .doit = nl80211_remove_link_station,
17489 .flags = GENL_UNS_ADMIN_PERM,
7b0a0e3c
JB
17490 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
17491 NL80211_FLAG_MLO_VALID_LINK_ID),
17492 },
cbbaf2bb
AS
17493 {
17494 .cmd = NL80211_CMD_SET_HW_TIMESTAMP,
17495 .doit = nl80211_set_hw_timestamp,
17496 .flags = GENL_UNS_ADMIN_PERM,
17497 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
17498 },
55682965 17499};
9588bbd5 17500
56989f6d 17501static struct genl_family nl80211_fam __ro_after_init = {
489111e5
JB
17502 .name = NL80211_GENL_NAME, /* have users key off the name instead */
17503 .hdrsize = 0, /* no private header */
17504 .version = 1, /* no particular meaning now */
17505 .maxattr = NL80211_ATTR_MAX,
3b0f31f2 17506 .policy = nl80211_policy,
489111e5
JB
17507 .netnsok = true,
17508 .pre_doit = nl80211_pre_doit,
17509 .post_doit = nl80211_post_doit,
17510 .module = THIS_MODULE,
17511 .ops = nl80211_ops,
17512 .n_ops = ARRAY_SIZE(nl80211_ops),
66a9b928
JK
17513 .small_ops = nl80211_small_ops,
17514 .n_small_ops = ARRAY_SIZE(nl80211_small_ops),
9c5d03d3 17515 .resv_start_op = NL80211_CMD_REMOVE_LINK_STA + 1,
489111e5
JB
17516 .mcgrps = nl80211_mcgrps,
17517 .n_mcgrps = ARRAY_SIZE(nl80211_mcgrps),
50508d94 17518 .parallel_ops = true,
489111e5
JB
17519};
17520
55682965
JB
17521/* notification functions */
17522
3bb20556
JB
17523void nl80211_notify_wiphy(struct cfg80211_registered_device *rdev,
17524 enum nl80211_commands cmd)
55682965
JB
17525{
17526 struct sk_buff *msg;
86e8cf98 17527 struct nl80211_dump_wiphy_state state = {};
55682965 17528
3bb20556
JB
17529 WARN_ON(cmd != NL80211_CMD_NEW_WIPHY &&
17530 cmd != NL80211_CMD_DEL_WIPHY);
17531
fd2120ca 17532 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
55682965
JB
17533 if (!msg)
17534 return;
17535
3bb20556 17536 if (nl80211_send_wiphy(rdev, cmd, msg, 0, 0, 0, &state) < 0) {
55682965
JB
17537 nlmsg_free(msg);
17538 return;
17539 }
17540
68eb5503 17541 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17542 NL80211_MCGRP_CONFIG, GFP_KERNEL);
55682965
JB
17543}
17544
896ff063
DK
17545void nl80211_notify_iface(struct cfg80211_registered_device *rdev,
17546 struct wireless_dev *wdev,
17547 enum nl80211_commands cmd)
17548{
17549 struct sk_buff *msg;
17550
896ff063
DK
17551 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
17552 if (!msg)
17553 return;
17554
3d1a5bbf 17555 if (nl80211_send_iface(msg, 0, 0, 0, rdev, wdev, cmd) < 0) {
896ff063
DK
17556 nlmsg_free(msg);
17557 return;
17558 }
17559
17560 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
17561 NL80211_MCGRP_CONFIG, GFP_KERNEL);
17562}
17563
362a415d
JB
17564static int nl80211_add_scan_req(struct sk_buff *msg,
17565 struct cfg80211_registered_device *rdev)
17566{
17567 struct cfg80211_scan_request *req = rdev->scan_req;
17568 struct nlattr *nest;
17569 int i;
c8cb5b85 17570 struct cfg80211_scan_info *info;
362a415d
JB
17571
17572 if (WARN_ON(!req))
17573 return 0;
17574
ae0be8de 17575 nest = nla_nest_start_noflag(msg, NL80211_ATTR_SCAN_SSIDS);
362a415d
JB
17576 if (!nest)
17577 goto nla_put_failure;
9360ffd1
DM
17578 for (i = 0; i < req->n_ssids; i++) {
17579 if (nla_put(msg, i, req->ssids[i].ssid_len, req->ssids[i].ssid))
17580 goto nla_put_failure;
17581 }
362a415d
JB
17582 nla_nest_end(msg, nest);
17583
2032f3b2
TP
17584 if (req->flags & NL80211_SCAN_FLAG_FREQ_KHZ) {
17585 nest = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQ_KHZ);
17586 if (!nest)
17587 goto nla_put_failure;
17588 for (i = 0; i < req->n_channels; i++) {
17589 if (nla_put_u32(msg, i,
17590 ieee80211_channel_to_khz(req->channels[i])))
17591 goto nla_put_failure;
17592 }
17593 nla_nest_end(msg, nest);
17594 } else {
17595 nest = nla_nest_start_noflag(msg,
17596 NL80211_ATTR_SCAN_FREQUENCIES);
17597 if (!nest)
9360ffd1 17598 goto nla_put_failure;
2032f3b2
TP
17599 for (i = 0; i < req->n_channels; i++) {
17600 if (nla_put_u32(msg, i, req->channels[i]->center_freq))
17601 goto nla_put_failure;
17602 }
17603 nla_nest_end(msg, nest);
9360ffd1 17604 }
362a415d 17605
9360ffd1
DM
17606 if (req->ie &&
17607 nla_put(msg, NL80211_ATTR_IE, req->ie_len, req->ie))
17608 goto nla_put_failure;
362a415d 17609
ae917c9f
JB
17610 if (req->flags &&
17611 nla_put_u32(msg, NL80211_ATTR_SCAN_FLAGS, req->flags))
17612 goto nla_put_failure;
ed473771 17613
c8cb5b85
TM
17614 info = rdev->int_scan_req ? &rdev->int_scan_req->info :
17615 &rdev->scan_req->info;
17616 if (info->scan_start_tsf &&
1d76250b 17617 (nla_put_u64_64bit(msg, NL80211_ATTR_SCAN_START_TIME_TSF,
c8cb5b85 17618 info->scan_start_tsf, NL80211_BSS_PAD) ||
1d76250b 17619 nla_put(msg, NL80211_ATTR_SCAN_START_TIME_TSF_BSSID, ETH_ALEN,
c8cb5b85 17620 info->tsf_bssid)))
1d76250b
AS
17621 goto nla_put_failure;
17622
362a415d
JB
17623 return 0;
17624 nla_put_failure:
17625 return -ENOBUFS;
17626}
17627
505a2e88 17628static int nl80211_prep_scan_msg(struct sk_buff *msg,
a538e2d5 17629 struct cfg80211_registered_device *rdev,
fd014284 17630 struct wireless_dev *wdev,
15e47304 17631 u32 portid, u32 seq, int flags,
a538e2d5 17632 u32 cmd)
2a519311
JB
17633{
17634 void *hdr;
17635
15e47304 17636 hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
2a519311
JB
17637 if (!hdr)
17638 return -1;
17639
9360ffd1 17640 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
fd014284
JB
17641 (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
17642 wdev->netdev->ifindex)) ||
2dad624e
ND
17643 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
17644 NL80211_ATTR_PAD))
9360ffd1 17645 goto nla_put_failure;
2a519311 17646
362a415d
JB
17647 /* ignore errors and send incomplete event anyway */
17648 nl80211_add_scan_req(msg, rdev);
2a519311 17649
053c095a
JB
17650 genlmsg_end(msg, hdr);
17651 return 0;
2a519311
JB
17652
17653 nla_put_failure:
17654 genlmsg_cancel(msg, hdr);
17655 return -EMSGSIZE;
17656}
17657
807f8a8c 17658static int
505a2e88 17659nl80211_prep_sched_scan_msg(struct sk_buff *msg,
96b08fd6 17660 struct cfg80211_sched_scan_request *req, u32 cmd)
807f8a8c
LC
17661{
17662 void *hdr;
17663
96b08fd6 17664 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
807f8a8c
LC
17665 if (!hdr)
17666 return -1;
17667
96b08fd6
AVS
17668 if (nla_put_u32(msg, NL80211_ATTR_WIPHY,
17669 wiphy_to_rdev(req->wiphy)->wiphy_idx) ||
17670 nla_put_u32(msg, NL80211_ATTR_IFINDEX, req->dev->ifindex) ||
17671 nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, req->reqid,
17672 NL80211_ATTR_PAD))
9360ffd1 17673 goto nla_put_failure;
807f8a8c 17674
053c095a
JB
17675 genlmsg_end(msg, hdr);
17676 return 0;
807f8a8c
LC
17677
17678 nla_put_failure:
17679 genlmsg_cancel(msg, hdr);
17680 return -EMSGSIZE;
17681}
17682
a538e2d5 17683void nl80211_send_scan_start(struct cfg80211_registered_device *rdev,
fd014284 17684 struct wireless_dev *wdev)
a538e2d5
JB
17685{
17686 struct sk_buff *msg;
17687
58050fce 17688 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
a538e2d5
JB
17689 if (!msg)
17690 return;
17691
505a2e88 17692 if (nl80211_prep_scan_msg(msg, rdev, wdev, 0, 0, 0,
a538e2d5
JB
17693 NL80211_CMD_TRIGGER_SCAN) < 0) {
17694 nlmsg_free(msg);
17695 return;
17696 }
17697
68eb5503 17698 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17699 NL80211_MCGRP_SCAN, GFP_KERNEL);
a538e2d5
JB
17700}
17701
f9d15d16
JB
17702struct sk_buff *nl80211_build_scan_msg(struct cfg80211_registered_device *rdev,
17703 struct wireless_dev *wdev, bool aborted)
2a519311
JB
17704{
17705 struct sk_buff *msg;
17706
fd2120ca 17707 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2a519311 17708 if (!msg)
f9d15d16 17709 return NULL;
2a519311 17710
505a2e88 17711 if (nl80211_prep_scan_msg(msg, rdev, wdev, 0, 0, 0,
f9d15d16
JB
17712 aborted ? NL80211_CMD_SCAN_ABORTED :
17713 NL80211_CMD_NEW_SCAN_RESULTS) < 0) {
2a519311 17714 nlmsg_free(msg);
f9d15d16 17715 return NULL;
2a519311
JB
17716 }
17717
f9d15d16 17718 return msg;
2a519311
JB
17719}
17720
505a2e88
AVS
17721/* send message created by nl80211_build_scan_msg() */
17722void nl80211_send_scan_msg(struct cfg80211_registered_device *rdev,
17723 struct sk_buff *msg)
807f8a8c 17724{
807f8a8c
LC
17725 if (!msg)
17726 return;
17727
68eb5503 17728 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17729 NL80211_MCGRP_SCAN, GFP_KERNEL);
807f8a8c
LC
17730}
17731
96b08fd6 17732void nl80211_send_sched_scan(struct cfg80211_sched_scan_request *req, u32 cmd)
807f8a8c
LC
17733{
17734 struct sk_buff *msg;
17735
58050fce 17736 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
807f8a8c
LC
17737 if (!msg)
17738 return;
17739
96b08fd6 17740 if (nl80211_prep_sched_scan_msg(msg, req, cmd) < 0) {
807f8a8c
LC
17741 nlmsg_free(msg);
17742 return;
17743 }
17744
96b08fd6 17745 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(req->wiphy), msg, 0,
2a94fe48 17746 NL80211_MCGRP_SCAN, GFP_KERNEL);
807f8a8c
LC
17747}
17748
b0d7aa59
JD
17749static bool nl80211_reg_change_event_fill(struct sk_buff *msg,
17750 struct regulatory_request *request)
73d54c9e 17751{
73d54c9e 17752 /* Userspace can always count this one always being set */
9360ffd1
DM
17753 if (nla_put_u8(msg, NL80211_ATTR_REG_INITIATOR, request->initiator))
17754 goto nla_put_failure;
17755
17756 if (request->alpha2[0] == '0' && request->alpha2[1] == '0') {
17757 if (nla_put_u8(msg, NL80211_ATTR_REG_TYPE,
17758 NL80211_REGDOM_TYPE_WORLD))
17759 goto nla_put_failure;
17760 } else if (request->alpha2[0] == '9' && request->alpha2[1] == '9') {
17761 if (nla_put_u8(msg, NL80211_ATTR_REG_TYPE,
17762 NL80211_REGDOM_TYPE_CUSTOM_WORLD))
17763 goto nla_put_failure;
17764 } else if ((request->alpha2[0] == '9' && request->alpha2[1] == '8') ||
17765 request->intersect) {
17766 if (nla_put_u8(msg, NL80211_ATTR_REG_TYPE,
17767 NL80211_REGDOM_TYPE_INTERSECTION))
17768 goto nla_put_failure;
17769 } else {
17770 if (nla_put_u8(msg, NL80211_ATTR_REG_TYPE,
17771 NL80211_REGDOM_TYPE_COUNTRY) ||
17772 nla_put_string(msg, NL80211_ATTR_REG_ALPHA2,
17773 request->alpha2))
17774 goto nla_put_failure;
17775 }
17776
ad30ca2c
AN
17777 if (request->wiphy_idx != WIPHY_IDX_INVALID) {
17778 struct wiphy *wiphy = wiphy_idx_to_wiphy(request->wiphy_idx);
17779
17780 if (wiphy &&
17781 nla_put_u32(msg, NL80211_ATTR_WIPHY, request->wiphy_idx))
17782 goto nla_put_failure;
1bdd716c
AN
17783
17784 if (wiphy &&
17785 wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED &&
17786 nla_put_flag(msg, NL80211_ATTR_WIPHY_SELF_MANAGED_REG))
17787 goto nla_put_failure;
ad30ca2c 17788 }
73d54c9e 17789
b0d7aa59
JD
17790 return true;
17791
17792nla_put_failure:
17793 return false;
17794}
17795
17796/*
17797 * This can happen on global regulatory changes or device specific settings
17798 * based on custom regulatory domains.
17799 */
17800void nl80211_common_reg_change_event(enum nl80211_commands cmd_id,
17801 struct regulatory_request *request)
17802{
17803 struct sk_buff *msg;
17804 void *hdr;
17805
17806 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
17807 if (!msg)
17808 return;
17809
17810 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd_id);
24f6d765 17811 if (!hdr)
17812 goto nla_put_failure;
b0d7aa59 17813
24f6d765 17814 if (!nl80211_reg_change_event_fill(msg, request))
b0d7aa59
JD
17815 goto nla_put_failure;
17816
3b7b72ee 17817 genlmsg_end(msg, hdr);
73d54c9e 17818
bc43b28c 17819 rcu_read_lock();
68eb5503 17820 genlmsg_multicast_allns(&nl80211_fam, msg, 0,
2a94fe48 17821 NL80211_MCGRP_REGULATORY, GFP_ATOMIC);
bc43b28c 17822 rcu_read_unlock();
73d54c9e
LR
17823
17824 return;
17825
17826nla_put_failure:
73d54c9e
LR
17827 nlmsg_free(msg);
17828}
17829
6039f6d2
JM
17830static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev,
17831 struct net_device *netdev,
17832 const u8 *buf, size_t len,
b0b6aa2c 17833 enum nl80211_commands cmd, gfp_t gfp,
4d9ec73d 17834 int uapsd_queues, const u8 *req_ies,
3bb02143 17835 size_t req_ies_len, bool reconnect)
6039f6d2
JM
17836{
17837 struct sk_buff *msg;
17838 void *hdr;
17839
4d9ec73d 17840 msg = nlmsg_new(100 + len + req_ies_len, gfp);
6039f6d2
JM
17841 if (!msg)
17842 return;
17843
17844 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
17845 if (!hdr) {
17846 nlmsg_free(msg);
17847 return;
17848 }
17849
9360ffd1
DM
17850 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
17851 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
4d9ec73d
JM
17852 nla_put(msg, NL80211_ATTR_FRAME, len, buf) ||
17853 (req_ies &&
17854 nla_put(msg, NL80211_ATTR_REQ_IE, req_ies_len, req_ies)))
9360ffd1 17855 goto nla_put_failure;
6039f6d2 17856
3bb02143
JB
17857 if (reconnect && nla_put_flag(msg, NL80211_ATTR_RECONNECT_REQUESTED))
17858 goto nla_put_failure;
17859
b0b6aa2c
EP
17860 if (uapsd_queues >= 0) {
17861 struct nlattr *nla_wmm =
ae0be8de 17862 nla_nest_start_noflag(msg, NL80211_ATTR_STA_WME);
b0b6aa2c
EP
17863 if (!nla_wmm)
17864 goto nla_put_failure;
17865
17866 if (nla_put_u8(msg, NL80211_STA_WME_UAPSD_QUEUES,
17867 uapsd_queues))
17868 goto nla_put_failure;
17869
17870 nla_nest_end(msg, nla_wmm);
17871 }
17872
3b7b72ee 17873 genlmsg_end(msg, hdr);
6039f6d2 17874
68eb5503 17875 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17876 NL80211_MCGRP_MLME, gfp);
6039f6d2
JM
17877 return;
17878
17879 nla_put_failure:
6039f6d2
JM
17880 nlmsg_free(msg);
17881}
17882
17883void nl80211_send_rx_auth(struct cfg80211_registered_device *rdev,
e6d6e342
JB
17884 struct net_device *netdev, const u8 *buf,
17885 size_t len, gfp_t gfp)
6039f6d2
JM
17886{
17887 nl80211_send_mlme_event(rdev, netdev, buf, len,
3bb02143
JB
17888 NL80211_CMD_AUTHENTICATE, gfp, -1, NULL, 0,
17889 false);
6039f6d2
JM
17890}
17891
17892void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev,
cd47c0f5
JB
17893 struct net_device *netdev,
17894 struct cfg80211_rx_assoc_resp *data)
6039f6d2 17895{
cd47c0f5
JB
17896 nl80211_send_mlme_event(rdev, netdev, data->buf, data->len,
17897 NL80211_CMD_ASSOCIATE, GFP_KERNEL,
17898 data->uapsd_queues,
17899 data->req_ies, data->req_ies_len, false);
6039f6d2
JM
17900}
17901
53b46b84 17902void nl80211_send_deauth(struct cfg80211_registered_device *rdev,
e6d6e342 17903 struct net_device *netdev, const u8 *buf,
3bb02143 17904 size_t len, bool reconnect, gfp_t gfp)
6039f6d2
JM
17905{
17906 nl80211_send_mlme_event(rdev, netdev, buf, len,
3bb02143
JB
17907 NL80211_CMD_DEAUTHENTICATE, gfp, -1, NULL, 0,
17908 reconnect);
6039f6d2
JM
17909}
17910
53b46b84
JM
17911void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,
17912 struct net_device *netdev, const u8 *buf,
3bb02143 17913 size_t len, bool reconnect, gfp_t gfp)
6039f6d2
JM
17914{
17915 nl80211_send_mlme_event(rdev, netdev, buf, len,
3bb02143
JB
17916 NL80211_CMD_DISASSOCIATE, gfp, -1, NULL, 0,
17917 reconnect);
6039f6d2
JM
17918}
17919
6ff57cf8
JB
17920void cfg80211_rx_unprot_mlme_mgmt(struct net_device *dev, const u8 *buf,
17921 size_t len)
cf4e594e 17922{
947add36
JB
17923 struct wireless_dev *wdev = dev->ieee80211_ptr;
17924 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 17925 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
6ff57cf8
JB
17926 const struct ieee80211_mgmt *mgmt = (void *)buf;
17927 u32 cmd;
947add36 17928
6ff57cf8
JB
17929 if (WARN_ON(len < 2))
17930 return;
cf4e594e 17931
4d797fce 17932 if (ieee80211_is_deauth(mgmt->frame_control)) {
6ff57cf8 17933 cmd = NL80211_CMD_UNPROT_DEAUTHENTICATE;
4d797fce 17934 } else if (ieee80211_is_disassoc(mgmt->frame_control)) {
6ff57cf8 17935 cmd = NL80211_CMD_UNPROT_DISASSOCIATE;
4d797fce
JM
17936 } else if (ieee80211_is_beacon(mgmt->frame_control)) {
17937 if (wdev->unprot_beacon_reported &&
17938 elapsed_jiffies_msecs(wdev->unprot_beacon_reported) < 10000)
17939 return;
17940 cmd = NL80211_CMD_UNPROT_BEACON;
17941 wdev->unprot_beacon_reported = jiffies;
17942 } else {
17943 return;
17944 }
947add36 17945
6ff57cf8 17946 trace_cfg80211_rx_unprot_mlme_mgmt(dev, buf, len);
4d9ec73d 17947 nl80211_send_mlme_event(rdev, dev, buf, len, cmd, GFP_ATOMIC, -1,
3bb02143 17948 NULL, 0, false);
cf4e594e 17949}
6ff57cf8 17950EXPORT_SYMBOL(cfg80211_rx_unprot_mlme_mgmt);
cf4e594e 17951
1b06bb40
LR
17952static void nl80211_send_mlme_timeout(struct cfg80211_registered_device *rdev,
17953 struct net_device *netdev, int cmd,
e6d6e342 17954 const u8 *addr, gfp_t gfp)
1965c853
JM
17955{
17956 struct sk_buff *msg;
17957 void *hdr;
17958
e6d6e342 17959 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
1965c853
JM
17960 if (!msg)
17961 return;
17962
17963 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
17964 if (!hdr) {
17965 nlmsg_free(msg);
17966 return;
17967 }
17968
9360ffd1
DM
17969 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
17970 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
17971 nla_put_flag(msg, NL80211_ATTR_TIMED_OUT) ||
17972 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr))
17973 goto nla_put_failure;
1965c853 17974
3b7b72ee 17975 genlmsg_end(msg, hdr);
1965c853 17976
68eb5503 17977 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17978 NL80211_MCGRP_MLME, gfp);
1965c853
JM
17979 return;
17980
17981 nla_put_failure:
1965c853
JM
17982 nlmsg_free(msg);
17983}
17984
17985void nl80211_send_auth_timeout(struct cfg80211_registered_device *rdev,
e6d6e342
JB
17986 struct net_device *netdev, const u8 *addr,
17987 gfp_t gfp)
1965c853
JM
17988{
17989 nl80211_send_mlme_timeout(rdev, netdev, NL80211_CMD_AUTHENTICATE,
e6d6e342 17990 addr, gfp);
1965c853
JM
17991}
17992
17993void nl80211_send_assoc_timeout(struct cfg80211_registered_device *rdev,
e6d6e342
JB
17994 struct net_device *netdev, const u8 *addr,
17995 gfp_t gfp)
1965c853 17996{
e6d6e342
JB
17997 nl80211_send_mlme_timeout(rdev, netdev, NL80211_CMD_ASSOCIATE,
17998 addr, gfp);
1965c853
JM
17999}
18000
b23aa676 18001void nl80211_send_connect_result(struct cfg80211_registered_device *rdev,
5349a0f7
VK
18002 struct net_device *netdev,
18003 struct cfg80211_connect_resp_params *cr,
3093ebbe 18004 gfp_t gfp)
b23aa676
SO
18005{
18006 struct sk_buff *msg;
18007 void *hdr;
efbabc11
VJ
18008 unsigned int link;
18009 size_t link_info_size = 0;
18010 const u8 *connected_addr = cr->valid_links ?
18011 cr->ap_mld_addr : cr->links[0].bssid;
18012
18013 if (cr->valid_links) {
18014 for_each_valid_link(cr, link) {
18015 /* Nested attribute header */
18016 link_info_size += NLA_HDRLEN;
18017 /* Link ID */
18018 link_info_size += nla_total_size(sizeof(u8));
18019 link_info_size += cr->links[link].addr ?
18020 nla_total_size(ETH_ALEN) : 0;
18021 link_info_size += (cr->links[link].bssid ||
18022 cr->links[link].bss) ?
18023 nla_total_size(ETH_ALEN) : 0;
53ad07e9 18024 link_info_size += nla_total_size(sizeof(u16));
efbabc11
VJ
18025 }
18026 }
b23aa676 18027
a3caf744 18028 msg = nlmsg_new(100 + cr->req_ie_len + cr->resp_ie_len +
76804d28 18029 cr->fils.kek_len + cr->fils.pmk_len +
efbabc11
VJ
18030 (cr->fils.pmkid ? WLAN_PMKID_LEN : 0) + link_info_size,
18031 gfp);
b23aa676
SO
18032 if (!msg)
18033 return;
18034
18035 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CONNECT);
18036 if (!hdr) {
18037 nlmsg_free(msg);
18038 return;
18039 }
18040
9360ffd1
DM
18041 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
18042 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
efbabc11
VJ
18043 (connected_addr &&
18044 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, connected_addr)) ||
bf1ecd21 18045 nla_put_u16(msg, NL80211_ATTR_STATUS_CODE,
5349a0f7
VK
18046 cr->status < 0 ? WLAN_STATUS_UNSPECIFIED_FAILURE :
18047 cr->status) ||
18048 (cr->status < 0 &&
3093ebbe 18049 (nla_put_flag(msg, NL80211_ATTR_TIMED_OUT) ||
5349a0f7
VK
18050 nla_put_u32(msg, NL80211_ATTR_TIMEOUT_REASON,
18051 cr->timeout_reason))) ||
18052 (cr->req_ie &&
18053 nla_put(msg, NL80211_ATTR_REQ_IE, cr->req_ie_len, cr->req_ie)) ||
18054 (cr->resp_ie &&
18055 nla_put(msg, NL80211_ATTR_RESP_IE, cr->resp_ie_len,
a3caf744 18056 cr->resp_ie)) ||
76804d28 18057 (cr->fils.update_erp_next_seq_num &&
a3caf744 18058 nla_put_u16(msg, NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM,
76804d28 18059 cr->fils.erp_next_seq_num)) ||
a3caf744 18060 (cr->status == WLAN_STATUS_SUCCESS &&
76804d28
AVS
18061 ((cr->fils.kek &&
18062 nla_put(msg, NL80211_ATTR_FILS_KEK, cr->fils.kek_len,
18063 cr->fils.kek)) ||
18064 (cr->fils.pmk &&
18065 nla_put(msg, NL80211_ATTR_PMK, cr->fils.pmk_len, cr->fils.pmk)) ||
18066 (cr->fils.pmkid &&
18067 nla_put(msg, NL80211_ATTR_PMKID, WLAN_PMKID_LEN, cr->fils.pmkid)))))
9360ffd1 18068 goto nla_put_failure;
b23aa676 18069
efbabc11
VJ
18070 if (cr->valid_links) {
18071 int i = 1;
18072 struct nlattr *nested;
18073
18074 nested = nla_nest_start(msg, NL80211_ATTR_MLO_LINKS);
18075 if (!nested)
18076 goto nla_put_failure;
18077
18078 for_each_valid_link(cr, link) {
18079 struct nlattr *nested_mlo_links;
18080 const u8 *bssid = cr->links[link].bss ?
18081 cr->links[link].bss->bssid :
18082 cr->links[link].bssid;
18083
18084 nested_mlo_links = nla_nest_start(msg, i);
18085 if (!nested_mlo_links)
18086 goto nla_put_failure;
18087
18088 if (nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link) ||
18089 (bssid &&
18090 nla_put(msg, NL80211_ATTR_BSSID, ETH_ALEN, bssid)) ||
18091 (cr->links[link].addr &&
18092 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN,
53ad07e9
JB
18093 cr->links[link].addr)) ||
18094 nla_put_u16(msg, NL80211_ATTR_STATUS_CODE,
18095 cr->links[link].status))
efbabc11
VJ
18096 goto nla_put_failure;
18097
18098 nla_nest_end(msg, nested_mlo_links);
18099 i++;
18100 }
18101 nla_nest_end(msg, nested);
18102 }
18103
3b7b72ee 18104 genlmsg_end(msg, hdr);
b23aa676 18105
68eb5503 18106 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18107 NL80211_MCGRP_MLME, gfp);
b23aa676
SO
18108 return;
18109
18110 nla_put_failure:
b23aa676 18111 nlmsg_free(msg);
b23aa676
SO
18112}
18113
18114void nl80211_send_roamed(struct cfg80211_registered_device *rdev,
29ce6ecb
AS
18115 struct net_device *netdev,
18116 struct cfg80211_roam_info *info, gfp_t gfp)
b23aa676
SO
18117{
18118 struct sk_buff *msg;
18119 void *hdr;
efbabc11
VJ
18120 size_t link_info_size = 0;
18121 unsigned int link;
18122 const u8 *connected_addr = info->ap_mld_addr ?
18123 info->ap_mld_addr :
18124 (info->links[0].bss ?
18125 info->links[0].bss->bssid :
18126 info->links[0].bssid);
18127
18128 if (info->valid_links) {
18129 for_each_valid_link(info, link) {
18130 /* Nested attribute header */
18131 link_info_size += NLA_HDRLEN;
18132 /* Link ID */
18133 link_info_size += nla_total_size(sizeof(u8));
18134 link_info_size += info->links[link].addr ?
18135 nla_total_size(ETH_ALEN) : 0;
18136 link_info_size += (info->links[link].bssid ||
18137 info->links[link].bss) ?
18138 nla_total_size(ETH_ALEN) : 0;
18139 }
18140 }
b23aa676 18141
e841b7b1
AVS
18142 msg = nlmsg_new(100 + info->req_ie_len + info->resp_ie_len +
18143 info->fils.kek_len + info->fils.pmk_len +
efbabc11
VJ
18144 (info->fils.pmkid ? WLAN_PMKID_LEN : 0) +
18145 link_info_size, gfp);
b23aa676
SO
18146 if (!msg)
18147 return;
18148
18149 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_ROAM);
18150 if (!hdr) {
18151 nlmsg_free(msg);
18152 return;
18153 }
18154
9360ffd1
DM
18155 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
18156 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
efbabc11 18157 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, connected_addr) ||
29ce6ecb
AS
18158 (info->req_ie &&
18159 nla_put(msg, NL80211_ATTR_REQ_IE, info->req_ie_len,
18160 info->req_ie)) ||
18161 (info->resp_ie &&
18162 nla_put(msg, NL80211_ATTR_RESP_IE, info->resp_ie_len,
e841b7b1
AVS
18163 info->resp_ie)) ||
18164 (info->fils.update_erp_next_seq_num &&
18165 nla_put_u16(msg, NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM,
18166 info->fils.erp_next_seq_num)) ||
18167 (info->fils.kek &&
18168 nla_put(msg, NL80211_ATTR_FILS_KEK, info->fils.kek_len,
18169 info->fils.kek)) ||
18170 (info->fils.pmk &&
18171 nla_put(msg, NL80211_ATTR_PMK, info->fils.pmk_len, info->fils.pmk)) ||
18172 (info->fils.pmkid &&
18173 nla_put(msg, NL80211_ATTR_PMKID, WLAN_PMKID_LEN, info->fils.pmkid)))
9360ffd1 18174 goto nla_put_failure;
b23aa676 18175
efbabc11
VJ
18176 if (info->valid_links) {
18177 int i = 1;
18178 struct nlattr *nested;
18179
18180 nested = nla_nest_start(msg, NL80211_ATTR_MLO_LINKS);
18181 if (!nested)
18182 goto nla_put_failure;
18183
18184 for_each_valid_link(info, link) {
18185 struct nlattr *nested_mlo_links;
18186 const u8 *bssid = info->links[link].bss ?
18187 info->links[link].bss->bssid :
18188 info->links[link].bssid;
18189
18190 nested_mlo_links = nla_nest_start(msg, i);
18191 if (!nested_mlo_links)
18192 goto nla_put_failure;
18193
18194 if (nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link) ||
18195 (bssid &&
18196 nla_put(msg, NL80211_ATTR_BSSID, ETH_ALEN, bssid)) ||
18197 (info->links[link].addr &&
18198 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN,
18199 info->links[link].addr)))
18200 goto nla_put_failure;
18201
18202 nla_nest_end(msg, nested_mlo_links);
18203 i++;
18204 }
18205 nla_nest_end(msg, nested);
18206 }
18207
3b7b72ee 18208 genlmsg_end(msg, hdr);
b23aa676 18209
68eb5503 18210 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18211 NL80211_MCGRP_MLME, gfp);
b23aa676
SO
18212 return;
18213
503c1fb9 18214 nla_put_failure:
503c1fb9
AS
18215 nlmsg_free(msg);
18216}
18217
18218void nl80211_send_port_authorized(struct cfg80211_registered_device *rdev,
0ff57171
VY
18219 struct net_device *netdev, const u8 *bssid,
18220 const u8 *td_bitmap, u8 td_bitmap_len)
503c1fb9
AS
18221{
18222 struct sk_buff *msg;
18223 void *hdr;
18224
18225 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
18226 if (!msg)
18227 return;
18228
18229 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_PORT_AUTHORIZED);
18230 if (!hdr) {
18231 nlmsg_free(msg);
18232 return;
18233 }
18234
f4d75993
CHH
18235 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
18236 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
18237 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid))
503c1fb9
AS
18238 goto nla_put_failure;
18239
0ff57171
VY
18240 if ((td_bitmap_len > 0) && td_bitmap)
18241 if (nla_put(msg, NL80211_ATTR_TD_BITMAP,
18242 td_bitmap_len, td_bitmap))
18243 goto nla_put_failure;
18244
503c1fb9
AS
18245 genlmsg_end(msg, hdr);
18246
18247 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
18248 NL80211_MCGRP_MLME, GFP_KERNEL);
18249 return;
18250
b23aa676 18251 nla_put_failure:
b23aa676 18252 nlmsg_free(msg);
b23aa676
SO
18253}
18254
18255void nl80211_send_disconnected(struct cfg80211_registered_device *rdev,
18256 struct net_device *netdev, u16 reason,
667503dd 18257 const u8 *ie, size_t ie_len, bool from_ap)
b23aa676
SO
18258{
18259 struct sk_buff *msg;
18260 void *hdr;
18261
4ef8c1c9 18262 msg = nlmsg_new(100 + ie_len, GFP_KERNEL);
b23aa676
SO
18263 if (!msg)
18264 return;
18265
18266 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_DISCONNECT);
18267 if (!hdr) {
18268 nlmsg_free(msg);
18269 return;
18270 }
18271
9360ffd1
DM
18272 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
18273 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
86b6c465 18274 (reason &&
9360ffd1
DM
18275 nla_put_u16(msg, NL80211_ATTR_REASON_CODE, reason)) ||
18276 (from_ap &&
18277 nla_put_flag(msg, NL80211_ATTR_DISCONNECTED_BY_AP)) ||
18278 (ie && nla_put(msg, NL80211_ATTR_IE, ie_len, ie)))
18279 goto nla_put_failure;
b23aa676 18280
3b7b72ee 18281 genlmsg_end(msg, hdr);
b23aa676 18282
68eb5503 18283 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18284 NL80211_MCGRP_MLME, GFP_KERNEL);
b23aa676
SO
18285 return;
18286
18287 nla_put_failure:
b23aa676 18288 nlmsg_free(msg);
b23aa676
SO
18289}
18290
065563b2
VJ
18291void cfg80211_links_removed(struct net_device *dev, u16 link_mask)
18292{
18293 struct wireless_dev *wdev = dev->ieee80211_ptr;
18294 struct wiphy *wiphy = wdev->wiphy;
18295 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
18296 struct sk_buff *msg;
18297 struct nlattr *links;
18298 void *hdr;
18299
18300 ASSERT_WDEV_LOCK(wdev);
18301 trace_cfg80211_links_removed(dev, link_mask);
18302
18303 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION &&
18304 wdev->iftype != NL80211_IFTYPE_P2P_CLIENT))
18305 return;
18306
18307 if (WARN_ON(!wdev->valid_links || !link_mask ||
18308 (wdev->valid_links & link_mask) != link_mask ||
18309 wdev->valid_links == link_mask))
18310 return;
18311
18312 cfg80211_wdev_release_link_bsses(wdev, link_mask);
18313 wdev->valid_links &= ~link_mask;
18314
18315 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
18316 if (!msg)
18317 return;
18318
18319 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_LINKS_REMOVED);
18320 if (!hdr) {
18321 nlmsg_free(msg);
18322 return;
18323 }
18324
18325 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
18326 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
18327 goto nla_put_failure;
18328
18329 links = nla_nest_start(msg, NL80211_ATTR_MLO_LINKS);
18330 if (!links)
18331 goto nla_put_failure;
18332
18333 while (link_mask) {
18334 struct nlattr *link;
18335 int link_id = __ffs(link_mask);
18336
18337 link = nla_nest_start(msg, link_id + 1);
18338 if (!link)
18339 goto nla_put_failure;
18340
18341 if (nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id))
18342 goto nla_put_failure;
18343
18344 nla_nest_end(msg, link);
18345 link_mask &= ~(1 << link_id);
18346 }
18347
18348 nla_nest_end(msg, links);
18349
18350 genlmsg_end(msg, hdr);
18351
18352 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
18353 NL80211_MCGRP_MLME, GFP_KERNEL);
18354 return;
18355
18356 nla_put_failure:
18357 nlmsg_free(msg);
18358}
18359EXPORT_SYMBOL(cfg80211_links_removed);
18360
04a773ad
JB
18361void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev,
18362 struct net_device *netdev, const u8 *bssid,
18363 gfp_t gfp)
18364{
18365 struct sk_buff *msg;
18366 void *hdr;
18367
fd2120ca 18368 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
04a773ad
JB
18369 if (!msg)
18370 return;
18371
18372 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_JOIN_IBSS);
18373 if (!hdr) {
18374 nlmsg_free(msg);
18375 return;
18376 }
18377
9360ffd1
DM
18378 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
18379 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
18380 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid))
18381 goto nla_put_failure;
04a773ad 18382
3b7b72ee 18383 genlmsg_end(msg, hdr);
04a773ad 18384
68eb5503 18385 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18386 NL80211_MCGRP_MLME, gfp);
04a773ad
JB
18387 return;
18388
18389 nla_put_failure:
04a773ad
JB
18390 nlmsg_free(msg);
18391}
18392
947add36 18393void cfg80211_notify_new_peer_candidate(struct net_device *dev, const u8 *addr,
ecbc12ad
BC
18394 const u8 *ie, u8 ie_len,
18395 int sig_dbm, gfp_t gfp)
c93b5e71 18396{
947add36 18397 struct wireless_dev *wdev = dev->ieee80211_ptr;
f26cbf40 18398 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
c93b5e71
JC
18399 struct sk_buff *msg;
18400 void *hdr;
18401
947add36
JB
18402 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_MESH_POINT))
18403 return;
18404
18405 trace_cfg80211_notify_new_peer_candidate(dev, addr);
18406
4ef8c1c9 18407 msg = nlmsg_new(100 + ie_len, gfp);
c93b5e71
JC
18408 if (!msg)
18409 return;
18410
18411 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NEW_PEER_CANDIDATE);
18412 if (!hdr) {
18413 nlmsg_free(msg);
18414 return;
18415 }
18416
9360ffd1 18417 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
947add36
JB
18418 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
18419 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
9360ffd1 18420 (ie_len && ie &&
ecbc12ad
BC
18421 nla_put(msg, NL80211_ATTR_IE, ie_len, ie)) ||
18422 (sig_dbm &&
18423 nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)))
9360ffd1 18424 goto nla_put_failure;
c93b5e71 18425
3b7b72ee 18426 genlmsg_end(msg, hdr);
c93b5e71 18427
68eb5503 18428 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18429 NL80211_MCGRP_MLME, gfp);
c93b5e71
JC
18430 return;
18431
18432 nla_put_failure:
c93b5e71
JC
18433 nlmsg_free(msg);
18434}
947add36 18435EXPORT_SYMBOL(cfg80211_notify_new_peer_candidate);
c93b5e71 18436
a3b8b056
JM
18437void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev,
18438 struct net_device *netdev, const u8 *addr,
18439 enum nl80211_key_type key_type, int key_id,
e6d6e342 18440 const u8 *tsc, gfp_t gfp)
a3b8b056
JM
18441{
18442 struct sk_buff *msg;
18443 void *hdr;
18444
e6d6e342 18445 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
a3b8b056
JM
18446 if (!msg)
18447 return;
18448
18449 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_MICHAEL_MIC_FAILURE);
18450 if (!hdr) {
18451 nlmsg_free(msg);
18452 return;
18453 }
18454
9360ffd1
DM
18455 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
18456 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
18457 (addr && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) ||
18458 nla_put_u32(msg, NL80211_ATTR_KEY_TYPE, key_type) ||
18459 (key_id != -1 &&
18460 nla_put_u8(msg, NL80211_ATTR_KEY_IDX, key_id)) ||
18461 (tsc && nla_put(msg, NL80211_ATTR_KEY_SEQ, 6, tsc)))
18462 goto nla_put_failure;
a3b8b056 18463
3b7b72ee 18464 genlmsg_end(msg, hdr);
a3b8b056 18465
68eb5503 18466 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18467 NL80211_MCGRP_MLME, gfp);
a3b8b056
JM
18468 return;
18469
18470 nla_put_failure:
a3b8b056
JM
18471 nlmsg_free(msg);
18472}
18473
6bad8766
LR
18474void nl80211_send_beacon_hint_event(struct wiphy *wiphy,
18475 struct ieee80211_channel *channel_before,
18476 struct ieee80211_channel *channel_after)
18477{
18478 struct sk_buff *msg;
18479 void *hdr;
18480 struct nlattr *nl_freq;
18481
fd2120ca 18482 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
6bad8766
LR
18483 if (!msg)
18484 return;
18485
18486 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_REG_BEACON_HINT);
18487 if (!hdr) {
18488 nlmsg_free(msg);
18489 return;
18490 }
18491
18492 /*
18493 * Since we are applying the beacon hint to a wiphy we know its
18494 * wiphy_idx is valid
18495 */
9360ffd1
DM
18496 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, get_wiphy_idx(wiphy)))
18497 goto nla_put_failure;
6bad8766
LR
18498
18499 /* Before */
ae0be8de 18500 nl_freq = nla_nest_start_noflag(msg, NL80211_ATTR_FREQ_BEFORE);
6bad8766
LR
18501 if (!nl_freq)
18502 goto nla_put_failure;
50f32718
HD
18503
18504 if (nl80211_msg_put_channel(msg, wiphy, channel_before, false))
6bad8766
LR
18505 goto nla_put_failure;
18506 nla_nest_end(msg, nl_freq);
18507
18508 /* After */
ae0be8de 18509 nl_freq = nla_nest_start_noflag(msg, NL80211_ATTR_FREQ_AFTER);
6bad8766
LR
18510 if (!nl_freq)
18511 goto nla_put_failure;
50f32718
HD
18512
18513 if (nl80211_msg_put_channel(msg, wiphy, channel_after, false))
6bad8766
LR
18514 goto nla_put_failure;
18515 nla_nest_end(msg, nl_freq);
18516
3b7b72ee 18517 genlmsg_end(msg, hdr);
6bad8766 18518
463d0183 18519 rcu_read_lock();
68eb5503 18520 genlmsg_multicast_allns(&nl80211_fam, msg, 0,
2a94fe48 18521 NL80211_MCGRP_REGULATORY, GFP_ATOMIC);
463d0183 18522 rcu_read_unlock();
6bad8766
LR
18523
18524 return;
18525
18526nla_put_failure:
6bad8766
LR
18527 nlmsg_free(msg);
18528}
18529
9588bbd5
JM
18530static void nl80211_send_remain_on_chan_event(
18531 int cmd, struct cfg80211_registered_device *rdev,
71bbc994 18532 struct wireless_dev *wdev, u64 cookie,
9588bbd5 18533 struct ieee80211_channel *chan,
9588bbd5
JM
18534 unsigned int duration, gfp_t gfp)
18535{
18536 struct sk_buff *msg;
18537 void *hdr;
18538
18539 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
18540 if (!msg)
18541 return;
18542
18543 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
18544 if (!hdr) {
18545 nlmsg_free(msg);
18546 return;
18547 }
18548
9360ffd1 18549 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
71bbc994
JB
18550 (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
18551 wdev->netdev->ifindex)) ||
2dad624e
ND
18552 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
18553 NL80211_ATTR_PAD) ||
9360ffd1 18554 nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, chan->center_freq) ||
42d97a59
JB
18555 nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
18556 NL80211_CHAN_NO_HT) ||
2dad624e
ND
18557 nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
18558 NL80211_ATTR_PAD))
9360ffd1 18559 goto nla_put_failure;
9588bbd5 18560
9360ffd1
DM
18561 if (cmd == NL80211_CMD_REMAIN_ON_CHANNEL &&
18562 nla_put_u32(msg, NL80211_ATTR_DURATION, duration))
18563 goto nla_put_failure;
9588bbd5 18564
3b7b72ee 18565 genlmsg_end(msg, hdr);
9588bbd5 18566
68eb5503 18567 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18568 NL80211_MCGRP_MLME, gfp);
9588bbd5
JM
18569 return;
18570
18571 nla_put_failure:
9588bbd5
JM
18572 nlmsg_free(msg);
18573}
18574
a083ee8a 18575void cfg80211_assoc_comeback(struct net_device *netdev,
e69dac88 18576 const u8 *ap_addr, u32 timeout)
a083ee8a
IP
18577{
18578 struct wireless_dev *wdev = netdev->ieee80211_ptr;
18579 struct wiphy *wiphy = wdev->wiphy;
18580 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
18581 struct sk_buff *msg;
18582 void *hdr;
18583
e69dac88 18584 trace_cfg80211_assoc_comeback(wdev, ap_addr, timeout);
a083ee8a
IP
18585
18586 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
18587 if (!msg)
18588 return;
18589
18590 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_ASSOC_COMEBACK);
18591 if (!hdr) {
18592 nlmsg_free(msg);
18593 return;
18594 }
18595
18596 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
18597 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
e69dac88 18598 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, ap_addr) ||
a083ee8a
IP
18599 nla_put_u32(msg, NL80211_ATTR_TIMEOUT, timeout))
18600 goto nla_put_failure;
18601
18602 genlmsg_end(msg, hdr);
18603
18604 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
18605 NL80211_MCGRP_MLME, GFP_KERNEL);
18606 return;
18607
18608 nla_put_failure:
18609 nlmsg_free(msg);
18610}
18611EXPORT_SYMBOL(cfg80211_assoc_comeback);
18612
947add36
JB
18613void cfg80211_ready_on_channel(struct wireless_dev *wdev, u64 cookie,
18614 struct ieee80211_channel *chan,
18615 unsigned int duration, gfp_t gfp)
9588bbd5 18616{
947add36 18617 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 18618 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
947add36
JB
18619
18620 trace_cfg80211_ready_on_channel(wdev, cookie, chan, duration);
9588bbd5 18621 nl80211_send_remain_on_chan_event(NL80211_CMD_REMAIN_ON_CHANNEL,
71bbc994 18622 rdev, wdev, cookie, chan,
42d97a59 18623 duration, gfp);
9588bbd5 18624}
947add36 18625EXPORT_SYMBOL(cfg80211_ready_on_channel);
9588bbd5 18626
947add36
JB
18627void cfg80211_remain_on_channel_expired(struct wireless_dev *wdev, u64 cookie,
18628 struct ieee80211_channel *chan,
18629 gfp_t gfp)
9588bbd5 18630{
947add36 18631 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 18632 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
947add36
JB
18633
18634 trace_cfg80211_ready_on_channel_expired(wdev, cookie, chan);
9588bbd5 18635 nl80211_send_remain_on_chan_event(NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL,
42d97a59 18636 rdev, wdev, cookie, chan, 0, gfp);
9588bbd5 18637}
947add36 18638EXPORT_SYMBOL(cfg80211_remain_on_channel_expired);
9588bbd5 18639
1c38c7f2
JP
18640void cfg80211_tx_mgmt_expired(struct wireless_dev *wdev, u64 cookie,
18641 struct ieee80211_channel *chan,
18642 gfp_t gfp)
18643{
18644 struct wiphy *wiphy = wdev->wiphy;
18645 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
18646
18647 trace_cfg80211_tx_mgmt_expired(wdev, cookie, chan);
18648 nl80211_send_remain_on_chan_event(NL80211_CMD_FRAME_WAIT_CANCEL,
18649 rdev, wdev, cookie, chan, 0, gfp);
18650}
18651EXPORT_SYMBOL(cfg80211_tx_mgmt_expired);
18652
947add36
JB
18653void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr,
18654 struct station_info *sinfo, gfp_t gfp)
98b62183 18655{
947add36 18656 struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
f26cbf40 18657 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
98b62183
JB
18658 struct sk_buff *msg;
18659
947add36
JB
18660 trace_cfg80211_new_sta(dev, mac_addr, sinfo);
18661
58050fce 18662 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
98b62183
JB
18663 if (!msg)
18664 return;
18665
cf5ead82 18666 if (nl80211_send_station(msg, NL80211_CMD_NEW_STATION, 0, 0, 0,
66266b3a 18667 rdev, dev, mac_addr, sinfo) < 0) {
98b62183
JB
18668 nlmsg_free(msg);
18669 return;
18670 }
18671
68eb5503 18672 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18673 NL80211_MCGRP_MLME, gfp);
98b62183 18674}
947add36 18675EXPORT_SYMBOL(cfg80211_new_sta);
98b62183 18676
cf5ead82
JB
18677void cfg80211_del_sta_sinfo(struct net_device *dev, const u8 *mac_addr,
18678 struct station_info *sinfo, gfp_t gfp)
ec15e68b 18679{
947add36 18680 struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
f26cbf40 18681 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
ec15e68b 18682 struct sk_buff *msg;
73887fd9 18683 struct station_info empty_sinfo = {};
cf5ead82 18684
73887fd9
JB
18685 if (!sinfo)
18686 sinfo = &empty_sinfo;
ec15e68b 18687
947add36
JB
18688 trace_cfg80211_del_sta(dev, mac_addr);
18689
58050fce 18690 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
7ea3e110
JB
18691 if (!msg) {
18692 cfg80211_sinfo_release_content(sinfo);
73887fd9 18693 return;
7ea3e110 18694 }
ec15e68b 18695
cf5ead82 18696 if (nl80211_send_station(msg, NL80211_CMD_DEL_STATION, 0, 0, 0,
57007121 18697 rdev, dev, mac_addr, sinfo) < 0) {
ec15e68b 18698 nlmsg_free(msg);
73887fd9 18699 return;
ec15e68b
JM
18700 }
18701
68eb5503 18702 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18703 NL80211_MCGRP_MLME, gfp);
ec15e68b 18704}
cf5ead82 18705EXPORT_SYMBOL(cfg80211_del_sta_sinfo);
ec15e68b 18706
947add36
JB
18707void cfg80211_conn_failed(struct net_device *dev, const u8 *mac_addr,
18708 enum nl80211_connect_failed_reason reason,
18709 gfp_t gfp)
ed44a951 18710{
947add36 18711 struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
f26cbf40 18712 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
ed44a951
PP
18713 struct sk_buff *msg;
18714 void *hdr;
18715
18716 msg = nlmsg_new(NLMSG_GOODSIZE, gfp);
18717 if (!msg)
18718 return;
18719
18720 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CONN_FAILED);
18721 if (!hdr) {
18722 nlmsg_free(msg);
18723 return;
18724 }
18725
18726 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
18727 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr) ||
18728 nla_put_u32(msg, NL80211_ATTR_CONN_FAILED_REASON, reason))
18729 goto nla_put_failure;
18730
18731 genlmsg_end(msg, hdr);
18732
68eb5503 18733 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18734 NL80211_MCGRP_MLME, gfp);
ed44a951
PP
18735 return;
18736
18737 nla_put_failure:
ed44a951
PP
18738 nlmsg_free(msg);
18739}
947add36 18740EXPORT_SYMBOL(cfg80211_conn_failed);
ed44a951 18741
b92ab5d8
JB
18742static bool __nl80211_unexpected_frame(struct net_device *dev, u8 cmd,
18743 const u8 *addr, gfp_t gfp)
28946da7
JB
18744{
18745 struct wireless_dev *wdev = dev->ieee80211_ptr;
f26cbf40 18746 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
28946da7
JB
18747 struct sk_buff *msg;
18748 void *hdr;
6aa7de05 18749 u32 nlportid = READ_ONCE(wdev->ap_unexpected_nlportid);
28946da7 18750
15e47304 18751 if (!nlportid)
28946da7
JB
18752 return false;
18753
18754 msg = nlmsg_new(100, gfp);
18755 if (!msg)
18756 return true;
18757
b92ab5d8 18758 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
28946da7
JB
18759 if (!hdr) {
18760 nlmsg_free(msg);
18761 return true;
18762 }
18763
9360ffd1
DM
18764 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
18765 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
18766 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr))
18767 goto nla_put_failure;
28946da7 18768
9c90a9f6 18769 genlmsg_end(msg, hdr);
15e47304 18770 genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid);
28946da7
JB
18771 return true;
18772
18773 nla_put_failure:
28946da7
JB
18774 nlmsg_free(msg);
18775 return true;
18776}
18777
947add36
JB
18778bool cfg80211_rx_spurious_frame(struct net_device *dev,
18779 const u8 *addr, gfp_t gfp)
b92ab5d8 18780{
947add36
JB
18781 struct wireless_dev *wdev = dev->ieee80211_ptr;
18782 bool ret;
18783
18784 trace_cfg80211_rx_spurious_frame(dev, addr);
18785
18786 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
18787 wdev->iftype != NL80211_IFTYPE_P2P_GO)) {
18788 trace_cfg80211_return_bool(false);
18789 return false;
18790 }
18791 ret = __nl80211_unexpected_frame(dev, NL80211_CMD_UNEXPECTED_FRAME,
18792 addr, gfp);
18793 trace_cfg80211_return_bool(ret);
18794 return ret;
b92ab5d8 18795}
947add36 18796EXPORT_SYMBOL(cfg80211_rx_spurious_frame);
b92ab5d8 18797
947add36
JB
18798bool cfg80211_rx_unexpected_4addr_frame(struct net_device *dev,
18799 const u8 *addr, gfp_t gfp)
b92ab5d8 18800{
947add36
JB
18801 struct wireless_dev *wdev = dev->ieee80211_ptr;
18802 bool ret;
18803
18804 trace_cfg80211_rx_unexpected_4addr_frame(dev, addr);
18805
18806 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
18807 wdev->iftype != NL80211_IFTYPE_P2P_GO &&
18808 wdev->iftype != NL80211_IFTYPE_AP_VLAN)) {
18809 trace_cfg80211_return_bool(false);
18810 return false;
18811 }
18812 ret = __nl80211_unexpected_frame(dev,
18813 NL80211_CMD_UNEXPECTED_4ADDR_FRAME,
18814 addr, gfp);
18815 trace_cfg80211_return_bool(ret);
18816 return ret;
b92ab5d8 18817}
947add36 18818EXPORT_SYMBOL(cfg80211_rx_unexpected_4addr_frame);
b92ab5d8 18819
2e161f78 18820int nl80211_send_mgmt(struct cfg80211_registered_device *rdev,
15e47304 18821 struct wireless_dev *wdev, u32 nlportid,
00b3d840 18822 struct cfg80211_rx_info *info, gfp_t gfp)
026331c4 18823{
71bbc994 18824 struct net_device *netdev = wdev->netdev;
026331c4
JM
18825 struct sk_buff *msg;
18826 void *hdr;
026331c4 18827
00b3d840 18828 msg = nlmsg_new(100 + info->len, gfp);
026331c4
JM
18829 if (!msg)
18830 return -ENOMEM;
18831
2e161f78 18832 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FRAME);
026331c4
JM
18833 if (!hdr) {
18834 nlmsg_free(msg);
18835 return -ENOMEM;
18836 }
18837
9360ffd1 18838 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
71bbc994
JB
18839 (netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
18840 netdev->ifindex)) ||
2dad624e
ND
18841 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
18842 NL80211_ATTR_PAD) ||
6074c9e5
JB
18843 (info->have_link_id &&
18844 nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, info->link_id)) ||
00b3d840
AS
18845 nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, KHZ_TO_MHZ(info->freq)) ||
18846 nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ_OFFSET, info->freq % 1000) ||
18847 (info->sig_dbm &&
18848 nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, info->sig_dbm)) ||
18849 nla_put(msg, NL80211_ATTR_FRAME, info->len, info->buf) ||
18850 (info->flags &&
1ff715ff
AS
18851 nla_put_u32(msg, NL80211_ATTR_RXMGMT_FLAGS, info->flags)) ||
18852 (info->rx_tstamp && nla_put_u64_64bit(msg,
18853 NL80211_ATTR_RX_HW_TIMESTAMP,
18854 info->rx_tstamp,
18855 NL80211_ATTR_PAD)) ||
18856 (info->ack_tstamp && nla_put_u64_64bit(msg,
18857 NL80211_ATTR_TX_HW_TIMESTAMP,
18858 info->ack_tstamp,
18859 NL80211_ATTR_PAD)))
9360ffd1 18860 goto nla_put_failure;
026331c4 18861
3b7b72ee 18862 genlmsg_end(msg, hdr);
026331c4 18863
15e47304 18864 return genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid);
026331c4
JM
18865
18866 nla_put_failure:
026331c4
JM
18867 nlmsg_free(msg);
18868 return -ENOBUFS;
18869}
18870
ea7d50c9
AS
18871static void nl80211_frame_tx_status(struct wireless_dev *wdev,
18872 struct cfg80211_tx_status *status,
dca9ca2d 18873 gfp_t gfp, enum nl80211_commands command)
026331c4 18874{
947add36 18875 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 18876 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
71bbc994 18877 struct net_device *netdev = wdev->netdev;
026331c4
JM
18878 struct sk_buff *msg;
18879 void *hdr;
18880
dca9ca2d 18881 if (command == NL80211_CMD_FRAME_TX_STATUS)
ea7d50c9
AS
18882 trace_cfg80211_mgmt_tx_status(wdev, status->cookie,
18883 status->ack);
dca9ca2d 18884 else
ea7d50c9
AS
18885 trace_cfg80211_control_port_tx_status(wdev, status->cookie,
18886 status->ack);
947add36 18887
ea7d50c9 18888 msg = nlmsg_new(100 + status->len, gfp);
026331c4
JM
18889 if (!msg)
18890 return;
18891
dca9ca2d 18892 hdr = nl80211hdr_put(msg, 0, 0, 0, command);
026331c4
JM
18893 if (!hdr) {
18894 nlmsg_free(msg);
18895 return;
18896 }
18897
9360ffd1 18898 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
71bbc994
JB
18899 (netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
18900 netdev->ifindex)) ||
2dad624e
ND
18901 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
18902 NL80211_ATTR_PAD) ||
ea7d50c9
AS
18903 nla_put(msg, NL80211_ATTR_FRAME, status->len, status->buf) ||
18904 nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, status->cookie,
2dad624e 18905 NL80211_ATTR_PAD) ||
ea7d50c9
AS
18906 (status->ack && nla_put_flag(msg, NL80211_ATTR_ACK)) ||
18907 (status->tx_tstamp &&
18908 nla_put_u64_64bit(msg, NL80211_ATTR_TX_HW_TIMESTAMP,
18909 status->tx_tstamp, NL80211_ATTR_PAD)) ||
18910 (status->ack_tstamp &&
18911 nla_put_u64_64bit(msg, NL80211_ATTR_RX_HW_TIMESTAMP,
18912 status->ack_tstamp, NL80211_ATTR_PAD)))
9360ffd1 18913 goto nla_put_failure;
026331c4 18914
3b7b72ee 18915 genlmsg_end(msg, hdr);
026331c4 18916
68eb5503 18917 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18918 NL80211_MCGRP_MLME, gfp);
026331c4
JM
18919 return;
18920
dca9ca2d 18921nla_put_failure:
026331c4
JM
18922 nlmsg_free(msg);
18923}
dca9ca2d
MT
18924
18925void cfg80211_control_port_tx_status(struct wireless_dev *wdev, u64 cookie,
18926 const u8 *buf, size_t len, bool ack,
18927 gfp_t gfp)
18928{
ea7d50c9
AS
18929 struct cfg80211_tx_status status = {
18930 .cookie = cookie,
18931 .buf = buf,
18932 .len = len,
18933 .ack = ack
18934 };
18935
18936 nl80211_frame_tx_status(wdev, &status, gfp,
dca9ca2d
MT
18937 NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS);
18938}
18939EXPORT_SYMBOL(cfg80211_control_port_tx_status);
18940
ea7d50c9
AS
18941void cfg80211_mgmt_tx_status_ext(struct wireless_dev *wdev,
18942 struct cfg80211_tx_status *status, gfp_t gfp)
dca9ca2d 18943{
ea7d50c9 18944 nl80211_frame_tx_status(wdev, status, gfp, NL80211_CMD_FRAME_TX_STATUS);
dca9ca2d 18945}
ea7d50c9 18946EXPORT_SYMBOL(cfg80211_mgmt_tx_status_ext);
026331c4 18947
6a671a50 18948static int __nl80211_rx_control_port(struct net_device *dev,
a948f713 18949 struct sk_buff *skb,
4c532321
JB
18950 bool unencrypted,
18951 int link_id,
18952 gfp_t gfp)
6a671a50
DK
18953{
18954 struct wireless_dev *wdev = dev->ieee80211_ptr;
18955 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
a948f713 18956 struct ethhdr *ehdr = eth_hdr(skb);
8d74a623 18957 const u8 *addr = ehdr->h_source;
a948f713 18958 u16 proto = be16_to_cpu(skb->protocol);
6a671a50
DK
18959 struct sk_buff *msg;
18960 void *hdr;
a948f713
DK
18961 struct nlattr *frame;
18962
6a671a50
DK
18963 u32 nlportid = READ_ONCE(wdev->conn_owner_nlportid);
18964
18965 if (!nlportid)
18966 return -ENOENT;
18967
a948f713 18968 msg = nlmsg_new(100 + skb->len, gfp);
6a671a50
DK
18969 if (!msg)
18970 return -ENOMEM;
18971
18972 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CONTROL_PORT_FRAME);
18973 if (!hdr) {
18974 nlmsg_free(msg);
18975 return -ENOBUFS;
18976 }
18977
18978 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
18979 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
18980 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
18981 NL80211_ATTR_PAD) ||
8d74a623 18982 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
6a671a50 18983 nla_put_u16(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE, proto) ||
4c532321
JB
18984 (link_id >= 0 &&
18985 nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id)) ||
6a671a50
DK
18986 (unencrypted && nla_put_flag(msg,
18987 NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT)))
18988 goto nla_put_failure;
18989
a948f713
DK
18990 frame = nla_reserve(msg, NL80211_ATTR_FRAME, skb->len);
18991 if (!frame)
18992 goto nla_put_failure;
18993
18994 skb_copy_bits(skb, 0, nla_data(frame), skb->len);
6a671a50
DK
18995 genlmsg_end(msg, hdr);
18996
18997 return genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid);
18998
18999 nla_put_failure:
19000 nlmsg_free(msg);
19001 return -ENOBUFS;
19002}
19003
4c532321
JB
19004bool cfg80211_rx_control_port(struct net_device *dev, struct sk_buff *skb,
19005 bool unencrypted, int link_id)
6a671a50
DK
19006{
19007 int ret;
19008
4c532321
JB
19009 trace_cfg80211_rx_control_port(dev, skb, unencrypted, link_id);
19010 ret = __nl80211_rx_control_port(dev, skb, unencrypted, link_id,
19011 GFP_ATOMIC);
6a671a50
DK
19012 trace_cfg80211_return_bool(ret == 0);
19013 return ret == 0;
19014}
19015EXPORT_SYMBOL(cfg80211_rx_control_port);
19016
5b97f49d
JB
19017static struct sk_buff *cfg80211_prepare_cqm(struct net_device *dev,
19018 const char *mac, gfp_t gfp)
d6dc1a38 19019{
947add36 19020 struct wireless_dev *wdev = dev->ieee80211_ptr;
5b97f49d
JB
19021 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
19022 struct sk_buff *msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
19023 void **cb;
947add36 19024
d6dc1a38 19025 if (!msg)
5b97f49d 19026 return NULL;
d6dc1a38 19027
5b97f49d
JB
19028 cb = (void **)msg->cb;
19029
19030 cb[0] = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NOTIFY_CQM);
19031 if (!cb[0]) {
d6dc1a38 19032 nlmsg_free(msg);
5b97f49d 19033 return NULL;
d6dc1a38
JO
19034 }
19035
9360ffd1 19036 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
947add36 19037 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
9360ffd1 19038 goto nla_put_failure;
d6dc1a38 19039
5b97f49d 19040 if (mac && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac))
d6dc1a38
JO
19041 goto nla_put_failure;
19042
ae0be8de 19043 cb[1] = nla_nest_start_noflag(msg, NL80211_ATTR_CQM);
5b97f49d 19044 if (!cb[1])
9360ffd1 19045 goto nla_put_failure;
d6dc1a38 19046
5b97f49d 19047 cb[2] = rdev;
d6dc1a38 19048
5b97f49d
JB
19049 return msg;
19050 nla_put_failure:
19051 nlmsg_free(msg);
19052 return NULL;
19053}
19054
19055static void cfg80211_send_cqm(struct sk_buff *msg, gfp_t gfp)
19056{
19057 void **cb = (void **)msg->cb;
19058 struct cfg80211_registered_device *rdev = cb[2];
19059
19060 nla_nest_end(msg, cb[1]);
19061 genlmsg_end(msg, cb[0]);
19062
19063 memset(msg->cb, 0, sizeof(msg->cb));
d6dc1a38 19064
68eb5503 19065 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 19066 NL80211_MCGRP_MLME, gfp);
5b97f49d
JB
19067}
19068
19069void cfg80211_cqm_rssi_notify(struct net_device *dev,
19070 enum nl80211_cqm_rssi_threshold_event rssi_event,
bee427b8 19071 s32 rssi_level, gfp_t gfp)
5b97f49d
JB
19072{
19073 struct sk_buff *msg;
4a4b8169
AZ
19074 struct wireless_dev *wdev = dev->ieee80211_ptr;
19075 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
5b97f49d 19076
bee427b8 19077 trace_cfg80211_cqm_rssi_notify(dev, rssi_event, rssi_level);
5b97f49d 19078
98f03342
JB
19079 if (WARN_ON(rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW &&
19080 rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH))
19081 return;
19082
4a4b8169
AZ
19083 if (wdev->cqm_config) {
19084 wdev->cqm_config->last_rssi_event_value = rssi_level;
19085
19086 cfg80211_cqm_rssi_update(rdev, dev);
19087
19088 if (rssi_level == 0)
19089 rssi_level = wdev->cqm_config->last_rssi_event_value;
19090 }
19091
5b97f49d
JB
19092 msg = cfg80211_prepare_cqm(dev, NULL, gfp);
19093 if (!msg)
19094 return;
19095
19096 if (nla_put_u32(msg, NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT,
19097 rssi_event))
19098 goto nla_put_failure;
19099
bee427b8
AZ
19100 if (rssi_level && nla_put_s32(msg, NL80211_ATTR_CQM_RSSI_LEVEL,
19101 rssi_level))
19102 goto nla_put_failure;
19103
5b97f49d
JB
19104 cfg80211_send_cqm(msg, gfp);
19105
d6dc1a38
JO
19106 return;
19107
19108 nla_put_failure:
d6dc1a38
JO
19109 nlmsg_free(msg);
19110}
947add36 19111EXPORT_SYMBOL(cfg80211_cqm_rssi_notify);
d6dc1a38 19112
5b97f49d
JB
19113void cfg80211_cqm_txe_notify(struct net_device *dev,
19114 const u8 *peer, u32 num_packets,
19115 u32 rate, u32 intvl, gfp_t gfp)
19116{
19117 struct sk_buff *msg;
19118
19119 msg = cfg80211_prepare_cqm(dev, peer, gfp);
19120 if (!msg)
19121 return;
19122
19123 if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_PKTS, num_packets))
19124 goto nla_put_failure;
19125
19126 if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_RATE, rate))
19127 goto nla_put_failure;
19128
19129 if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_INTVL, intvl))
19130 goto nla_put_failure;
19131
19132 cfg80211_send_cqm(msg, gfp);
19133 return;
19134
19135 nla_put_failure:
19136 nlmsg_free(msg);
19137}
19138EXPORT_SYMBOL(cfg80211_cqm_txe_notify);
19139
19140void cfg80211_cqm_pktloss_notify(struct net_device *dev,
19141 const u8 *peer, u32 num_packets, gfp_t gfp)
19142{
19143 struct sk_buff *msg;
19144
19145 trace_cfg80211_cqm_pktloss_notify(dev, peer, num_packets);
19146
19147 msg = cfg80211_prepare_cqm(dev, peer, gfp);
19148 if (!msg)
19149 return;
19150
19151 if (nla_put_u32(msg, NL80211_ATTR_CQM_PKT_LOSS_EVENT, num_packets))
19152 goto nla_put_failure;
19153
19154 cfg80211_send_cqm(msg, gfp);
19155 return;
19156
19157 nla_put_failure:
19158 nlmsg_free(msg);
19159}
19160EXPORT_SYMBOL(cfg80211_cqm_pktloss_notify);
19161
98f03342
JB
19162void cfg80211_cqm_beacon_loss_notify(struct net_device *dev, gfp_t gfp)
19163{
19164 struct sk_buff *msg;
19165
19166 msg = cfg80211_prepare_cqm(dev, NULL, gfp);
19167 if (!msg)
19168 return;
19169
19170 if (nla_put_flag(msg, NL80211_ATTR_CQM_BEACON_LOSS_EVENT))
19171 goto nla_put_failure;
19172
19173 cfg80211_send_cqm(msg, gfp);
19174 return;
19175
19176 nla_put_failure:
19177 nlmsg_free(msg);
19178}
19179EXPORT_SYMBOL(cfg80211_cqm_beacon_loss_notify);
19180
947add36
JB
19181static void nl80211_gtk_rekey_notify(struct cfg80211_registered_device *rdev,
19182 struct net_device *netdev, const u8 *bssid,
19183 const u8 *replay_ctr, gfp_t gfp)
e5497d76
JB
19184{
19185 struct sk_buff *msg;
19186 struct nlattr *rekey_attr;
19187 void *hdr;
19188
58050fce 19189 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
e5497d76
JB
19190 if (!msg)
19191 return;
19192
19193 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_SET_REKEY_OFFLOAD);
19194 if (!hdr) {
19195 nlmsg_free(msg);
19196 return;
19197 }
19198
9360ffd1
DM
19199 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
19200 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
19201 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid))
19202 goto nla_put_failure;
e5497d76 19203
ae0be8de 19204 rekey_attr = nla_nest_start_noflag(msg, NL80211_ATTR_REKEY_DATA);
e5497d76
JB
19205 if (!rekey_attr)
19206 goto nla_put_failure;
19207
9360ffd1
DM
19208 if (nla_put(msg, NL80211_REKEY_DATA_REPLAY_CTR,
19209 NL80211_REPLAY_CTR_LEN, replay_ctr))
19210 goto nla_put_failure;
e5497d76
JB
19211
19212 nla_nest_end(msg, rekey_attr);
19213
3b7b72ee 19214 genlmsg_end(msg, hdr);
e5497d76 19215
68eb5503 19216 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 19217 NL80211_MCGRP_MLME, gfp);
e5497d76
JB
19218 return;
19219
19220 nla_put_failure:
e5497d76
JB
19221 nlmsg_free(msg);
19222}
19223
947add36
JB
19224void cfg80211_gtk_rekey_notify(struct net_device *dev, const u8 *bssid,
19225 const u8 *replay_ctr, gfp_t gfp)
19226{
19227 struct wireless_dev *wdev = dev->ieee80211_ptr;
19228 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 19229 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
947add36
JB
19230
19231 trace_cfg80211_gtk_rekey_notify(dev, bssid);
19232 nl80211_gtk_rekey_notify(rdev, dev, bssid, replay_ctr, gfp);
19233}
19234EXPORT_SYMBOL(cfg80211_gtk_rekey_notify);
19235
19236static void
19237nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev,
19238 struct net_device *netdev, int index,
19239 const u8 *bssid, bool preauth, gfp_t gfp)
c9df56b4
JM
19240{
19241 struct sk_buff *msg;
19242 struct nlattr *attr;
19243 void *hdr;
19244
58050fce 19245 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
c9df56b4
JM
19246 if (!msg)
19247 return;
19248
19249 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_PMKSA_CANDIDATE);
19250 if (!hdr) {
19251 nlmsg_free(msg);
19252 return;
19253 }
19254
9360ffd1
DM
19255 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
19256 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex))
19257 goto nla_put_failure;
c9df56b4 19258
ae0be8de 19259 attr = nla_nest_start_noflag(msg, NL80211_ATTR_PMKSA_CANDIDATE);
c9df56b4
JM
19260 if (!attr)
19261 goto nla_put_failure;
19262
9360ffd1
DM
19263 if (nla_put_u32(msg, NL80211_PMKSA_CANDIDATE_INDEX, index) ||
19264 nla_put(msg, NL80211_PMKSA_CANDIDATE_BSSID, ETH_ALEN, bssid) ||
19265 (preauth &&
19266 nla_put_flag(msg, NL80211_PMKSA_CANDIDATE_PREAUTH)))
19267 goto nla_put_failure;
c9df56b4
JM
19268
19269 nla_nest_end(msg, attr);
19270
3b7b72ee 19271 genlmsg_end(msg, hdr);
c9df56b4 19272
68eb5503 19273 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 19274 NL80211_MCGRP_MLME, gfp);
c9df56b4
JM
19275 return;
19276
19277 nla_put_failure:
c9df56b4
JM
19278 nlmsg_free(msg);
19279}
19280
947add36
JB
19281void cfg80211_pmksa_candidate_notify(struct net_device *dev, int index,
19282 const u8 *bssid, bool preauth, gfp_t gfp)
19283{
19284 struct wireless_dev *wdev = dev->ieee80211_ptr;
19285 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 19286 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
947add36
JB
19287
19288 trace_cfg80211_pmksa_candidate_notify(dev, index, bssid, preauth);
19289 nl80211_pmksa_candidate_notify(rdev, dev, index, bssid, preauth, gfp);
19290}
19291EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify);
19292
19293static void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
19294 struct net_device *netdev,
b8c9024e 19295 unsigned int link_id,
947add36 19296 struct cfg80211_chan_def *chandef,
f8d7552e
LC
19297 gfp_t gfp,
19298 enum nl80211_commands notif,
b345f063 19299 u8 count, bool quiet, u16 punct_bitmap)
5314526b 19300{
b8c9024e 19301 struct wireless_dev *wdev = netdev->ieee80211_ptr;
5314526b
TP
19302 struct sk_buff *msg;
19303 void *hdr;
19304
58050fce 19305 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
5314526b
TP
19306 if (!msg)
19307 return;
19308
f8d7552e 19309 hdr = nl80211hdr_put(msg, 0, 0, 0, notif);
5314526b
TP
19310 if (!hdr) {
19311 nlmsg_free(msg);
19312 return;
19313 }
19314
683b6d3b
JB
19315 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex))
19316 goto nla_put_failure;
19317
b8c9024e
VJ
19318 if (wdev->valid_links &&
19319 nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id))
19320 goto nla_put_failure;
19321
683b6d3b 19322 if (nl80211_send_chandef(msg, chandef))
7eab0f64 19323 goto nla_put_failure;
5314526b 19324
669b8413
JB
19325 if (notif == NL80211_CMD_CH_SWITCH_STARTED_NOTIFY) {
19326 if (nla_put_u32(msg, NL80211_ATTR_CH_SWITCH_COUNT, count))
f8d7552e 19327 goto nla_put_failure;
669b8413
JB
19328 if (quiet &&
19329 nla_put_flag(msg, NL80211_ATTR_CH_SWITCH_BLOCK_TX))
f8d7552e 19330 goto nla_put_failure;
669b8413 19331 }
f8d7552e 19332
b345f063
AD
19333 if (nla_put_u32(msg, NL80211_ATTR_PUNCT_BITMAP, punct_bitmap))
19334 goto nla_put_failure;
19335
5314526b
TP
19336 genlmsg_end(msg, hdr);
19337
68eb5503 19338 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 19339 NL80211_MCGRP_MLME, gfp);
5314526b
TP
19340 return;
19341
19342 nla_put_failure:
5314526b
TP
19343 nlmsg_free(msg);
19344}
19345
947add36 19346void cfg80211_ch_switch_notify(struct net_device *dev,
7b0a0e3c 19347 struct cfg80211_chan_def *chandef,
b345f063 19348 unsigned int link_id, u16 punct_bitmap)
84f10708 19349{
947add36
JB
19350 struct wireless_dev *wdev = dev->ieee80211_ptr;
19351 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 19352 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
947add36 19353
e487eaeb 19354 ASSERT_WDEV_LOCK(wdev);
7b0a0e3c 19355 WARN_INVALID_LINK_ID(wdev, link_id);
947add36 19356
b345f063 19357 trace_cfg80211_ch_switch_notify(dev, chandef, link_id, punct_bitmap);
5dc8cdce 19358
7b0a0e3c
JB
19359 switch (wdev->iftype) {
19360 case NL80211_IFTYPE_STATION:
19361 case NL80211_IFTYPE_P2P_CLIENT:
19362 if (!WARN_ON(!wdev->links[link_id].client.current_bss))
19363 cfg80211_update_assoc_bss_entry(wdev, link_id,
19364 chandef->chan);
19365 break;
19366 case NL80211_IFTYPE_MESH_POINT:
19367 wdev->u.mesh.chandef = *chandef;
19368 wdev->u.mesh.preset_chandef = *chandef;
19369 break;
19370 case NL80211_IFTYPE_AP:
19371 case NL80211_IFTYPE_P2P_GO:
19372 wdev->links[link_id].ap.chandef = *chandef;
19373 break;
77e7b6ba
JB
19374 case NL80211_IFTYPE_ADHOC:
19375 wdev->u.ibss.chandef = *chandef;
19376 break;
7b0a0e3c
JB
19377 default:
19378 WARN_ON(1);
19379 break;
19380 }
5dc8cdce 19381
d34990bb
MV
19382 cfg80211_sched_dfs_chan_update(rdev);
19383
b8c9024e 19384 nl80211_ch_switch_notify(rdev, dev, link_id, chandef, GFP_KERNEL,
b345f063
AD
19385 NL80211_CMD_CH_SWITCH_NOTIFY, 0, false,
19386 punct_bitmap);
947add36
JB
19387}
19388EXPORT_SYMBOL(cfg80211_ch_switch_notify);
19389
f8d7552e
LC
19390void cfg80211_ch_switch_started_notify(struct net_device *dev,
19391 struct cfg80211_chan_def *chandef,
b8c9024e 19392 unsigned int link_id, u8 count,
b345f063 19393 bool quiet, u16 punct_bitmap)
f8d7552e
LC
19394{
19395 struct wireless_dev *wdev = dev->ieee80211_ptr;
19396 struct wiphy *wiphy = wdev->wiphy;
19397 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
19398
b8c9024e
VJ
19399 ASSERT_WDEV_LOCK(wdev);
19400 WARN_INVALID_LINK_ID(wdev, link_id);
19401
b345f063
AD
19402 trace_cfg80211_ch_switch_started_notify(dev, chandef, link_id,
19403 punct_bitmap);
19404
f8d7552e 19405
b8c9024e 19406 nl80211_ch_switch_notify(rdev, dev, link_id, chandef, GFP_KERNEL,
669b8413 19407 NL80211_CMD_CH_SWITCH_STARTED_NOTIFY,
b345f063 19408 count, quiet, punct_bitmap);
f8d7552e
LC
19409}
19410EXPORT_SYMBOL(cfg80211_ch_switch_started_notify);
19411
935ef47b 19412int cfg80211_bss_color_notify(struct net_device *dev,
0d2ab3ae
JC
19413 enum nl80211_commands cmd, u8 count,
19414 u64 color_bitmap)
19415{
19416 struct wireless_dev *wdev = dev->ieee80211_ptr;
19417 struct wiphy *wiphy = wdev->wiphy;
19418 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
19419 struct sk_buff *msg;
19420 void *hdr;
19421
19422 ASSERT_WDEV_LOCK(wdev);
19423
19424 trace_cfg80211_bss_color_notify(dev, cmd, count, color_bitmap);
19425
935ef47b 19426 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
0d2ab3ae
JC
19427 if (!msg)
19428 return -ENOMEM;
19429
19430 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
19431 if (!hdr)
19432 goto nla_put_failure;
19433
19434 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
19435 goto nla_put_failure;
19436
19437 if (cmd == NL80211_CMD_COLOR_CHANGE_STARTED &&
19438 nla_put_u32(msg, NL80211_ATTR_COLOR_CHANGE_COUNT, count))
19439 goto nla_put_failure;
19440
19441 if (cmd == NL80211_CMD_OBSS_COLOR_COLLISION &&
19442 nla_put_u64_64bit(msg, NL80211_ATTR_OBSS_COLOR_BITMAP,
19443 color_bitmap, NL80211_ATTR_PAD))
19444 goto nla_put_failure;
19445
19446 genlmsg_end(msg, hdr);
19447
19448 return genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
935ef47b 19449 msg, 0, NL80211_MCGRP_MLME, GFP_KERNEL);
0d2ab3ae
JC
19450
19451nla_put_failure:
19452 nlmsg_free(msg);
19453 return -EINVAL;
19454}
19455EXPORT_SYMBOL(cfg80211_bss_color_notify);
19456
04f39047
SW
19457void
19458nl80211_radar_notify(struct cfg80211_registered_device *rdev,
d2859df5 19459 const struct cfg80211_chan_def *chandef,
04f39047
SW
19460 enum nl80211_radar_event event,
19461 struct net_device *netdev, gfp_t gfp)
19462{
19463 struct sk_buff *msg;
19464 void *hdr;
19465
19466 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
19467 if (!msg)
19468 return;
19469
19470 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_RADAR_DETECT);
19471 if (!hdr) {
19472 nlmsg_free(msg);
19473 return;
19474 }
19475
19476 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx))
19477 goto nla_put_failure;
19478
19479 /* NOP and radar events don't need a netdev parameter */
19480 if (netdev) {
19481 struct wireless_dev *wdev = netdev->ieee80211_ptr;
19482
19483 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
2dad624e
ND
19484 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
19485 NL80211_ATTR_PAD))
04f39047
SW
19486 goto nla_put_failure;
19487 }
19488
19489 if (nla_put_u32(msg, NL80211_ATTR_RADAR_EVENT, event))
19490 goto nla_put_failure;
19491
19492 if (nl80211_send_chandef(msg, chandef))
19493 goto nla_put_failure;
19494
9c90a9f6 19495 genlmsg_end(msg, hdr);
04f39047 19496
68eb5503 19497 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 19498 NL80211_MCGRP_MLME, gfp);
04f39047
SW
19499 return;
19500
19501 nla_put_failure:
04f39047
SW
19502 nlmsg_free(msg);
19503}
19504
466b9936 19505void cfg80211_sta_opmode_change_notify(struct net_device *dev, const u8 *mac,
19506 struct sta_opmode_info *sta_opmode,
19507 gfp_t gfp)
19508{
19509 struct sk_buff *msg;
19510 struct wireless_dev *wdev = dev->ieee80211_ptr;
19511 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
19512 void *hdr;
19513
19514 if (WARN_ON(!mac))
19515 return;
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_STA_OPMODE_CHANGED);
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 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
19531 goto nla_put_failure;
19532
19533 if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac))
19534 goto nla_put_failure;
19535
19536 if ((sta_opmode->changed & STA_OPMODE_SMPS_MODE_CHANGED) &&
19537 nla_put_u8(msg, NL80211_ATTR_SMPS_MODE, sta_opmode->smps_mode))
19538 goto nla_put_failure;
19539
19540 if ((sta_opmode->changed & STA_OPMODE_MAX_BW_CHANGED) &&
0016d320 19541 nla_put_u32(msg, NL80211_ATTR_CHANNEL_WIDTH, sta_opmode->bw))
466b9936 19542 goto nla_put_failure;
19543
19544 if ((sta_opmode->changed & STA_OPMODE_N_SS_CHANGED) &&
19545 nla_put_u8(msg, NL80211_ATTR_NSS, sta_opmode->rx_nss))
19546 goto nla_put_failure;
19547
19548 genlmsg_end(msg, hdr);
19549
19550 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
19551 NL80211_MCGRP_MLME, gfp);
19552
19553 return;
19554
19555nla_put_failure:
19556 nlmsg_free(msg);
19557}
19558EXPORT_SYMBOL(cfg80211_sta_opmode_change_notify);
19559
7f6cf311 19560void cfg80211_probe_status(struct net_device *dev, const u8 *addr,
c4b50cd3
VN
19561 u64 cookie, bool acked, s32 ack_signal,
19562 bool is_valid_ack_signal, gfp_t gfp)
7f6cf311
JB
19563{
19564 struct wireless_dev *wdev = dev->ieee80211_ptr;
f26cbf40 19565 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
7f6cf311
JB
19566 struct sk_buff *msg;
19567 void *hdr;
7f6cf311 19568
4ee3e063
BL
19569 trace_cfg80211_probe_status(dev, addr, cookie, acked);
19570
58050fce 19571 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
4ee3e063 19572
7f6cf311
JB
19573 if (!msg)
19574 return;
19575
19576 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_PROBE_CLIENT);
19577 if (!hdr) {
19578 nlmsg_free(msg);
19579 return;
19580 }
19581
9360ffd1
DM
19582 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
19583 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
19584 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
2dad624e
ND
19585 nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
19586 NL80211_ATTR_PAD) ||
c4b50cd3
VN
19587 (acked && nla_put_flag(msg, NL80211_ATTR_ACK)) ||
19588 (is_valid_ack_signal && nla_put_s32(msg, NL80211_ATTR_ACK_SIGNAL,
19589 ack_signal)))
9360ffd1 19590 goto nla_put_failure;
7f6cf311 19591
9c90a9f6 19592 genlmsg_end(msg, hdr);
7f6cf311 19593
68eb5503 19594 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 19595 NL80211_MCGRP_MLME, gfp);
7f6cf311
JB
19596 return;
19597
19598 nla_put_failure:
7f6cf311
JB
19599 nlmsg_free(msg);
19600}
19601EXPORT_SYMBOL(cfg80211_probe_status);
19602
e76fede8
TP
19603void cfg80211_report_obss_beacon_khz(struct wiphy *wiphy, const u8 *frame,
19604 size_t len, int freq, int sig_dbm)
5e760230 19605{
f26cbf40 19606 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
5e760230
JB
19607 struct sk_buff *msg;
19608 void *hdr;
37c73b5f 19609 struct cfg80211_beacon_registration *reg;
5e760230 19610
4ee3e063
BL
19611 trace_cfg80211_report_obss_beacon(wiphy, frame, len, freq, sig_dbm);
19612
37c73b5f
BG
19613 spin_lock_bh(&rdev->beacon_registrations_lock);
19614 list_for_each_entry(reg, &rdev->beacon_registrations, list) {
19615 msg = nlmsg_new(len + 100, GFP_ATOMIC);
19616 if (!msg) {
19617 spin_unlock_bh(&rdev->beacon_registrations_lock);
19618 return;
19619 }
5e760230 19620
37c73b5f
BG
19621 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FRAME);
19622 if (!hdr)
19623 goto nla_put_failure;
5e760230 19624
37c73b5f
BG
19625 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
19626 (freq &&
942ba88b
TP
19627 (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
19628 KHZ_TO_MHZ(freq)) ||
19629 nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ_OFFSET,
19630 freq % 1000))) ||
37c73b5f
BG
19631 (sig_dbm &&
19632 nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)) ||
19633 nla_put(msg, NL80211_ATTR_FRAME, len, frame))
19634 goto nla_put_failure;
5e760230 19635
37c73b5f 19636 genlmsg_end(msg, hdr);
5e760230 19637
37c73b5f
BG
19638 genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, reg->nlportid);
19639 }
19640 spin_unlock_bh(&rdev->beacon_registrations_lock);
5e760230
JB
19641 return;
19642
19643 nla_put_failure:
37c73b5f 19644 spin_unlock_bh(&rdev->beacon_registrations_lock);
5e760230
JB
19645 nlmsg_free(msg);
19646}
e76fede8 19647EXPORT_SYMBOL(cfg80211_report_obss_beacon_khz);
5e760230 19648
cd8f7cb4 19649#ifdef CONFIG_PM
8cd4d456
LC
19650static int cfg80211_net_detect_results(struct sk_buff *msg,
19651 struct cfg80211_wowlan_wakeup *wakeup)
19652{
19653 struct cfg80211_wowlan_nd_info *nd = wakeup->net_detect;
19654 struct nlattr *nl_results, *nl_match, *nl_freqs;
19655 int i, j;
19656
ae0be8de
MK
19657 nl_results = nla_nest_start_noflag(msg,
19658 NL80211_WOWLAN_TRIG_NET_DETECT_RESULTS);
8cd4d456
LC
19659 if (!nl_results)
19660 return -EMSGSIZE;
19661
19662 for (i = 0; i < nd->n_matches; i++) {
19663 struct cfg80211_wowlan_nd_match *match = nd->matches[i];
19664
ae0be8de 19665 nl_match = nla_nest_start_noflag(msg, i);
8cd4d456
LC
19666 if (!nl_match)
19667 break;
19668
19669 /* The SSID attribute is optional in nl80211, but for
19670 * simplicity reasons it's always present in the
19671 * cfg80211 structure. If a driver can't pass the
19672 * SSID, that needs to be changed. A zero length SSID
19673 * is still a valid SSID (wildcard), so it cannot be
19674 * used for this purpose.
19675 */
19676 if (nla_put(msg, NL80211_ATTR_SSID, match->ssid.ssid_len,
19677 match->ssid.ssid)) {
19678 nla_nest_cancel(msg, nl_match);
19679 goto out;
19680 }
19681
19682 if (match->n_channels) {
ae0be8de
MK
19683 nl_freqs = nla_nest_start_noflag(msg,
19684 NL80211_ATTR_SCAN_FREQUENCIES);
8cd4d456
LC
19685 if (!nl_freqs) {
19686 nla_nest_cancel(msg, nl_match);
19687 goto out;
19688 }
19689
19690 for (j = 0; j < match->n_channels; j++) {
5528fae8 19691 if (nla_put_u32(msg, j, match->channels[j])) {
8cd4d456
LC
19692 nla_nest_cancel(msg, nl_freqs);
19693 nla_nest_cancel(msg, nl_match);
19694 goto out;
19695 }
19696 }
19697
19698 nla_nest_end(msg, nl_freqs);
19699 }
19700
19701 nla_nest_end(msg, nl_match);
19702 }
19703
19704out:
19705 nla_nest_end(msg, nl_results);
19706 return 0;
19707}
19708
cd8f7cb4
JB
19709void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev,
19710 struct cfg80211_wowlan_wakeup *wakeup,
19711 gfp_t gfp)
19712{
f26cbf40 19713 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
cd8f7cb4
JB
19714 struct sk_buff *msg;
19715 void *hdr;
9c90a9f6 19716 int size = 200;
cd8f7cb4
JB
19717
19718 trace_cfg80211_report_wowlan_wakeup(wdev->wiphy, wdev, wakeup);
19719
19720 if (wakeup)
19721 size += wakeup->packet_present_len;
19722
19723 msg = nlmsg_new(size, gfp);
19724 if (!msg)
19725 return;
19726
19727 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_SET_WOWLAN);
19728 if (!hdr)
19729 goto free_msg;
19730
19731 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
2dad624e
ND
19732 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
19733 NL80211_ATTR_PAD))
cd8f7cb4
JB
19734 goto free_msg;
19735
19736 if (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
19737 wdev->netdev->ifindex))
19738 goto free_msg;
19739
19740 if (wakeup) {
19741 struct nlattr *reasons;
19742
ae0be8de
MK
19743 reasons = nla_nest_start_noflag(msg,
19744 NL80211_ATTR_WOWLAN_TRIGGERS);
7fa322c8
JB
19745 if (!reasons)
19746 goto free_msg;
cd8f7cb4
JB
19747
19748 if (wakeup->disconnect &&
19749 nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT))
19750 goto free_msg;
19751 if (wakeup->magic_pkt &&
19752 nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT))
19753 goto free_msg;
19754 if (wakeup->gtk_rekey_failure &&
19755 nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE))
19756 goto free_msg;
19757 if (wakeup->eap_identity_req &&
19758 nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST))
19759 goto free_msg;
19760 if (wakeup->four_way_handshake &&
19761 nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE))
19762 goto free_msg;
19763 if (wakeup->rfkill_release &&
19764 nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE))
19765 goto free_msg;
19766
19767 if (wakeup->pattern_idx >= 0 &&
19768 nla_put_u32(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN,
19769 wakeup->pattern_idx))
19770 goto free_msg;
19771
ae917c9f
JB
19772 if (wakeup->tcp_match &&
19773 nla_put_flag(msg, NL80211_WOWLAN_TRIG_WAKEUP_TCP_MATCH))
19774 goto free_msg;
2a0e047e 19775
ae917c9f
JB
19776 if (wakeup->tcp_connlost &&
19777 nla_put_flag(msg, NL80211_WOWLAN_TRIG_WAKEUP_TCP_CONNLOST))
19778 goto free_msg;
2a0e047e 19779
ae917c9f
JB
19780 if (wakeup->tcp_nomoretokens &&
19781 nla_put_flag(msg,
19782 NL80211_WOWLAN_TRIG_WAKEUP_TCP_NOMORETOKENS))
19783 goto free_msg;
2a0e047e 19784
cd8f7cb4
JB
19785 if (wakeup->packet) {
19786 u32 pkt_attr = NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211;
19787 u32 len_attr = NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN;
19788
19789 if (!wakeup->packet_80211) {
19790 pkt_attr =
19791 NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023;
19792 len_attr =
19793 NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023_LEN;
19794 }
19795
19796 if (wakeup->packet_len &&
19797 nla_put_u32(msg, len_attr, wakeup->packet_len))
19798 goto free_msg;
19799
19800 if (nla_put(msg, pkt_attr, wakeup->packet_present_len,
19801 wakeup->packet))
19802 goto free_msg;
19803 }
19804
8cd4d456
LC
19805 if (wakeup->net_detect &&
19806 cfg80211_net_detect_results(msg, wakeup))
19807 goto free_msg;
19808
cd8f7cb4
JB
19809 nla_nest_end(msg, reasons);
19810 }
19811
9c90a9f6 19812 genlmsg_end(msg, hdr);
cd8f7cb4 19813
68eb5503 19814 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 19815 NL80211_MCGRP_MLME, gfp);
cd8f7cb4
JB
19816 return;
19817
19818 free_msg:
19819 nlmsg_free(msg);
19820}
19821EXPORT_SYMBOL(cfg80211_report_wowlan_wakeup);
19822#endif
19823
3475b094
JM
19824void cfg80211_tdls_oper_request(struct net_device *dev, const u8 *peer,
19825 enum nl80211_tdls_operation oper,
19826 u16 reason_code, gfp_t gfp)
19827{
19828 struct wireless_dev *wdev = dev->ieee80211_ptr;
f26cbf40 19829 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
3475b094
JM
19830 struct sk_buff *msg;
19831 void *hdr;
3475b094
JM
19832
19833 trace_cfg80211_tdls_oper_request(wdev->wiphy, dev, peer, oper,
19834 reason_code);
19835
19836 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
19837 if (!msg)
19838 return;
19839
19840 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_TDLS_OPER);
19841 if (!hdr) {
19842 nlmsg_free(msg);
19843 return;
19844 }
19845
19846 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
19847 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
19848 nla_put_u8(msg, NL80211_ATTR_TDLS_OPERATION, oper) ||
19849 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, peer) ||
19850 (reason_code > 0 &&
19851 nla_put_u16(msg, NL80211_ATTR_REASON_CODE, reason_code)))
19852 goto nla_put_failure;
19853
9c90a9f6 19854 genlmsg_end(msg, hdr);
3475b094 19855
68eb5503 19856 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 19857 NL80211_MCGRP_MLME, gfp);
3475b094
JM
19858 return;
19859
19860 nla_put_failure:
3475b094
JM
19861 nlmsg_free(msg);
19862}
19863EXPORT_SYMBOL(cfg80211_tdls_oper_request);
19864
026331c4
JM
19865static int nl80211_netlink_notify(struct notifier_block * nb,
19866 unsigned long state,
19867 void *_notify)
19868{
19869 struct netlink_notify *notify = _notify;
19870 struct cfg80211_registered_device *rdev;
19871 struct wireless_dev *wdev;
37c73b5f 19872 struct cfg80211_beacon_registration *reg, *tmp;
026331c4 19873
8f815cdd 19874 if (state != NETLINK_URELEASE || notify->protocol != NETLINK_GENERIC)
026331c4
JM
19875 return NOTIFY_DONE;
19876
19877 rcu_read_lock();
19878
5e760230 19879 list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) {
ca986ad9 19880 struct cfg80211_sched_scan_request *sched_scan_req;
753aacfd 19881
ca986ad9
AVS
19882 list_for_each_entry_rcu(sched_scan_req,
19883 &rdev->sched_scan_req_list,
19884 list) {
19885 if (sched_scan_req->owner_nlportid == notify->portid) {
19886 sched_scan_req->nl_owner_dead = true;
c88d7178
JB
19887 wiphy_work_queue(&rdev->wiphy,
19888 &rdev->sched_scan_stop_wk);
ca986ad9 19889 }
753aacfd 19890 }
78f22b6a 19891
53873f13 19892 list_for_each_entry_rcu(wdev, &rdev->wiphy.wdev_list, list) {
15e47304 19893 cfg80211_mlme_unregister_socket(wdev, notify->portid);
37c73b5f 19894
ab81007a
JB
19895 if (wdev->owner_nlportid == notify->portid) {
19896 wdev->nl_owner_dead = true;
19897 schedule_work(&rdev->destroy_work);
19898 } else if (wdev->conn_owner_nlportid == notify->portid) {
bd2522b1 19899 schedule_work(&wdev->disconnect_wk);
ab81007a 19900 }
9bb7e0f2
JB
19901
19902 cfg80211_release_pmsr(wdev, notify->portid);
78f22b6a
JB
19903 }
19904
37c73b5f
BG
19905 spin_lock_bh(&rdev->beacon_registrations_lock);
19906 list_for_each_entry_safe(reg, tmp, &rdev->beacon_registrations,
19907 list) {
19908 if (reg->nlportid == notify->portid) {
19909 list_del(&reg->list);
19910 kfree(reg);
19911 break;
19912 }
19913 }
19914 spin_unlock_bh(&rdev->beacon_registrations_lock);
5e760230 19915 }
026331c4
JM
19916
19917 rcu_read_unlock();
19918
05050753
I
19919 /*
19920 * It is possible that the user space process that is controlling the
19921 * indoor setting disappeared, so notify the regulatory core.
19922 */
19923 regulatory_netlink_notify(notify->portid);
6784c7db 19924 return NOTIFY_OK;
026331c4
JM
19925}
19926
19927static struct notifier_block nl80211_netlink_notifier = {
19928 .notifier_call = nl80211_netlink_notify,
19929};
19930
355199e0
JM
19931void cfg80211_ft_event(struct net_device *netdev,
19932 struct cfg80211_ft_event_params *ft_event)
19933{
19934 struct wiphy *wiphy = netdev->ieee80211_ptr->wiphy;
f26cbf40 19935 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
355199e0
JM
19936 struct sk_buff *msg;
19937 void *hdr;
355199e0
JM
19938
19939 trace_cfg80211_ft_event(wiphy, netdev, ft_event);
19940
19941 if (!ft_event->target_ap)
19942 return;
19943
1039d081
DL
19944 msg = nlmsg_new(100 + ft_event->ies_len + ft_event->ric_ies_len,
19945 GFP_KERNEL);
355199e0
JM
19946 if (!msg)
19947 return;
19948
19949 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FT_EVENT);
ae917c9f
JB
19950 if (!hdr)
19951 goto out;
355199e0 19952
ae917c9f
JB
19953 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
19954 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
19955 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, ft_event->target_ap))
19956 goto out;
355199e0 19957
ae917c9f
JB
19958 if (ft_event->ies &&
19959 nla_put(msg, NL80211_ATTR_IE, ft_event->ies_len, ft_event->ies))
19960 goto out;
19961 if (ft_event->ric_ies &&
19962 nla_put(msg, NL80211_ATTR_IE_RIC, ft_event->ric_ies_len,
19963 ft_event->ric_ies))
19964 goto out;
355199e0 19965
9c90a9f6 19966 genlmsg_end(msg, hdr);
355199e0 19967
68eb5503 19968 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 19969 NL80211_MCGRP_MLME, GFP_KERNEL);
ae917c9f
JB
19970 return;
19971 out:
19972 nlmsg_free(msg);
355199e0
JM
19973}
19974EXPORT_SYMBOL(cfg80211_ft_event);
19975
5de17984
AS
19976void cfg80211_crit_proto_stopped(struct wireless_dev *wdev, gfp_t gfp)
19977{
19978 struct cfg80211_registered_device *rdev;
19979 struct sk_buff *msg;
19980 void *hdr;
19981 u32 nlportid;
19982
f26cbf40 19983 rdev = wiphy_to_rdev(wdev->wiphy);
5de17984
AS
19984 if (!rdev->crit_proto_nlportid)
19985 return;
19986
19987 nlportid = rdev->crit_proto_nlportid;
19988 rdev->crit_proto_nlportid = 0;
19989
19990 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
19991 if (!msg)
19992 return;
19993
19994 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CRIT_PROTOCOL_STOP);
19995 if (!hdr)
19996 goto nla_put_failure;
19997
19998 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
2dad624e
ND
19999 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
20000 NL80211_ATTR_PAD))
5de17984
AS
20001 goto nla_put_failure;
20002
20003 genlmsg_end(msg, hdr);
20004
20005 genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid);
20006 return;
20007
20008 nla_put_failure:
5de17984 20009 nlmsg_free(msg);
5de17984
AS
20010}
20011EXPORT_SYMBOL(cfg80211_crit_proto_stopped);
20012
cba7217a 20013void nl80211_send_ap_stopped(struct wireless_dev *wdev, unsigned int link_id)
348baf0e
JB
20014{
20015 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 20016 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
348baf0e
JB
20017 struct sk_buff *msg;
20018 void *hdr;
20019
20020 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
20021 if (!msg)
20022 return;
20023
20024 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_STOP_AP);
20025 if (!hdr)
20026 goto out;
20027
20028 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
20029 nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex) ||
2dad624e 20030 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
cba7217a
20031 NL80211_ATTR_PAD) ||
20032 (wdev->valid_links &&
20033 nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id)))
348baf0e
JB
20034 goto out;
20035
20036 genlmsg_end(msg, hdr);
20037
20038 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(wiphy), msg, 0,
20039 NL80211_MCGRP_MLME, GFP_KERNEL);
20040 return;
20041 out:
20042 nlmsg_free(msg);
20043}
20044
40cbfa90
SD
20045int cfg80211_external_auth_request(struct net_device *dev,
20046 struct cfg80211_external_auth_params *params,
20047 gfp_t gfp)
20048{
20049 struct wireless_dev *wdev = dev->ieee80211_ptr;
20050 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
20051 struct sk_buff *msg;
20052 void *hdr;
20053
20054 if (!wdev->conn_owner_nlportid)
20055 return -EINVAL;
20056
20057 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
20058 if (!msg)
20059 return -ENOMEM;
20060
20061 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_EXTERNAL_AUTH);
20062 if (!hdr)
20063 goto nla_put_failure;
20064
20065 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
20066 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
20067 nla_put_u32(msg, NL80211_ATTR_AKM_SUITES, params->key_mgmt_suite) ||
20068 nla_put_u32(msg, NL80211_ATTR_EXTERNAL_AUTH_ACTION,
20069 params->action) ||
20070 nla_put(msg, NL80211_ATTR_BSSID, ETH_ALEN, params->bssid) ||
20071 nla_put(msg, NL80211_ATTR_SSID, params->ssid.ssid_len,
9a47c1ef
VJ
20072 params->ssid.ssid) ||
20073 (!is_zero_ether_addr(params->mld_addr) &&
20074 nla_put(msg, NL80211_ATTR_MLD_ADDR, ETH_ALEN, params->mld_addr)))
40cbfa90
SD
20075 goto nla_put_failure;
20076
20077 genlmsg_end(msg, hdr);
20078 genlmsg_unicast(wiphy_net(&rdev->wiphy), msg,
20079 wdev->conn_owner_nlportid);
20080 return 0;
20081
20082 nla_put_failure:
20083 nlmsg_free(msg);
20084 return -ENOBUFS;
20085}
20086EXPORT_SYMBOL(cfg80211_external_auth_request);
20087
cb74e977
SD
20088void cfg80211_update_owe_info_event(struct net_device *netdev,
20089 struct cfg80211_update_owe_info *owe_info,
20090 gfp_t gfp)
20091{
20092 struct wiphy *wiphy = netdev->ieee80211_ptr->wiphy;
20093 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
20094 struct sk_buff *msg;
20095 void *hdr;
20096
20097 trace_cfg80211_update_owe_info_event(wiphy, netdev, owe_info);
20098
20099 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
20100 if (!msg)
20101 return;
20102
20103 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_UPDATE_OWE_INFO);
20104 if (!hdr)
20105 goto nla_put_failure;
20106
20107 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
20108 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
20109 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, owe_info->peer))
20110 goto nla_put_failure;
20111
20112 if (!owe_info->ie_len ||
20113 nla_put(msg, NL80211_ATTR_IE, owe_info->ie_len, owe_info->ie))
20114 goto nla_put_failure;
20115
8bb588d9
VJ
20116 if (owe_info->assoc_link_id != -1) {
20117 if (nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID,
20118 owe_info->assoc_link_id))
20119 goto nla_put_failure;
20120
20121 if (!is_zero_ether_addr(owe_info->peer_mld_addr) &&
20122 nla_put(msg, NL80211_ATTR_MLD_ADDR, ETH_ALEN,
20123 owe_info->peer_mld_addr))
20124 goto nla_put_failure;
20125 }
20126
cb74e977
SD
20127 genlmsg_end(msg, hdr);
20128
20129 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
20130 NL80211_MCGRP_MLME, gfp);
20131 return;
20132
20133nla_put_failure:
20134 genlmsg_cancel(msg, hdr);
20135 nlmsg_free(msg);
20136}
20137EXPORT_SYMBOL(cfg80211_update_owe_info_event);
20138
55682965
JB
20139/* initialisation/exit functions */
20140
56989f6d 20141int __init nl80211_init(void)
55682965 20142{
0d63cbb5 20143 int err;
55682965 20144
489111e5 20145 err = genl_register_family(&nl80211_fam);
55682965
JB
20146 if (err)
20147 return err;
20148
026331c4
JM
20149 err = netlink_register_notifier(&nl80211_netlink_notifier);
20150 if (err)
20151 goto err_out;
20152
55682965
JB
20153 return 0;
20154 err_out:
20155 genl_unregister_family(&nl80211_fam);
20156 return err;
20157}
20158
20159void nl80211_exit(void)
20160{
026331c4 20161 netlink_unregister_notifier(&nl80211_netlink_notifier);
55682965
JB
20162 genl_unregister_family(&nl80211_fam);
20163}