wifi: cfg80211: clean up links appropriately
[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
ea05fd35 8 * Copyright (C) 2018-2022 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
d15da2a2 459static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
6d4dd4ef 460 [0] = { .strict_start_type = NL80211_ATTR_HE_OBSS_PD },
55682965
JB
461 [NL80211_ATTR_WIPHY] = { .type = NLA_U32 },
462 [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING,
079e24ed 463 .len = 20-1 },
31888487 464 [NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED },
3d9d1d66 465
72bdcf34 466 [NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 },
094d05dc 467 [NL80211_ATTR_WIPHY_CHANNEL_TYPE] = { .type = NLA_U32 },
2a38075c
AAL
468 [NL80211_ATTR_WIPHY_EDMG_CHANNELS] = NLA_POLICY_RANGE(NLA_U8,
469 NL80211_EDMG_CHANNELS_MIN,
470 NL80211_EDMG_CHANNELS_MAX),
471 [NL80211_ATTR_WIPHY_EDMG_BW_CONFIG] = NLA_POLICY_RANGE(NLA_U8,
472 NL80211_EDMG_BW_CONFIG_MIN,
473 NL80211_EDMG_BW_CONFIG_MAX),
474
3d9d1d66
JB
475 [NL80211_ATTR_CHANNEL_WIDTH] = { .type = NLA_U32 },
476 [NL80211_ATTR_CENTER_FREQ1] = { .type = NLA_U32 },
942ba88b 477 [NL80211_ATTR_CENTER_FREQ1_OFFSET] = NLA_POLICY_RANGE(NLA_U32, 0, 999),
3d9d1d66
JB
478 [NL80211_ATTR_CENTER_FREQ2] = { .type = NLA_U32 },
479
ab0d76f6
JB
480 [NL80211_ATTR_WIPHY_RETRY_SHORT] = NLA_POLICY_MIN(NLA_U8, 1),
481 [NL80211_ATTR_WIPHY_RETRY_LONG] = NLA_POLICY_MIN(NLA_U8, 1),
b9a5f8ca
JM
482 [NL80211_ATTR_WIPHY_FRAG_THRESHOLD] = { .type = NLA_U32 },
483 [NL80211_ATTR_WIPHY_RTS_THRESHOLD] = { .type = NLA_U32 },
81077e82 484 [NL80211_ATTR_WIPHY_COVERAGE_CLASS] = { .type = NLA_U8 },
3057dbfd 485 [NL80211_ATTR_WIPHY_DYN_ACK] = { .type = NLA_FLAG },
55682965 486
ab0d76f6 487 [NL80211_ATTR_IFTYPE] = NLA_POLICY_MAX(NLA_U32, NL80211_IFTYPE_MAX),
55682965
JB
488 [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 },
489 [NL80211_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 },
41ade00f 490
c7721c05
JB
491 [NL80211_ATTR_MAC] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
492 [NL80211_ATTR_PREV_BSSID] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
41ade00f 493
b9454e83 494 [NL80211_ATTR_KEY] = { .type = NLA_NESTED, },
41ade00f
JB
495 [NL80211_ATTR_KEY_DATA] = { .type = NLA_BINARY,
496 .len = WLAN_MAX_KEY_LEN },
56be393f 497 [NL80211_ATTR_KEY_IDX] = NLA_POLICY_MAX(NLA_U8, 7),
41ade00f
JB
498 [NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 },
499 [NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG },
81962267 500 [NL80211_ATTR_KEY_SEQ] = { .type = NLA_BINARY, .len = 16 },
ab0d76f6
JB
501 [NL80211_ATTR_KEY_TYPE] =
502 NLA_POLICY_MAX(NLA_U32, NUM_NL80211_KEYTYPES),
ed1b6cc7
JB
503
504 [NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 },
505 [NL80211_ATTR_DTIM_PERIOD] = { .type = NLA_U32 },
f88eb7c0
JB
506 [NL80211_ATTR_BEACON_HEAD] =
507 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_beacon_head,
508 IEEE80211_MAX_DATA_LEN),
3d7af878
JB
509 [NL80211_ATTR_BEACON_TAIL] =
510 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr,
511 IEEE80211_MAX_DATA_LEN),
ab0d76f6
JB
512 [NL80211_ATTR_STA_AID] =
513 NLA_POLICY_RANGE(NLA_U16, 1, IEEE80211_MAX_AID),
5727ef1b
JB
514 [NL80211_ATTR_STA_FLAGS] = { .type = NLA_NESTED },
515 [NL80211_ATTR_STA_LISTEN_INTERVAL] = { .type = NLA_U16 },
516 [NL80211_ATTR_STA_SUPPORTED_RATES] = { .type = NLA_BINARY,
517 .len = NL80211_MAX_SUPP_RATES },
ab0d76f6
JB
518 [NL80211_ATTR_STA_PLINK_ACTION] =
519 NLA_POLICY_MAX(NLA_U8, NUM_NL80211_PLINK_ACTIONS - 1),
e96d1cd2
ARN
520 [NL80211_ATTR_STA_TX_POWER_SETTING] =
521 NLA_POLICY_RANGE(NLA_U8,
522 NL80211_TX_POWER_AUTOMATIC,
523 NL80211_TX_POWER_FIXED),
524 [NL80211_ATTR_STA_TX_POWER] = { .type = NLA_S16 },
5727ef1b 525 [NL80211_ATTR_STA_VLAN] = { .type = NLA_U32 },
0a9542ee 526 [NL80211_ATTR_MNTR_FLAGS] = { /* NLA_NESTED can't be empty */ },
2ec600d6 527 [NL80211_ATTR_MESH_ID] = { .type = NLA_BINARY,
a4f606ea 528 .len = IEEE80211_MAX_MESH_ID_LEN },
1fab1b89 529 [NL80211_ATTR_MPATH_NEXT_HOP] = NLA_POLICY_ETH_ADDR_COMPAT,
9f1ba906 530
6624bb34
JB
531 /* allow 3 for NUL-termination, we used to declare this NLA_STRING */
532 [NL80211_ATTR_REG_ALPHA2] = NLA_POLICY_RANGE(NLA_BINARY, 2, 3),
b2e1b302
LR
533 [NL80211_ATTR_REG_RULES] = { .type = NLA_NESTED },
534
9f1ba906
JM
535 [NL80211_ATTR_BSS_CTS_PROT] = { .type = NLA_U8 },
536 [NL80211_ATTR_BSS_SHORT_PREAMBLE] = { .type = NLA_U8 },
537 [NL80211_ATTR_BSS_SHORT_SLOT_TIME] = { .type = NLA_U8 },
90c97a04
JM
538 [NL80211_ATTR_BSS_BASIC_RATES] = { .type = NLA_BINARY,
539 .len = NL80211_MAX_SUPP_RATES },
50b12f59 540 [NL80211_ATTR_BSS_HT_OPMODE] = { .type = NLA_U16 },
36aedc90 541
24bdd9f4 542 [NL80211_ATTR_MESH_CONFIG] = { .type = NLA_NESTED },
15d5dda6 543 [NL80211_ATTR_SUPPORT_MESH_AUTH] = { .type = NLA_FLAG },
93da9cc1 544
c7721c05 545 [NL80211_ATTR_HT_CAPABILITY] = NLA_POLICY_EXACT_LEN_WARN(NL80211_HT_CAPABILITY_LEN),
9aed3cc1
JM
546
547 [NL80211_ATTR_MGMT_SUBTYPE] = { .type = NLA_U8 },
3d7af878
JB
548 [NL80211_ATTR_IE] = NLA_POLICY_VALIDATE_FN(NLA_BINARY,
549 validate_ie_attr,
550 IEEE80211_MAX_DATA_LEN),
2a519311
JB
551 [NL80211_ATTR_SCAN_FREQUENCIES] = { .type = NLA_NESTED },
552 [NL80211_ATTR_SCAN_SSIDS] = { .type = NLA_NESTED },
636a5d36
JM
553
554 [NL80211_ATTR_SSID] = { .type = NLA_BINARY,
555 .len = IEEE80211_MAX_SSID_LEN },
556 [NL80211_ATTR_AUTH_TYPE] = { .type = NLA_U32 },
557 [NL80211_ATTR_REASON_CODE] = { .type = NLA_U16 },
04a773ad 558 [NL80211_ATTR_FREQ_FIXED] = { .type = NLA_FLAG },
1965c853 559 [NL80211_ATTR_TIMED_OUT] = { .type = NLA_FLAG },
ab0d76f6
JB
560 [NL80211_ATTR_USE_MFP] = NLA_POLICY_RANGE(NLA_U32,
561 NL80211_MFP_NO,
562 NL80211_MFP_OPTIONAL),
eccb8e8f
JB
563 [NL80211_ATTR_STA_FLAGS2] = {
564 .len = sizeof(struct nl80211_sta_flag_update),
565 },
3f77316c 566 [NL80211_ATTR_CONTROL_PORT] = { .type = NLA_FLAG },
c0692b8f
JB
567 [NL80211_ATTR_CONTROL_PORT_ETHERTYPE] = { .type = NLA_U16 },
568 [NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT] = { .type = NLA_FLAG },
64bf3d4b 569 [NL80211_ATTR_CONTROL_PORT_OVER_NL80211] = { .type = NLA_FLAG },
b23aa676 570 [NL80211_ATTR_PRIVACY] = { .type = NLA_FLAG },
ea750801 571 [NL80211_ATTR_STATUS_CODE] = { .type = NLA_U16 },
b23aa676
SO
572 [NL80211_ATTR_CIPHER_SUITE_GROUP] = { .type = NLA_U32 },
573 [NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 },
463d0183 574 [NL80211_ATTR_PID] = { .type = NLA_U32 },
8b787643 575 [NL80211_ATTR_4ADDR] = { .type = NLA_U8 },
c7721c05 576 [NL80211_ATTR_PMKID] = NLA_POLICY_EXACT_LEN_WARN(WLAN_PMKID_LEN),
9588bbd5
JM
577 [NL80211_ATTR_DURATION] = { .type = NLA_U32 },
578 [NL80211_ATTR_COOKIE] = { .type = NLA_U64 },
13ae75b1 579 [NL80211_ATTR_TX_RATES] = { .type = NLA_NESTED },
026331c4
JM
580 [NL80211_ATTR_FRAME] = { .type = NLA_BINARY,
581 .len = IEEE80211_MAX_DATA_LEN },
582 [NL80211_ATTR_FRAME_MATCH] = { .type = NLA_BINARY, },
ab0d76f6
JB
583 [NL80211_ATTR_PS_STATE] = NLA_POLICY_RANGE(NLA_U32,
584 NL80211_PS_DISABLED,
585 NL80211_PS_ENABLED),
d6dc1a38 586 [NL80211_ATTR_CQM] = { .type = NLA_NESTED, },
d5cdfacb 587 [NL80211_ATTR_LOCAL_STATE_CHANGE] = { .type = NLA_FLAG },
fd8aaaf3 588 [NL80211_ATTR_AP_ISOLATE] = { .type = NLA_U8 },
98d2ff8b
JO
589 [NL80211_ATTR_WIPHY_TX_POWER_SETTING] = { .type = NLA_U32 },
590 [NL80211_ATTR_WIPHY_TX_POWER_LEVEL] = { .type = NLA_U32 },
2e161f78 591 [NL80211_ATTR_FRAME_TYPE] = { .type = NLA_U16 },
afe0cbf8
BR
592 [NL80211_ATTR_WIPHY_ANTENNA_TX] = { .type = NLA_U32 },
593 [NL80211_ATTR_WIPHY_ANTENNA_RX] = { .type = NLA_U32 },
885a46d0 594 [NL80211_ATTR_MCAST_RATE] = { .type = NLA_U32 },
f7ca38df 595 [NL80211_ATTR_OFFCHANNEL_TX_OK] = { .type = NLA_FLAG },
dbd2fd65 596 [NL80211_ATTR_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED },
ff1b6e69 597 [NL80211_ATTR_WOWLAN_TRIGGERS] = { .type = NLA_NESTED },
ab0d76f6
JB
598 [NL80211_ATTR_STA_PLINK_STATE] =
599 NLA_POLICY_MAX(NLA_U8, NUM_NL80211_PLINK_STATES - 1),
056e9375
JK
600 [NL80211_ATTR_MEASUREMENT_DURATION] = { .type = NLA_U16 },
601 [NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY] = { .type = NLA_FLAG },
ab0d76f6
JB
602 [NL80211_ATTR_MESH_PEER_AID] =
603 NLA_POLICY_RANGE(NLA_U16, 1, IEEE80211_MAX_AID),
bbe6ad6d 604 [NL80211_ATTR_SCHED_SCAN_INTERVAL] = { .type = NLA_U32 },
e5497d76 605 [NL80211_ATTR_REKEY_DATA] = { .type = NLA_NESTED },
34850ab2 606 [NL80211_ATTR_SCAN_SUPP_RATES] = { .type = NLA_NESTED },
ab0d76f6
JB
607 [NL80211_ATTR_HIDDEN_SSID] =
608 NLA_POLICY_RANGE(NLA_U32,
609 NL80211_HIDDEN_SSID_NOT_IN_USE,
610 NL80211_HIDDEN_SSID_ZERO_CONTENTS),
3d7af878
JB
611 [NL80211_ATTR_IE_PROBE_RESP] =
612 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr,
613 IEEE80211_MAX_DATA_LEN),
614 [NL80211_ATTR_IE_ASSOC_RESP] =
615 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr,
616 IEEE80211_MAX_DATA_LEN),
f4b34b55 617 [NL80211_ATTR_ROAM_SUPPORT] = { .type = NLA_FLAG },
a1f1c21c 618 [NL80211_ATTR_SCHED_SCAN_MATCH] = { .type = NLA_NESTED },
e9f935e3 619 [NL80211_ATTR_TX_NO_CCK_RATE] = { .type = NLA_FLAG },
109086ce
AN
620 [NL80211_ATTR_TDLS_ACTION] = { .type = NLA_U8 },
621 [NL80211_ATTR_TDLS_DIALOG_TOKEN] = { .type = NLA_U8 },
622 [NL80211_ATTR_TDLS_OPERATION] = { .type = NLA_U8 },
623 [NL80211_ATTR_TDLS_SUPPORT] = { .type = NLA_FLAG },
624 [NL80211_ATTR_TDLS_EXTERNAL_SETUP] = { .type = NLA_FLAG },
31fa97c5 625 [NL80211_ATTR_TDLS_INITIATOR] = { .type = NLA_FLAG },
e247bd90 626 [NL80211_ATTR_DONT_WAIT_FOR_ACK] = { .type = NLA_FLAG },
00f740e1
AN
627 [NL80211_ATTR_PROBE_RESP] = { .type = NLA_BINARY,
628 .len = IEEE80211_MAX_DATA_LEN },
8b60b078 629 [NL80211_ATTR_DFS_REGION] = { .type = NLA_U8 },
7e7c8926
BG
630 [NL80211_ATTR_DISABLE_HT] = { .type = NLA_FLAG },
631 [NL80211_ATTR_HT_CAPABILITY_MASK] = {
632 .len = NL80211_HT_CAPABILITY_LEN
633 },
1d9d9213 634 [NL80211_ATTR_NOACK_MAP] = { .type = NLA_U16 },
1b658f11 635 [NL80211_ATTR_INACTIVITY_TIMEOUT] = { .type = NLA_U16 },
4486ea98 636 [NL80211_ATTR_BG_SCAN_PERIOD] = { .type = NLA_U16 },
89a54e48 637 [NL80211_ATTR_WDEV] = { .type = NLA_U64 },
57b5ce07 638 [NL80211_ATTR_USER_REG_HINT_TYPE] = { .type = NLA_U32 },
cb9abd48
JB
639
640 /* need to include at least Auth Transaction and Status Code */
641 [NL80211_ATTR_AUTH_DATA] = NLA_POLICY_MIN_LEN(4),
642
c7721c05 643 [NL80211_ATTR_VHT_CAPABILITY] = NLA_POLICY_EXACT_LEN_WARN(NL80211_VHT_CAPABILITY_LEN),
ed473771 644 [NL80211_ATTR_SCAN_FLAGS] = { .type = NLA_U32 },
ab0d76f6
JB
645 [NL80211_ATTR_P2P_CTWINDOW] = NLA_POLICY_MAX(NLA_U8, 127),
646 [NL80211_ATTR_P2P_OPPPS] = NLA_POLICY_MAX(NLA_U8, 1),
647 [NL80211_ATTR_LOCAL_MESH_POWER_MODE] =
648 NLA_POLICY_RANGE(NLA_U32,
649 NL80211_MESH_POWER_UNKNOWN + 1,
650 NL80211_MESH_POWER_MAX),
77765eaf
VT
651 [NL80211_ATTR_ACL_POLICY] = {. type = NLA_U32 },
652 [NL80211_ATTR_MAC_ADDRS] = { .type = NLA_NESTED },
9d62a986
JM
653 [NL80211_ATTR_STA_CAPABILITY] = { .type = NLA_U16 },
654 [NL80211_ATTR_STA_EXT_CAPABILITY] = { .type = NLA_BINARY, },
3713b4e3 655 [NL80211_ATTR_SPLIT_WIPHY_DUMP] = { .type = NLA_FLAG, },
ee2aca34
JB
656 [NL80211_ATTR_DISABLE_VHT] = { .type = NLA_FLAG },
657 [NL80211_ATTR_VHT_CAPABILITY_MASK] = {
658 .len = NL80211_VHT_CAPABILITY_LEN,
659 },
355199e0
JM
660 [NL80211_ATTR_MDID] = { .type = NLA_U16 },
661 [NL80211_ATTR_IE_RIC] = { .type = NLA_BINARY,
662 .len = IEEE80211_MAX_DATA_LEN },
0e1a1d85 663 [NL80211_ATTR_CRIT_PROT_ID] = { .type = NLA_U16 },
cb9abd48
JB
664 [NL80211_ATTR_MAX_CRIT_PROT_DURATION] =
665 NLA_POLICY_MAX(NLA_U16, NL80211_CRIT_PROTO_MAX_DURATION),
ab0d76f6
JB
666 [NL80211_ATTR_PEER_AID] =
667 NLA_POLICY_RANGE(NLA_U16, 1, IEEE80211_MAX_AID),
16ef1fe2
SW
668 [NL80211_ATTR_CH_SWITCH_COUNT] = { .type = NLA_U32 },
669 [NL80211_ATTR_CH_SWITCH_BLOCK_TX] = { .type = NLA_FLAG },
670 [NL80211_ATTR_CSA_IES] = { .type = NLA_NESTED },
00c207ed
JC
671 [NL80211_ATTR_CNTDWN_OFFS_BEACON] = { .type = NLA_BINARY },
672 [NL80211_ATTR_CNTDWN_OFFS_PRESP] = { .type = NLA_BINARY },
cb9abd48 673 [NL80211_ATTR_STA_SUPPORTED_CHANNELS] = NLA_POLICY_MIN_LEN(2),
c8b82802
JB
674 /*
675 * The value of the Length field of the Supported Operating
676 * Classes element is between 2 and 253.
677 */
678 [NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES] =
679 NLA_POLICY_RANGE(NLA_BINARY, 2, 253),
5336fa88 680 [NL80211_ATTR_HANDLE_DFS] = { .type = NLA_FLAG },
60f4a7b1 681 [NL80211_ATTR_OPMODE_NOTIF] = { .type = NLA_U8 },
ad7e718c
JB
682 [NL80211_ATTR_VENDOR_ID] = { .type = NLA_U32 },
683 [NL80211_ATTR_VENDOR_SUBCMD] = { .type = NLA_U32 },
684 [NL80211_ATTR_VENDOR_DATA] = { .type = NLA_BINARY },
c8b82802
JB
685 [NL80211_ATTR_QOS_MAP] = NLA_POLICY_RANGE(NLA_BINARY,
686 IEEE80211_QOS_MAP_LEN_MIN,
687 IEEE80211_QOS_MAP_LEN_MAX),
c7721c05 688 [NL80211_ATTR_MAC_HINT] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
1df4a510 689 [NL80211_ATTR_WIPHY_FREQ_HINT] = { .type = NLA_U32 },
df942e7b 690 [NL80211_ATTR_TDLS_PEER_CAPABILITY] = { .type = NLA_U32 },
18e5ca65 691 [NL80211_ATTR_SOCKET_OWNER] = { .type = NLA_FLAG },
34d22ce2 692 [NL80211_ATTR_CSA_C_OFFSETS_TX] = { .type = NLA_BINARY },
bab5ab7d 693 [NL80211_ATTR_USE_RRM] = { .type = NLA_FLAG },
ab0d76f6
JB
694 [NL80211_ATTR_TSID] = NLA_POLICY_MAX(NLA_U8, IEEE80211_NUM_TIDS - 1),
695 [NL80211_ATTR_USER_PRIO] =
696 NLA_POLICY_MAX(NLA_U8, IEEE80211_NUM_UPS - 1),
960d01ac 697 [NL80211_ATTR_ADMITTED_TIME] = { .type = NLA_U16 },
18998c38 698 [NL80211_ATTR_SMPS_MODE] = { .type = NLA_U8 },
5cde05c6 699 [NL80211_ATTR_OPER_CLASS] = { .type = NLA_U8 },
c7721c05 700 [NL80211_ATTR_MAC_MASK] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
1bdd716c 701 [NL80211_ATTR_WIPHY_SELF_MANAGED_REG] = { .type = NLA_FLAG },
4b681c82 702 [NL80211_ATTR_NETNS_FD] = { .type = NLA_U32 },
9c748934 703 [NL80211_ATTR_SCHED_SCAN_DELAY] = { .type = NLA_U32 },
05050753 704 [NL80211_ATTR_REG_INDOOR] = { .type = NLA_FLAG },
34d50519 705 [NL80211_ATTR_PBSS] = { .type = NLA_FLAG },
38de03d2 706 [NL80211_ATTR_BSS_SELECT] = { .type = NLA_NESTED },
ab0d76f6
JB
707 [NL80211_ATTR_STA_SUPPORT_P2P_PS] =
708 NLA_POLICY_MAX(NLA_U8, NUM_NL80211_P2P_PS_STATUS - 1),
c6e6a0c8
AE
709 [NL80211_ATTR_MU_MIMO_GROUP_DATA] = {
710 .len = VHT_MUMIMO_GROUPS_DATA_LEN
711 },
c7721c05 712 [NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
ab0d76f6 713 [NL80211_ATTR_NAN_MASTER_PREF] = NLA_POLICY_MIN(NLA_U8, 1),
8585989d 714 [NL80211_ATTR_BANDS] = { .type = NLA_U32 },
a442b761 715 [NL80211_ATTR_NAN_FUNC] = { .type = NLA_NESTED },
348bd456
JM
716 [NL80211_ATTR_FILS_KEK] = { .type = NLA_BINARY,
717 .len = FILS_MAX_KEK_LEN },
c7721c05 718 [NL80211_ATTR_FILS_NONCES] = NLA_POLICY_EXACT_LEN_WARN(2 * FILS_NONCE_LEN),
ce0ce13a 719 [NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED] = { .type = NLA_FLAG, },
c7721c05 720 [NL80211_ATTR_BSSID] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
bf95ecdb 721 [NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI] = { .type = NLA_S8 },
722 [NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST] = {
723 .len = sizeof(struct nl80211_bss_select_rssi_adjust)
724 },
3093ebbe 725 [NL80211_ATTR_TIMEOUT_REASON] = { .type = NLA_U32 },
a3caf744
VK
726 [NL80211_ATTR_FILS_ERP_USERNAME] = { .type = NLA_BINARY,
727 .len = FILS_ERP_MAX_USERNAME_LEN },
728 [NL80211_ATTR_FILS_ERP_REALM] = { .type = NLA_BINARY,
729 .len = FILS_ERP_MAX_REALM_LEN },
730 [NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] = { .type = NLA_U16 },
731 [NL80211_ATTR_FILS_ERP_RRK] = { .type = NLA_BINARY,
732 .len = FILS_ERP_MAX_RRK_LEN },
c7721c05 733 [NL80211_ATTR_FILS_CACHE_ID] = NLA_POLICY_EXACT_LEN_WARN(2),
a3caf744 734 [NL80211_ATTR_PMK] = { .type = NLA_BINARY, .len = PMK_MAX_LEN },
cb9abd48 735 [NL80211_ATTR_PMKR0_NAME] = NLA_POLICY_EXACT_LEN(WLAN_PMK_NAME_LEN),
ca986ad9 736 [NL80211_ATTR_SCHED_SCAN_MULTI] = { .type = NLA_FLAG },
40cbfa90 737 [NL80211_ATTR_EXTERNAL_AUTH_SUPPORT] = { .type = NLA_FLAG },
52539ca8
THJ
738
739 [NL80211_ATTR_TXQ_LIMIT] = { .type = NLA_U32 },
740 [NL80211_ATTR_TXQ_MEMORY_LIMIT] = { .type = NLA_U32 },
741 [NL80211_ATTR_TXQ_QUANTUM] = { .type = NLA_U32 },
c8b82802 742 [NL80211_ATTR_HE_CAPABILITY] =
a3a20feb
JB
743 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_he_capa,
744 NL80211_HE_MAX_CAPABILITY_LEN),
0e012b4e
JB
745 [NL80211_ATTR_FTM_RESPONDER] =
746 NLA_POLICY_NESTED(nl80211_ftm_responder_policy),
9bb7e0f2
JB
747 [NL80211_ATTR_TIMEOUT] = NLA_POLICY_MIN(NLA_U32, 1),
748 [NL80211_ATTR_PEER_MEASUREMENTS] =
23323289 749 NLA_POLICY_NESTED(nl80211_pmsr_attr_policy),
36647055 750 [NL80211_ATTR_AIRTIME_WEIGHT] = NLA_POLICY_MIN(NLA_U16, 1),
26f7044e
CHH
751 [NL80211_ATTR_SAE_PASSWORD] = { .type = NLA_BINARY,
752 .len = SAE_PASSWORD_MAX_LEN },
a0de1ca3 753 [NL80211_ATTR_TWT_RESPONDER] = { .type = NLA_FLAG },
796e90f4 754 [NL80211_ATTR_HE_OBSS_PD] = NLA_POLICY_NESTED(he_obss_pd_policy),
14f34e36 755 [NL80211_ATTR_VLAN_ID] = NLA_POLICY_RANGE(NLA_U16, 1, VLAN_N_VID - 2),
5c5e52d1 756 [NL80211_ATTR_HE_BSS_COLOR] = NLA_POLICY_NESTED(he_bss_color_policy),
77f576de
T
757 [NL80211_ATTR_TID_CONFIG] =
758 NLA_POLICY_NESTED_ARRAY(nl80211_tid_config_attr_policy),
5631d96a 759 [NL80211_ATTR_CONTROL_PORT_NO_PREAUTH] = { .type = NLA_FLAG },
7fc82af8
VJ
760 [NL80211_ATTR_PMK_LIFETIME] = NLA_POLICY_MIN(NLA_U32, 1),
761 [NL80211_ATTR_PMK_REAUTH_THRESHOLD] = NLA_POLICY_RANGE(NLA_U8, 1, 100),
9dba48a6 762 [NL80211_ATTR_RECEIVE_MULTICAST] = { .type = NLA_FLAG },
942ba88b 763 [NL80211_ATTR_WIPHY_FREQ_OFFSET] = NLA_POLICY_RANGE(NLA_U32, 0, 999),
2032f3b2 764 [NL80211_ATTR_SCAN_FREQ_KHZ] = { .type = NLA_NESTED },
8140860c
JB
765 [NL80211_ATTR_HE_6GHZ_CAPABILITY] =
766 NLA_POLICY_EXACT_LEN(sizeof(struct ieee80211_he_6ghz_capa)),
291c49de
AD
767 [NL80211_ATTR_FILS_DISCOVERY] =
768 NLA_POLICY_NESTED(nl80211_fils_discovery_policy),
7443dcd1
AD
769 [NL80211_ATTR_UNSOL_BCAST_PROBE_RESP] =
770 NLA_POLICY_NESTED(nl80211_unsol_bcast_probe_resp_policy),
d2b7588a
TP
771 [NL80211_ATTR_S1G_CAPABILITY] =
772 NLA_POLICY_EXACT_LEN(IEEE80211_S1G_CAPABILITY_LEN),
773 [NL80211_ATTR_S1G_CAPABILITY_MASK] =
774 NLA_POLICY_EXACT_LEN(IEEE80211_S1G_CAPABILITY_LEN),
9f0ffa41
RD
775 [NL80211_ATTR_SAE_PWE] =
776 NLA_POLICY_RANGE(NLA_U8, NL80211_SAE_PWE_HUNT_AND_PECK,
777 NL80211_SAE_PWE_BOTH),
3bb02143 778 [NL80211_ATTR_RECONNECT_REQUESTED] = { .type = NLA_REJECT },
6bdb68ce 779 [NL80211_ATTR_SAR_SPEC] = NLA_POLICY_NESTED(sar_policy),
b6db0f89 780 [NL80211_ATTR_DISABLE_HE] = { .type = NLA_FLAG },
0d2ab3ae
JC
781 [NL80211_ATTR_OBSS_COLOR_BITMAP] = { .type = NLA_U64 },
782 [NL80211_ATTR_COLOR_CHANGE_COUNT] = { .type = NLA_U8 },
783 [NL80211_ATTR_COLOR_CHANGE_COLOR] = { .type = NLA_U8 },
784 [NL80211_ATTR_COLOR_CHANGE_ELEMS] = NLA_POLICY_NESTED(nl80211_policy),
dc1e3cb8
JC
785 [NL80211_ATTR_MBSSID_CONFIG] =
786 NLA_POLICY_NESTED(nl80211_mbssid_config_policy),
787 [NL80211_ATTR_MBSSID_ELEMS] = { .type = NLA_NESTED },
a95bfb87 788 [NL80211_ATTR_RADAR_BACKGROUND] = { .type = NLA_FLAG },
47301a74 789 [NL80211_ATTR_AP_SETTINGS_FLAGS] = { .type = NLA_U32 },
ea05fd35
IP
790 [NL80211_ATTR_EHT_CAPABILITY] =
791 NLA_POLICY_RANGE(NLA_BINARY,
792 NL80211_EHT_MIN_CAPABILITY_LEN,
793 NL80211_EHT_MAX_CAPABILITY_LEN),
36f84235 794 [NL80211_ATTR_DISABLE_EHT] = { .type = NLA_FLAG },
7b0a0e3c
JB
795 [NL80211_ATTR_MLO_LINKS] =
796 NLA_POLICY_NESTED_ARRAY(nl80211_policy),
797 [NL80211_ATTR_MLO_LINK_ID] =
798 NLA_POLICY_RANGE(NLA_U8, 0, IEEE80211_MLD_MAX_NUM_LINKS),
d648c230 799 [NL80211_ATTR_MLD_ADDR] = NLA_POLICY_EXACT_LEN(ETH_ALEN),
efbabc11 800 [NL80211_ATTR_MLO_SUPPORT] = { .type = NLA_FLAG },
ecad3b0b 801 [NL80211_ATTR_MAX_NUM_AKM_SUITES] = { .type = NLA_REJECT },
55682965
JB
802};
803
e31b8213 804/* policy for the key attributes */
b54452b0 805static const struct nla_policy nl80211_key_policy[NL80211_KEY_MAX + 1] = {
fffd0934 806 [NL80211_KEY_DATA] = { .type = NLA_BINARY, .len = WLAN_MAX_KEY_LEN },
b9454e83
JB
807 [NL80211_KEY_IDX] = { .type = NLA_U8 },
808 [NL80211_KEY_CIPHER] = { .type = NLA_U32 },
81962267 809 [NL80211_KEY_SEQ] = { .type = NLA_BINARY, .len = 16 },
b9454e83
JB
810 [NL80211_KEY_DEFAULT] = { .type = NLA_FLAG },
811 [NL80211_KEY_DEFAULT_MGMT] = { .type = NLA_FLAG },
ab0d76f6 812 [NL80211_KEY_TYPE] = NLA_POLICY_MAX(NLA_U32, NUM_NL80211_KEYTYPES - 1),
dbd2fd65 813 [NL80211_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED },
6cdd3979 814 [NL80211_KEY_MODE] = NLA_POLICY_RANGE(NLA_U8, 0, NL80211_KEY_SET_TX),
dbd2fd65
JB
815};
816
817/* policy for the key default flags */
818static const struct nla_policy
819nl80211_key_default_policy[NUM_NL80211_KEY_DEFAULT_TYPES] = {
820 [NL80211_KEY_DEFAULT_TYPE_UNICAST] = { .type = NLA_FLAG },
821 [NL80211_KEY_DEFAULT_TYPE_MULTICAST] = { .type = NLA_FLAG },
b9454e83
JB
822};
823
f83ace3b 824#ifdef CONFIG_PM
ff1b6e69
JB
825/* policy for WoWLAN attributes */
826static const struct nla_policy
827nl80211_wowlan_policy[NUM_NL80211_WOWLAN_TRIG] = {
828 [NL80211_WOWLAN_TRIG_ANY] = { .type = NLA_FLAG },
829 [NL80211_WOWLAN_TRIG_DISCONNECT] = { .type = NLA_FLAG },
830 [NL80211_WOWLAN_TRIG_MAGIC_PKT] = { .type = NLA_FLAG },
831 [NL80211_WOWLAN_TRIG_PKT_PATTERN] = { .type = NLA_NESTED },
77dbbb13
JB
832 [NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE] = { .type = NLA_FLAG },
833 [NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST] = { .type = NLA_FLAG },
834 [NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE] = { .type = NLA_FLAG },
835 [NL80211_WOWLAN_TRIG_RFKILL_RELEASE] = { .type = NLA_FLAG },
2a0e047e 836 [NL80211_WOWLAN_TRIG_TCP_CONNECTION] = { .type = NLA_NESTED },
8cd4d456 837 [NL80211_WOWLAN_TRIG_NET_DETECT] = { .type = NLA_NESTED },
2a0e047e
JB
838};
839
840static const struct nla_policy
841nl80211_wowlan_tcp_policy[NUM_NL80211_WOWLAN_TCP] = {
842 [NL80211_WOWLAN_TCP_SRC_IPV4] = { .type = NLA_U32 },
843 [NL80211_WOWLAN_TCP_DST_IPV4] = { .type = NLA_U32 },
c7721c05 844 [NL80211_WOWLAN_TCP_DST_MAC] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
2a0e047e
JB
845 [NL80211_WOWLAN_TCP_SRC_PORT] = { .type = NLA_U16 },
846 [NL80211_WOWLAN_TCP_DST_PORT] = { .type = NLA_U16 },
bc043585 847 [NL80211_WOWLAN_TCP_DATA_PAYLOAD] = NLA_POLICY_MIN_LEN(1),
2a0e047e
JB
848 [NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ] = {
849 .len = sizeof(struct nl80211_wowlan_tcp_data_seq)
850 },
851 [NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN] = {
852 .len = sizeof(struct nl80211_wowlan_tcp_data_token)
853 },
854 [NL80211_WOWLAN_TCP_DATA_INTERVAL] = { .type = NLA_U32 },
bc043585
JB
855 [NL80211_WOWLAN_TCP_WAKE_PAYLOAD] = NLA_POLICY_MIN_LEN(1),
856 [NL80211_WOWLAN_TCP_WAKE_MASK] = NLA_POLICY_MIN_LEN(1),
ff1b6e69 857};
f83ace3b 858#endif /* CONFIG_PM */
ff1b6e69 859
be29b99a
AK
860/* policy for coalesce rule attributes */
861static const struct nla_policy
862nl80211_coalesce_policy[NUM_NL80211_ATTR_COALESCE_RULE] = {
863 [NL80211_ATTR_COALESCE_RULE_DELAY] = { .type = NLA_U32 },
ab0d76f6
JB
864 [NL80211_ATTR_COALESCE_RULE_CONDITION] =
865 NLA_POLICY_RANGE(NLA_U32,
866 NL80211_COALESCE_CONDITION_MATCH,
867 NL80211_COALESCE_CONDITION_NO_MATCH),
be29b99a
AK
868 [NL80211_ATTR_COALESCE_RULE_PKT_PATTERN] = { .type = NLA_NESTED },
869};
870
e5497d76
JB
871/* policy for GTK rekey offload attributes */
872static const struct nla_policy
873nl80211_rekey_policy[NUM_NL80211_REKEY_DATA] = {
093a48d2
NE
874 [NL80211_REKEY_DATA_KEK] = {
875 .type = NLA_BINARY,
876 .len = NL80211_KEK_EXT_LEN
877 },
878 [NL80211_REKEY_DATA_KCK] = {
879 .type = NLA_BINARY,
880 .len = NL80211_KCK_EXT_LEN
881 },
cb9abd48 882 [NL80211_REKEY_DATA_REPLAY_CTR] = NLA_POLICY_EXACT_LEN(NL80211_REPLAY_CTR_LEN),
093a48d2 883 [NL80211_REKEY_DATA_AKM] = { .type = NLA_U32 },
e5497d76
JB
884};
885
1e1b11b6 886static const struct nla_policy
887nl80211_match_band_rssi_policy[NUM_NL80211_BANDS] = {
888 [NL80211_BAND_2GHZ] = { .type = NLA_S32 },
889 [NL80211_BAND_5GHZ] = { .type = NLA_S32 },
e548a1c3 890 [NL80211_BAND_6GHZ] = { .type = NLA_S32 },
1e1b11b6 891 [NL80211_BAND_60GHZ] = { .type = NLA_S32 },
63fa0426 892 [NL80211_BAND_LC] = { .type = NLA_S32 },
1e1b11b6 893};
894
a1f1c21c
LC
895static const struct nla_policy
896nl80211_match_policy[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1] = {
4a4ab0d7 897 [NL80211_SCHED_SCAN_MATCH_ATTR_SSID] = { .type = NLA_BINARY,
a1f1c21c 898 .len = IEEE80211_MAX_SSID_LEN },
c7721c05 899 [NL80211_SCHED_SCAN_MATCH_ATTR_BSSID] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
88e920b4 900 [NL80211_SCHED_SCAN_MATCH_ATTR_RSSI] = { .type = NLA_U32 },
1e1b11b6 901 [NL80211_SCHED_SCAN_MATCH_PER_BAND_RSSI] =
902 NLA_POLICY_NESTED(nl80211_match_band_rssi_policy),
a1f1c21c
LC
903};
904
3b06d277
AS
905static const struct nla_policy
906nl80211_plan_policy[NL80211_SCHED_SCAN_PLAN_MAX + 1] = {
907 [NL80211_SCHED_SCAN_PLAN_INTERVAL] = { .type = NLA_U32 },
908 [NL80211_SCHED_SCAN_PLAN_ITERATIONS] = { .type = NLA_U32 },
909};
910
38de03d2
AS
911static const struct nla_policy
912nl80211_bss_select_policy[NL80211_BSS_SELECT_ATTR_MAX + 1] = {
913 [NL80211_BSS_SELECT_ATTR_RSSI] = { .type = NLA_FLAG },
914 [NL80211_BSS_SELECT_ATTR_BAND_PREF] = { .type = NLA_U32 },
915 [NL80211_BSS_SELECT_ATTR_RSSI_ADJUST] = {
916 .len = sizeof(struct nl80211_bss_select_rssi_adjust)
917 },
918};
919
a442b761
AB
920/* policy for NAN function attributes */
921static const struct nla_policy
922nl80211_nan_func_policy[NL80211_NAN_FUNC_ATTR_MAX + 1] = {
cb9abd48
JB
923 [NL80211_NAN_FUNC_TYPE] =
924 NLA_POLICY_MAX(NLA_U8, NL80211_NAN_FUNC_MAX_TYPE),
0a27844c 925 [NL80211_NAN_FUNC_SERVICE_ID] = {
a442b761
AB
926 .len = NL80211_NAN_FUNC_SERVICE_ID_LEN },
927 [NL80211_NAN_FUNC_PUBLISH_TYPE] = { .type = NLA_U8 },
928 [NL80211_NAN_FUNC_PUBLISH_BCAST] = { .type = NLA_FLAG },
929 [NL80211_NAN_FUNC_SUBSCRIBE_ACTIVE] = { .type = NLA_FLAG },
930 [NL80211_NAN_FUNC_FOLLOW_UP_ID] = { .type = NLA_U8 },
931 [NL80211_NAN_FUNC_FOLLOW_UP_REQ_ID] = { .type = NLA_U8 },
c7721c05 932 [NL80211_NAN_FUNC_FOLLOW_UP_DEST] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
a442b761
AB
933 [NL80211_NAN_FUNC_CLOSE_RANGE] = { .type = NLA_FLAG },
934 [NL80211_NAN_FUNC_TTL] = { .type = NLA_U32 },
935 [NL80211_NAN_FUNC_SERVICE_INFO] = { .type = NLA_BINARY,
936 .len = NL80211_NAN_FUNC_SERVICE_SPEC_INFO_MAX_LEN },
937 [NL80211_NAN_FUNC_SRF] = { .type = NLA_NESTED },
938 [NL80211_NAN_FUNC_RX_MATCH_FILTER] = { .type = NLA_NESTED },
939 [NL80211_NAN_FUNC_TX_MATCH_FILTER] = { .type = NLA_NESTED },
940 [NL80211_NAN_FUNC_INSTANCE_ID] = { .type = NLA_U8 },
941 [NL80211_NAN_FUNC_TERM_REASON] = { .type = NLA_U8 },
942};
943
944/* policy for Service Response Filter attributes */
945static const struct nla_policy
946nl80211_nan_srf_policy[NL80211_NAN_SRF_ATTR_MAX + 1] = {
947 [NL80211_NAN_SRF_INCLUDE] = { .type = NLA_FLAG },
948 [NL80211_NAN_SRF_BF] = { .type = NLA_BINARY,
949 .len = NL80211_NAN_FUNC_SRF_MAX_LEN },
950 [NL80211_NAN_SRF_BF_IDX] = { .type = NLA_U8 },
951 [NL80211_NAN_SRF_MAC_ADDRS] = { .type = NLA_NESTED },
952};
953
ad670233
PX
954/* policy for packet pattern attributes */
955static const struct nla_policy
956nl80211_packet_pattern_policy[MAX_NL80211_PKTPAT + 1] = {
957 [NL80211_PKTPAT_MASK] = { .type = NLA_BINARY, },
958 [NL80211_PKTPAT_PATTERN] = { .type = NLA_BINARY, },
959 [NL80211_PKTPAT_OFFSET] = { .type = NLA_U32 },
960};
961
ce6b6974
JB
962static int nl80211_prepare_wdev_dump(struct netlink_callback *cb,
963 struct cfg80211_registered_device **rdev,
964 struct wireless_dev **wdev,
965 struct nlattr **attrbuf)
a043897a 966{
97990a06 967 int err;
a043897a 968
97990a06 969 if (!cb->args[0]) {
ce6b6974
JB
970 struct nlattr **attrbuf_free = NULL;
971
972 if (!attrbuf) {
973 attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf),
974 GFP_KERNEL);
975 if (!attrbuf)
976 return -ENOMEM;
977 attrbuf_free = attrbuf;
978 }
50508d94 979
8cb08174
JB
980 err = nlmsg_parse_deprecated(cb->nlh,
981 GENL_HDRLEN + nl80211_fam.hdrsize,
50508d94 982 attrbuf, nl80211_fam.maxattr,
8cb08174 983 nl80211_policy, NULL);
50508d94 984 if (err) {
ce6b6974 985 kfree(attrbuf_free);
ea90e0dc 986 return err;
50508d94 987 }
67748893 988
a05829a7
JB
989 rtnl_lock();
990 *wdev = __cfg80211_wdev_from_attrs(NULL, sock_net(cb->skb->sk),
50508d94 991 attrbuf);
ce6b6974 992 kfree(attrbuf_free);
a05829a7
JB
993 if (IS_ERR(*wdev)) {
994 rtnl_unlock();
ea90e0dc 995 return PTR_ERR(*wdev);
a05829a7 996 }
f26cbf40 997 *rdev = wiphy_to_rdev((*wdev)->wiphy);
a05829a7
JB
998 mutex_lock(&(*rdev)->wiphy.mtx);
999 rtnl_unlock();
c319d50b
JB
1000 /* 0 is the first index - add 1 to parse only once */
1001 cb->args[0] = (*rdev)->wiphy_idx + 1;
97990a06
JB
1002 cb->args[1] = (*wdev)->identifier;
1003 } else {
c319d50b 1004 /* subtract the 1 again here */
a05829a7 1005 struct wiphy *wiphy;
97990a06 1006 struct wireless_dev *tmp;
67748893 1007
a05829a7
JB
1008 rtnl_lock();
1009 wiphy = wiphy_idx_to_wiphy(cb->args[0] - 1);
1010 if (!wiphy) {
1011 rtnl_unlock();
ea90e0dc 1012 return -ENODEV;
a05829a7 1013 }
f26cbf40 1014 *rdev = wiphy_to_rdev(wiphy);
97990a06 1015 *wdev = NULL;
67748893 1016
53873f13 1017 list_for_each_entry(tmp, &(*rdev)->wiphy.wdev_list, list) {
97990a06
JB
1018 if (tmp->identifier == cb->args[1]) {
1019 *wdev = tmp;
1020 break;
1021 }
1022 }
67748893 1023
a05829a7
JB
1024 if (!*wdev) {
1025 rtnl_unlock();
ea90e0dc 1026 return -ENODEV;
a05829a7
JB
1027 }
1028 mutex_lock(&(*rdev)->wiphy.mtx);
1029 rtnl_unlock();
67748893
JB
1030 }
1031
67748893 1032 return 0;
67748893
JB
1033}
1034
55682965 1035/* message building helper */
9bb7e0f2
JB
1036void *nl80211hdr_put(struct sk_buff *skb, u32 portid, u32 seq,
1037 int flags, u8 cmd)
55682965
JB
1038{
1039 /* since there is no private header just add the generic one */
15e47304 1040 return genlmsg_put(skb, portid, seq, &nl80211_fam, flags, cmd);
55682965
JB
1041}
1042
50f32718
HD
1043static int nl80211_msg_put_wmm_rules(struct sk_buff *msg,
1044 const struct ieee80211_reg_rule *rule)
1045{
1046 int j;
1047 struct nlattr *nl_wmm_rules =
ae0be8de 1048 nla_nest_start_noflag(msg, NL80211_FREQUENCY_ATTR_WMM);
50f32718
HD
1049
1050 if (!nl_wmm_rules)
1051 goto nla_put_failure;
1052
1053 for (j = 0; j < IEEE80211_NUM_ACS; j++) {
ae0be8de 1054 struct nlattr *nl_wmm_rule = nla_nest_start_noflag(msg, j);
50f32718
HD
1055
1056 if (!nl_wmm_rule)
1057 goto nla_put_failure;
1058
1059 if (nla_put_u16(msg, NL80211_WMMR_CW_MIN,
38cb87ee 1060 rule->wmm_rule.client[j].cw_min) ||
50f32718 1061 nla_put_u16(msg, NL80211_WMMR_CW_MAX,
38cb87ee 1062 rule->wmm_rule.client[j].cw_max) ||
50f32718 1063 nla_put_u8(msg, NL80211_WMMR_AIFSN,
38cb87ee 1064 rule->wmm_rule.client[j].aifsn) ||
d3c89bbc
HD
1065 nla_put_u16(msg, NL80211_WMMR_TXOP,
1066 rule->wmm_rule.client[j].cot))
50f32718
HD
1067 goto nla_put_failure;
1068
1069 nla_nest_end(msg, nl_wmm_rule);
1070 }
1071 nla_nest_end(msg, nl_wmm_rules);
1072
1073 return 0;
1074
1075nla_put_failure:
1076 return -ENOBUFS;
1077}
1078
1079static int nl80211_msg_put_channel(struct sk_buff *msg, struct wiphy *wiphy,
cdc89b97
JB
1080 struct ieee80211_channel *chan,
1081 bool large)
5dab3b8a 1082{
ea077c1c
RL
1083 /* Some channels must be completely excluded from the
1084 * list to protect old user-space tools from breaking
1085 */
1086 if (!large && chan->flags &
1087 (IEEE80211_CHAN_NO_10MHZ | IEEE80211_CHAN_NO_20MHZ))
1088 return 0;
f8d504ca
JB
1089 if (!large && chan->freq_offset)
1090 return 0;
ea077c1c 1091
9360ffd1
DM
1092 if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_FREQ,
1093 chan->center_freq))
1094 goto nla_put_failure;
5dab3b8a 1095
942ba88b
TP
1096 if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_OFFSET, chan->freq_offset))
1097 goto nla_put_failure;
1098
9360ffd1
DM
1099 if ((chan->flags & IEEE80211_CHAN_DISABLED) &&
1100 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_DISABLED))
1101 goto nla_put_failure;
8fe02e16
LR
1102 if (chan->flags & IEEE80211_CHAN_NO_IR) {
1103 if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_IR))
1104 goto nla_put_failure;
1105 if (nla_put_flag(msg, __NL80211_FREQUENCY_ATTR_NO_IBSS))
1106 goto nla_put_failure;
1107 }
cdc89b97
JB
1108 if (chan->flags & IEEE80211_CHAN_RADAR) {
1109 if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR))
1110 goto nla_put_failure;
1111 if (large) {
1112 u32 time;
1113
1114 time = elapsed_jiffies_msecs(chan->dfs_state_entered);
1115
1116 if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_STATE,
1117 chan->dfs_state))
1118 goto nla_put_failure;
1119 if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_TIME,
1120 time))
1121 goto nla_put_failure;
089027e5
JD
1122 if (nla_put_u32(msg,
1123 NL80211_FREQUENCY_ATTR_DFS_CAC_TIME,
1124 chan->dfs_cac_ms))
1125 goto nla_put_failure;
cdc89b97
JB
1126 }
1127 }
5dab3b8a 1128
fe1abafd
JB
1129 if (large) {
1130 if ((chan->flags & IEEE80211_CHAN_NO_HT40MINUS) &&
1131 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HT40_MINUS))
1132 goto nla_put_failure;
1133 if ((chan->flags & IEEE80211_CHAN_NO_HT40PLUS) &&
1134 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HT40_PLUS))
1135 goto nla_put_failure;
1136 if ((chan->flags & IEEE80211_CHAN_NO_80MHZ) &&
1137 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_80MHZ))
1138 goto nla_put_failure;
1139 if ((chan->flags & IEEE80211_CHAN_NO_160MHZ) &&
1140 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_160MHZ))
1141 goto nla_put_failure;
570dbde1
DS
1142 if ((chan->flags & IEEE80211_CHAN_INDOOR_ONLY) &&
1143 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_INDOOR_ONLY))
1144 goto nla_put_failure;
06f207fc
AN
1145 if ((chan->flags & IEEE80211_CHAN_IR_CONCURRENT) &&
1146 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_IR_CONCURRENT))
570dbde1 1147 goto nla_put_failure;
ea077c1c
RL
1148 if ((chan->flags & IEEE80211_CHAN_NO_20MHZ) &&
1149 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_20MHZ))
1150 goto nla_put_failure;
1151 if ((chan->flags & IEEE80211_CHAN_NO_10MHZ) &&
1152 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_10MHZ))
1153 goto nla_put_failure;
1e61d82c
HD
1154 if ((chan->flags & IEEE80211_CHAN_NO_HE) &&
1155 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HE))
1156 goto nla_put_failure;
d65a9770
TP
1157 if ((chan->flags & IEEE80211_CHAN_1MHZ) &&
1158 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_1MHZ))
1159 goto nla_put_failure;
1160 if ((chan->flags & IEEE80211_CHAN_2MHZ) &&
1161 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_2MHZ))
1162 goto nla_put_failure;
1163 if ((chan->flags & IEEE80211_CHAN_4MHZ) &&
1164 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_4MHZ))
1165 goto nla_put_failure;
1166 if ((chan->flags & IEEE80211_CHAN_8MHZ) &&
1167 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_8MHZ))
1168 goto nla_put_failure;
1169 if ((chan->flags & IEEE80211_CHAN_16MHZ) &&
1170 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_16MHZ))
1171 goto nla_put_failure;
c2b3d769
S
1172 if ((chan->flags & IEEE80211_CHAN_NO_320MHZ) &&
1173 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_320MHZ))
1174 goto nla_put_failure;
31846b65
IP
1175 if ((chan->flags & IEEE80211_CHAN_NO_EHT) &&
1176 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_EHT))
1177 goto nla_put_failure;
fe1abafd
JB
1178 }
1179
9360ffd1
DM
1180 if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER,
1181 DBM_TO_MBM(chan->max_power)))
1182 goto nla_put_failure;
5dab3b8a 1183
50f32718
HD
1184 if (large) {
1185 const struct ieee80211_reg_rule *rule =
b88d26d9 1186 freq_reg_info(wiphy, MHZ_TO_KHZ(chan->center_freq));
50f32718 1187
38cb87ee 1188 if (!IS_ERR_OR_NULL(rule) && rule->has_wmm) {
50f32718
HD
1189 if (nl80211_msg_put_wmm_rules(msg, rule))
1190 goto nla_put_failure;
1191 }
1192 }
1193
5dab3b8a
LR
1194 return 0;
1195
1196 nla_put_failure:
1197 return -ENOBUFS;
1198}
1199
52539ca8
THJ
1200static bool nl80211_put_txq_stats(struct sk_buff *msg,
1201 struct cfg80211_txq_stats *txqstats,
1202 int attrtype)
1203{
1204 struct nlattr *txqattr;
1205
1206#define PUT_TXQVAL_U32(attr, memb) do { \
1207 if (txqstats->filled & BIT(NL80211_TXQ_STATS_ ## attr) && \
1208 nla_put_u32(msg, NL80211_TXQ_STATS_ ## attr, txqstats->memb)) \
1209 return false; \
1210 } while (0)
1211
ae0be8de 1212 txqattr = nla_nest_start_noflag(msg, attrtype);
52539ca8
THJ
1213 if (!txqattr)
1214 return false;
1215
1216 PUT_TXQVAL_U32(BACKLOG_BYTES, backlog_bytes);
1217 PUT_TXQVAL_U32(BACKLOG_PACKETS, backlog_packets);
1218 PUT_TXQVAL_U32(FLOWS, flows);
1219 PUT_TXQVAL_U32(DROPS, drops);
1220 PUT_TXQVAL_U32(ECN_MARKS, ecn_marks);
1221 PUT_TXQVAL_U32(OVERLIMIT, overlimit);
1222 PUT_TXQVAL_U32(OVERMEMORY, overmemory);
1223 PUT_TXQVAL_U32(COLLISIONS, collisions);
1224 PUT_TXQVAL_U32(TX_BYTES, tx_bytes);
1225 PUT_TXQVAL_U32(TX_PACKETS, tx_packets);
1226 PUT_TXQVAL_U32(MAX_FLOWS, max_flows);
1227 nla_nest_end(msg, txqattr);
1228
1229#undef PUT_TXQVAL_U32
1230 return true;
1231}
1232
55682965
JB
1233/* netlink command implementations */
1234
7b0a0e3c
JB
1235/**
1236 * nl80211_link_id - return link ID
1237 * @attrs: attributes to look at
1238 *
1239 * Returns: the link ID or 0 if not given
1240 *
1241 * Note this function doesn't do any validation of the link
1242 * ID validity wrt. links that were actually added, so it must
1243 * be called only from ops with %NL80211_FLAG_MLO_VALID_LINK_ID
1244 * or if additional validation is done.
1245 */
1246static unsigned int nl80211_link_id(struct nlattr **attrs)
1247{
1248 struct nlattr *linkid = attrs[NL80211_ATTR_MLO_LINK_ID];
1249
1250 if (!linkid)
1251 return 0;
1252
1253 return nla_get_u8(linkid);
1254}
1255
1256static int nl80211_link_id_or_invalid(struct nlattr **attrs)
1257{
1258 struct nlattr *linkid = attrs[NL80211_ATTR_MLO_LINK_ID];
1259
1260 if (!linkid)
1261 return -1;
1262
1263 return nla_get_u8(linkid);
1264}
1265
b9454e83
JB
1266struct key_parse {
1267 struct key_params p;
1268 int idx;
e31b8213 1269 int type;
56be393f 1270 bool def, defmgmt, defbeacon;
dbd2fd65 1271 bool def_uni, def_multi;
b9454e83
JB
1272};
1273
768075eb
JB
1274static int nl80211_parse_key_new(struct genl_info *info, struct nlattr *key,
1275 struct key_parse *k)
b9454e83
JB
1276{
1277 struct nlattr *tb[NL80211_KEY_MAX + 1];
8cb08174
JB
1278 int err = nla_parse_nested_deprecated(tb, NL80211_KEY_MAX, key,
1279 nl80211_key_policy,
1280 info->extack);
b9454e83
JB
1281 if (err)
1282 return err;
1283
1284 k->def = !!tb[NL80211_KEY_DEFAULT];
1285 k->defmgmt = !!tb[NL80211_KEY_DEFAULT_MGMT];
56be393f 1286 k->defbeacon = !!tb[NL80211_KEY_DEFAULT_BEACON];
b9454e83 1287
dbd2fd65
JB
1288 if (k->def) {
1289 k->def_uni = true;
1290 k->def_multi = true;
1291 }
56be393f 1292 if (k->defmgmt || k->defbeacon)
dbd2fd65
JB
1293 k->def_multi = true;
1294
b9454e83
JB
1295 if (tb[NL80211_KEY_IDX])
1296 k->idx = nla_get_u8(tb[NL80211_KEY_IDX]);
1297
1298 if (tb[NL80211_KEY_DATA]) {
1299 k->p.key = nla_data(tb[NL80211_KEY_DATA]);
1300 k->p.key_len = nla_len(tb[NL80211_KEY_DATA]);
1301 }
1302
1303 if (tb[NL80211_KEY_SEQ]) {
1304 k->p.seq = nla_data(tb[NL80211_KEY_SEQ]);
1305 k->p.seq_len = nla_len(tb[NL80211_KEY_SEQ]);
1306 }
1307
1308 if (tb[NL80211_KEY_CIPHER])
1309 k->p.cipher = nla_get_u32(tb[NL80211_KEY_CIPHER]);
1310
ab0d76f6 1311 if (tb[NL80211_KEY_TYPE])
e31b8213 1312 k->type = nla_get_u32(tb[NL80211_KEY_TYPE]);
e31b8213 1313
dbd2fd65
JB
1314 if (tb[NL80211_KEY_DEFAULT_TYPES]) {
1315 struct nlattr *kdt[NUM_NL80211_KEY_DEFAULT_TYPES];
7a087e74 1316
8cb08174
JB
1317 err = nla_parse_nested_deprecated(kdt,
1318 NUM_NL80211_KEY_DEFAULT_TYPES - 1,
1319 tb[NL80211_KEY_DEFAULT_TYPES],
1320 nl80211_key_default_policy,
1321 info->extack);
dbd2fd65
JB
1322 if (err)
1323 return err;
1324
1325 k->def_uni = kdt[NL80211_KEY_DEFAULT_TYPE_UNICAST];
1326 k->def_multi = kdt[NL80211_KEY_DEFAULT_TYPE_MULTICAST];
1327 }
1328
6cdd3979
AW
1329 if (tb[NL80211_KEY_MODE])
1330 k->p.mode = nla_get_u8(tb[NL80211_KEY_MODE]);
1331
b9454e83
JB
1332 return 0;
1333}
1334
1335static int nl80211_parse_key_old(struct genl_info *info, struct key_parse *k)
1336{
1337 if (info->attrs[NL80211_ATTR_KEY_DATA]) {
1338 k->p.key = nla_data(info->attrs[NL80211_ATTR_KEY_DATA]);
1339 k->p.key_len = nla_len(info->attrs[NL80211_ATTR_KEY_DATA]);
1340 }
1341
1342 if (info->attrs[NL80211_ATTR_KEY_SEQ]) {
1343 k->p.seq = nla_data(info->attrs[NL80211_ATTR_KEY_SEQ]);
1344 k->p.seq_len = nla_len(info->attrs[NL80211_ATTR_KEY_SEQ]);
1345 }
1346
1347 if (info->attrs[NL80211_ATTR_KEY_IDX])
1348 k->idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
1349
1350 if (info->attrs[NL80211_ATTR_KEY_CIPHER])
1351 k->p.cipher = nla_get_u32(info->attrs[NL80211_ATTR_KEY_CIPHER]);
1352
1353 k->def = !!info->attrs[NL80211_ATTR_KEY_DEFAULT];
1354 k->defmgmt = !!info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT];
1355
dbd2fd65
JB
1356 if (k->def) {
1357 k->def_uni = true;
1358 k->def_multi = true;
1359 }
1360 if (k->defmgmt)
1361 k->def_multi = true;
1362
ab0d76f6 1363 if (info->attrs[NL80211_ATTR_KEY_TYPE])
e31b8213 1364 k->type = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]);
e31b8213 1365
dbd2fd65
JB
1366 if (info->attrs[NL80211_ATTR_KEY_DEFAULT_TYPES]) {
1367 struct nlattr *kdt[NUM_NL80211_KEY_DEFAULT_TYPES];
8cb08174
JB
1368 int err = nla_parse_nested_deprecated(kdt,
1369 NUM_NL80211_KEY_DEFAULT_TYPES - 1,
1370 info->attrs[NL80211_ATTR_KEY_DEFAULT_TYPES],
1371 nl80211_key_default_policy,
1372 info->extack);
dbd2fd65
JB
1373 if (err)
1374 return err;
1375
1376 k->def_uni = kdt[NL80211_KEY_DEFAULT_TYPE_UNICAST];
1377 k->def_multi = kdt[NL80211_KEY_DEFAULT_TYPE_MULTICAST];
1378 }
1379
b9454e83
JB
1380 return 0;
1381}
1382
1383static int nl80211_parse_key(struct genl_info *info, struct key_parse *k)
1384{
1385 int err;
1386
1387 memset(k, 0, sizeof(*k));
1388 k->idx = -1;
e31b8213 1389 k->type = -1;
b9454e83
JB
1390
1391 if (info->attrs[NL80211_ATTR_KEY])
768075eb 1392 err = nl80211_parse_key_new(info, info->attrs[NL80211_ATTR_KEY], k);
b9454e83
JB
1393 else
1394 err = nl80211_parse_key_old(info, k);
1395
1396 if (err)
1397 return err;
1398
56be393f
JM
1399 if ((k->def ? 1 : 0) + (k->defmgmt ? 1 : 0) +
1400 (k->defbeacon ? 1 : 0) > 1) {
1401 GENL_SET_ERR_MSG(info,
1402 "key with multiple default flags is invalid");
b9454e83 1403 return -EINVAL;
768075eb 1404 }
b9454e83 1405
56be393f 1406 if (k->defmgmt || k->defbeacon) {
768075eb 1407 if (k->def_uni || !k->def_multi) {
56be393f
JM
1408 GENL_SET_ERR_MSG(info,
1409 "defmgmt/defbeacon key must be mcast");
dbd2fd65 1410 return -EINVAL;
768075eb 1411 }
dbd2fd65
JB
1412 }
1413
b9454e83
JB
1414 if (k->idx != -1) {
1415 if (k->defmgmt) {
768075eb
JB
1416 if (k->idx < 4 || k->idx > 5) {
1417 GENL_SET_ERR_MSG(info,
1418 "defmgmt key idx not 4 or 5");
b9454e83 1419 return -EINVAL;
768075eb 1420 }
56be393f
JM
1421 } else if (k->defbeacon) {
1422 if (k->idx < 6 || k->idx > 7) {
1423 GENL_SET_ERR_MSG(info,
1424 "defbeacon key idx not 6 or 7");
1425 return -EINVAL;
1426 }
b9454e83 1427 } else if (k->def) {
768075eb
JB
1428 if (k->idx < 0 || k->idx > 3) {
1429 GENL_SET_ERR_MSG(info, "def key idx not 0-3");
b9454e83 1430 return -EINVAL;
768075eb 1431 }
b9454e83 1432 } else {
56be393f
JM
1433 if (k->idx < 0 || k->idx > 7) {
1434 GENL_SET_ERR_MSG(info, "key idx not 0-7");
b9454e83 1435 return -EINVAL;
768075eb 1436 }
b9454e83
JB
1437 }
1438 }
1439
1440 return 0;
1441}
1442
fffd0934
JB
1443static struct cfg80211_cached_keys *
1444nl80211_parse_connkeys(struct cfg80211_registered_device *rdev,
768075eb 1445 struct genl_info *info, bool *no_ht)
fffd0934 1446{
768075eb 1447 struct nlattr *keys = info->attrs[NL80211_ATTR_KEYS];
fffd0934
JB
1448 struct key_parse parse;
1449 struct nlattr *key;
1450 struct cfg80211_cached_keys *result;
1451 int rem, err, def = 0;
f1c1f17a
JB
1452 bool have_key = false;
1453
1454 nla_for_each_nested(key, keys, rem) {
1455 have_key = true;
1456 break;
1457 }
1458
1459 if (!have_key)
1460 return NULL;
fffd0934
JB
1461
1462 result = kzalloc(sizeof(*result), GFP_KERNEL);
1463 if (!result)
1464 return ERR_PTR(-ENOMEM);
1465
1466 result->def = -1;
fffd0934
JB
1467
1468 nla_for_each_nested(key, keys, rem) {
1469 memset(&parse, 0, sizeof(parse));
1470 parse.idx = -1;
1471
768075eb 1472 err = nl80211_parse_key_new(info, key, &parse);
fffd0934
JB
1473 if (err)
1474 goto error;
1475 err = -EINVAL;
1476 if (!parse.p.key)
1477 goto error;
768075eb
JB
1478 if (parse.idx < 0 || parse.idx > 3) {
1479 GENL_SET_ERR_MSG(info, "key index out of range [0-3]");
fffd0934 1480 goto error;
768075eb 1481 }
fffd0934 1482 if (parse.def) {
768075eb
JB
1483 if (def) {
1484 GENL_SET_ERR_MSG(info,
1485 "only one key can be default");
fffd0934 1486 goto error;
768075eb 1487 }
fffd0934
JB
1488 def = 1;
1489 result->def = parse.idx;
dbd2fd65
JB
1490 if (!parse.def_uni || !parse.def_multi)
1491 goto error;
fffd0934
JB
1492 } else if (parse.defmgmt)
1493 goto error;
1494 err = cfg80211_validate_key_settings(rdev, &parse.p,
e31b8213 1495 parse.idx, false, NULL);
fffd0934
JB
1496 if (err)
1497 goto error;
386b1f27
JB
1498 if (parse.p.cipher != WLAN_CIPHER_SUITE_WEP40 &&
1499 parse.p.cipher != WLAN_CIPHER_SUITE_WEP104) {
768075eb 1500 GENL_SET_ERR_MSG(info, "connect key must be WEP");
386b1f27
JB
1501 err = -EINVAL;
1502 goto error;
1503 }
fffd0934
JB
1504 result->params[parse.idx].cipher = parse.p.cipher;
1505 result->params[parse.idx].key_len = parse.p.key_len;
1506 result->params[parse.idx].key = result->data[parse.idx];
1507 memcpy(result->data[parse.idx], parse.p.key, parse.p.key_len);
de7044ee 1508
386b1f27
JB
1509 /* must be WEP key if we got here */
1510 if (no_ht)
1511 *no_ht = true;
fffd0934
JB
1512 }
1513
f1c1f17a
JB
1514 if (result->def < 0) {
1515 err = -EINVAL;
768075eb 1516 GENL_SET_ERR_MSG(info, "need a default/TX key");
f1c1f17a
JB
1517 goto error;
1518 }
1519
fffd0934
JB
1520 return result;
1521 error:
1522 kfree(result);
1523 return ERR_PTR(err);
1524}
1525
1526static int nl80211_key_allowed(struct wireless_dev *wdev)
1527{
1528 ASSERT_WDEV_LOCK(wdev);
1529
fffd0934
JB
1530 switch (wdev->iftype) {
1531 case NL80211_IFTYPE_AP:
1532 case NL80211_IFTYPE_AP_VLAN:
074ac8df 1533 case NL80211_IFTYPE_P2P_GO:
ff973af7 1534 case NL80211_IFTYPE_MESH_POINT:
fffd0934
JB
1535 break;
1536 case NL80211_IFTYPE_ADHOC:
7b0a0e3c
JB
1537 if (wdev->u.ibss.current_bss)
1538 return 0;
1539 return -ENOLINK;
fffd0934 1540 case NL80211_IFTYPE_STATION:
074ac8df 1541 case NL80211_IFTYPE_P2P_CLIENT:
7b0a0e3c
JB
1542 /* for MLO, require driver validation of the link ID */
1543 if (wdev->connected)
1544 return 0;
1545 return -ENOLINK;
de4fcbad 1546 case NL80211_IFTYPE_UNSPECIFIED:
6e0bd6c3 1547 case NL80211_IFTYPE_OCB:
de4fcbad 1548 case NL80211_IFTYPE_MONITOR:
cb3b7d87 1549 case NL80211_IFTYPE_NAN:
de4fcbad
JB
1550 case NL80211_IFTYPE_P2P_DEVICE:
1551 case NL80211_IFTYPE_WDS:
1552 case NUM_NL80211_IFTYPES:
fffd0934
JB
1553 return -EINVAL;
1554 }
1555
1556 return 0;
1557}
1558
664834de 1559static struct ieee80211_channel *nl80211_get_valid_chan(struct wiphy *wiphy,
942ba88b 1560 u32 freq)
664834de
JM
1561{
1562 struct ieee80211_channel *chan;
1563
942ba88b 1564 chan = ieee80211_get_channel_khz(wiphy, freq);
664834de
JM
1565 if (!chan || chan->flags & IEEE80211_CHAN_DISABLED)
1566 return NULL;
1567 return chan;
1568}
1569
7527a782
JB
1570static int nl80211_put_iftypes(struct sk_buff *msg, u32 attr, u16 ifmodes)
1571{
ae0be8de 1572 struct nlattr *nl_modes = nla_nest_start_noflag(msg, attr);
7527a782
JB
1573 int i;
1574
1575 if (!nl_modes)
1576 goto nla_put_failure;
1577
1578 i = 0;
1579 while (ifmodes) {
9360ffd1
DM
1580 if ((ifmodes & 1) && nla_put_flag(msg, i))
1581 goto nla_put_failure;
7527a782
JB
1582 ifmodes >>= 1;
1583 i++;
1584 }
1585
1586 nla_nest_end(msg, nl_modes);
1587 return 0;
1588
1589nla_put_failure:
1590 return -ENOBUFS;
1591}
1592
1593static int nl80211_put_iface_combinations(struct wiphy *wiphy,
cdc89b97
JB
1594 struct sk_buff *msg,
1595 bool large)
7527a782
JB
1596{
1597 struct nlattr *nl_combis;
1598 int i, j;
1599
ae0be8de
MK
1600 nl_combis = nla_nest_start_noflag(msg,
1601 NL80211_ATTR_INTERFACE_COMBINATIONS);
7527a782
JB
1602 if (!nl_combis)
1603 goto nla_put_failure;
1604
1605 for (i = 0; i < wiphy->n_iface_combinations; i++) {
1606 const struct ieee80211_iface_combination *c;
1607 struct nlattr *nl_combi, *nl_limits;
1608
1609 c = &wiphy->iface_combinations[i];
1610
ae0be8de 1611 nl_combi = nla_nest_start_noflag(msg, i + 1);
7527a782
JB
1612 if (!nl_combi)
1613 goto nla_put_failure;
1614
ae0be8de
MK
1615 nl_limits = nla_nest_start_noflag(msg,
1616 NL80211_IFACE_COMB_LIMITS);
7527a782
JB
1617 if (!nl_limits)
1618 goto nla_put_failure;
1619
1620 for (j = 0; j < c->n_limits; j++) {
1621 struct nlattr *nl_limit;
1622
ae0be8de 1623 nl_limit = nla_nest_start_noflag(msg, j + 1);
7527a782
JB
1624 if (!nl_limit)
1625 goto nla_put_failure;
9360ffd1
DM
1626 if (nla_put_u32(msg, NL80211_IFACE_LIMIT_MAX,
1627 c->limits[j].max))
1628 goto nla_put_failure;
7527a782
JB
1629 if (nl80211_put_iftypes(msg, NL80211_IFACE_LIMIT_TYPES,
1630 c->limits[j].types))
1631 goto nla_put_failure;
1632 nla_nest_end(msg, nl_limit);
1633 }
1634
1635 nla_nest_end(msg, nl_limits);
1636
9360ffd1
DM
1637 if (c->beacon_int_infra_match &&
1638 nla_put_flag(msg, NL80211_IFACE_COMB_STA_AP_BI_MATCH))
1639 goto nla_put_failure;
1640 if (nla_put_u32(msg, NL80211_IFACE_COMB_NUM_CHANNELS,
1641 c->num_different_channels) ||
1642 nla_put_u32(msg, NL80211_IFACE_COMB_MAXNUM,
1643 c->max_interfaces))
1644 goto nla_put_failure;
cdc89b97 1645 if (large &&
8c48b50a
FF
1646 (nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS,
1647 c->radar_detect_widths) ||
1648 nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_REGIONS,
1649 c->radar_detect_regions)))
cdc89b97 1650 goto nla_put_failure;
0c317a02
PK
1651 if (c->beacon_int_min_gcd &&
1652 nla_put_u32(msg, NL80211_IFACE_COMB_BI_MIN_GCD,
1653 c->beacon_int_min_gcd))
1654 goto nla_put_failure;
7527a782
JB
1655
1656 nla_nest_end(msg, nl_combi);
1657 }
1658
1659 nla_nest_end(msg, nl_combis);
1660
1661 return 0;
1662nla_put_failure:
1663 return -ENOBUFS;
1664}
1665
3713b4e3 1666#ifdef CONFIG_PM
b56cf720
JB
1667static int nl80211_send_wowlan_tcp_caps(struct cfg80211_registered_device *rdev,
1668 struct sk_buff *msg)
1669{
964dc9e2 1670 const struct wiphy_wowlan_tcp_support *tcp = rdev->wiphy.wowlan->tcp;
b56cf720
JB
1671 struct nlattr *nl_tcp;
1672
1673 if (!tcp)
1674 return 0;
1675
ae0be8de
MK
1676 nl_tcp = nla_nest_start_noflag(msg,
1677 NL80211_WOWLAN_TRIG_TCP_CONNECTION);
b56cf720
JB
1678 if (!nl_tcp)
1679 return -ENOBUFS;
1680
1681 if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD,
1682 tcp->data_payload_max))
1683 return -ENOBUFS;
1684
1685 if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD,
1686 tcp->data_payload_max))
1687 return -ENOBUFS;
1688
1689 if (tcp->seq && nla_put_flag(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ))
1690 return -ENOBUFS;
1691
1692 if (tcp->tok && nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN,
1693 sizeof(*tcp->tok), tcp->tok))
1694 return -ENOBUFS;
1695
1696 if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_INTERVAL,
1697 tcp->data_interval_max))
1698 return -ENOBUFS;
1699
1700 if (nla_put_u32(msg, NL80211_WOWLAN_TCP_WAKE_PAYLOAD,
1701 tcp->wake_payload_max))
1702 return -ENOBUFS;
1703
1704 nla_nest_end(msg, nl_tcp);
1705 return 0;
1706}
1707
3713b4e3 1708static int nl80211_send_wowlan(struct sk_buff *msg,
1b8ec87a 1709 struct cfg80211_registered_device *rdev,
b56cf720 1710 bool large)
55682965 1711{
3713b4e3 1712 struct nlattr *nl_wowlan;
55682965 1713
1b8ec87a 1714 if (!rdev->wiphy.wowlan)
3713b4e3 1715 return 0;
55682965 1716
ae0be8de
MK
1717 nl_wowlan = nla_nest_start_noflag(msg,
1718 NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED);
3713b4e3
JB
1719 if (!nl_wowlan)
1720 return -ENOBUFS;
9360ffd1 1721
1b8ec87a 1722 if (((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_ANY) &&
3713b4e3 1723 nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) ||
1b8ec87a 1724 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_DISCONNECT) &&
3713b4e3 1725 nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) ||
1b8ec87a 1726 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_MAGIC_PKT) &&
3713b4e3 1727 nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) ||
1b8ec87a 1728 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_SUPPORTS_GTK_REKEY) &&
3713b4e3 1729 nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED)) ||
1b8ec87a 1730 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE) &&
3713b4e3 1731 nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) ||
1b8ec87a 1732 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ) &&
3713b4e3 1733 nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) ||
1b8ec87a 1734 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_4WAY_HANDSHAKE) &&
3713b4e3 1735 nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) ||
1b8ec87a 1736 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_RFKILL_RELEASE) &&
3713b4e3
JB
1737 nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE)))
1738 return -ENOBUFS;
9360ffd1 1739
1b8ec87a 1740 if (rdev->wiphy.wowlan->n_patterns) {
50ac6607 1741 struct nl80211_pattern_support pat = {
1b8ec87a
ZG
1742 .max_patterns = rdev->wiphy.wowlan->n_patterns,
1743 .min_pattern_len = rdev->wiphy.wowlan->pattern_min_len,
1744 .max_pattern_len = rdev->wiphy.wowlan->pattern_max_len,
1745 .max_pkt_offset = rdev->wiphy.wowlan->max_pkt_offset,
3713b4e3 1746 };
9360ffd1 1747
3713b4e3
JB
1748 if (nla_put(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN,
1749 sizeof(pat), &pat))
1750 return -ENOBUFS;
1751 }
9360ffd1 1752
75453ccb
LC
1753 if ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_NET_DETECT) &&
1754 nla_put_u32(msg, NL80211_WOWLAN_TRIG_NET_DETECT,
1755 rdev->wiphy.wowlan->max_nd_match_sets))
1756 return -ENOBUFS;
1757
1b8ec87a 1758 if (large && nl80211_send_wowlan_tcp_caps(rdev, msg))
b56cf720
JB
1759 return -ENOBUFS;
1760
3713b4e3 1761 nla_nest_end(msg, nl_wowlan);
9360ffd1 1762
3713b4e3
JB
1763 return 0;
1764}
1765#endif
9360ffd1 1766
be29b99a 1767static int nl80211_send_coalesce(struct sk_buff *msg,
1b8ec87a 1768 struct cfg80211_registered_device *rdev)
be29b99a
AK
1769{
1770 struct nl80211_coalesce_rule_support rule;
1771
1b8ec87a 1772 if (!rdev->wiphy.coalesce)
be29b99a
AK
1773 return 0;
1774
1b8ec87a
ZG
1775 rule.max_rules = rdev->wiphy.coalesce->n_rules;
1776 rule.max_delay = rdev->wiphy.coalesce->max_delay;
1777 rule.pat.max_patterns = rdev->wiphy.coalesce->n_patterns;
1778 rule.pat.min_pattern_len = rdev->wiphy.coalesce->pattern_min_len;
1779 rule.pat.max_pattern_len = rdev->wiphy.coalesce->pattern_max_len;
1780 rule.pat.max_pkt_offset = rdev->wiphy.coalesce->max_pkt_offset;
be29b99a
AK
1781
1782 if (nla_put(msg, NL80211_ATTR_COALESCE_RULE, sizeof(rule), &rule))
1783 return -ENOBUFS;
1784
1785 return 0;
1786}
1787
c4cbaf79
LC
1788static int
1789nl80211_send_iftype_data(struct sk_buff *msg,
22395217 1790 const struct ieee80211_supported_band *sband,
c4cbaf79
LC
1791 const struct ieee80211_sband_iftype_data *iftdata)
1792{
1793 const struct ieee80211_sta_he_cap *he_cap = &iftdata->he_cap;
5cd5a8a3 1794 const struct ieee80211_sta_eht_cap *eht_cap = &iftdata->eht_cap;
c4cbaf79
LC
1795
1796 if (nl80211_put_iftypes(msg, NL80211_BAND_IFTYPE_ATTR_IFTYPES,
1797 iftdata->types_mask))
1798 return -ENOBUFS;
1799
1800 if (he_cap->has_he) {
1801 if (nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_CAP_MAC,
1802 sizeof(he_cap->he_cap_elem.mac_cap_info),
1803 he_cap->he_cap_elem.mac_cap_info) ||
1804 nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY,
1805 sizeof(he_cap->he_cap_elem.phy_cap_info),
1806 he_cap->he_cap_elem.phy_cap_info) ||
1807 nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET,
1808 sizeof(he_cap->he_mcs_nss_supp),
1809 &he_cap->he_mcs_nss_supp) ||
1810 nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE,
1811 sizeof(he_cap->ppe_thres), he_cap->ppe_thres))
1812 return -ENOBUFS;
1813 }
1814
5cd5a8a3
IP
1815 if (eht_cap->has_eht && he_cap->has_he) {
1816 u8 mcs_nss_size, ppe_thresh_size;
1817 u16 ppe_thres_hdr;
1818
1819 mcs_nss_size =
1820 ieee80211_eht_mcs_nss_size(&he_cap->he_cap_elem,
1821 &eht_cap->eht_cap_elem);
1822
1823 ppe_thres_hdr = get_unaligned_le16(&eht_cap->eht_ppe_thres[0]);
1824 ppe_thresh_size =
1825 ieee80211_eht_ppe_size(ppe_thres_hdr,
1826 eht_cap->eht_cap_elem.phy_cap_info);
1827
1828 if (nla_put(msg, NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MAC,
1829 sizeof(eht_cap->eht_cap_elem.mac_cap_info),
1830 eht_cap->eht_cap_elem.mac_cap_info) ||
1831 nla_put(msg, NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY,
1832 sizeof(eht_cap->eht_cap_elem.phy_cap_info),
1833 eht_cap->eht_cap_elem.phy_cap_info) ||
1834 nla_put(msg, NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MCS_SET,
1835 mcs_nss_size, &eht_cap->eht_mcs_nss_supp) ||
1836 nla_put(msg, NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PPE,
1837 ppe_thresh_size, eht_cap->eht_ppe_thres))
1838 return -ENOBUFS;
1839 }
1840
22395217
JB
1841 if (sband->band == NL80211_BAND_6GHZ &&
1842 nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA,
1843 sizeof(iftdata->he_6ghz_capa),
1844 &iftdata->he_6ghz_capa))
1845 return -ENOBUFS;
1846
f4f86505
JB
1847 if (iftdata->vendor_elems.data && iftdata->vendor_elems.len &&
1848 nla_put(msg, NL80211_BAND_IFTYPE_ATTR_VENDOR_ELEMS,
1849 iftdata->vendor_elems.len, iftdata->vendor_elems.data))
1850 return -ENOBUFS;
1851
c4cbaf79
LC
1852 return 0;
1853}
1854
3713b4e3 1855static int nl80211_send_band_rateinfo(struct sk_buff *msg,
f8d504ca
JB
1856 struct ieee80211_supported_band *sband,
1857 bool large)
3713b4e3
JB
1858{
1859 struct nlattr *nl_rates, *nl_rate;
1860 struct ieee80211_rate *rate;
1861 int i;
87bbbe22 1862
3713b4e3
JB
1863 /* add HT info */
1864 if (sband->ht_cap.ht_supported &&
1865 (nla_put(msg, NL80211_BAND_ATTR_HT_MCS_SET,
1866 sizeof(sband->ht_cap.mcs),
1867 &sband->ht_cap.mcs) ||
1868 nla_put_u16(msg, NL80211_BAND_ATTR_HT_CAPA,
1869 sband->ht_cap.cap) ||
1870 nla_put_u8(msg, NL80211_BAND_ATTR_HT_AMPDU_FACTOR,
1871 sband->ht_cap.ampdu_factor) ||
1872 nla_put_u8(msg, NL80211_BAND_ATTR_HT_AMPDU_DENSITY,
1873 sband->ht_cap.ampdu_density)))
1874 return -ENOBUFS;
afe0cbf8 1875
3713b4e3
JB
1876 /* add VHT info */
1877 if (sband->vht_cap.vht_supported &&
1878 (nla_put(msg, NL80211_BAND_ATTR_VHT_MCS_SET,
1879 sizeof(sband->vht_cap.vht_mcs),
1880 &sband->vht_cap.vht_mcs) ||
1881 nla_put_u32(msg, NL80211_BAND_ATTR_VHT_CAPA,
1882 sband->vht_cap.cap)))
1883 return -ENOBUFS;
f59ac048 1884
f8d504ca 1885 if (large && sband->n_iftype_data) {
c4cbaf79 1886 struct nlattr *nl_iftype_data =
ae0be8de
MK
1887 nla_nest_start_noflag(msg,
1888 NL80211_BAND_ATTR_IFTYPE_DATA);
c4cbaf79
LC
1889 int err;
1890
1891 if (!nl_iftype_data)
1892 return -ENOBUFS;
1893
1894 for (i = 0; i < sband->n_iftype_data; i++) {
1895 struct nlattr *iftdata;
1896
ae0be8de 1897 iftdata = nla_nest_start_noflag(msg, i + 1);
c4cbaf79
LC
1898 if (!iftdata)
1899 return -ENOBUFS;
1900
22395217 1901 err = nl80211_send_iftype_data(msg, sband,
c4cbaf79
LC
1902 &sband->iftype_data[i]);
1903 if (err)
1904 return err;
1905
1906 nla_nest_end(msg, iftdata);
1907 }
1908
1909 nla_nest_end(msg, nl_iftype_data);
1910 }
1911
2a38075c 1912 /* add EDMG info */
f8d504ca 1913 if (large && sband->edmg_cap.channels &&
2a38075c
AAL
1914 (nla_put_u8(msg, NL80211_BAND_ATTR_EDMG_CHANNELS,
1915 sband->edmg_cap.channels) ||
1916 nla_put_u8(msg, NL80211_BAND_ATTR_EDMG_BW_CONFIG,
1917 sband->edmg_cap.bw_config)))
1918
1919 return -ENOBUFS;
1920
3713b4e3 1921 /* add bitrates */
ae0be8de 1922 nl_rates = nla_nest_start_noflag(msg, NL80211_BAND_ATTR_RATES);
3713b4e3
JB
1923 if (!nl_rates)
1924 return -ENOBUFS;
ee688b00 1925
3713b4e3 1926 for (i = 0; i < sband->n_bitrates; i++) {
ae0be8de 1927 nl_rate = nla_nest_start_noflag(msg, i);
3713b4e3
JB
1928 if (!nl_rate)
1929 return -ENOBUFS;
ee688b00 1930
3713b4e3
JB
1931 rate = &sband->bitrates[i];
1932 if (nla_put_u32(msg, NL80211_BITRATE_ATTR_RATE,
1933 rate->bitrate))
1934 return -ENOBUFS;
1935 if ((rate->flags & IEEE80211_RATE_SHORT_PREAMBLE) &&
1936 nla_put_flag(msg,
1937 NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE))
1938 return -ENOBUFS;
ee688b00 1939
3713b4e3
JB
1940 nla_nest_end(msg, nl_rate);
1941 }
d51626df 1942
3713b4e3 1943 nla_nest_end(msg, nl_rates);
bf0c111e 1944
3713b4e3
JB
1945 return 0;
1946}
ee688b00 1947
3713b4e3
JB
1948static int
1949nl80211_send_mgmt_stypes(struct sk_buff *msg,
1950 const struct ieee80211_txrx_stypes *mgmt_stypes)
1951{
1952 u16 stypes;
1953 struct nlattr *nl_ftypes, *nl_ifs;
1954 enum nl80211_iftype ift;
1955 int i;
ee688b00 1956
3713b4e3
JB
1957 if (!mgmt_stypes)
1958 return 0;
5dab3b8a 1959
ae0be8de 1960 nl_ifs = nla_nest_start_noflag(msg, NL80211_ATTR_TX_FRAME_TYPES);
3713b4e3
JB
1961 if (!nl_ifs)
1962 return -ENOBUFS;
e2f367f2 1963
3713b4e3 1964 for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) {
ae0be8de 1965 nl_ftypes = nla_nest_start_noflag(msg, ift);
3713b4e3
JB
1966 if (!nl_ftypes)
1967 return -ENOBUFS;
1968 i = 0;
1969 stypes = mgmt_stypes[ift].tx;
1970 while (stypes) {
1971 if ((stypes & 1) &&
1972 nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE,
1973 (i << 4) | IEEE80211_FTYPE_MGMT))
1974 return -ENOBUFS;
1975 stypes >>= 1;
1976 i++;
ee688b00 1977 }
3713b4e3
JB
1978 nla_nest_end(msg, nl_ftypes);
1979 }
ee688b00 1980
3713b4e3 1981 nla_nest_end(msg, nl_ifs);
ee688b00 1982
ae0be8de 1983 nl_ifs = nla_nest_start_noflag(msg, NL80211_ATTR_RX_FRAME_TYPES);
3713b4e3
JB
1984 if (!nl_ifs)
1985 return -ENOBUFS;
ee688b00 1986
3713b4e3 1987 for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) {
ae0be8de 1988 nl_ftypes = nla_nest_start_noflag(msg, ift);
3713b4e3
JB
1989 if (!nl_ftypes)
1990 return -ENOBUFS;
1991 i = 0;
1992 stypes = mgmt_stypes[ift].rx;
1993 while (stypes) {
1994 if ((stypes & 1) &&
1995 nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE,
1996 (i << 4) | IEEE80211_FTYPE_MGMT))
1997 return -ENOBUFS;
1998 stypes >>= 1;
1999 i++;
2000 }
2001 nla_nest_end(msg, nl_ftypes);
2002 }
2003 nla_nest_end(msg, nl_ifs);
ee688b00 2004
3713b4e3
JB
2005 return 0;
2006}
ee688b00 2007
1794899e
JB
2008#define CMD(op, n) \
2009 do { \
2010 if (rdev->ops->op) { \
2011 i++; \
2012 if (nla_put_u32(msg, i, NL80211_CMD_ ## n)) \
2013 goto nla_put_failure; \
2014 } \
2015 } while (0)
2016
2017static int nl80211_add_commands_unsplit(struct cfg80211_registered_device *rdev,
2018 struct sk_buff *msg)
2019{
2020 int i = 0;
2021
2022 /*
2023 * do *NOT* add anything into this function, new things need to be
2024 * advertised only to new versions of userspace that can deal with
2025 * the split (and they can't possibly care about new features...
2026 */
2027 CMD(add_virtual_intf, NEW_INTERFACE);
2028 CMD(change_virtual_intf, SET_INTERFACE);
2029 CMD(add_key, NEW_KEY);
2030 CMD(start_ap, START_AP);
2031 CMD(add_station, NEW_STATION);
2032 CMD(add_mpath, NEW_MPATH);
2033 CMD(update_mesh_config, SET_MESH_CONFIG);
2034 CMD(change_bss, SET_BSS);
2035 CMD(auth, AUTHENTICATE);
2036 CMD(assoc, ASSOCIATE);
2037 CMD(deauth, DEAUTHENTICATE);
2038 CMD(disassoc, DISASSOCIATE);
2039 CMD(join_ibss, JOIN_IBSS);
2040 CMD(join_mesh, JOIN_MESH);
2041 CMD(set_pmksa, SET_PMKSA);
2042 CMD(del_pmksa, DEL_PMKSA);
2043 CMD(flush_pmksa, FLUSH_PMKSA);
2044 if (rdev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL)
2045 CMD(remain_on_channel, REMAIN_ON_CHANNEL);
2046 CMD(set_bitrate_mask, SET_TX_BITRATE_MASK);
2047 CMD(mgmt_tx, FRAME);
2048 CMD(mgmt_tx_cancel_wait, FRAME_WAIT_CANCEL);
2049 if (rdev->wiphy.flags & WIPHY_FLAG_NETNS_OK) {
2050 i++;
2051 if (nla_put_u32(msg, i, NL80211_CMD_SET_WIPHY_NETNS))
2052 goto nla_put_failure;
2053 }
2054 if (rdev->ops->set_monitor_channel || rdev->ops->start_ap ||
2055 rdev->ops->join_mesh) {
2056 i++;
2057 if (nla_put_u32(msg, i, NL80211_CMD_SET_CHANNEL))
2058 goto nla_put_failure;
2059 }
1794899e
JB
2060 if (rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) {
2061 CMD(tdls_mgmt, TDLS_MGMT);
2062 CMD(tdls_oper, TDLS_OPER);
2063 }
ca986ad9 2064 if (rdev->wiphy.max_sched_scan_reqs)
1794899e
JB
2065 CMD(sched_scan_start, START_SCHED_SCAN);
2066 CMD(probe_client, PROBE_CLIENT);
2067 CMD(set_noack_map, SET_NOACK_MAP);
2068 if (rdev->wiphy.flags & WIPHY_FLAG_REPORTS_OBSS) {
2069 i++;
2070 if (nla_put_u32(msg, i, NL80211_CMD_REGISTER_BEACONS))
2071 goto nla_put_failure;
2072 }
2073 CMD(start_p2p_device, START_P2P_DEVICE);
2074 CMD(set_mcast_rate, SET_MCAST_RATE);
2075#ifdef CONFIG_NL80211_TESTMODE
2076 CMD(testmode_cmd, TESTMODE);
2077#endif
2078
2079 if (rdev->ops->connect || rdev->ops->auth) {
2080 i++;
2081 if (nla_put_u32(msg, i, NL80211_CMD_CONNECT))
2082 goto nla_put_failure;
2083 }
2084
2085 if (rdev->ops->disconnect || rdev->ops->deauth) {
2086 i++;
2087 if (nla_put_u32(msg, i, NL80211_CMD_DISCONNECT))
2088 goto nla_put_failure;
2089 }
2090
2091 return i;
2092 nla_put_failure:
2093 return -ENOBUFS;
2094}
2095
9bb7e0f2
JB
2096static int
2097nl80211_send_pmsr_ftm_capa(const struct cfg80211_pmsr_capabilities *cap,
2098 struct sk_buff *msg)
2099{
2100 struct nlattr *ftm;
2101
2102 if (!cap->ftm.supported)
2103 return 0;
2104
ae0be8de 2105 ftm = nla_nest_start_noflag(msg, NL80211_PMSR_TYPE_FTM);
9bb7e0f2
JB
2106 if (!ftm)
2107 return -ENOBUFS;
2108
2109 if (cap->ftm.asap && nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_ASAP))
2110 return -ENOBUFS;
2111 if (cap->ftm.non_asap &&
2112 nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_NON_ASAP))
2113 return -ENOBUFS;
2114 if (cap->ftm.request_lci &&
2115 nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_REQ_LCI))
2116 return -ENOBUFS;
2117 if (cap->ftm.request_civicloc &&
2118 nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_REQ_CIVICLOC))
2119 return -ENOBUFS;
2120 if (nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_PREAMBLES,
2121 cap->ftm.preambles))
2122 return -ENOBUFS;
2123 if (nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_BANDWIDTHS,
2124 cap->ftm.bandwidths))
2125 return -ENOBUFS;
2126 if (cap->ftm.max_bursts_exponent >= 0 &&
2127 nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_MAX_BURSTS_EXPONENT,
2128 cap->ftm.max_bursts_exponent))
2129 return -ENOBUFS;
2130 if (cap->ftm.max_ftms_per_burst &&
2131 nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_MAX_FTMS_PER_BURST,
2132 cap->ftm.max_ftms_per_burst))
2133 return -ENOBUFS;
efb5520d
AS
2134 if (cap->ftm.trigger_based &&
2135 nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_TRIGGER_BASED))
2136 return -ENOBUFS;
2137 if (cap->ftm.non_trigger_based &&
2138 nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_NON_TRIGGER_BASED))
2139 return -ENOBUFS;
9bb7e0f2
JB
2140
2141 nla_nest_end(msg, ftm);
2142 return 0;
2143}
2144
2145static int nl80211_send_pmsr_capa(struct cfg80211_registered_device *rdev,
2146 struct sk_buff *msg)
2147{
2148 const struct cfg80211_pmsr_capabilities *cap = rdev->wiphy.pmsr_capa;
2149 struct nlattr *pmsr, *caps;
2150
2151 if (!cap)
2152 return 0;
2153
2154 /*
2155 * we don't need to clean up anything here since the caller
2156 * will genlmsg_cancel() if we fail
2157 */
2158
ae0be8de 2159 pmsr = nla_nest_start_noflag(msg, NL80211_ATTR_PEER_MEASUREMENTS);
9bb7e0f2
JB
2160 if (!pmsr)
2161 return -ENOBUFS;
2162
2163 if (nla_put_u32(msg, NL80211_PMSR_ATTR_MAX_PEERS, cap->max_peers))
2164 return -ENOBUFS;
2165
2166 if (cap->report_ap_tsf &&
2167 nla_put_flag(msg, NL80211_PMSR_ATTR_REPORT_AP_TSF))
2168 return -ENOBUFS;
2169
2170 if (cap->randomize_mac_addr &&
2171 nla_put_flag(msg, NL80211_PMSR_ATTR_RANDOMIZE_MAC_ADDR))
2172 return -ENOBUFS;
2173
ae0be8de 2174 caps = nla_nest_start_noflag(msg, NL80211_PMSR_ATTR_TYPE_CAPA);
9bb7e0f2
JB
2175 if (!caps)
2176 return -ENOBUFS;
2177
2178 if (nl80211_send_pmsr_ftm_capa(cap, msg))
2179 return -ENOBUFS;
2180
2181 nla_nest_end(msg, caps);
2182 nla_nest_end(msg, pmsr);
2183
2184 return 0;
2185}
2186
d6039a34
VJ
2187static int
2188nl80211_put_iftype_akm_suites(struct cfg80211_registered_device *rdev,
2189 struct sk_buff *msg)
2190{
2191 int i;
2192 struct nlattr *nested, *nested_akms;
2193 const struct wiphy_iftype_akm_suites *iftype_akms;
2194
2195 if (!rdev->wiphy.num_iftype_akm_suites ||
2196 !rdev->wiphy.iftype_akm_suites)
2197 return 0;
2198
2199 nested = nla_nest_start(msg, NL80211_ATTR_IFTYPE_AKM_SUITES);
2200 if (!nested)
2201 return -ENOBUFS;
2202
2203 for (i = 0; i < rdev->wiphy.num_iftype_akm_suites; i++) {
2204 nested_akms = nla_nest_start(msg, i + 1);
2205 if (!nested_akms)
2206 return -ENOBUFS;
2207
2208 iftype_akms = &rdev->wiphy.iftype_akm_suites[i];
2209
2210 if (nl80211_put_iftypes(msg, NL80211_IFTYPE_AKM_ATTR_IFTYPES,
2211 iftype_akms->iftypes_mask))
2212 return -ENOBUFS;
2213
2214 if (nla_put(msg, NL80211_IFTYPE_AKM_ATTR_SUITES,
2215 sizeof(u32) * iftype_akms->n_akm_suites,
2216 iftype_akms->akm_suites)) {
2217 return -ENOBUFS;
2218 }
2219 nla_nest_end(msg, nested_akms);
2220 }
2221
2222 nla_nest_end(msg, nested);
2223
2224 return 0;
2225}
2226
3710a8a6
JB
2227static int
2228nl80211_put_tid_config_support(struct cfg80211_registered_device *rdev,
2229 struct sk_buff *msg)
2230{
2231 struct nlattr *supp;
2232
2233 if (!rdev->wiphy.tid_config_support.vif &&
2234 !rdev->wiphy.tid_config_support.peer)
2235 return 0;
2236
2237 supp = nla_nest_start(msg, NL80211_ATTR_TID_CONFIG);
2238 if (!supp)
2239 return -ENOSPC;
2240
2241 if (rdev->wiphy.tid_config_support.vif &&
2242 nla_put_u64_64bit(msg, NL80211_TID_CONFIG_ATTR_VIF_SUPP,
2243 rdev->wiphy.tid_config_support.vif,
2244 NL80211_TID_CONFIG_ATTR_PAD))
2245 goto fail;
2246
2247 if (rdev->wiphy.tid_config_support.peer &&
2248 nla_put_u64_64bit(msg, NL80211_TID_CONFIG_ATTR_PEER_SUPP,
2249 rdev->wiphy.tid_config_support.peer,
2250 NL80211_TID_CONFIG_ATTR_PAD))
2251 goto fail;
2252
6a21d16c
T
2253 /* for now we just use the same value ... makes more sense */
2254 if (nla_put_u8(msg, NL80211_TID_CONFIG_ATTR_RETRY_SHORT,
2255 rdev->wiphy.tid_config_support.max_retry))
2256 goto fail;
2257 if (nla_put_u8(msg, NL80211_TID_CONFIG_ATTR_RETRY_LONG,
2258 rdev->wiphy.tid_config_support.max_retry))
2259 goto fail;
2260
3710a8a6
JB
2261 nla_nest_end(msg, supp);
2262
2263 return 0;
2264fail:
2265 nla_nest_cancel(msg, supp);
2266 return -ENOBUFS;
2267}
2268
6bdb68ce
CH
2269static int
2270nl80211_put_sar_specs(struct cfg80211_registered_device *rdev,
2271 struct sk_buff *msg)
2272{
2273 struct nlattr *sar_capa, *specs, *sub_freq_range;
2274 u8 num_freq_ranges;
2275 int i;
2276
2277 if (!rdev->wiphy.sar_capa)
2278 return 0;
2279
2280 num_freq_ranges = rdev->wiphy.sar_capa->num_freq_ranges;
2281
2282 sar_capa = nla_nest_start(msg, NL80211_ATTR_SAR_SPEC);
2283 if (!sar_capa)
2284 return -ENOSPC;
2285
2286 if (nla_put_u32(msg, NL80211_SAR_ATTR_TYPE, rdev->wiphy.sar_capa->type))
2287 goto fail;
2288
2289 specs = nla_nest_start(msg, NL80211_SAR_ATTR_SPECS);
2290 if (!specs)
2291 goto fail;
2292
2293 /* report supported freq_ranges */
2294 for (i = 0; i < num_freq_ranges; i++) {
2295 sub_freq_range = nla_nest_start(msg, i + 1);
2296 if (!sub_freq_range)
2297 goto fail;
2298
2299 if (nla_put_u32(msg, NL80211_SAR_ATTR_SPECS_START_FREQ,
2300 rdev->wiphy.sar_capa->freq_ranges[i].start_freq))
2301 goto fail;
2302
2303 if (nla_put_u32(msg, NL80211_SAR_ATTR_SPECS_END_FREQ,
2304 rdev->wiphy.sar_capa->freq_ranges[i].end_freq))
2305 goto fail;
2306
2307 nla_nest_end(msg, sub_freq_range);
2308 }
2309
2310 nla_nest_end(msg, specs);
2311 nla_nest_end(msg, sar_capa);
2312
2313 return 0;
2314fail:
2315 nla_nest_cancel(msg, sar_capa);
2316 return -ENOBUFS;
2317}
2318
dc1e3cb8
JC
2319static int nl80211_put_mbssid_support(struct wiphy *wiphy, struct sk_buff *msg)
2320{
2321 struct nlattr *config;
2322
2323 if (!wiphy->mbssid_max_interfaces)
2324 return 0;
2325
2326 config = nla_nest_start(msg, NL80211_ATTR_MBSSID_CONFIG);
2327 if (!config)
2328 return -ENOBUFS;
2329
2330 if (nla_put_u8(msg, NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES,
2331 wiphy->mbssid_max_interfaces))
2332 goto fail;
2333
2334 if (wiphy->ema_max_profile_periodicity &&
2335 nla_put_u8(msg,
2336 NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY,
2337 wiphy->ema_max_profile_periodicity))
2338 goto fail;
2339
2340 nla_nest_end(msg, config);
2341 return 0;
2342
2343fail:
2344 nla_nest_cancel(msg, config);
2345 return -ENOBUFS;
2346}
2347
86e8cf98
JB
2348struct nl80211_dump_wiphy_state {
2349 s64 filter_wiphy;
2350 long start;
019ae3a9 2351 long split_start, band_start, chan_start, capa_start;
86e8cf98
JB
2352 bool split;
2353};
2354
1b8ec87a 2355static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
3bb20556 2356 enum nl80211_commands cmd,
3713b4e3 2357 struct sk_buff *msg, u32 portid, u32 seq,
86e8cf98 2358 int flags, struct nl80211_dump_wiphy_state *state)
3713b4e3
JB
2359{
2360 void *hdr;
2361 struct nlattr *nl_bands, *nl_band;
2362 struct nlattr *nl_freqs, *nl_freq;
2363 struct nlattr *nl_cmds;
57fbcce3 2364 enum nl80211_band band;
3713b4e3
JB
2365 struct ieee80211_channel *chan;
2366 int i;
2367 const struct ieee80211_txrx_stypes *mgmt_stypes =
1b8ec87a 2368 rdev->wiphy.mgmt_stypes;
fe1abafd 2369 u32 features;
ee688b00 2370
3bb20556 2371 hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
3713b4e3
JB
2372 if (!hdr)
2373 return -ENOBUFS;
ee688b00 2374
86e8cf98
JB
2375 if (WARN_ON(!state))
2376 return -EINVAL;
ee688b00 2377
1b8ec87a 2378 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
3713b4e3 2379 nla_put_string(msg, NL80211_ATTR_WIPHY_NAME,
1b8ec87a 2380 wiphy_name(&rdev->wiphy)) ||
3713b4e3
JB
2381 nla_put_u32(msg, NL80211_ATTR_GENERATION,
2382 cfg80211_rdev_list_generation))
8fdc621d
JB
2383 goto nla_put_failure;
2384
3bb20556
JB
2385 if (cmd != NL80211_CMD_NEW_WIPHY)
2386 goto finish;
2387
86e8cf98 2388 switch (state->split_start) {
3713b4e3
JB
2389 case 0:
2390 if (nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_SHORT,
1b8ec87a 2391 rdev->wiphy.retry_short) ||
3713b4e3 2392 nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_LONG,
1b8ec87a 2393 rdev->wiphy.retry_long) ||
3713b4e3 2394 nla_put_u32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD,
1b8ec87a 2395 rdev->wiphy.frag_threshold) ||
3713b4e3 2396 nla_put_u32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD,
1b8ec87a 2397 rdev->wiphy.rts_threshold) ||
3713b4e3 2398 nla_put_u8(msg, NL80211_ATTR_WIPHY_COVERAGE_CLASS,
1b8ec87a 2399 rdev->wiphy.coverage_class) ||
3713b4e3 2400 nla_put_u8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS,
1b8ec87a 2401 rdev->wiphy.max_scan_ssids) ||
3713b4e3 2402 nla_put_u8(msg, NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS,
1b8ec87a 2403 rdev->wiphy.max_sched_scan_ssids) ||
3713b4e3 2404 nla_put_u16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN,
1b8ec87a 2405 rdev->wiphy.max_scan_ie_len) ||
3713b4e3 2406 nla_put_u16(msg, NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN,
1b8ec87a 2407 rdev->wiphy.max_sched_scan_ie_len) ||
3713b4e3 2408 nla_put_u8(msg, NL80211_ATTR_MAX_MATCH_SETS,
f8d504ca 2409 rdev->wiphy.max_match_sets))
9360ffd1 2410 goto nla_put_failure;
3713b4e3 2411
1b8ec87a 2412 if ((rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN) &&
3713b4e3 2413 nla_put_flag(msg, NL80211_ATTR_SUPPORT_IBSS_RSN))
aa430da4 2414 goto nla_put_failure;
1b8ec87a 2415 if ((rdev->wiphy.flags & WIPHY_FLAG_MESH_AUTH) &&
3713b4e3
JB
2416 nla_put_flag(msg, NL80211_ATTR_SUPPORT_MESH_AUTH))
2417 goto nla_put_failure;
1b8ec87a 2418 if ((rdev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) &&
3713b4e3
JB
2419 nla_put_flag(msg, NL80211_ATTR_SUPPORT_AP_UAPSD))
2420 goto nla_put_failure;
1b8ec87a 2421 if ((rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_FW_ROAM) &&
3713b4e3
JB
2422 nla_put_flag(msg, NL80211_ATTR_ROAM_SUPPORT))
2423 goto nla_put_failure;
1b8ec87a 2424 if ((rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) &&
3713b4e3
JB
2425 nla_put_flag(msg, NL80211_ATTR_TDLS_SUPPORT))
2426 goto nla_put_failure;
1b8ec87a 2427 if ((rdev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP) &&
3713b4e3 2428 nla_put_flag(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP))
9360ffd1 2429 goto nla_put_failure;
86e8cf98
JB
2430 state->split_start++;
2431 if (state->split)
3713b4e3 2432 break;
7b506ff6 2433 fallthrough;
3713b4e3
JB
2434 case 1:
2435 if (nla_put(msg, NL80211_ATTR_CIPHER_SUITES,
1b8ec87a
ZG
2436 sizeof(u32) * rdev->wiphy.n_cipher_suites,
2437 rdev->wiphy.cipher_suites))
3713b4e3 2438 goto nla_put_failure;
4745fc09 2439
3713b4e3 2440 if (nla_put_u8(msg, NL80211_ATTR_MAX_NUM_PMKIDS,
1b8ec87a 2441 rdev->wiphy.max_num_pmkids))
3713b4e3 2442 goto nla_put_failure;
b23aa676 2443
1b8ec87a 2444 if ((rdev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) &&
3713b4e3 2445 nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE))
9360ffd1 2446 goto nla_put_failure;
b23aa676 2447
3713b4e3 2448 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX,
1b8ec87a 2449 rdev->wiphy.available_antennas_tx) ||
3713b4e3 2450 nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX,
1b8ec87a 2451 rdev->wiphy.available_antennas_rx))
9360ffd1 2452 goto nla_put_failure;
b23aa676 2453
1b8ec87a 2454 if ((rdev->wiphy.flags & WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD) &&
3713b4e3 2455 nla_put_u32(msg, NL80211_ATTR_PROBE_RESP_OFFLOAD,
1b8ec87a 2456 rdev->wiphy.probe_resp_offload))
3713b4e3 2457 goto nla_put_failure;
8fdc621d 2458
1b8ec87a
ZG
2459 if ((rdev->wiphy.available_antennas_tx ||
2460 rdev->wiphy.available_antennas_rx) &&
2461 rdev->ops->get_antenna) {
3713b4e3
JB
2462 u32 tx_ant = 0, rx_ant = 0;
2463 int res;
7a087e74 2464
1b8ec87a 2465 res = rdev_get_antenna(rdev, &tx_ant, &rx_ant);
3713b4e3
JB
2466 if (!res) {
2467 if (nla_put_u32(msg,
2468 NL80211_ATTR_WIPHY_ANTENNA_TX,
2469 tx_ant) ||
2470 nla_put_u32(msg,
2471 NL80211_ATTR_WIPHY_ANTENNA_RX,
2472 rx_ant))
2473 goto nla_put_failure;
2474 }
2475 }
a293911d 2476
86e8cf98
JB
2477 state->split_start++;
2478 if (state->split)
3713b4e3 2479 break;
7b506ff6 2480 fallthrough;
3713b4e3
JB
2481 case 2:
2482 if (nl80211_put_iftypes(msg, NL80211_ATTR_SUPPORTED_IFTYPES,
1b8ec87a 2483 rdev->wiphy.interface_modes))
3713b4e3 2484 goto nla_put_failure;
86e8cf98
JB
2485 state->split_start++;
2486 if (state->split)
3713b4e3 2487 break;
7b506ff6 2488 fallthrough;
3713b4e3 2489 case 3:
ae0be8de
MK
2490 nl_bands = nla_nest_start_noflag(msg,
2491 NL80211_ATTR_WIPHY_BANDS);
3713b4e3
JB
2492 if (!nl_bands)
2493 goto nla_put_failure;
f7ca38df 2494
86e8cf98 2495 for (band = state->band_start;
0d059964
JB
2496 band < (state->split ?
2497 NUM_NL80211_BANDS :
2498 NL80211_BAND_60GHZ + 1);
2499 band++) {
3713b4e3 2500 struct ieee80211_supported_band *sband;
2e161f78 2501
f8d504ca
JB
2502 /* omit higher bands for ancient software */
2503 if (band > NL80211_BAND_5GHZ && !state->split)
2504 break;
2505
1b8ec87a 2506 sband = rdev->wiphy.bands[band];
2e161f78 2507
3713b4e3
JB
2508 if (!sband)
2509 continue;
2510
ae0be8de 2511 nl_band = nla_nest_start_noflag(msg, band);
3713b4e3 2512 if (!nl_band)
2e161f78 2513 goto nla_put_failure;
3713b4e3 2514
86e8cf98 2515 switch (state->chan_start) {
3713b4e3 2516 case 0:
f8d504ca
JB
2517 if (nl80211_send_band_rateinfo(msg, sband,
2518 state->split))
9360ffd1 2519 goto nla_put_failure;
86e8cf98
JB
2520 state->chan_start++;
2521 if (state->split)
3713b4e3 2522 break;
7b506ff6 2523 fallthrough;
3713b4e3
JB
2524 default:
2525 /* add frequencies */
ae0be8de
MK
2526 nl_freqs = nla_nest_start_noflag(msg,
2527 NL80211_BAND_ATTR_FREQS);
3713b4e3
JB
2528 if (!nl_freqs)
2529 goto nla_put_failure;
2530
86e8cf98 2531 for (i = state->chan_start - 1;
3713b4e3
JB
2532 i < sband->n_channels;
2533 i++) {
ae0be8de
MK
2534 nl_freq = nla_nest_start_noflag(msg,
2535 i);
3713b4e3
JB
2536 if (!nl_freq)
2537 goto nla_put_failure;
2538
2539 chan = &sband->channels[i];
2540
86e8cf98 2541 if (nl80211_msg_put_channel(
50f32718 2542 msg, &rdev->wiphy, chan,
86e8cf98 2543 state->split))
3713b4e3
JB
2544 goto nla_put_failure;
2545
2546 nla_nest_end(msg, nl_freq);
86e8cf98 2547 if (state->split)
3713b4e3
JB
2548 break;
2549 }
2550 if (i < sband->n_channels)
86e8cf98 2551 state->chan_start = i + 2;
3713b4e3 2552 else
86e8cf98 2553 state->chan_start = 0;
3713b4e3
JB
2554 nla_nest_end(msg, nl_freqs);
2555 }
2556
2557 nla_nest_end(msg, nl_band);
2558
86e8cf98 2559 if (state->split) {
3713b4e3 2560 /* start again here */
86e8cf98 2561 if (state->chan_start)
3713b4e3
JB
2562 band--;
2563 break;
2e161f78 2564 }
2e161f78 2565 }
3713b4e3 2566 nla_nest_end(msg, nl_bands);
2e161f78 2567
57fbcce3 2568 if (band < NUM_NL80211_BANDS)
86e8cf98 2569 state->band_start = band + 1;
3713b4e3 2570 else
86e8cf98 2571 state->band_start = 0;
74b70a4e 2572
3713b4e3 2573 /* if bands & channels are done, continue outside */
86e8cf98
JB
2574 if (state->band_start == 0 && state->chan_start == 0)
2575 state->split_start++;
2576 if (state->split)
3713b4e3 2577 break;
7b506ff6 2578 fallthrough;
3713b4e3 2579 case 4:
ae0be8de
MK
2580 nl_cmds = nla_nest_start_noflag(msg,
2581 NL80211_ATTR_SUPPORTED_COMMANDS);
3713b4e3 2582 if (!nl_cmds)
2e161f78
JB
2583 goto nla_put_failure;
2584
1794899e
JB
2585 i = nl80211_add_commands_unsplit(rdev, msg);
2586 if (i < 0)
2587 goto nla_put_failure;
86e8cf98 2588 if (state->split) {
5de17984
AS
2589 CMD(crit_proto_start, CRIT_PROTOCOL_START);
2590 CMD(crit_proto_stop, CRIT_PROTOCOL_STOP);
1b8ec87a 2591 if (rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH)
16ef1fe2 2592 CMD(channel_switch, CHANNEL_SWITCH);
02df00eb 2593 CMD(set_qos_map, SET_QOS_MAP);
723e73ac
JB
2594 if (rdev->wiphy.features &
2595 NL80211_FEATURE_SUPPORTS_WMM_ADMISSION)
960d01ac 2596 CMD(add_tx_ts, ADD_TX_TS);
ce0ce13a 2597 CMD(set_multicast_to_unicast, SET_MULTICAST_TO_UNICAST);
088e8df8 2598 CMD(update_connect_params, UPDATE_CONNECT_PARAMS);
7010998c 2599 CMD(update_ft_ies, UPDATE_FT_IES);
6bdb68ce
CH
2600 if (rdev->wiphy.sar_capa)
2601 CMD(set_sar_specs, SET_SAR_SPECS);
5de17984 2602 }
3713b4e3 2603#undef CMD
ff1b6e69 2604
3713b4e3 2605 nla_nest_end(msg, nl_cmds);
86e8cf98
JB
2606 state->split_start++;
2607 if (state->split)
3713b4e3 2608 break;
7b506ff6 2609 fallthrough;
3713b4e3 2610 case 5:
1b8ec87a
ZG
2611 if (rdev->ops->remain_on_channel &&
2612 (rdev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL) &&
3713b4e3
JB
2613 nla_put_u32(msg,
2614 NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION,
1b8ec87a 2615 rdev->wiphy.max_remain_on_channel_duration))
3713b4e3
JB
2616 goto nla_put_failure;
2617
1b8ec87a 2618 if ((rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX) &&
3713b4e3
JB
2619 nla_put_flag(msg, NL80211_ATTR_OFFCHANNEL_TX_OK))
2620 goto nla_put_failure;
2621
86e8cf98
JB
2622 state->split_start++;
2623 if (state->split)
3713b4e3 2624 break;
7b506ff6 2625 fallthrough;
3713b4e3
JB
2626 case 6:
2627#ifdef CONFIG_PM
1b8ec87a 2628 if (nl80211_send_wowlan(msg, rdev, state->split))
3713b4e3 2629 goto nla_put_failure;
86e8cf98
JB
2630 state->split_start++;
2631 if (state->split)
3713b4e3
JB
2632 break;
2633#else
86e8cf98 2634 state->split_start++;
dfb89c56 2635#endif
7b506ff6 2636 fallthrough;
3713b4e3
JB
2637 case 7:
2638 if (nl80211_put_iftypes(msg, NL80211_ATTR_SOFTWARE_IFTYPES,
1b8ec87a 2639 rdev->wiphy.software_iftypes))
3713b4e3 2640 goto nla_put_failure;
ff1b6e69 2641
1b8ec87a 2642 if (nl80211_put_iface_combinations(&rdev->wiphy, msg,
86e8cf98 2643 state->split))
3713b4e3 2644 goto nla_put_failure;
7527a782 2645
86e8cf98
JB
2646 state->split_start++;
2647 if (state->split)
3713b4e3 2648 break;
7b506ff6 2649 fallthrough;
3713b4e3 2650 case 8:
1b8ec87a 2651 if ((rdev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME) &&
3713b4e3 2652 nla_put_u32(msg, NL80211_ATTR_DEVICE_AP_SME,
1b8ec87a 2653 rdev->wiphy.ap_sme_capa))
3713b4e3 2654 goto nla_put_failure;
7527a782 2655
1b8ec87a 2656 features = rdev->wiphy.features;
fe1abafd
JB
2657 /*
2658 * We can only add the per-channel limit information if the
2659 * dump is split, otherwise it makes it too big. Therefore
2660 * only advertise it in that case.
2661 */
86e8cf98 2662 if (state->split)
fe1abafd
JB
2663 features |= NL80211_FEATURE_ADVERTISE_CHAN_LIMITS;
2664 if (nla_put_u32(msg, NL80211_ATTR_FEATURE_FLAGS, features))
3713b4e3 2665 goto nla_put_failure;
562a7480 2666
1b8ec87a 2667 if (rdev->wiphy.ht_capa_mod_mask &&
3713b4e3 2668 nla_put(msg, NL80211_ATTR_HT_CAPABILITY_MASK,
1b8ec87a
ZG
2669 sizeof(*rdev->wiphy.ht_capa_mod_mask),
2670 rdev->wiphy.ht_capa_mod_mask))
3713b4e3 2671 goto nla_put_failure;
1f074bd8 2672
1b8ec87a
ZG
2673 if (rdev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME &&
2674 rdev->wiphy.max_acl_mac_addrs &&
3713b4e3 2675 nla_put_u32(msg, NL80211_ATTR_MAC_ACL_MAX,
1b8ec87a 2676 rdev->wiphy.max_acl_mac_addrs))
3713b4e3 2677 goto nla_put_failure;
7e7c8926 2678
3713b4e3
JB
2679 /*
2680 * Any information below this point is only available to
2681 * applications that can deal with it being split. This
2682 * helps ensure that newly added capabilities don't break
2683 * older tools by overrunning their buffers.
2684 *
2685 * We still increment split_start so that in the split
2686 * case we'll continue with more data in the next round,
2687 * but break unconditionally so unsplit data stops here.
2688 */
ab10c22b
JB
2689 if (state->split)
2690 state->split_start++;
2691 else
2692 state->split_start = 0;
3713b4e3
JB
2693 break;
2694 case 9:
f8d504ca
JB
2695 if (nl80211_send_mgmt_stypes(msg, mgmt_stypes))
2696 goto nla_put_failure;
2697
2698 if (nla_put_u32(msg, NL80211_ATTR_MAX_NUM_SCHED_SCAN_PLANS,
2699 rdev->wiphy.max_sched_scan_plans) ||
2700 nla_put_u32(msg, NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL,
2701 rdev->wiphy.max_sched_scan_plan_interval) ||
2702 nla_put_u32(msg, NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS,
2703 rdev->wiphy.max_sched_scan_plan_iterations))
2704 goto nla_put_failure;
2705
1b8ec87a 2706 if (rdev->wiphy.extended_capabilities &&
fe1abafd 2707 (nla_put(msg, NL80211_ATTR_EXT_CAPA,
1b8ec87a
ZG
2708 rdev->wiphy.extended_capabilities_len,
2709 rdev->wiphy.extended_capabilities) ||
fe1abafd 2710 nla_put(msg, NL80211_ATTR_EXT_CAPA_MASK,
1b8ec87a
ZG
2711 rdev->wiphy.extended_capabilities_len,
2712 rdev->wiphy.extended_capabilities_mask)))
fe1abafd 2713 goto nla_put_failure;
a50df0c4 2714
1b8ec87a 2715 if (rdev->wiphy.vht_capa_mod_mask &&
ee2aca34 2716 nla_put(msg, NL80211_ATTR_VHT_CAPABILITY_MASK,
1b8ec87a
ZG
2717 sizeof(*rdev->wiphy.vht_capa_mod_mask),
2718 rdev->wiphy.vht_capa_mod_mask))
ee2aca34
JB
2719 goto nla_put_failure;
2720
ae6fa4d5
DK
2721 if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN,
2722 rdev->wiphy.perm_addr))
2723 goto nla_put_failure;
2724
2725 if (!is_zero_ether_addr(rdev->wiphy.addr_mask) &&
2726 nla_put(msg, NL80211_ATTR_MAC_MASK, ETH_ALEN,
2727 rdev->wiphy.addr_mask))
2728 goto nla_put_failure;
2729
2730 if (rdev->wiphy.n_addresses > 1) {
2731 void *attr;
2732
2733 attr = nla_nest_start(msg, NL80211_ATTR_MAC_ADDRS);
2734 if (!attr)
2735 goto nla_put_failure;
2736
2737 for (i = 0; i < rdev->wiphy.n_addresses; i++)
2738 if (nla_put(msg, i + 1, ETH_ALEN,
2739 rdev->wiphy.addresses[i].addr))
2740 goto nla_put_failure;
2741
2742 nla_nest_end(msg, attr);
2743 }
2744
be29b99a
AK
2745 state->split_start++;
2746 break;
2747 case 10:
1b8ec87a 2748 if (nl80211_send_coalesce(msg, rdev))
be29b99a
AK
2749 goto nla_put_failure;
2750
1b8ec87a 2751 if ((rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_5_10_MHZ) &&
01e0daa4
FF
2752 (nla_put_flag(msg, NL80211_ATTR_SUPPORT_5_MHZ) ||
2753 nla_put_flag(msg, NL80211_ATTR_SUPPORT_10_MHZ)))
2754 goto nla_put_failure;
b43504cf 2755
1b8ec87a 2756 if (rdev->wiphy.max_ap_assoc_sta &&
b43504cf 2757 nla_put_u32(msg, NL80211_ATTR_MAX_AP_ASSOC_STA,
1b8ec87a 2758 rdev->wiphy.max_ap_assoc_sta))
b43504cf
JM
2759 goto nla_put_failure;
2760
ad7e718c
JB
2761 state->split_start++;
2762 break;
2763 case 11:
1b8ec87a 2764 if (rdev->wiphy.n_vendor_commands) {
567ffc35
JB
2765 const struct nl80211_vendor_cmd_info *info;
2766 struct nlattr *nested;
2767
ae0be8de
MK
2768 nested = nla_nest_start_noflag(msg,
2769 NL80211_ATTR_VENDOR_DATA);
567ffc35
JB
2770 if (!nested)
2771 goto nla_put_failure;
2772
1b8ec87a
ZG
2773 for (i = 0; i < rdev->wiphy.n_vendor_commands; i++) {
2774 info = &rdev->wiphy.vendor_commands[i].info;
567ffc35
JB
2775 if (nla_put(msg, i + 1, sizeof(*info), info))
2776 goto nla_put_failure;
2777 }
2778 nla_nest_end(msg, nested);
2779 }
2780
1b8ec87a 2781 if (rdev->wiphy.n_vendor_events) {
567ffc35
JB
2782 const struct nl80211_vendor_cmd_info *info;
2783 struct nlattr *nested;
ad7e718c 2784
ae0be8de
MK
2785 nested = nla_nest_start_noflag(msg,
2786 NL80211_ATTR_VENDOR_EVENTS);
567ffc35 2787 if (!nested)
ad7e718c 2788 goto nla_put_failure;
567ffc35 2789
1b8ec87a
ZG
2790 for (i = 0; i < rdev->wiphy.n_vendor_events; i++) {
2791 info = &rdev->wiphy.vendor_events[i];
567ffc35
JB
2792 if (nla_put(msg, i + 1, sizeof(*info), info))
2793 goto nla_put_failure;
2794 }
2795 nla_nest_end(msg, nested);
2796 }
9a774c78
AO
2797 state->split_start++;
2798 break;
2799 case 12:
2800 if (rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH &&
2801 nla_put_u8(msg, NL80211_ATTR_MAX_CSA_COUNTERS,
2802 rdev->wiphy.max_num_csa_counters))
2803 goto nla_put_failure;
01e0daa4 2804
1bdd716c
AN
2805 if (rdev->wiphy.regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED &&
2806 nla_put_flag(msg, NL80211_ATTR_WIPHY_SELF_MANAGED_REG))
2807 goto nla_put_failure;
2808
ca986ad9
AVS
2809 if (rdev->wiphy.max_sched_scan_reqs &&
2810 nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_MAX_REQS,
2811 rdev->wiphy.max_sched_scan_reqs))
2812 goto nla_put_failure;
2813
d75bb06b
GKS
2814 if (nla_put(msg, NL80211_ATTR_EXT_FEATURES,
2815 sizeof(rdev->wiphy.ext_features),
2816 rdev->wiphy.ext_features))
2817 goto nla_put_failure;
2818
38de03d2
AS
2819 if (rdev->wiphy.bss_select_support) {
2820 struct nlattr *nested;
2821 u32 bss_select_support = rdev->wiphy.bss_select_support;
2822
ae0be8de
MK
2823 nested = nla_nest_start_noflag(msg,
2824 NL80211_ATTR_BSS_SELECT);
38de03d2
AS
2825 if (!nested)
2826 goto nla_put_failure;
2827
2828 i = 0;
2829 while (bss_select_support) {
2830 if ((bss_select_support & 1) &&
2831 nla_put_flag(msg, i))
2832 goto nla_put_failure;
2833 i++;
2834 bss_select_support >>= 1;
2835 }
2836 nla_nest_end(msg, nested);
2837 }
2838
019ae3a9
KV
2839 state->split_start++;
2840 break;
2841 case 13:
2842 if (rdev->wiphy.num_iftype_ext_capab &&
2843 rdev->wiphy.iftype_ext_capab) {
2844 struct nlattr *nested_ext_capab, *nested;
2845
ae0be8de
MK
2846 nested = nla_nest_start_noflag(msg,
2847 NL80211_ATTR_IFTYPE_EXT_CAPA);
019ae3a9
KV
2848 if (!nested)
2849 goto nla_put_failure;
2850
2851 for (i = state->capa_start;
2852 i < rdev->wiphy.num_iftype_ext_capab; i++) {
2853 const struct wiphy_iftype_ext_capab *capab;
2854
2855 capab = &rdev->wiphy.iftype_ext_capab[i];
2856
ae0be8de
MK
2857 nested_ext_capab = nla_nest_start_noflag(msg,
2858 i);
019ae3a9
KV
2859 if (!nested_ext_capab ||
2860 nla_put_u32(msg, NL80211_ATTR_IFTYPE,
2861 capab->iftype) ||
2862 nla_put(msg, NL80211_ATTR_EXT_CAPA,
2863 capab->extended_capabilities_len,
2864 capab->extended_capabilities) ||
2865 nla_put(msg, NL80211_ATTR_EXT_CAPA_MASK,
2866 capab->extended_capabilities_len,
2867 capab->extended_capabilities_mask))
2868 goto nla_put_failure;
2869
2870 nla_nest_end(msg, nested_ext_capab);
2871 if (state->split)
2872 break;
2873 }
2874 nla_nest_end(msg, nested);
2875 if (i < rdev->wiphy.num_iftype_ext_capab) {
2876 state->capa_start = i + 1;
2877 break;
2878 }
2879 }
2880
8585989d
LC
2881 if (nla_put_u32(msg, NL80211_ATTR_BANDS,
2882 rdev->wiphy.nan_supported_bands))
2883 goto nla_put_failure;
2884
52539ca8
THJ
2885 if (wiphy_ext_feature_isset(&rdev->wiphy,
2886 NL80211_EXT_FEATURE_TXQS)) {
2887 struct cfg80211_txq_stats txqstats = {};
2888 int res;
2889
2890 res = rdev_get_txq_stats(rdev, NULL, &txqstats);
2891 if (!res &&
2892 !nl80211_put_txq_stats(msg, &txqstats,
2893 NL80211_ATTR_TXQ_STATS))
2894 goto nla_put_failure;
2895
2896 if (nla_put_u32(msg, NL80211_ATTR_TXQ_LIMIT,
2897 rdev->wiphy.txq_limit))
2898 goto nla_put_failure;
2899 if (nla_put_u32(msg, NL80211_ATTR_TXQ_MEMORY_LIMIT,
2900 rdev->wiphy.txq_memory_limit))
2901 goto nla_put_failure;
2902 if (nla_put_u32(msg, NL80211_ATTR_TXQ_QUANTUM,
2903 rdev->wiphy.txq_quantum))
2904 goto nla_put_failure;
2905 }
2906
9bb7e0f2
JB
2907 state->split_start++;
2908 break;
2909 case 14:
2910 if (nl80211_send_pmsr_capa(rdev, msg))
2911 goto nla_put_failure;
2912
ab4dfa20
VJ
2913 state->split_start++;
2914 break;
2915 case 15:
2916 if (rdev->wiphy.akm_suites &&
2917 nla_put(msg, NL80211_ATTR_AKM_SUITES,
2918 sizeof(u32) * rdev->wiphy.n_akm_suites,
2919 rdev->wiphy.akm_suites))
2920 goto nla_put_failure;
2921
d6039a34
VJ
2922 if (nl80211_put_iftype_akm_suites(rdev, msg))
2923 goto nla_put_failure;
2924
3710a8a6
JB
2925 if (nl80211_put_tid_config_support(rdev, msg))
2926 goto nla_put_failure;
6bdb68ce
CH
2927 state->split_start++;
2928 break;
2929 case 16:
2930 if (nl80211_put_sar_specs(rdev, msg))
2931 goto nla_put_failure;
3710a8a6 2932
dc1e3cb8
JC
2933 if (nl80211_put_mbssid_support(&rdev->wiphy, msg))
2934 goto nla_put_failure;
2935
ecad3b0b
VJ
2936 if (nla_put_u16(msg, NL80211_ATTR_MAX_NUM_AKM_SUITES,
2937 rdev->wiphy.max_num_akm_suites))
2938 goto nla_put_failure;
2939
3713b4e3 2940 /* done */
86e8cf98 2941 state->split_start = 0;
3713b4e3
JB
2942 break;
2943 }
3bb20556 2944 finish:
053c095a
JB
2945 genlmsg_end(msg, hdr);
2946 return 0;
55682965
JB
2947
2948 nla_put_failure:
bc3ed28c
TG
2949 genlmsg_cancel(msg, hdr);
2950 return -EMSGSIZE;
55682965
JB
2951}
2952
86e8cf98
JB
2953static int nl80211_dump_wiphy_parse(struct sk_buff *skb,
2954 struct netlink_callback *cb,
2955 struct nl80211_dump_wiphy_state *state)
2956{
50508d94
JB
2957 struct nlattr **tb = kcalloc(NUM_NL80211_ATTR, sizeof(*tb), GFP_KERNEL);
2958 int ret;
2959
2960 if (!tb)
2961 return -ENOMEM;
2962
2963 ret = nlmsg_parse_deprecated(cb->nlh,
2964 GENL_HDRLEN + nl80211_fam.hdrsize,
2965 tb, nl80211_fam.maxattr,
2966 nl80211_policy, NULL);
86e8cf98 2967 /* ignore parse errors for backward compatibility */
50508d94
JB
2968 if (ret) {
2969 ret = 0;
2970 goto out;
2971 }
86e8cf98
JB
2972
2973 state->split = tb[NL80211_ATTR_SPLIT_WIPHY_DUMP];
2974 if (tb[NL80211_ATTR_WIPHY])
2975 state->filter_wiphy = nla_get_u32(tb[NL80211_ATTR_WIPHY]);
2976 if (tb[NL80211_ATTR_WDEV])
2977 state->filter_wiphy = nla_get_u64(tb[NL80211_ATTR_WDEV]) >> 32;
2978 if (tb[NL80211_ATTR_IFINDEX]) {
2979 struct net_device *netdev;
2980 struct cfg80211_registered_device *rdev;
2981 int ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
2982
7f2b8562 2983 netdev = __dev_get_by_index(sock_net(skb->sk), ifidx);
50508d94
JB
2984 if (!netdev) {
2985 ret = -ENODEV;
2986 goto out;
2987 }
86e8cf98 2988 if (netdev->ieee80211_ptr) {
f26cbf40 2989 rdev = wiphy_to_rdev(
86e8cf98
JB
2990 netdev->ieee80211_ptr->wiphy);
2991 state->filter_wiphy = rdev->wiphy_idx;
2992 }
86e8cf98
JB
2993 }
2994
50508d94
JB
2995 ret = 0;
2996out:
2997 kfree(tb);
2998 return ret;
86e8cf98
JB
2999}
3000
55682965
JB
3001static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
3002{
645e77de 3003 int idx = 0, ret;
86e8cf98 3004 struct nl80211_dump_wiphy_state *state = (void *)cb->args[0];
1b8ec87a 3005 struct cfg80211_registered_device *rdev;
3a5a423b 3006
5fe231e8 3007 rtnl_lock();
86e8cf98
JB
3008 if (!state) {
3009 state = kzalloc(sizeof(*state), GFP_KERNEL);
57ed5cd6
JL
3010 if (!state) {
3011 rtnl_unlock();
86e8cf98 3012 return -ENOMEM;
3713b4e3 3013 }
86e8cf98
JB
3014 state->filter_wiphy = -1;
3015 ret = nl80211_dump_wiphy_parse(skb, cb, state);
3016 if (ret) {
3017 kfree(state);
3018 rtnl_unlock();
3019 return ret;
3713b4e3 3020 }
86e8cf98 3021 cb->args[0] = (long)state;
3713b4e3
JB
3022 }
3023
1b8ec87a
ZG
3024 list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
3025 if (!net_eq(wiphy_net(&rdev->wiphy), sock_net(skb->sk)))
463d0183 3026 continue;
86e8cf98 3027 if (++idx <= state->start)
55682965 3028 continue;
86e8cf98 3029 if (state->filter_wiphy != -1 &&
1b8ec87a 3030 state->filter_wiphy != rdev->wiphy_idx)
3713b4e3
JB
3031 continue;
3032 /* attempt to fit multiple wiphy data chunks into the skb */
3033 do {
3bb20556
JB
3034 ret = nl80211_send_wiphy(rdev, NL80211_CMD_NEW_WIPHY,
3035 skb,
3713b4e3
JB
3036 NETLINK_CB(cb->skb).portid,
3037 cb->nlh->nlmsg_seq,
86e8cf98 3038 NLM_F_MULTI, state);
3713b4e3
JB
3039 if (ret < 0) {
3040 /*
3041 * If sending the wiphy data didn't fit (ENOBUFS
3042 * or EMSGSIZE returned), this SKB is still
3043 * empty (so it's not too big because another
3044 * wiphy dataset is already in the skb) and
3045 * we've not tried to adjust the dump allocation
3046 * yet ... then adjust the alloc size to be
3047 * bigger, and return 1 but with the empty skb.
3048 * This results in an empty message being RX'ed
3049 * in userspace, but that is ignored.
3050 *
3051 * We can then retry with the larger buffer.
3052 */
3053 if ((ret == -ENOBUFS || ret == -EMSGSIZE) &&
f12cb289 3054 !skb->len && !state->split &&
3713b4e3
JB
3055 cb->min_dump_alloc < 4096) {
3056 cb->min_dump_alloc = 4096;
f12cb289 3057 state->split_start = 0;
d98cae64 3058 rtnl_unlock();
3713b4e3
JB
3059 return 1;
3060 }
3061 idx--;
3062 break;
645e77de 3063 }
86e8cf98 3064 } while (state->split_start > 0);
3713b4e3 3065 break;
55682965 3066 }
5fe231e8 3067 rtnl_unlock();
55682965 3068
86e8cf98 3069 state->start = idx;
55682965
JB
3070
3071 return skb->len;
3072}
3073
86e8cf98
JB
3074static int nl80211_dump_wiphy_done(struct netlink_callback *cb)
3075{
3076 kfree((void *)cb->args[0]);
3077 return 0;
3078}
3079
55682965
JB
3080static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info)
3081{
3082 struct sk_buff *msg;
1b8ec87a 3083 struct cfg80211_registered_device *rdev = info->user_ptr[0];
86e8cf98 3084 struct nl80211_dump_wiphy_state state = {};
55682965 3085
645e77de 3086 msg = nlmsg_new(4096, GFP_KERNEL);
55682965 3087 if (!msg)
4c476991 3088 return -ENOMEM;
55682965 3089
3bb20556
JB
3090 if (nl80211_send_wiphy(rdev, NL80211_CMD_NEW_WIPHY, msg,
3091 info->snd_portid, info->snd_seq, 0,
86e8cf98 3092 &state) < 0) {
4c476991
JB
3093 nlmsg_free(msg);
3094 return -ENOBUFS;
3095 }
55682965 3096
134e6375 3097 return genlmsg_reply(msg, info);
55682965
JB
3098}
3099
31888487
JM
3100static const struct nla_policy txq_params_policy[NL80211_TXQ_ATTR_MAX + 1] = {
3101 [NL80211_TXQ_ATTR_QUEUE] = { .type = NLA_U8 },
3102 [NL80211_TXQ_ATTR_TXOP] = { .type = NLA_U16 },
3103 [NL80211_TXQ_ATTR_CWMIN] = { .type = NLA_U16 },
3104 [NL80211_TXQ_ATTR_CWMAX] = { .type = NLA_U16 },
3105 [NL80211_TXQ_ATTR_AIFS] = { .type = NLA_U8 },
3106};
3107
3108static int parse_txq_params(struct nlattr *tb[],
3109 struct ieee80211_txq_params *txq_params)
3110{
259d8c1e
DW
3111 u8 ac;
3112
a3304b0a 3113 if (!tb[NL80211_TXQ_ATTR_AC] || !tb[NL80211_TXQ_ATTR_TXOP] ||
31888487
JM
3114 !tb[NL80211_TXQ_ATTR_CWMIN] || !tb[NL80211_TXQ_ATTR_CWMAX] ||
3115 !tb[NL80211_TXQ_ATTR_AIFS])
3116 return -EINVAL;
3117
259d8c1e 3118 ac = nla_get_u8(tb[NL80211_TXQ_ATTR_AC]);
31888487
JM
3119 txq_params->txop = nla_get_u16(tb[NL80211_TXQ_ATTR_TXOP]);
3120 txq_params->cwmin = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMIN]);
3121 txq_params->cwmax = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMAX]);
3122 txq_params->aifs = nla_get_u8(tb[NL80211_TXQ_ATTR_AIFS]);
3123
259d8c1e 3124 if (ac >= NL80211_NUM_ACS)
a3304b0a 3125 return -EINVAL;
259d8c1e 3126 txq_params->ac = array_index_nospec(ac, NL80211_NUM_ACS);
31888487
JM
3127 return 0;
3128}
3129
f444de05
JB
3130static bool nl80211_can_set_dev_channel(struct wireless_dev *wdev)
3131{
3132 /*
e7e0517c
JB
3133 * You can only set the channel explicitly for some interfaces,
3134 * most have their channel managed via their respective
cc1d2806
JB
3135 * "establish a connection" command (connect, join, ...)
3136 *
3137 * For AP/GO and mesh mode, the channel can be set with the
3138 * channel userspace API, but is only stored and passed to the
3139 * low-level driver when the AP starts or the mesh is joined.
3140 * This is for backward compatibility, userspace can also give
3141 * the channel in the start-ap or join-mesh commands instead.
f444de05
JB
3142 *
3143 * Monitors are special as they are normally slaved to
e8c9bd5b
JB
3144 * whatever else is going on, so they have their own special
3145 * operation to set the monitor channel if possible.
f444de05
JB
3146 */
3147 return !wdev ||
3148 wdev->iftype == NL80211_IFTYPE_AP ||
f444de05 3149 wdev->iftype == NL80211_IFTYPE_MESH_POINT ||
074ac8df
JB
3150 wdev->iftype == NL80211_IFTYPE_MONITOR ||
3151 wdev->iftype == NL80211_IFTYPE_P2P_GO;
f444de05
JB
3152}
3153
9bb7e0f2
JB
3154int nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
3155 struct genl_info *info,
3156 struct cfg80211_chan_def *chandef)
683b6d3b 3157{
49f9cf0e
JB
3158 struct netlink_ext_ack *extack = info->extack;
3159 struct nlattr **attrs = info->attrs;
dbeca2ea 3160 u32 control_freq;
683b6d3b 3161
49f9cf0e 3162 if (!attrs[NL80211_ATTR_WIPHY_FREQ])
683b6d3b
JB
3163 return -EINVAL;
3164
942ba88b
TP
3165 control_freq = MHZ_TO_KHZ(
3166 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
3167 if (info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET])
3168 control_freq +=
3169 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET]);
683b6d3b 3170
f43e5210 3171 memset(chandef, 0, sizeof(*chandef));
942ba88b 3172 chandef->chan = ieee80211_get_channel_khz(&rdev->wiphy, control_freq);
3d9d1d66 3173 chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
942ba88b
TP
3174 chandef->center_freq1 = KHZ_TO_MHZ(control_freq);
3175 chandef->freq1_offset = control_freq % 1000;
3d9d1d66 3176 chandef->center_freq2 = 0;
683b6d3b
JB
3177
3178 /* Primary channel not allowed */
49f9cf0e
JB
3179 if (!chandef->chan || chandef->chan->flags & IEEE80211_CHAN_DISABLED) {
3180 NL_SET_ERR_MSG_ATTR(extack, attrs[NL80211_ATTR_WIPHY_FREQ],
3181 "Channel is disabled");
683b6d3b 3182 return -EINVAL;
49f9cf0e 3183 }
683b6d3b 3184
49f9cf0e 3185 if (attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
3d9d1d66
JB
3186 enum nl80211_channel_type chantype;
3187
49f9cf0e 3188 chantype = nla_get_u32(attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
3d9d1d66
JB
3189
3190 switch (chantype) {
3191 case NL80211_CHAN_NO_HT:
3192 case NL80211_CHAN_HT20:
3193 case NL80211_CHAN_HT40PLUS:
3194 case NL80211_CHAN_HT40MINUS:
3195 cfg80211_chandef_create(chandef, chandef->chan,
3196 chantype);
ffa4629e 3197 /* user input for center_freq is incorrect */
49f9cf0e
JB
3198 if (attrs[NL80211_ATTR_CENTER_FREQ1] &&
3199 chandef->center_freq1 != nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ1])) {
3200 NL_SET_ERR_MSG_ATTR(extack,
3201 attrs[NL80211_ATTR_CENTER_FREQ1],
3202 "bad center frequency 1");
ffa4629e 3203 return -EINVAL;
49f9cf0e 3204 }
ffa4629e 3205 /* center_freq2 must be zero */
49f9cf0e
JB
3206 if (attrs[NL80211_ATTR_CENTER_FREQ2] &&
3207 nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ2])) {
3208 NL_SET_ERR_MSG_ATTR(extack,
3209 attrs[NL80211_ATTR_CENTER_FREQ2],
3210 "center frequency 2 can't be used");
ffa4629e 3211 return -EINVAL;
49f9cf0e 3212 }
3d9d1d66
JB
3213 break;
3214 default:
49f9cf0e
JB
3215 NL_SET_ERR_MSG_ATTR(extack,
3216 attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE],
3217 "invalid channel type");
3d9d1d66
JB
3218 return -EINVAL;
3219 }
49f9cf0e 3220 } else if (attrs[NL80211_ATTR_CHANNEL_WIDTH]) {
3d9d1d66 3221 chandef->width =
49f9cf0e 3222 nla_get_u32(attrs[NL80211_ATTR_CHANNEL_WIDTH]);
5d087aa7
KF
3223 if (chandef->chan->band == NL80211_BAND_S1GHZ) {
3224 /* User input error for channel width doesn't match channel */
3225 if (chandef->width != ieee80211_s1g_channel_width(chandef->chan)) {
3226 NL_SET_ERR_MSG_ATTR(extack,
3227 attrs[NL80211_ATTR_CHANNEL_WIDTH],
3228 "bad channel width");
3229 return -EINVAL;
3230 }
3231 }
942ba88b 3232 if (attrs[NL80211_ATTR_CENTER_FREQ1]) {
3d9d1d66 3233 chandef->center_freq1 =
49f9cf0e 3234 nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ1]);
942ba88b
TP
3235 if (attrs[NL80211_ATTR_CENTER_FREQ1_OFFSET])
3236 chandef->freq1_offset = nla_get_u32(
3237 attrs[NL80211_ATTR_CENTER_FREQ1_OFFSET]);
3238 else
3239 chandef->freq1_offset = 0;
3240 }
49f9cf0e 3241 if (attrs[NL80211_ATTR_CENTER_FREQ2])
3d9d1d66 3242 chandef->center_freq2 =
49f9cf0e 3243 nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ2]);
3d9d1d66
JB
3244 }
3245
2a38075c
AAL
3246 if (info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]) {
3247 chandef->edmg.channels =
3248 nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]);
3249
3250 if (info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG])
3251 chandef->edmg.bw_config =
3252 nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG]);
3253 } else {
3254 chandef->edmg.bw_config = 0;
3255 chandef->edmg.channels = 0;
3256 }
3257
49f9cf0e
JB
3258 if (!cfg80211_chandef_valid(chandef)) {
3259 NL_SET_ERR_MSG(extack, "invalid channel definition");
3d9d1d66 3260 return -EINVAL;
49f9cf0e 3261 }
3d9d1d66 3262
9f5e8f6e 3263 if (!cfg80211_chandef_usable(&rdev->wiphy, chandef,
49f9cf0e
JB
3264 IEEE80211_CHAN_DISABLED)) {
3265 NL_SET_ERR_MSG(extack, "(extension) channel is disabled");
3d9d1d66 3266 return -EINVAL;
49f9cf0e 3267 }
3d9d1d66 3268
2f301ab2
SW
3269 if ((chandef->width == NL80211_CHAN_WIDTH_5 ||
3270 chandef->width == NL80211_CHAN_WIDTH_10) &&
49f9cf0e
JB
3271 !(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_5_10_MHZ)) {
3272 NL_SET_ERR_MSG(extack, "5/10 MHz not supported");
2f301ab2 3273 return -EINVAL;
49f9cf0e 3274 }
2f301ab2 3275
683b6d3b
JB
3276 return 0;
3277}
3278
f444de05 3279static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
e16821bc 3280 struct net_device *dev,
7b0a0e3c
JB
3281 struct genl_info *info,
3282 int _link_id)
f444de05 3283{
683b6d3b 3284 struct cfg80211_chan_def chandef;
f444de05 3285 int result;
e8c9bd5b 3286 enum nl80211_iftype iftype = NL80211_IFTYPE_MONITOR;
e16821bc 3287 struct wireless_dev *wdev = NULL;
7b0a0e3c 3288 int link_id = _link_id;
e8c9bd5b 3289
e16821bc
JM
3290 if (dev)
3291 wdev = dev->ieee80211_ptr;
f444de05
JB
3292 if (!nl80211_can_set_dev_channel(wdev))
3293 return -EOPNOTSUPP;
e16821bc
JM
3294 if (wdev)
3295 iftype = wdev->iftype;
f444de05 3296
7b0a0e3c
JB
3297 if (link_id < 0) {
3298 if (wdev && wdev->valid_links)
3299 return -EINVAL;
3300 link_id = 0;
3301 }
3302
683b6d3b
JB
3303 result = nl80211_parse_chandef(rdev, info, &chandef);
3304 if (result)
3305 return result;
f444de05 3306
e8c9bd5b 3307 switch (iftype) {
aa430da4
JB
3308 case NL80211_IFTYPE_AP:
3309 case NL80211_IFTYPE_P2P_GO:
923b352f 3310 if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &chandef,
7b0a0e3c
JB
3311 iftype))
3312 return -EINVAL;
3313 if (wdev->links[link_id].ap.beacon_interval) {
3314 struct ieee80211_channel *cur_chan;
3315
e16821bc
JM
3316 if (!dev || !rdev->ops->set_ap_chanwidth ||
3317 !(rdev->wiphy.features &
7b0a0e3c
JB
3318 NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE))
3319 return -EBUSY;
e16821bc
JM
3320
3321 /* Only allow dynamic channel width changes */
7b0a0e3c
JB
3322 cur_chan = wdev->links[link_id].ap.chandef.chan;
3323 if (chandef.chan != cur_chan)
3324 return -EBUSY;
3325
3326 result = rdev_set_ap_chanwidth(rdev, dev, link_id,
3327 &chandef);
e16821bc 3328 if (result)
7b0a0e3c
JB
3329 return result;
3330 wdev->links[link_id].ap.chandef = chandef;
3331 } else {
3332 wdev->u.ap.preset_chandef = chandef;
e16821bc 3333 }
7b0a0e3c 3334 return 0;
cc1d2806 3335 case NL80211_IFTYPE_MESH_POINT:
7b0a0e3c 3336 return cfg80211_set_mesh_channel(rdev, wdev, &chandef);
e8c9bd5b 3337 case NL80211_IFTYPE_MONITOR:
7b0a0e3c 3338 return cfg80211_set_monitor_channel(rdev, &chandef);
aa430da4 3339 default:
7b0a0e3c 3340 break;
f444de05 3341 }
f444de05 3342
7b0a0e3c 3343 return -EINVAL;
f444de05
JB
3344}
3345
3346static int nl80211_set_channel(struct sk_buff *skb, struct genl_info *info)
3347{
4c476991 3348 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7b0a0e3c 3349 int link_id = nl80211_link_id_or_invalid(info->attrs);
4c476991 3350 struct net_device *netdev = info->user_ptr[1];
4e2f3d67
JB
3351 int ret;
3352
3353 wdev_lock(netdev->ieee80211_ptr);
3354 ret = __nl80211_set_channel(rdev, netdev, info, link_id);
3355 wdev_unlock(netdev->ieee80211_ptr);
f444de05 3356
4e2f3d67 3357 return ret;
f444de05
JB
3358}
3359
55682965
JB
3360static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
3361{
a05829a7 3362 struct cfg80211_registered_device *rdev = NULL;
f444de05
JB
3363 struct net_device *netdev = NULL;
3364 struct wireless_dev *wdev;
a1e567c8 3365 int result = 0, rem_txq_params = 0;
31888487 3366 struct nlattr *nl_txq_params;
b9a5f8ca
JM
3367 u32 changed;
3368 u8 retry_short = 0, retry_long = 0;
3369 u32 frag_threshold = 0, rts_threshold = 0;
81077e82 3370 u8 coverage_class = 0;
52539ca8 3371 u32 txq_limit = 0, txq_memory_limit = 0, txq_quantum = 0;
55682965 3372
a05829a7 3373 rtnl_lock();
f444de05
JB
3374 /*
3375 * Try to find the wiphy and netdev. Normally this
3376 * function shouldn't need the netdev, but this is
3377 * done for backward compatibility -- previously
3378 * setting the channel was done per wiphy, but now
3379 * it is per netdev. Previous userland like hostapd
3380 * also passed a netdev to set_wiphy, so that it is
3381 * possible to let that go to the right netdev!
3382 */
4bbf4d56 3383
f444de05
JB
3384 if (info->attrs[NL80211_ATTR_IFINDEX]) {
3385 int ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]);
3386
7f2b8562 3387 netdev = __dev_get_by_index(genl_info_net(info), ifindex);
5fe231e8 3388 if (netdev && netdev->ieee80211_ptr)
f26cbf40 3389 rdev = wiphy_to_rdev(netdev->ieee80211_ptr->wiphy);
5fe231e8 3390 else
f444de05 3391 netdev = NULL;
4bbf4d56
JB
3392 }
3393
f444de05 3394 if (!netdev) {
878d9ec7
JB
3395 rdev = __cfg80211_rdev_from_attrs(genl_info_net(info),
3396 info->attrs);
a05829a7
JB
3397 if (IS_ERR(rdev)) {
3398 rtnl_unlock();
4c476991 3399 return PTR_ERR(rdev);
a05829a7 3400 }
f444de05
JB
3401 wdev = NULL;
3402 netdev = NULL;
3403 result = 0;
71fe96bf 3404 } else
f444de05 3405 wdev = netdev->ieee80211_ptr;
f444de05 3406
a05829a7 3407 wiphy_lock(&rdev->wiphy);
a05829a7 3408
f444de05
JB
3409 /*
3410 * end workaround code, by now the rdev is available
3411 * and locked, and wdev may or may not be NULL.
3412 */
4bbf4d56
JB
3413
3414 if (info->attrs[NL80211_ATTR_WIPHY_NAME])
31888487
JM
3415 result = cfg80211_dev_rename(
3416 rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME]));
0391a45c 3417 rtnl_unlock();
4bbf4d56 3418
4bbf4d56 3419 if (result)
a05829a7 3420 goto out;
31888487
JM
3421
3422 if (info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS]) {
3423 struct ieee80211_txq_params txq_params;
3424 struct nlattr *tb[NL80211_TXQ_ATTR_MAX + 1];
3425
a05829a7
JB
3426 if (!rdev->ops->set_txq_params) {
3427 result = -EOPNOTSUPP;
3428 goto out;
3429 }
31888487 3430
a05829a7
JB
3431 if (!netdev) {
3432 result = -EINVAL;
3433 goto out;
3434 }
f70f01c2 3435
133a3ff2 3436 if (netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
a05829a7
JB
3437 netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
3438 result = -EINVAL;
3439 goto out;
3440 }
133a3ff2 3441
a05829a7
JB
3442 if (!netif_running(netdev)) {
3443 result = -ENETDOWN;
3444 goto out;
3445 }
2b5f8b0b 3446
31888487
JM
3447 nla_for_each_nested(nl_txq_params,
3448 info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS],
3449 rem_txq_params) {
8cb08174
JB
3450 result = nla_parse_nested_deprecated(tb,
3451 NL80211_TXQ_ATTR_MAX,
3452 nl_txq_params,
3453 txq_params_policy,
3454 info->extack);
ae811e21 3455 if (result)
a05829a7 3456 goto out;
31888487
JM
3457 result = parse_txq_params(tb, &txq_params);
3458 if (result)
a05829a7 3459 goto out;
31888487 3460
e35e4d28
HG
3461 result = rdev_set_txq_params(rdev, netdev,
3462 &txq_params);
31888487 3463 if (result)
a05829a7 3464 goto out;
31888487
JM
3465 }
3466 }
55682965 3467
72bdcf34 3468 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
4e2f3d67
JB
3469 if (wdev) {
3470 wdev_lock(wdev);
3471 result = __nl80211_set_channel(
3472 rdev,
3473 nl80211_can_set_dev_channel(wdev) ? netdev : NULL,
3474 info, -1);
3475 wdev_unlock(wdev);
3476 } else {
3477 result = __nl80211_set_channel(rdev, netdev, info, -1);
3478 }
72bdcf34 3479 if (result)
a05829a7 3480 goto out;
72bdcf34
JM
3481 }
3482
98d2ff8b 3483 if (info->attrs[NL80211_ATTR_WIPHY_TX_POWER_SETTING]) {
c8442118 3484 struct wireless_dev *txp_wdev = wdev;
98d2ff8b
JO
3485 enum nl80211_tx_power_setting type;
3486 int idx, mbm = 0;
3487
c8442118
JB
3488 if (!(rdev->wiphy.features & NL80211_FEATURE_VIF_TXPOWER))
3489 txp_wdev = NULL;
3490
a05829a7
JB
3491 if (!rdev->ops->set_tx_power) {
3492 result = -EOPNOTSUPP;
3493 goto out;
3494 }
98d2ff8b
JO
3495
3496 idx = NL80211_ATTR_WIPHY_TX_POWER_SETTING;
3497 type = nla_get_u32(info->attrs[idx]);
3498
3499 if (!info->attrs[NL80211_ATTR_WIPHY_TX_POWER_LEVEL] &&
a05829a7
JB
3500 (type != NL80211_TX_POWER_AUTOMATIC)) {
3501 result = -EINVAL;
3502 goto out;
3503 }
98d2ff8b
JO
3504
3505 if (type != NL80211_TX_POWER_AUTOMATIC) {
3506 idx = NL80211_ATTR_WIPHY_TX_POWER_LEVEL;
3507 mbm = nla_get_u32(info->attrs[idx]);
3508 }
3509
c8442118 3510 result = rdev_set_tx_power(rdev, txp_wdev, type, mbm);
98d2ff8b 3511 if (result)
a05829a7 3512 goto out;
98d2ff8b
JO
3513 }
3514
afe0cbf8
BR
3515 if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX] &&
3516 info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]) {
3517 u32 tx_ant, rx_ant;
7a087e74 3518
7f531e03
BR
3519 if ((!rdev->wiphy.available_antennas_tx &&
3520 !rdev->wiphy.available_antennas_rx) ||
a05829a7
JB
3521 !rdev->ops->set_antenna) {
3522 result = -EOPNOTSUPP;
3523 goto out;
3524 }
afe0cbf8
BR
3525
3526 tx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX]);
3527 rx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]);
3528
a7ffac95 3529 /* reject antenna configurations which don't match the
7f531e03
BR
3530 * available antenna masks, except for the "all" mask */
3531 if ((~tx_ant && (tx_ant & ~rdev->wiphy.available_antennas_tx)) ||
a05829a7
JB
3532 (~rx_ant && (rx_ant & ~rdev->wiphy.available_antennas_rx))) {
3533 result = -EINVAL;
3534 goto out;
3535 }
a7ffac95 3536
7f531e03
BR
3537 tx_ant = tx_ant & rdev->wiphy.available_antennas_tx;
3538 rx_ant = rx_ant & rdev->wiphy.available_antennas_rx;
a7ffac95 3539
e35e4d28 3540 result = rdev_set_antenna(rdev, tx_ant, rx_ant);
afe0cbf8 3541 if (result)
a05829a7 3542 goto out;
afe0cbf8
BR
3543 }
3544
b9a5f8ca
JM
3545 changed = 0;
3546
3547 if (info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]) {
3548 retry_short = nla_get_u8(
3549 info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]);
7f2b8562 3550
b9a5f8ca
JM
3551 changed |= WIPHY_PARAM_RETRY_SHORT;
3552 }
3553
3554 if (info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]) {
3555 retry_long = nla_get_u8(
3556 info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]);
7f2b8562 3557
b9a5f8ca
JM
3558 changed |= WIPHY_PARAM_RETRY_LONG;
3559 }
3560
3561 if (info->attrs[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]) {
3562 frag_threshold = nla_get_u32(
3563 info->attrs[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]);
a05829a7
JB
3564 if (frag_threshold < 256) {
3565 result = -EINVAL;
3566 goto out;
3567 }
7f2b8562 3568
b9a5f8ca
JM
3569 if (frag_threshold != (u32) -1) {
3570 /*
3571 * Fragments (apart from the last one) are required to
3572 * have even length. Make the fragmentation code
3573 * simpler by stripping LSB should someone try to use
3574 * odd threshold value.
3575 */
3576 frag_threshold &= ~0x1;
3577 }
3578 changed |= WIPHY_PARAM_FRAG_THRESHOLD;
3579 }
3580
3581 if (info->attrs[NL80211_ATTR_WIPHY_RTS_THRESHOLD]) {
3582 rts_threshold = nla_get_u32(
3583 info->attrs[NL80211_ATTR_WIPHY_RTS_THRESHOLD]);
3584 changed |= WIPHY_PARAM_RTS_THRESHOLD;
3585 }
3586
81077e82 3587 if (info->attrs[NL80211_ATTR_WIPHY_COVERAGE_CLASS]) {
a05829a7
JB
3588 if (info->attrs[NL80211_ATTR_WIPHY_DYN_ACK]) {
3589 result = -EINVAL;
3590 goto out;
3591 }
3057dbfd 3592
81077e82
LT
3593 coverage_class = nla_get_u8(
3594 info->attrs[NL80211_ATTR_WIPHY_COVERAGE_CLASS]);
3595 changed |= WIPHY_PARAM_COVERAGE_CLASS;
3596 }
3597
3057dbfd 3598 if (info->attrs[NL80211_ATTR_WIPHY_DYN_ACK]) {
a05829a7
JB
3599 if (!(rdev->wiphy.features & NL80211_FEATURE_ACKTO_ESTIMATION)) {
3600 result = -EOPNOTSUPP;
3601 goto out;
3602 }
3057dbfd
LB
3603
3604 changed |= WIPHY_PARAM_DYN_ACK;
81077e82
LT
3605 }
3606
52539ca8
THJ
3607 if (info->attrs[NL80211_ATTR_TXQ_LIMIT]) {
3608 if (!wiphy_ext_feature_isset(&rdev->wiphy,
a05829a7
JB
3609 NL80211_EXT_FEATURE_TXQS)) {
3610 result = -EOPNOTSUPP;
3611 goto out;
3612 }
52539ca8
THJ
3613 txq_limit = nla_get_u32(
3614 info->attrs[NL80211_ATTR_TXQ_LIMIT]);
3615 changed |= WIPHY_PARAM_TXQ_LIMIT;
3616 }
3617
3618 if (info->attrs[NL80211_ATTR_TXQ_MEMORY_LIMIT]) {
3619 if (!wiphy_ext_feature_isset(&rdev->wiphy,
a05829a7
JB
3620 NL80211_EXT_FEATURE_TXQS)) {
3621 result = -EOPNOTSUPP;
3622 goto out;
3623 }
52539ca8
THJ
3624 txq_memory_limit = nla_get_u32(
3625 info->attrs[NL80211_ATTR_TXQ_MEMORY_LIMIT]);
3626 changed |= WIPHY_PARAM_TXQ_MEMORY_LIMIT;
3627 }
3628
3629 if (info->attrs[NL80211_ATTR_TXQ_QUANTUM]) {
3630 if (!wiphy_ext_feature_isset(&rdev->wiphy,
a05829a7
JB
3631 NL80211_EXT_FEATURE_TXQS)) {
3632 result = -EOPNOTSUPP;
3633 goto out;
3634 }
52539ca8
THJ
3635 txq_quantum = nla_get_u32(
3636 info->attrs[NL80211_ATTR_TXQ_QUANTUM]);
3637 changed |= WIPHY_PARAM_TXQ_QUANTUM;
3638 }
3639
b9a5f8ca
JM
3640 if (changed) {
3641 u8 old_retry_short, old_retry_long;
3642 u32 old_frag_threshold, old_rts_threshold;
81077e82 3643 u8 old_coverage_class;
52539ca8 3644 u32 old_txq_limit, old_txq_memory_limit, old_txq_quantum;
b9a5f8ca 3645
a05829a7
JB
3646 if (!rdev->ops->set_wiphy_params) {
3647 result = -EOPNOTSUPP;
3648 goto out;
3649 }
b9a5f8ca
JM
3650
3651 old_retry_short = rdev->wiphy.retry_short;
3652 old_retry_long = rdev->wiphy.retry_long;
3653 old_frag_threshold = rdev->wiphy.frag_threshold;
3654 old_rts_threshold = rdev->wiphy.rts_threshold;
81077e82 3655 old_coverage_class = rdev->wiphy.coverage_class;
52539ca8
THJ
3656 old_txq_limit = rdev->wiphy.txq_limit;
3657 old_txq_memory_limit = rdev->wiphy.txq_memory_limit;
3658 old_txq_quantum = rdev->wiphy.txq_quantum;
b9a5f8ca
JM
3659
3660 if (changed & WIPHY_PARAM_RETRY_SHORT)
3661 rdev->wiphy.retry_short = retry_short;
3662 if (changed & WIPHY_PARAM_RETRY_LONG)
3663 rdev->wiphy.retry_long = retry_long;
3664 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
3665 rdev->wiphy.frag_threshold = frag_threshold;
3666 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
3667 rdev->wiphy.rts_threshold = rts_threshold;
81077e82
LT
3668 if (changed & WIPHY_PARAM_COVERAGE_CLASS)
3669 rdev->wiphy.coverage_class = coverage_class;
52539ca8
THJ
3670 if (changed & WIPHY_PARAM_TXQ_LIMIT)
3671 rdev->wiphy.txq_limit = txq_limit;
3672 if (changed & WIPHY_PARAM_TXQ_MEMORY_LIMIT)
3673 rdev->wiphy.txq_memory_limit = txq_memory_limit;
3674 if (changed & WIPHY_PARAM_TXQ_QUANTUM)
3675 rdev->wiphy.txq_quantum = txq_quantum;
b9a5f8ca 3676
e35e4d28 3677 result = rdev_set_wiphy_params(rdev, changed);
b9a5f8ca
JM
3678 if (result) {
3679 rdev->wiphy.retry_short = old_retry_short;
3680 rdev->wiphy.retry_long = old_retry_long;
3681 rdev->wiphy.frag_threshold = old_frag_threshold;
3682 rdev->wiphy.rts_threshold = old_rts_threshold;
81077e82 3683 rdev->wiphy.coverage_class = old_coverage_class;
52539ca8
THJ
3684 rdev->wiphy.txq_limit = old_txq_limit;
3685 rdev->wiphy.txq_memory_limit = old_txq_memory_limit;
3686 rdev->wiphy.txq_quantum = old_txq_quantum;
a05829a7 3687 goto out;
b9a5f8ca
JM
3688 }
3689 }
a05829a7
JB
3690
3691 result = 0;
3692
3693out:
3694 wiphy_unlock(&rdev->wiphy);
3695 return result;
55682965
JB
3696}
3697
683b6d3b 3698static int nl80211_send_chandef(struct sk_buff *msg,
d2859df5 3699 const struct cfg80211_chan_def *chandef)
683b6d3b 3700{
601555cd
JB
3701 if (WARN_ON(!cfg80211_chandef_valid(chandef)))
3702 return -EINVAL;
3d9d1d66 3703
683b6d3b
JB
3704 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
3705 chandef->chan->center_freq))
3706 return -ENOBUFS;
942ba88b
TP
3707 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ_OFFSET,
3708 chandef->chan->freq_offset))
3709 return -ENOBUFS;
3d9d1d66
JB
3710 switch (chandef->width) {
3711 case NL80211_CHAN_WIDTH_20_NOHT:
3712 case NL80211_CHAN_WIDTH_20:
3713 case NL80211_CHAN_WIDTH_40:
3714 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
3715 cfg80211_get_chandef_type(chandef)))
3716 return -ENOBUFS;
3717 break;
3718 default:
3719 break;
3720 }
3721 if (nla_put_u32(msg, NL80211_ATTR_CHANNEL_WIDTH, chandef->width))
3722 return -ENOBUFS;
3723 if (nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ1, chandef->center_freq1))
3724 return -ENOBUFS;
3725 if (chandef->center_freq2 &&
3726 nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ2, chandef->center_freq2))
683b6d3b
JB
3727 return -ENOBUFS;
3728 return 0;
3729}
3730
15e47304 3731static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flags,
d726405a 3732 struct cfg80211_registered_device *rdev,
3d1a5bbf
AZ
3733 struct wireless_dev *wdev,
3734 enum nl80211_commands cmd)
55682965 3735{
72fb2abc 3736 struct net_device *dev = wdev->netdev;
55682965
JB
3737 void *hdr;
3738
3d1a5bbf
AZ
3739 WARN_ON(cmd != NL80211_CMD_NEW_INTERFACE &&
3740 cmd != NL80211_CMD_DEL_INTERFACE &&
3741 cmd != NL80211_CMD_SET_INTERFACE);
8f894be2
TB
3742
3743 hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
55682965
JB
3744 if (!hdr)
3745 return -1;
3746
72fb2abc
JB
3747 if (dev &&
3748 (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
98104fde 3749 nla_put_string(msg, NL80211_ATTR_IFNAME, dev->name)))
72fb2abc
JB
3750 goto nla_put_failure;
3751
3752 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
3753 nla_put_u32(msg, NL80211_ATTR_IFTYPE, wdev->iftype) ||
2dad624e
ND
3754 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
3755 NL80211_ATTR_PAD) ||
98104fde 3756 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, wdev_address(wdev)) ||
9360ffd1
DM
3757 nla_put_u32(msg, NL80211_ATTR_GENERATION,
3758 rdev->devlist_generation ^
446faa15
AQ
3759 (cfg80211_rdev_list_generation << 2)) ||
3760 nla_put_u8(msg, NL80211_ATTR_4ADDR, wdev->use_4addr))
9360ffd1 3761 goto nla_put_failure;
f5ea9120 3762
7b0a0e3c 3763 if (rdev->ops->get_channel && !wdev->valid_links) {
f43e5210 3764 struct cfg80211_chan_def chandef = {};
7b0a0e3c 3765 int ret;
683b6d3b 3766
7b0a0e3c
JB
3767 ret = rdev_get_channel(rdev, wdev, 0, &chandef);
3768 if (ret == 0 && nl80211_send_chandef(msg, &chandef))
3769 goto nla_put_failure;
d91df0e3
PF
3770 }
3771
d55d0d59
RM
3772 if (rdev->ops->get_tx_power) {
3773 int dbm, ret;
3774
3775 ret = rdev_get_tx_power(rdev, wdev, &dbm);
3776 if (ret == 0 &&
3777 nla_put_u32(msg, NL80211_ATTR_WIPHY_TX_POWER_LEVEL,
3778 DBM_TO_MBM(dbm)))
3779 goto nla_put_failure;
3780 }
3781
44905265
JB
3782 wdev_lock(wdev);
3783 switch (wdev->iftype) {
3784 case NL80211_IFTYPE_AP:
a75971bc 3785 case NL80211_IFTYPE_P2P_GO:
7b0a0e3c
JB
3786 if (wdev->u.ap.ssid_len &&
3787 nla_put(msg, NL80211_ATTR_SSID, wdev->u.ap.ssid_len,
3788 wdev->u.ap.ssid))
4564b187 3789 goto nla_put_failure_locked;
44905265
JB
3790 break;
3791 case NL80211_IFTYPE_STATION:
3792 case NL80211_IFTYPE_P2P_CLIENT:
7b0a0e3c
JB
3793 if (wdev->u.client.ssid_len &&
3794 nla_put(msg, NL80211_ATTR_SSID, wdev->u.client.ssid_len,
3795 wdev->u.client.ssid))
3796 goto nla_put_failure_locked;
3797 break;
3798 case NL80211_IFTYPE_ADHOC:
3799 if (wdev->u.ibss.ssid_len &&
3800 nla_put(msg, NL80211_ATTR_SSID, wdev->u.ibss.ssid_len,
3801 wdev->u.ibss.ssid))
3802 goto nla_put_failure_locked;
44905265 3803 break;
44905265
JB
3804 default:
3805 /* nothing */
3806 break;
b84e7a05 3807 }
44905265 3808 wdev_unlock(wdev);
b84e7a05 3809
52539ca8
THJ
3810 if (rdev->ops->get_txq_stats) {
3811 struct cfg80211_txq_stats txqstats = {};
3812 int ret = rdev_get_txq_stats(rdev, wdev, &txqstats);
3813
3814 if (ret == 0 &&
3815 !nl80211_put_txq_stats(msg, &txqstats,
3816 NL80211_ATTR_TXQ_STATS))
3817 goto nla_put_failure;
3818 }
3819
ce08cd34
JB
3820 if (wdev->valid_links) {
3821 unsigned int link_id;
3822 struct nlattr *links = nla_nest_start(msg,
3823 NL80211_ATTR_MLO_LINKS);
3824
3825 if (!links)
3826 goto nla_put_failure;
3827
3828 for_each_valid_link(wdev, link_id) {
3829 struct nlattr *link = nla_nest_start(msg, link_id + 1);
3830
3831 if (nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id))
3832 goto nla_put_failure;
3833 if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN,
3834 wdev->links[link_id].addr))
3835 goto nla_put_failure;
3836 nla_nest_end(msg, link);
3837 }
3838
3839 nla_nest_end(msg, links);
3840 }
3841
053c095a
JB
3842 genlmsg_end(msg, hdr);
3843 return 0;
55682965 3844
4564b187
JB
3845 nla_put_failure_locked:
3846 wdev_unlock(wdev);
55682965 3847 nla_put_failure:
bc3ed28c
TG
3848 genlmsg_cancel(msg, hdr);
3849 return -EMSGSIZE;
55682965
JB
3850}
3851
3852static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *cb)
3853{
3854 int wp_idx = 0;
3855 int if_idx = 0;
3856 int wp_start = cb->args[0];
3857 int if_start = cb->args[1];
b7fb44da 3858 int filter_wiphy = -1;
f5ea9120 3859 struct cfg80211_registered_device *rdev;
55682965 3860 struct wireless_dev *wdev;
ea90e0dc 3861 int ret;
55682965 3862
5fe231e8 3863 rtnl_lock();
b7fb44da
DK
3864 if (!cb->args[2]) {
3865 struct nl80211_dump_wiphy_state state = {
3866 .filter_wiphy = -1,
3867 };
b7fb44da
DK
3868
3869 ret = nl80211_dump_wiphy_parse(skb, cb, &state);
3870 if (ret)
ea90e0dc 3871 goto out_unlock;
b7fb44da
DK
3872
3873 filter_wiphy = state.filter_wiphy;
3874
3875 /*
3876 * if filtering, set cb->args[2] to +1 since 0 is the default
3877 * value needed to determine that parsing is necessary.
3878 */
3879 if (filter_wiphy >= 0)
3880 cb->args[2] = filter_wiphy + 1;
3881 else
3882 cb->args[2] = -1;
3883 } else if (cb->args[2] > 0) {
3884 filter_wiphy = cb->args[2] - 1;
3885 }
3886
f5ea9120
JB
3887 list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
3888 if (!net_eq(wiphy_net(&rdev->wiphy), sock_net(skb->sk)))
463d0183 3889 continue;
bba95fef
JB
3890 if (wp_idx < wp_start) {
3891 wp_idx++;
55682965 3892 continue;
bba95fef 3893 }
b7fb44da
DK
3894
3895 if (filter_wiphy >= 0 && filter_wiphy != rdev->wiphy_idx)
3896 continue;
3897
55682965
JB
3898 if_idx = 0;
3899
53873f13 3900 list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
bba95fef
JB
3901 if (if_idx < if_start) {
3902 if_idx++;
55682965 3903 continue;
bba95fef 3904 }
15e47304 3905 if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).portid,
55682965 3906 cb->nlh->nlmsg_seq, NLM_F_MULTI,
3d1a5bbf
AZ
3907 rdev, wdev,
3908 NL80211_CMD_NEW_INTERFACE) < 0) {
bba95fef
JB
3909 goto out;
3910 }
3911 if_idx++;
55682965 3912 }
bba95fef
JB
3913
3914 wp_idx++;
55682965 3915 }
bba95fef 3916 out:
55682965
JB
3917 cb->args[0] = wp_idx;
3918 cb->args[1] = if_idx;
3919
ea90e0dc
JB
3920 ret = skb->len;
3921 out_unlock:
3922 rtnl_unlock();
3923
3924 return ret;
55682965
JB
3925}
3926
3927static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info)
3928{
3929 struct sk_buff *msg;
1b8ec87a 3930 struct cfg80211_registered_device *rdev = info->user_ptr[0];
72fb2abc 3931 struct wireless_dev *wdev = info->user_ptr[1];
55682965 3932
fd2120ca 3933 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
55682965 3934 if (!msg)
4c476991 3935 return -ENOMEM;
55682965 3936
15e47304 3937 if (nl80211_send_iface(msg, info->snd_portid, info->snd_seq, 0,
3d1a5bbf 3938 rdev, wdev, NL80211_CMD_NEW_INTERFACE) < 0) {
4c476991
JB
3939 nlmsg_free(msg);
3940 return -ENOBUFS;
3941 }
55682965 3942
134e6375 3943 return genlmsg_reply(msg, info);
55682965
JB
3944}
3945
66f7ac50
MW
3946static const struct nla_policy mntr_flags_policy[NL80211_MNTR_FLAG_MAX + 1] = {
3947 [NL80211_MNTR_FLAG_FCSFAIL] = { .type = NLA_FLAG },
3948 [NL80211_MNTR_FLAG_PLCPFAIL] = { .type = NLA_FLAG },
3949 [NL80211_MNTR_FLAG_CONTROL] = { .type = NLA_FLAG },
3950 [NL80211_MNTR_FLAG_OTHER_BSS] = { .type = NLA_FLAG },
3951 [NL80211_MNTR_FLAG_COOK_FRAMES] = { .type = NLA_FLAG },
e057d3c3 3952 [NL80211_MNTR_FLAG_ACTIVE] = { .type = NLA_FLAG },
66f7ac50
MW
3953};
3954
3955static int parse_monitor_flags(struct nlattr *nla, u32 *mntrflags)
3956{
3957 struct nlattr *flags[NL80211_MNTR_FLAG_MAX + 1];
3958 int flag;
3959
3960 *mntrflags = 0;
3961
3962 if (!nla)
3963 return -EINVAL;
3964
8cb08174 3965 if (nla_parse_nested_deprecated(flags, NL80211_MNTR_FLAG_MAX, nla, mntr_flags_policy, NULL))
66f7ac50
MW
3966 return -EINVAL;
3967
3968 for (flag = 1; flag <= NL80211_MNTR_FLAG_MAX; flag++)
3969 if (flags[flag])
3970 *mntrflags |= (1<<flag);
3971
818a986e
JB
3972 *mntrflags |= MONITOR_FLAG_CHANGED;
3973
66f7ac50
MW
3974 return 0;
3975}
3976
1db77596
JB
3977static int nl80211_parse_mon_options(struct cfg80211_registered_device *rdev,
3978 enum nl80211_iftype type,
3979 struct genl_info *info,
3980 struct vif_params *params)
3981{
3982 bool change = false;
3983 int err;
3984
3985 if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) {
3986 if (type != NL80211_IFTYPE_MONITOR)
3987 return -EINVAL;
3988
3989 err = parse_monitor_flags(info->attrs[NL80211_ATTR_MNTR_FLAGS],
3990 &params->flags);
3991 if (err)
3992 return err;
3993
3994 change = true;
3995 }
3996
3997 if (params->flags & MONITOR_FLAG_ACTIVE &&
3998 !(rdev->wiphy.features & NL80211_FEATURE_ACTIVE_MONITOR))
3999 return -EOPNOTSUPP;
4000
4001 if (info->attrs[NL80211_ATTR_MU_MIMO_GROUP_DATA]) {
4002 const u8 *mumimo_groups;
4003 u32 cap_flag = NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER;
4004
4005 if (type != NL80211_IFTYPE_MONITOR)
4006 return -EINVAL;
4007
4008 if (!wiphy_ext_feature_isset(&rdev->wiphy, cap_flag))
4009 return -EOPNOTSUPP;
4010
4011 mumimo_groups =
4012 nla_data(info->attrs[NL80211_ATTR_MU_MIMO_GROUP_DATA]);
4013
4014 /* bits 0 and 63 are reserved and must be zero */
4954601f
JB
4015 if ((mumimo_groups[0] & BIT(0)) ||
4016 (mumimo_groups[VHT_MUMIMO_GROUPS_DATA_LEN - 1] & BIT(7)))
1db77596
JB
4017 return -EINVAL;
4018
4019 params->vht_mumimo_groups = mumimo_groups;
4020 change = true;
4021 }
4022
4023 if (info->attrs[NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR]) {
4024 u32 cap_flag = NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER;
4025
4026 if (type != NL80211_IFTYPE_MONITOR)
4027 return -EINVAL;
4028
4029 if (!wiphy_ext_feature_isset(&rdev->wiphy, cap_flag))
4030 return -EOPNOTSUPP;
4031
4032 params->vht_mumimo_follow_addr =
4033 nla_data(info->attrs[NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR]);
4034 change = true;
4035 }
4036
4037 return change ? 1 : 0;
4038}
4039
9bc383de 4040static int nl80211_valid_4addr(struct cfg80211_registered_device *rdev,
ad4bb6f8
JB
4041 struct net_device *netdev, u8 use_4addr,
4042 enum nl80211_iftype iftype)
9bc383de 4043{
ad4bb6f8 4044 if (!use_4addr) {
2e92a2d0 4045 if (netdev && netif_is_bridge_port(netdev))
ad4bb6f8 4046 return -EBUSY;
9bc383de 4047 return 0;
ad4bb6f8 4048 }
9bc383de
JB
4049
4050 switch (iftype) {
4051 case NL80211_IFTYPE_AP_VLAN:
4052 if (rdev->wiphy.flags & WIPHY_FLAG_4ADDR_AP)
4053 return 0;
4054 break;
4055 case NL80211_IFTYPE_STATION:
4056 if (rdev->wiphy.flags & WIPHY_FLAG_4ADDR_STATION)
4057 return 0;
4058 break;
4059 default:
4060 break;
4061 }
4062
4063 return -EOPNOTSUPP;
4064}
4065
55682965
JB
4066static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
4067{
4c476991 4068 struct cfg80211_registered_device *rdev = info->user_ptr[0];
2ec600d6 4069 struct vif_params params;
e36d56b6 4070 int err;
04a773ad 4071 enum nl80211_iftype otype, ntype;
4c476991 4072 struct net_device *dev = info->user_ptr[1];
ac7f9cfa 4073 bool change = false;
55682965 4074
2ec600d6
LCC
4075 memset(&params, 0, sizeof(params));
4076
04a773ad 4077 otype = ntype = dev->ieee80211_ptr->iftype;
55682965 4078
723b038d 4079 if (info->attrs[NL80211_ATTR_IFTYPE]) {
ac7f9cfa 4080 ntype = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
04a773ad 4081 if (otype != ntype)
ac7f9cfa 4082 change = true;
723b038d
JB
4083 }
4084
92ffe055 4085 if (info->attrs[NL80211_ATTR_MESH_ID]) {
29cbe68c
JB
4086 struct wireless_dev *wdev = dev->ieee80211_ptr;
4087
4c476991
JB
4088 if (ntype != NL80211_IFTYPE_MESH_POINT)
4089 return -EINVAL;
29cbe68c
JB
4090 if (netif_running(dev))
4091 return -EBUSY;
4092
4093 wdev_lock(wdev);
4094 BUILD_BUG_ON(IEEE80211_MAX_SSID_LEN !=
4095 IEEE80211_MAX_MESH_ID_LEN);
7b0a0e3c 4096 wdev->u.mesh.id_up_len =
29cbe68c 4097 nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
7b0a0e3c
JB
4098 memcpy(wdev->u.mesh.id,
4099 nla_data(info->attrs[NL80211_ATTR_MESH_ID]),
4100 wdev->u.mesh.id_up_len);
29cbe68c 4101 wdev_unlock(wdev);
2ec600d6
LCC
4102 }
4103
8b787643
FF
4104 if (info->attrs[NL80211_ATTR_4ADDR]) {
4105 params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]);
4106 change = true;
ad4bb6f8 4107 err = nl80211_valid_4addr(rdev, dev, params.use_4addr, ntype);
9bc383de 4108 if (err)
4c476991 4109 return err;
8b787643
FF
4110 } else {
4111 params.use_4addr = -1;
4112 }
4113
1db77596
JB
4114 err = nl80211_parse_mon_options(rdev, ntype, info, &params);
4115 if (err < 0)
4116 return err;
4117 if (err > 0)
c6e6a0c8 4118 change = true;
e057d3c3 4119
ac7f9cfa 4120 if (change)
818a986e 4121 err = cfg80211_change_iface(rdev, dev, ntype, &params);
ac7f9cfa
JB
4122 else
4123 err = 0;
60719ffd 4124
9bc383de
JB
4125 if (!err && params.use_4addr != -1)
4126 dev->ieee80211_ptr->use_4addr = params.use_4addr;
4127
3d1a5bbf
AZ
4128 if (change && !err) {
4129 struct wireless_dev *wdev = dev->ieee80211_ptr;
4130
4131 nl80211_notify_iface(rdev, wdev, NL80211_CMD_SET_INTERFACE);
4132 }
4133
55682965
JB
4134 return err;
4135}
4136
ea6b2098 4137static int _nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
55682965 4138{
4c476991 4139 struct cfg80211_registered_device *rdev = info->user_ptr[0];
2ec600d6 4140 struct vif_params params;
84efbb84 4141 struct wireless_dev *wdev;
896ff063 4142 struct sk_buff *msg;
55682965
JB
4143 int err;
4144 enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED;
4145
2ec600d6
LCC
4146 memset(&params, 0, sizeof(params));
4147
55682965
JB
4148 if (!info->attrs[NL80211_ATTR_IFNAME])
4149 return -EINVAL;
4150
ab0d76f6 4151 if (info->attrs[NL80211_ATTR_IFTYPE])
55682965 4152 type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
55682965 4153
33d915d9 4154 if (!rdev->ops->add_virtual_intf)
4c476991 4155 return -EOPNOTSUPP;
55682965 4156
cb3b7d87 4157 if ((type == NL80211_IFTYPE_P2P_DEVICE || type == NL80211_IFTYPE_NAN ||
e8f479b1
BG
4158 rdev->wiphy.features & NL80211_FEATURE_MAC_ON_CREATE) &&
4159 info->attrs[NL80211_ATTR_MAC]) {
1c18f145
AS
4160 nla_memcpy(params.macaddr, info->attrs[NL80211_ATTR_MAC],
4161 ETH_ALEN);
4162 if (!is_valid_ether_addr(params.macaddr))
4163 return -EADDRNOTAVAIL;
4164 }
4165
9bc383de 4166 if (info->attrs[NL80211_ATTR_4ADDR]) {
8b787643 4167 params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]);
ad4bb6f8 4168 err = nl80211_valid_4addr(rdev, NULL, params.use_4addr, type);
9bc383de 4169 if (err)
4c476991 4170 return err;
9bc383de 4171 }
8b787643 4172
e6f40511 4173 if (!cfg80211_iftype_allowed(&rdev->wiphy, type, params.use_4addr, 0))
33d915d9
MP
4174 return -EOPNOTSUPP;
4175
1db77596
JB
4176 err = nl80211_parse_mon_options(rdev, type, info, &params);
4177 if (err < 0)
4178 return err;
e057d3c3 4179
a18c7192
JB
4180 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4181 if (!msg)
4182 return -ENOMEM;
4183
e35e4d28
HG
4184 wdev = rdev_add_virtual_intf(rdev,
4185 nla_data(info->attrs[NL80211_ATTR_IFNAME]),
818a986e 4186 NET_NAME_USER, type, &params);
d687cbb7
RM
4187 if (WARN_ON(!wdev)) {
4188 nlmsg_free(msg);
4189 return -EPROTO;
4190 } else if (IS_ERR(wdev)) {
1c90f9d4 4191 nlmsg_free(msg);
84efbb84 4192 return PTR_ERR(wdev);
1c90f9d4 4193 }
2ec600d6 4194
18e5ca65 4195 if (info->attrs[NL80211_ATTR_SOCKET_OWNER])
78f22b6a
JB
4196 wdev->owner_nlportid = info->snd_portid;
4197
98104fde
JB
4198 switch (type) {
4199 case NL80211_IFTYPE_MESH_POINT:
4200 if (!info->attrs[NL80211_ATTR_MESH_ID])
4201 break;
29cbe68c
JB
4202 wdev_lock(wdev);
4203 BUILD_BUG_ON(IEEE80211_MAX_SSID_LEN !=
4204 IEEE80211_MAX_MESH_ID_LEN);
7b0a0e3c 4205 wdev->u.mesh.id_up_len =
29cbe68c 4206 nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
7b0a0e3c
JB
4207 memcpy(wdev->u.mesh.id,
4208 nla_data(info->attrs[NL80211_ATTR_MESH_ID]),
4209 wdev->u.mesh.id_up_len);
29cbe68c 4210 wdev_unlock(wdev);
98104fde 4211 break;
cb3b7d87 4212 case NL80211_IFTYPE_NAN:
98104fde
JB
4213 case NL80211_IFTYPE_P2P_DEVICE:
4214 /*
cb3b7d87 4215 * P2P Device and NAN do not have a netdev, so don't go
98104fde
JB
4216 * through the netdev notifier and must be added here
4217 */
9bdaf3b9
JB
4218 cfg80211_init_wdev(wdev);
4219 cfg80211_register_wdev(rdev, wdev);
98104fde
JB
4220 break;
4221 default:
4222 break;
29cbe68c
JB
4223 }
4224
15e47304 4225 if (nl80211_send_iface(msg, info->snd_portid, info->snd_seq, 0,
3d1a5bbf 4226 rdev, wdev, NL80211_CMD_NEW_INTERFACE) < 0) {
1c90f9d4
JB
4227 nlmsg_free(msg);
4228 return -ENOBUFS;
4229 }
4230
4231 return genlmsg_reply(msg, info);
55682965
JB
4232}
4233
ea6b2098
JB
4234static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
4235{
4236 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4237 int ret;
4238
4239 /* to avoid failing a new interface creation due to pending removal */
4240 cfg80211_destroy_ifaces(rdev);
4241
4242 wiphy_lock(&rdev->wiphy);
4243 ret = _nl80211_new_interface(skb, info);
4244 wiphy_unlock(&rdev->wiphy);
4245
4246 return ret;
4247}
4248
55682965
JB
4249static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
4250{
4c476991 4251 struct cfg80211_registered_device *rdev = info->user_ptr[0];
84efbb84 4252 struct wireless_dev *wdev = info->user_ptr[1];
55682965 4253
4c476991
JB
4254 if (!rdev->ops->del_virtual_intf)
4255 return -EOPNOTSUPP;
55682965 4256
a05829a7
JB
4257 /*
4258 * We hold RTNL, so this is safe, without RTNL opencount cannot
4259 * reach 0, and thus the rdev cannot be deleted.
4260 *
4261 * We need to do it for the dev_close(), since that will call
4262 * the netdev notifiers, and we need to acquire the mutex there
4263 * but don't know if we get there from here or from some other
4264 * place (e.g. "ip link set ... down").
4265 */
4266 mutex_unlock(&rdev->wiphy.mtx);
4267
84efbb84
JB
4268 /*
4269 * If we remove a wireless device without a netdev then clear
4270 * user_ptr[1] so that nl80211_post_doit won't dereference it
4271 * to check if it needs to do dev_put(). Otherwise it crashes
4272 * since the wdev has been freed, unlike with a netdev where
4273 * we need the dev_put() for the netdev to really be freed.
4274 */
4275 if (!wdev->netdev)
4276 info->user_ptr[1] = NULL;
a05829a7
JB
4277 else
4278 dev_close(wdev->netdev);
4279
4280 mutex_lock(&rdev->wiphy.mtx);
84efbb84 4281
cdf0a0a8 4282 return cfg80211_remove_virtual_intf(rdev, wdev);
55682965
JB
4283}
4284
1d9d9213
SW
4285static int nl80211_set_noack_map(struct sk_buff *skb, struct genl_info *info)
4286{
4287 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4288 struct net_device *dev = info->user_ptr[1];
4289 u16 noack_map;
4290
4291 if (!info->attrs[NL80211_ATTR_NOACK_MAP])
4292 return -EINVAL;
4293
4294 if (!rdev->ops->set_noack_map)
4295 return -EOPNOTSUPP;
4296
4297 noack_map = nla_get_u16(info->attrs[NL80211_ATTR_NOACK_MAP]);
4298
e35e4d28 4299 return rdev_set_noack_map(rdev, dev, noack_map);
1d9d9213
SW
4300}
4301
41ade00f
JB
4302struct get_key_cookie {
4303 struct sk_buff *msg;
4304 int error;
b9454e83 4305 int idx;
41ade00f
JB
4306};
4307
4308static void get_key_callback(void *c, struct key_params *params)
4309{
b9454e83 4310 struct nlattr *key;
41ade00f
JB
4311 struct get_key_cookie *cookie = c;
4312
9360ffd1
DM
4313 if ((params->key &&
4314 nla_put(cookie->msg, NL80211_ATTR_KEY_DATA,
4315 params->key_len, params->key)) ||
4316 (params->seq &&
4317 nla_put(cookie->msg, NL80211_ATTR_KEY_SEQ,
4318 params->seq_len, params->seq)) ||
4319 (params->cipher &&
4320 nla_put_u32(cookie->msg, NL80211_ATTR_KEY_CIPHER,
4321 params->cipher)))
4322 goto nla_put_failure;
41ade00f 4323
ae0be8de 4324 key = nla_nest_start_noflag(cookie->msg, NL80211_ATTR_KEY);
b9454e83
JB
4325 if (!key)
4326 goto nla_put_failure;
4327
9360ffd1
DM
4328 if ((params->key &&
4329 nla_put(cookie->msg, NL80211_KEY_DATA,
4330 params->key_len, params->key)) ||
4331 (params->seq &&
4332 nla_put(cookie->msg, NL80211_KEY_SEQ,
4333 params->seq_len, params->seq)) ||
4334 (params->cipher &&
4335 nla_put_u32(cookie->msg, NL80211_KEY_CIPHER,
4336 params->cipher)))
4337 goto nla_put_failure;
b9454e83 4338
efdfce72 4339 if (nla_put_u8(cookie->msg, NL80211_KEY_IDX, cookie->idx))
9360ffd1 4340 goto nla_put_failure;
b9454e83
JB
4341
4342 nla_nest_end(cookie->msg, key);
4343
41ade00f
JB
4344 return;
4345 nla_put_failure:
4346 cookie->error = 1;
4347}
4348
4349static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
4350{
4c476991 4351 struct cfg80211_registered_device *rdev = info->user_ptr[0];
41ade00f 4352 int err;
4c476991 4353 struct net_device *dev = info->user_ptr[1];
41ade00f 4354 u8 key_idx = 0;
e31b8213
JB
4355 const u8 *mac_addr = NULL;
4356 bool pairwise;
41ade00f
JB
4357 struct get_key_cookie cookie = {
4358 .error = 0,
4359 };
4360 void *hdr;
4361 struct sk_buff *msg;
155d7c73
JB
4362 bool bigtk_support = false;
4363
4364 if (wiphy_ext_feature_isset(&rdev->wiphy,
4365 NL80211_EXT_FEATURE_BEACON_PROTECTION))
4366 bigtk_support = true;
4367
4368 if ((dev->ieee80211_ptr->iftype == NL80211_IFTYPE_STATION ||
4369 dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_CLIENT) &&
4370 wiphy_ext_feature_isset(&rdev->wiphy,
4371 NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT))
4372 bigtk_support = true;
41ade00f 4373
56be393f 4374 if (info->attrs[NL80211_ATTR_KEY_IDX]) {
41ade00f 4375 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
155d7c73
JB
4376
4377 if (key_idx >= 6 && key_idx <= 7 && !bigtk_support) {
4378 GENL_SET_ERR_MSG(info, "BIGTK not supported");
56be393f 4379 return -EINVAL;
155d7c73 4380 }
56be393f 4381 }
41ade00f 4382
41ade00f
JB
4383 if (info->attrs[NL80211_ATTR_MAC])
4384 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
4385
e31b8213
JB
4386 pairwise = !!mac_addr;
4387 if (info->attrs[NL80211_ATTR_KEY_TYPE]) {
4388 u32 kt = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]);
7a087e74 4389
e31b8213
JB
4390 if (kt != NL80211_KEYTYPE_GROUP &&
4391 kt != NL80211_KEYTYPE_PAIRWISE)
4392 return -EINVAL;
4393 pairwise = kt == NL80211_KEYTYPE_PAIRWISE;
4394 }
4395
4c476991
JB
4396 if (!rdev->ops->get_key)
4397 return -EOPNOTSUPP;
41ade00f 4398
0fa7b391
JB
4399 if (!pairwise && mac_addr && !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
4400 return -ENOENT;
4401
fd2120ca 4402 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4c476991
JB
4403 if (!msg)
4404 return -ENOMEM;
41ade00f 4405
15e47304 4406 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
41ade00f 4407 NL80211_CMD_NEW_KEY);
cb35fba3 4408 if (!hdr)
9fe271af 4409 goto nla_put_failure;
41ade00f
JB
4410
4411 cookie.msg = msg;
b9454e83 4412 cookie.idx = key_idx;
41ade00f 4413
9360ffd1
DM
4414 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
4415 nla_put_u8(msg, NL80211_ATTR_KEY_IDX, key_idx))
4416 goto nla_put_failure;
4417 if (mac_addr &&
4418 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr))
4419 goto nla_put_failure;
41ade00f 4420
e35e4d28
HG
4421 err = rdev_get_key(rdev, dev, key_idx, pairwise, mac_addr, &cookie,
4422 get_key_callback);
41ade00f
JB
4423
4424 if (err)
6c95e2a2 4425 goto free_msg;
41ade00f
JB
4426
4427 if (cookie.error)
4428 goto nla_put_failure;
4429
4430 genlmsg_end(msg, hdr);
4c476991 4431 return genlmsg_reply(msg, info);
41ade00f
JB
4432
4433 nla_put_failure:
4434 err = -ENOBUFS;
6c95e2a2 4435 free_msg:
41ade00f 4436 nlmsg_free(msg);
41ade00f
JB
4437 return err;
4438}
4439
4440static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
4441{
4c476991 4442 struct cfg80211_registered_device *rdev = info->user_ptr[0];
b9454e83 4443 struct key_parse key;
41ade00f 4444 int err;
4c476991 4445 struct net_device *dev = info->user_ptr[1];
41ade00f 4446
b9454e83
JB
4447 err = nl80211_parse_key(info, &key);
4448 if (err)
4449 return err;
41ade00f 4450
b9454e83 4451 if (key.idx < 0)
41ade00f
JB
4452 return -EINVAL;
4453
6cdd3979
AW
4454 /* Only support setting default key and
4455 * Extended Key ID action NL80211_KEY_SET_TX.
4456 */
56be393f 4457 if (!key.def && !key.defmgmt && !key.defbeacon &&
6cdd3979 4458 !(key.p.mode == NL80211_KEY_SET_TX))
41ade00f
JB
4459 return -EINVAL;
4460
dbd2fd65 4461 wdev_lock(dev->ieee80211_ptr);
3cfcf6ac 4462
dbd2fd65
JB
4463 if (key.def) {
4464 if (!rdev->ops->set_default_key) {
4465 err = -EOPNOTSUPP;
4466 goto out;
4467 }
41ade00f 4468
dbd2fd65
JB
4469 err = nl80211_key_allowed(dev->ieee80211_ptr);
4470 if (err)
4471 goto out;
4472
e35e4d28 4473 err = rdev_set_default_key(rdev, dev, key.idx,
dbd2fd65
JB
4474 key.def_uni, key.def_multi);
4475
4476 if (err)
4477 goto out;
fffd0934 4478
3d23e349 4479#ifdef CONFIG_CFG80211_WEXT
dbd2fd65
JB
4480 dev->ieee80211_ptr->wext.default_key = key.idx;
4481#endif
6cdd3979 4482 } else if (key.defmgmt) {
dbd2fd65
JB
4483 if (key.def_uni || !key.def_multi) {
4484 err = -EINVAL;
4485 goto out;
4486 }
4487
4488 if (!rdev->ops->set_default_mgmt_key) {
4489 err = -EOPNOTSUPP;
4490 goto out;
4491 }
4492
4493 err = nl80211_key_allowed(dev->ieee80211_ptr);
4494 if (err)
4495 goto out;
4496
e35e4d28 4497 err = rdev_set_default_mgmt_key(rdev, dev, key.idx);
dbd2fd65
JB
4498 if (err)
4499 goto out;
4500
4501#ifdef CONFIG_CFG80211_WEXT
4502 dev->ieee80211_ptr->wext.default_mgmt_key = key.idx;
08645126 4503#endif
56be393f
JM
4504 } else if (key.defbeacon) {
4505 if (key.def_uni || !key.def_multi) {
4506 err = -EINVAL;
4507 goto out;
4508 }
4509
4510 if (!rdev->ops->set_default_beacon_key) {
4511 err = -EOPNOTSUPP;
4512 goto out;
4513 }
4514
4515 err = nl80211_key_allowed(dev->ieee80211_ptr);
4516 if (err)
4517 goto out;
4518
4519 err = rdev_set_default_beacon_key(rdev, dev, key.idx);
4520 if (err)
4521 goto out;
6cdd3979
AW
4522 } else if (key.p.mode == NL80211_KEY_SET_TX &&
4523 wiphy_ext_feature_isset(&rdev->wiphy,
4524 NL80211_EXT_FEATURE_EXT_KEY_ID)) {
4525 u8 *mac_addr = NULL;
4526
4527 if (info->attrs[NL80211_ATTR_MAC])
4528 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
4529
4530 if (!mac_addr || key.idx < 0 || key.idx > 1) {
4531 err = -EINVAL;
4532 goto out;
4533 }
dbd2fd65 4534
6cdd3979
AW
4535 err = rdev_add_key(rdev, dev, key.idx,
4536 NL80211_KEYTYPE_PAIRWISE,
4537 mac_addr, &key.p);
4538 } else {
4539 err = -EINVAL;
4540 }
dbd2fd65 4541 out:
fffd0934 4542 wdev_unlock(dev->ieee80211_ptr);
41ade00f 4543
41ade00f
JB
4544 return err;
4545}
4546
4547static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
4548{
4c476991 4549 struct cfg80211_registered_device *rdev = info->user_ptr[0];
fffd0934 4550 int err;
4c476991 4551 struct net_device *dev = info->user_ptr[1];
b9454e83 4552 struct key_parse key;
e31b8213 4553 const u8 *mac_addr = NULL;
41ade00f 4554
b9454e83
JB
4555 err = nl80211_parse_key(info, &key);
4556 if (err)
4557 return err;
41ade00f 4558
f8af764b
JM
4559 if (!key.p.key) {
4560 GENL_SET_ERR_MSG(info, "no key");
41ade00f 4561 return -EINVAL;
f8af764b 4562 }
41ade00f 4563
41ade00f
JB
4564 if (info->attrs[NL80211_ATTR_MAC])
4565 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
4566
e31b8213
JB
4567 if (key.type == -1) {
4568 if (mac_addr)
4569 key.type = NL80211_KEYTYPE_PAIRWISE;
4570 else
4571 key.type = NL80211_KEYTYPE_GROUP;
4572 }
4573
4574 /* for now */
4575 if (key.type != NL80211_KEYTYPE_PAIRWISE &&
f8af764b
JM
4576 key.type != NL80211_KEYTYPE_GROUP) {
4577 GENL_SET_ERR_MSG(info, "key type not pairwise or group");
e31b8213 4578 return -EINVAL;
f8af764b 4579 }
e31b8213 4580
14f34e36
GG
4581 if (key.type == NL80211_KEYTYPE_GROUP &&
4582 info->attrs[NL80211_ATTR_VLAN_ID])
4583 key.p.vlan_id = nla_get_u16(info->attrs[NL80211_ATTR_VLAN_ID]);
4584
4c476991
JB
4585 if (!rdev->ops->add_key)
4586 return -EOPNOTSUPP;
25e47c18 4587
e31b8213
JB
4588 if (cfg80211_validate_key_settings(rdev, &key.p, key.idx,
4589 key.type == NL80211_KEYTYPE_PAIRWISE,
f8af764b
JM
4590 mac_addr)) {
4591 GENL_SET_ERR_MSG(info, "key setting validation failed");
4c476991 4592 return -EINVAL;
f8af764b 4593 }
41ade00f 4594
fffd0934
JB
4595 wdev_lock(dev->ieee80211_ptr);
4596 err = nl80211_key_allowed(dev->ieee80211_ptr);
f8af764b
JM
4597 if (err)
4598 GENL_SET_ERR_MSG(info, "key not allowed");
4599 if (!err) {
e35e4d28
HG
4600 err = rdev_add_key(rdev, dev, key.idx,
4601 key.type == NL80211_KEYTYPE_PAIRWISE,
4602 mac_addr, &key.p);
f8af764b
JM
4603 if (err)
4604 GENL_SET_ERR_MSG(info, "key addition failed");
4605 }
fffd0934 4606 wdev_unlock(dev->ieee80211_ptr);
41ade00f 4607
41ade00f
JB
4608 return err;
4609}
4610
4611static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
4612{
4c476991 4613 struct cfg80211_registered_device *rdev = info->user_ptr[0];
41ade00f 4614 int err;
4c476991 4615 struct net_device *dev = info->user_ptr[1];
41ade00f 4616 u8 *mac_addr = NULL;
b9454e83 4617 struct key_parse key;
41ade00f 4618
b9454e83
JB
4619 err = nl80211_parse_key(info, &key);
4620 if (err)
4621 return err;
41ade00f
JB
4622
4623 if (info->attrs[NL80211_ATTR_MAC])
4624 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
4625
e31b8213
JB
4626 if (key.type == -1) {
4627 if (mac_addr)
4628 key.type = NL80211_KEYTYPE_PAIRWISE;
4629 else
4630 key.type = NL80211_KEYTYPE_GROUP;
4631 }
4632
4633 /* for now */
4634 if (key.type != NL80211_KEYTYPE_PAIRWISE &&
4635 key.type != NL80211_KEYTYPE_GROUP)
4636 return -EINVAL;
4637
2d946308
AT
4638 if (!cfg80211_valid_key_idx(rdev, key.idx,
4639 key.type == NL80211_KEYTYPE_PAIRWISE))
4640 return -EINVAL;
4641
4c476991
JB
4642 if (!rdev->ops->del_key)
4643 return -EOPNOTSUPP;
41ade00f 4644
fffd0934
JB
4645 wdev_lock(dev->ieee80211_ptr);
4646 err = nl80211_key_allowed(dev->ieee80211_ptr);
e31b8213 4647
0fa7b391 4648 if (key.type == NL80211_KEYTYPE_GROUP && mac_addr &&
e31b8213
JB
4649 !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
4650 err = -ENOENT;
4651
fffd0934 4652 if (!err)
e35e4d28
HG
4653 err = rdev_del_key(rdev, dev, key.idx,
4654 key.type == NL80211_KEYTYPE_PAIRWISE,
4655 mac_addr);
41ade00f 4656
3d23e349 4657#ifdef CONFIG_CFG80211_WEXT
08645126 4658 if (!err) {
b9454e83 4659 if (key.idx == dev->ieee80211_ptr->wext.default_key)
08645126 4660 dev->ieee80211_ptr->wext.default_key = -1;
b9454e83 4661 else if (key.idx == dev->ieee80211_ptr->wext.default_mgmt_key)
08645126
JB
4662 dev->ieee80211_ptr->wext.default_mgmt_key = -1;
4663 }
4664#endif
fffd0934 4665 wdev_unlock(dev->ieee80211_ptr);
08645126 4666
41ade00f
JB
4667 return err;
4668}
4669
77765eaf
VT
4670/* This function returns an error or the number of nested attributes */
4671static int validate_acl_mac_addrs(struct nlattr *nl_attr)
4672{
4673 struct nlattr *attr;
4674 int n_entries = 0, tmp;
4675
4676 nla_for_each_nested(attr, nl_attr, tmp) {
4677 if (nla_len(attr) != ETH_ALEN)
4678 return -EINVAL;
4679
4680 n_entries++;
4681 }
4682
4683 return n_entries;
4684}
4685
4686/*
4687 * This function parses ACL information and allocates memory for ACL data.
4688 * On successful return, the calling function is responsible to free the
4689 * ACL buffer returned by this function.
4690 */
4691static struct cfg80211_acl_data *parse_acl_data(struct wiphy *wiphy,
4692 struct genl_info *info)
4693{
4694 enum nl80211_acl_policy acl_policy;
4695 struct nlattr *attr;
4696 struct cfg80211_acl_data *acl;
4697 int i = 0, n_entries, tmp;
4698
4699 if (!wiphy->max_acl_mac_addrs)
4700 return ERR_PTR(-EOPNOTSUPP);
4701
4702 if (!info->attrs[NL80211_ATTR_ACL_POLICY])
4703 return ERR_PTR(-EINVAL);
4704
4705 acl_policy = nla_get_u32(info->attrs[NL80211_ATTR_ACL_POLICY]);
4706 if (acl_policy != NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED &&
4707 acl_policy != NL80211_ACL_POLICY_DENY_UNLESS_LISTED)
4708 return ERR_PTR(-EINVAL);
4709
4710 if (!info->attrs[NL80211_ATTR_MAC_ADDRS])
4711 return ERR_PTR(-EINVAL);
4712
4713 n_entries = validate_acl_mac_addrs(info->attrs[NL80211_ATTR_MAC_ADDRS]);
4714 if (n_entries < 0)
4715 return ERR_PTR(n_entries);
4716
4717 if (n_entries > wiphy->max_acl_mac_addrs)
4718 return ERR_PTR(-ENOTSUPP);
4719
391d132c 4720 acl = kzalloc(struct_size(acl, mac_addrs, n_entries), GFP_KERNEL);
77765eaf
VT
4721 if (!acl)
4722 return ERR_PTR(-ENOMEM);
4723
4724 nla_for_each_nested(attr, info->attrs[NL80211_ATTR_MAC_ADDRS], tmp) {
4725 memcpy(acl->mac_addrs[i].addr, nla_data(attr), ETH_ALEN);
4726 i++;
4727 }
4728
4729 acl->n_acl_entries = n_entries;
4730 acl->acl_policy = acl_policy;
4731
4732 return acl;
4733}
4734
4735static int nl80211_set_mac_acl(struct sk_buff *skb, struct genl_info *info)
4736{
4737 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4738 struct net_device *dev = info->user_ptr[1];
4739 struct cfg80211_acl_data *acl;
4740 int err;
4741
4742 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
4743 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
4744 return -EOPNOTSUPP;
4745
7b0a0e3c 4746 if (!dev->ieee80211_ptr->links[0].ap.beacon_interval)
77765eaf
VT
4747 return -EINVAL;
4748
4749 acl = parse_acl_data(&rdev->wiphy, info);
4750 if (IS_ERR(acl))
4751 return PTR_ERR(acl);
4752
4753 err = rdev_set_mac_acl(rdev, dev, acl);
4754
4755 kfree(acl);
4756
4757 return err;
4758}
4759
a7c7fbff
PK
4760static u32 rateset_to_mask(struct ieee80211_supported_band *sband,
4761 u8 *rates, u8 rates_len)
4762{
4763 u8 i;
4764 u32 mask = 0;
4765
4766 for (i = 0; i < rates_len; i++) {
4767 int rate = (rates[i] & 0x7f) * 5;
4768 int ridx;
4769
4770 for (ridx = 0; ridx < sband->n_bitrates; ridx++) {
4771 struct ieee80211_rate *srate =
4772 &sband->bitrates[ridx];
4773 if (rate == srate->bitrate) {
4774 mask |= 1 << ridx;
4775 break;
4776 }
4777 }
4778 if (ridx == sband->n_bitrates)
4779 return 0; /* rate not found */
4780 }
4781
4782 return mask;
4783}
4784
4785static bool ht_rateset_to_mask(struct ieee80211_supported_band *sband,
4786 u8 *rates, u8 rates_len,
4787 u8 mcs[IEEE80211_HT_MCS_MASK_LEN])
4788{
4789 u8 i;
4790
4791 memset(mcs, 0, IEEE80211_HT_MCS_MASK_LEN);
4792
4793 for (i = 0; i < rates_len; i++) {
4794 int ridx, rbit;
4795
4796 ridx = rates[i] / 8;
4797 rbit = BIT(rates[i] % 8);
4798
4799 /* check validity */
4800 if ((ridx < 0) || (ridx >= IEEE80211_HT_MCS_MASK_LEN))
4801 return false;
4802
4803 /* check availability */
30fe6d50 4804 ridx = array_index_nospec(ridx, IEEE80211_HT_MCS_MASK_LEN);
a7c7fbff
PK
4805 if (sband->ht_cap.mcs.rx_mask[ridx] & rbit)
4806 mcs[ridx] |= rbit;
4807 else
4808 return false;
4809 }
4810
4811 return true;
4812}
4813
4814static u16 vht_mcs_map_to_mcs_mask(u8 vht_mcs_map)
4815{
4816 u16 mcs_mask = 0;
4817
4818 switch (vht_mcs_map) {
4819 case IEEE80211_VHT_MCS_NOT_SUPPORTED:
4820 break;
4821 case IEEE80211_VHT_MCS_SUPPORT_0_7:
4822 mcs_mask = 0x00FF;
4823 break;
4824 case IEEE80211_VHT_MCS_SUPPORT_0_8:
4825 mcs_mask = 0x01FF;
4826 break;
4827 case IEEE80211_VHT_MCS_SUPPORT_0_9:
4828 mcs_mask = 0x03FF;
4829 break;
4830 default:
4831 break;
4832 }
4833
4834 return mcs_mask;
4835}
4836
4837static void vht_build_mcs_mask(u16 vht_mcs_map,
4838 u16 vht_mcs_mask[NL80211_VHT_NSS_MAX])
4839{
4840 u8 nss;
4841
4842 for (nss = 0; nss < NL80211_VHT_NSS_MAX; nss++) {
4843 vht_mcs_mask[nss] = vht_mcs_map_to_mcs_mask(vht_mcs_map & 0x03);
4844 vht_mcs_map >>= 2;
4845 }
4846}
4847
4848static bool vht_set_mcs_mask(struct ieee80211_supported_band *sband,
4849 struct nl80211_txrate_vht *txrate,
4850 u16 mcs[NL80211_VHT_NSS_MAX])
4851{
4852 u16 tx_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map);
4853 u16 tx_mcs_mask[NL80211_VHT_NSS_MAX] = {};
4854 u8 i;
4855
4856 if (!sband->vht_cap.vht_supported)
4857 return false;
4858
4859 memset(mcs, 0, sizeof(u16) * NL80211_VHT_NSS_MAX);
4860
4861 /* Build vht_mcs_mask from VHT capabilities */
4862 vht_build_mcs_mask(tx_mcs_map, tx_mcs_mask);
4863
4864 for (i = 0; i < NL80211_VHT_NSS_MAX; i++) {
4865 if ((tx_mcs_mask[i] & txrate->mcs[i]) == txrate->mcs[i])
4866 mcs[i] = txrate->mcs[i];
4867 else
4868 return false;
4869 }
4870
4871 return true;
4872}
4873
eb89a6a6
MH
4874static u16 he_mcs_map_to_mcs_mask(u8 he_mcs_map)
4875{
4876 switch (he_mcs_map) {
4877 case IEEE80211_HE_MCS_NOT_SUPPORTED:
4878 return 0;
4879 case IEEE80211_HE_MCS_SUPPORT_0_7:
4880 return 0x00FF;
4881 case IEEE80211_HE_MCS_SUPPORT_0_9:
4882 return 0x03FF;
4883 case IEEE80211_HE_MCS_SUPPORT_0_11:
4884 return 0xFFF;
4885 default:
4886 break;
4887 }
4888 return 0;
4889}
4890
4891static void he_build_mcs_mask(u16 he_mcs_map,
4892 u16 he_mcs_mask[NL80211_HE_NSS_MAX])
4893{
4894 u8 nss;
4895
4896 for (nss = 0; nss < NL80211_HE_NSS_MAX; nss++) {
4897 he_mcs_mask[nss] = he_mcs_map_to_mcs_mask(he_mcs_map & 0x03);
4898 he_mcs_map >>= 2;
4899 }
4900}
4901
7b0a0e3c 4902static u16 he_get_txmcsmap(struct genl_info *info, unsigned int link_id,
eb89a6a6
MH
4903 const struct ieee80211_sta_he_cap *he_cap)
4904{
4905 struct net_device *dev = info->user_ptr[1];
4906 struct wireless_dev *wdev = dev->ieee80211_ptr;
7b0a0e3c
JB
4907 struct cfg80211_chan_def *chandef;
4908 __le16 tx_mcs;
eb89a6a6 4909
7b0a0e3c
JB
4910 chandef = wdev_chandef(wdev, link_id);
4911 if (!chandef) {
4912 /*
4913 * This is probably broken, but we never maintained
4914 * a chandef in these cases, so it always was.
4915 */
4916 return le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_80);
4917 }
4918
4919 switch (chandef->width) {
eb89a6a6
MH
4920 case NL80211_CHAN_WIDTH_80P80:
4921 tx_mcs = he_cap->he_mcs_nss_supp.tx_mcs_80p80;
4922 break;
4923 case NL80211_CHAN_WIDTH_160:
4924 tx_mcs = he_cap->he_mcs_nss_supp.tx_mcs_160;
4925 break;
4926 default:
4927 tx_mcs = he_cap->he_mcs_nss_supp.tx_mcs_80;
4928 break;
4929 }
7b0a0e3c 4930
eb89a6a6
MH
4931 return le16_to_cpu(tx_mcs);
4932}
4933
4934static bool he_set_mcs_mask(struct genl_info *info,
4935 struct wireless_dev *wdev,
4936 struct ieee80211_supported_band *sband,
4937 struct nl80211_txrate_he *txrate,
7b0a0e3c
JB
4938 u16 mcs[NL80211_HE_NSS_MAX],
4939 unsigned int link_id)
eb89a6a6
MH
4940{
4941 const struct ieee80211_sta_he_cap *he_cap;
4942 u16 tx_mcs_mask[NL80211_HE_NSS_MAX] = {};
4943 u16 tx_mcs_map = 0;
4944 u8 i;
4945
4946 he_cap = ieee80211_get_he_iftype_cap(sband, wdev->iftype);
4947 if (!he_cap)
4948 return false;
4949
4950 memset(mcs, 0, sizeof(u16) * NL80211_HE_NSS_MAX);
4951
7b0a0e3c 4952 tx_mcs_map = he_get_txmcsmap(info, link_id, he_cap);
eb89a6a6
MH
4953
4954 /* Build he_mcs_mask from HE capabilities */
4955 he_build_mcs_mask(tx_mcs_map, tx_mcs_mask);
4956
4957 for (i = 0; i < NL80211_HE_NSS_MAX; i++) {
4958 if ((tx_mcs_mask[i] & txrate->mcs[i]) == txrate->mcs[i])
4959 mcs[i] = txrate->mcs[i];
4960 else
4961 return false;
4962 }
4963
4964 return true;
4965}
4966
a7c7fbff 4967static int nl80211_parse_tx_bitrate_mask(struct genl_info *info,
9a5f6488
TC
4968 struct nlattr *attrs[],
4969 enum nl80211_attrs attr,
eb89a6a6 4970 struct cfg80211_bitrate_mask *mask,
857b34c4 4971 struct net_device *dev,
7b0a0e3c
JB
4972 bool default_all_enabled,
4973 unsigned int link_id)
a7c7fbff
PK
4974{
4975 struct nlattr *tb[NL80211_TXRATE_MAX + 1];
4976 struct cfg80211_registered_device *rdev = info->user_ptr[0];
eb89a6a6 4977 struct wireless_dev *wdev = dev->ieee80211_ptr;
a7c7fbff
PK
4978 int rem, i;
4979 struct nlattr *tx_rates;
4980 struct ieee80211_supported_band *sband;
eb89a6a6 4981 u16 vht_tx_mcs_map, he_tx_mcs_map;
a7c7fbff
PK
4982
4983 memset(mask, 0, sizeof(*mask));
4984 /* Default to all rates enabled */
4985 for (i = 0; i < NUM_NL80211_BANDS; i++) {
eb89a6a6
MH
4986 const struct ieee80211_sta_he_cap *he_cap;
4987
857b34c4
RM
4988 if (!default_all_enabled)
4989 break;
4990
a7c7fbff
PK
4991 sband = rdev->wiphy.bands[i];
4992
4993 if (!sband)
4994 continue;
4995
4996 mask->control[i].legacy = (1 << sband->n_bitrates) - 1;
4997 memcpy(mask->control[i].ht_mcs,
4998 sband->ht_cap.mcs.rx_mask,
4999 sizeof(mask->control[i].ht_mcs));
5000
9df66d5b
PKS
5001 if (sband->vht_cap.vht_supported) {
5002 vht_tx_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map);
5003 vht_build_mcs_mask(vht_tx_mcs_map, mask->control[i].vht_mcs);
5004 }
eb89a6a6
MH
5005
5006 he_cap = ieee80211_get_he_iftype_cap(sband, wdev->iftype);
5007 if (!he_cap)
5008 continue;
5009
7b0a0e3c 5010 he_tx_mcs_map = he_get_txmcsmap(info, link_id, he_cap);
eb89a6a6
MH
5011 he_build_mcs_mask(he_tx_mcs_map, mask->control[i].he_mcs);
5012
5013 mask->control[i].he_gi = 0xFF;
5014 mask->control[i].he_ltf = 0xFF;
a7c7fbff
PK
5015 }
5016
5017 /* if no rates are given set it back to the defaults */
9a5f6488 5018 if (!attrs[attr])
a7c7fbff
PK
5019 goto out;
5020
5021 /* The nested attribute uses enum nl80211_band as the index. This maps
5022 * directly to the enum nl80211_band values used in cfg80211.
5023 */
5024 BUILD_BUG_ON(NL80211_MAX_SUPP_HT_RATES > IEEE80211_HT_MCS_MASK_LEN * 8);
9a5f6488 5025 nla_for_each_nested(tx_rates, attrs[attr], rem) {
a7c7fbff
PK
5026 enum nl80211_band band = nla_type(tx_rates);
5027 int err;
5028
5029 if (band < 0 || band >= NUM_NL80211_BANDS)
5030 return -EINVAL;
5031 sband = rdev->wiphy.bands[band];
5032 if (sband == NULL)
5033 return -EINVAL;
8cb08174
JB
5034 err = nla_parse_nested_deprecated(tb, NL80211_TXRATE_MAX,
5035 tx_rates,
5036 nl80211_txattr_policy,
5037 info->extack);
a7c7fbff
PK
5038 if (err)
5039 return err;
5040 if (tb[NL80211_TXRATE_LEGACY]) {
5041 mask->control[band].legacy = rateset_to_mask(
5042 sband,
5043 nla_data(tb[NL80211_TXRATE_LEGACY]),
5044 nla_len(tb[NL80211_TXRATE_LEGACY]));
5045 if ((mask->control[band].legacy == 0) &&
5046 nla_len(tb[NL80211_TXRATE_LEGACY]))
5047 return -EINVAL;
5048 }
5049 if (tb[NL80211_TXRATE_HT]) {
5050 if (!ht_rateset_to_mask(
5051 sband,
5052 nla_data(tb[NL80211_TXRATE_HT]),
5053 nla_len(tb[NL80211_TXRATE_HT]),
5054 mask->control[band].ht_mcs))
5055 return -EINVAL;
5056 }
c4a30446 5057
a7c7fbff
PK
5058 if (tb[NL80211_TXRATE_VHT]) {
5059 if (!vht_set_mcs_mask(
5060 sband,
5061 nla_data(tb[NL80211_TXRATE_VHT]),
5062 mask->control[band].vht_mcs))
5063 return -EINVAL;
5064 }
c4a30446 5065
a7c7fbff
PK
5066 if (tb[NL80211_TXRATE_GI]) {
5067 mask->control[band].gi =
5068 nla_get_u8(tb[NL80211_TXRATE_GI]);
5069 if (mask->control[band].gi > NL80211_TXRATE_FORCE_LGI)
5070 return -EINVAL;
5071 }
eb89a6a6
MH
5072 if (tb[NL80211_TXRATE_HE] &&
5073 !he_set_mcs_mask(info, wdev, sband,
5074 nla_data(tb[NL80211_TXRATE_HE]),
7b0a0e3c
JB
5075 mask->control[band].he_mcs,
5076 link_id))
eb89a6a6 5077 return -EINVAL;
c4a30446 5078
eb89a6a6
MH
5079 if (tb[NL80211_TXRATE_HE_GI])
5080 mask->control[band].he_gi =
5081 nla_get_u8(tb[NL80211_TXRATE_HE_GI]);
5082 if (tb[NL80211_TXRATE_HE_LTF])
5083 mask->control[band].he_ltf =
5084 nla_get_u8(tb[NL80211_TXRATE_HE_LTF]);
a7c7fbff
PK
5085
5086 if (mask->control[band].legacy == 0) {
eb89a6a6 5087 /* don't allow empty legacy rates if HT, VHT or HE
a7c7fbff
PK
5088 * are not even supported.
5089 */
5090 if (!(rdev->wiphy.bands[band]->ht_cap.ht_supported ||
eb89a6a6
MH
5091 rdev->wiphy.bands[band]->vht_cap.vht_supported ||
5092 ieee80211_get_he_iftype_cap(sband, wdev->iftype)))
a7c7fbff
PK
5093 return -EINVAL;
5094
5095 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++)
5096 if (mask->control[band].ht_mcs[i])
5097 goto out;
5098
5099 for (i = 0; i < NL80211_VHT_NSS_MAX; i++)
5100 if (mask->control[band].vht_mcs[i])
5101 goto out;
5102
eb89a6a6
MH
5103 for (i = 0; i < NL80211_HE_NSS_MAX; i++)
5104 if (mask->control[band].he_mcs[i])
5105 goto out;
5106
a7c7fbff
PK
5107 /* legacy and mcs rates may not be both empty */
5108 return -EINVAL;
5109 }
5110 }
5111
5112out:
5113 return 0;
5114}
5115
8564e382
JB
5116static int validate_beacon_tx_rate(struct cfg80211_registered_device *rdev,
5117 enum nl80211_band band,
5118 struct cfg80211_bitrate_mask *beacon_rate)
a7c7fbff 5119{
c4a30446 5120 u32 count_ht, count_vht, count_he, i;
8564e382 5121 u32 rate = beacon_rate->control[band].legacy;
a7c7fbff
PK
5122
5123 /* Allow only one rate */
5124 if (hweight32(rate) > 1)
5125 return -EINVAL;
5126
5127 count_ht = 0;
5128 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
8564e382 5129 if (hweight8(beacon_rate->control[band].ht_mcs[i]) > 1) {
a7c7fbff 5130 return -EINVAL;
8564e382 5131 } else if (beacon_rate->control[band].ht_mcs[i]) {
a7c7fbff
PK
5132 count_ht++;
5133 if (count_ht > 1)
5134 return -EINVAL;
5135 }
5136 if (count_ht && rate)
5137 return -EINVAL;
5138 }
5139
5140 count_vht = 0;
5141 for (i = 0; i < NL80211_VHT_NSS_MAX; i++) {
8564e382 5142 if (hweight16(beacon_rate->control[band].vht_mcs[i]) > 1) {
a7c7fbff 5143 return -EINVAL;
8564e382 5144 } else if (beacon_rate->control[band].vht_mcs[i]) {
a7c7fbff
PK
5145 count_vht++;
5146 if (count_vht > 1)
5147 return -EINVAL;
5148 }
5149 if (count_vht && rate)
5150 return -EINVAL;
5151 }
5152
c4a30446
RM
5153 count_he = 0;
5154 for (i = 0; i < NL80211_HE_NSS_MAX; i++) {
5155 if (hweight16(beacon_rate->control[band].he_mcs[i]) > 1) {
5156 return -EINVAL;
5157 } else if (beacon_rate->control[band].he_mcs[i]) {
5158 count_he++;
5159 if (count_he > 1)
5160 return -EINVAL;
5161 }
5162 if (count_he && rate)
5163 return -EINVAL;
5164 }
5165
5166 if ((count_ht && count_vht && count_he) ||
5167 (!rate && !count_ht && !count_vht && !count_he))
a7c7fbff
PK
5168 return -EINVAL;
5169
8564e382
JB
5170 if (rate &&
5171 !wiphy_ext_feature_isset(&rdev->wiphy,
5172 NL80211_EXT_FEATURE_BEACON_RATE_LEGACY))
5173 return -EINVAL;
5174 if (count_ht &&
5175 !wiphy_ext_feature_isset(&rdev->wiphy,
5176 NL80211_EXT_FEATURE_BEACON_RATE_HT))
5177 return -EINVAL;
5178 if (count_vht &&
5179 !wiphy_ext_feature_isset(&rdev->wiphy,
5180 NL80211_EXT_FEATURE_BEACON_RATE_VHT))
5181 return -EINVAL;
c4a30446
RM
5182 if (count_he &&
5183 !wiphy_ext_feature_isset(&rdev->wiphy,
5184 NL80211_EXT_FEATURE_BEACON_RATE_HE))
5185 return -EINVAL;
8564e382 5186
a7c7fbff
PK
5187 return 0;
5188}
5189
dc1e3cb8
JC
5190static int nl80211_parse_mbssid_config(struct wiphy *wiphy,
5191 struct net_device *dev,
5192 struct nlattr *attrs,
5193 struct cfg80211_mbssid_config *config,
5194 u8 num_elems)
5195{
5196 struct nlattr *tb[NL80211_MBSSID_CONFIG_ATTR_MAX + 1];
5197
5198 if (!wiphy->mbssid_max_interfaces)
5199 return -EOPNOTSUPP;
5200
5201 if (nla_parse_nested(tb, NL80211_MBSSID_CONFIG_ATTR_MAX, attrs, NULL,
5202 NULL) ||
5203 !tb[NL80211_MBSSID_CONFIG_ATTR_INDEX])
5204 return -EINVAL;
5205
5206 config->ema = nla_get_flag(tb[NL80211_MBSSID_CONFIG_ATTR_EMA]);
5207 if (config->ema) {
5208 if (!wiphy->ema_max_profile_periodicity)
5209 return -EOPNOTSUPP;
5210
5211 if (num_elems > wiphy->ema_max_profile_periodicity)
5212 return -EINVAL;
5213 }
5214
5215 config->index = nla_get_u8(tb[NL80211_MBSSID_CONFIG_ATTR_INDEX]);
5216 if (config->index >= wiphy->mbssid_max_interfaces ||
5217 (!config->index && !num_elems))
5218 return -EINVAL;
5219
5220 if (tb[NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX]) {
5221 u32 tx_ifindex =
5222 nla_get_u32(tb[NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX]);
5223
5224 if ((!config->index && tx_ifindex != dev->ifindex) ||
5225 (config->index && tx_ifindex == dev->ifindex))
5226 return -EINVAL;
5227
5228 if (tx_ifindex != dev->ifindex) {
5229 struct net_device *tx_netdev =
5230 dev_get_by_index(wiphy_net(wiphy), tx_ifindex);
5231
5232 if (!tx_netdev || !tx_netdev->ieee80211_ptr ||
5233 tx_netdev->ieee80211_ptr->wiphy != wiphy ||
5234 tx_netdev->ieee80211_ptr->iftype !=
5235 NL80211_IFTYPE_AP) {
5236 dev_put(tx_netdev);
5237 return -EINVAL;
5238 }
5239
5240 config->tx_wdev = tx_netdev->ieee80211_ptr;
5241 } else {
5242 config->tx_wdev = dev->ieee80211_ptr;
5243 }
5244 } else if (!config->index) {
5245 config->tx_wdev = dev->ieee80211_ptr;
5246 } else {
5247 return -EINVAL;
5248 }
5249
5250 return 0;
5251}
5252
5253static struct cfg80211_mbssid_elems *
5254nl80211_parse_mbssid_elems(struct wiphy *wiphy, struct nlattr *attrs)
5255{
5256 struct nlattr *nl_elems;
5257 struct cfg80211_mbssid_elems *elems;
5258 int rem_elems;
5259 u8 i = 0, num_elems = 0;
5260
5261 if (!wiphy->mbssid_max_interfaces)
5262 return ERR_PTR(-EINVAL);
5263
5264 nla_for_each_nested(nl_elems, attrs, rem_elems)
5265 num_elems++;
5266
5267 elems = kzalloc(struct_size(elems, elem, num_elems), GFP_KERNEL);
5268 if (!elems)
5269 return ERR_PTR(-ENOMEM);
5270
5271 nla_for_each_nested(nl_elems, attrs, rem_elems) {
5272 elems->elem[i].data = nla_data(nl_elems);
5273 elems->elem[i].len = nla_len(nl_elems);
5274 i++;
5275 }
5276 elems->cnt = num_elems;
5277 return elems;
5278}
5279
3d48cb74
RS
5280static int nl80211_parse_he_bss_color(struct nlattr *attrs,
5281 struct cfg80211_he_bss_color *he_bss_color)
5282{
5283 struct nlattr *tb[NL80211_HE_BSS_COLOR_ATTR_MAX + 1];
5284 int err;
5285
5286 err = nla_parse_nested(tb, NL80211_HE_BSS_COLOR_ATTR_MAX, attrs,
5287 he_bss_color_policy, NULL);
5288 if (err)
5289 return err;
5290
5291 if (!tb[NL80211_HE_BSS_COLOR_ATTR_COLOR])
5292 return -EINVAL;
5293
5294 he_bss_color->color =
5295 nla_get_u8(tb[NL80211_HE_BSS_COLOR_ATTR_COLOR]);
5296 he_bss_color->enabled =
5297 !nla_get_flag(tb[NL80211_HE_BSS_COLOR_ATTR_DISABLED]);
5298 he_bss_color->partial =
5299 nla_get_flag(tb[NL80211_HE_BSS_COLOR_ATTR_PARTIAL]);
5300
5301 return 0;
5302}
5303
81e54d08
PKC
5304static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev,
5305 struct nlattr *attrs[],
8860020e 5306 struct cfg80211_beacon_data *bcn)
ed1b6cc7 5307{
8860020e 5308 bool haveinfo = false;
81e54d08 5309 int err;
ed1b6cc7 5310
8860020e 5311 memset(bcn, 0, sizeof(*bcn));
ed1b6cc7 5312
7b0a0e3c
JB
5313 bcn->link_id = nl80211_link_id(attrs);
5314
a1193be8
SW
5315 if (attrs[NL80211_ATTR_BEACON_HEAD]) {
5316 bcn->head = nla_data(attrs[NL80211_ATTR_BEACON_HEAD]);
5317 bcn->head_len = nla_len(attrs[NL80211_ATTR_BEACON_HEAD]);
8860020e
JB
5318 if (!bcn->head_len)
5319 return -EINVAL;
5320 haveinfo = true;
ed1b6cc7
JB
5321 }
5322
a1193be8
SW
5323 if (attrs[NL80211_ATTR_BEACON_TAIL]) {
5324 bcn->tail = nla_data(attrs[NL80211_ATTR_BEACON_TAIL]);
5325 bcn->tail_len = nla_len(attrs[NL80211_ATTR_BEACON_TAIL]);
8860020e 5326 haveinfo = true;
ed1b6cc7
JB
5327 }
5328
4c476991
JB
5329 if (!haveinfo)
5330 return -EINVAL;
3b85875a 5331
a1193be8
SW
5332 if (attrs[NL80211_ATTR_IE]) {
5333 bcn->beacon_ies = nla_data(attrs[NL80211_ATTR_IE]);
5334 bcn->beacon_ies_len = nla_len(attrs[NL80211_ATTR_IE]);
9946ecfb
JM
5335 }
5336
a1193be8 5337 if (attrs[NL80211_ATTR_IE_PROBE_RESP]) {
8860020e 5338 bcn->proberesp_ies =
a1193be8 5339 nla_data(attrs[NL80211_ATTR_IE_PROBE_RESP]);
8860020e 5340 bcn->proberesp_ies_len =
a1193be8 5341 nla_len(attrs[NL80211_ATTR_IE_PROBE_RESP]);
9946ecfb
JM
5342 }
5343
a1193be8 5344 if (attrs[NL80211_ATTR_IE_ASSOC_RESP]) {
8860020e 5345 bcn->assocresp_ies =
a1193be8 5346 nla_data(attrs[NL80211_ATTR_IE_ASSOC_RESP]);
8860020e 5347 bcn->assocresp_ies_len =
a1193be8 5348 nla_len(attrs[NL80211_ATTR_IE_ASSOC_RESP]);
9946ecfb
JM
5349 }
5350
a1193be8
SW
5351 if (attrs[NL80211_ATTR_PROBE_RESP]) {
5352 bcn->probe_resp = nla_data(attrs[NL80211_ATTR_PROBE_RESP]);
5353 bcn->probe_resp_len = nla_len(attrs[NL80211_ATTR_PROBE_RESP]);
00f740e1
AN
5354 }
5355
81e54d08
PKC
5356 if (attrs[NL80211_ATTR_FTM_RESPONDER]) {
5357 struct nlattr *tb[NL80211_FTM_RESP_ATTR_MAX + 1];
5358
8cb08174
JB
5359 err = nla_parse_nested_deprecated(tb,
5360 NL80211_FTM_RESP_ATTR_MAX,
5361 attrs[NL80211_ATTR_FTM_RESPONDER],
5362 NULL, NULL);
81e54d08
PKC
5363 if (err)
5364 return err;
5365
5366 if (tb[NL80211_FTM_RESP_ATTR_ENABLED] &&
5367 wiphy_ext_feature_isset(&rdev->wiphy,
5368 NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER))
5369 bcn->ftm_responder = 1;
5370 else
5371 return -EOPNOTSUPP;
5372
5373 if (tb[NL80211_FTM_RESP_ATTR_LCI]) {
5374 bcn->lci = nla_data(tb[NL80211_FTM_RESP_ATTR_LCI]);
5375 bcn->lci_len = nla_len(tb[NL80211_FTM_RESP_ATTR_LCI]);
5376 }
5377
5378 if (tb[NL80211_FTM_RESP_ATTR_CIVICLOC]) {
5379 bcn->civicloc = nla_data(tb[NL80211_FTM_RESP_ATTR_CIVICLOC]);
5380 bcn->civicloc_len = nla_len(tb[NL80211_FTM_RESP_ATTR_CIVICLOC]);
5381 }
5382 } else {
5383 bcn->ftm_responder = -1;
5384 }
5385
3d48cb74
RS
5386 if (attrs[NL80211_ATTR_HE_BSS_COLOR]) {
5387 err = nl80211_parse_he_bss_color(attrs[NL80211_ATTR_HE_BSS_COLOR],
5388 &bcn->he_bss_color);
5389 if (err)
5390 return err;
5391 bcn->he_bss_color_valid = true;
5392 }
5393
dc1e3cb8
JC
5394 if (attrs[NL80211_ATTR_MBSSID_ELEMS]) {
5395 struct cfg80211_mbssid_elems *mbssid =
5396 nl80211_parse_mbssid_elems(&rdev->wiphy,
5397 attrs[NL80211_ATTR_MBSSID_ELEMS]);
5398
5399 if (IS_ERR(mbssid))
5400 return PTR_ERR(mbssid);
5401
5402 bcn->mbssid_ies = mbssid;
5403 }
5404
8860020e
JB
5405 return 0;
5406}
5407
796e90f4
JC
5408static int nl80211_parse_he_obss_pd(struct nlattr *attrs,
5409 struct ieee80211_he_obss_pd *he_obss_pd)
5410{
5411 struct nlattr *tb[NL80211_HE_OBSS_PD_ATTR_MAX + 1];
5412 int err;
5413
5414 err = nla_parse_nested(tb, NL80211_HE_OBSS_PD_ATTR_MAX, attrs,
5415 he_obss_pd_policy, NULL);
5416 if (err)
5417 return err;
5418
f5bec330
RM
5419 if (!tb[NL80211_HE_OBSS_PD_ATTR_SR_CTRL])
5420 return -EINVAL;
5421
5422 he_obss_pd->sr_ctrl = nla_get_u8(tb[NL80211_HE_OBSS_PD_ATTR_SR_CTRL]);
5423
6c8b6e4a
RM
5424 if (tb[NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET])
5425 he_obss_pd->min_offset =
5426 nla_get_u8(tb[NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET]);
5427 if (tb[NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET])
5428 he_obss_pd->max_offset =
5429 nla_get_u8(tb[NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET]);
f5bec330
RM
5430 if (tb[NL80211_HE_OBSS_PD_ATTR_NON_SRG_MAX_OFFSET])
5431 he_obss_pd->non_srg_max_offset =
5432 nla_get_u8(tb[NL80211_HE_OBSS_PD_ATTR_NON_SRG_MAX_OFFSET]);
6c8b6e4a
RM
5433
5434 if (he_obss_pd->min_offset > he_obss_pd->max_offset)
796e90f4
JC
5435 return -EINVAL;
5436
f5bec330
RM
5437 if (tb[NL80211_HE_OBSS_PD_ATTR_BSS_COLOR_BITMAP])
5438 memcpy(he_obss_pd->bss_color_bitmap,
5439 nla_data(tb[NL80211_HE_OBSS_PD_ATTR_BSS_COLOR_BITMAP]),
5440 sizeof(he_obss_pd->bss_color_bitmap));
5441
5442 if (tb[NL80211_HE_OBSS_PD_ATTR_PARTIAL_BSSID_BITMAP])
5443 memcpy(he_obss_pd->partial_bssid_bitmap,
5444 nla_data(tb[NL80211_HE_OBSS_PD_ATTR_PARTIAL_BSSID_BITMAP]),
5445 sizeof(he_obss_pd->partial_bssid_bitmap));
5446
796e90f4
JC
5447 he_obss_pd->enable = true;
5448
5449 return 0;
5450}
5451
291c49de
AD
5452static int nl80211_parse_fils_discovery(struct cfg80211_registered_device *rdev,
5453 struct nlattr *attrs,
5454 struct cfg80211_ap_settings *params)
5455{
5456 struct nlattr *tb[NL80211_FILS_DISCOVERY_ATTR_MAX + 1];
5457 int ret;
5458 struct cfg80211_fils_discovery *fd = &params->fils_discovery;
5459
5460 if (!wiphy_ext_feature_isset(&rdev->wiphy,
5461 NL80211_EXT_FEATURE_FILS_DISCOVERY))
5462 return -EINVAL;
5463
5464 ret = nla_parse_nested(tb, NL80211_FILS_DISCOVERY_ATTR_MAX, attrs,
5465 NULL, NULL);
5466 if (ret)
5467 return ret;
5468
5469 if (!tb[NL80211_FILS_DISCOVERY_ATTR_INT_MIN] ||
5470 !tb[NL80211_FILS_DISCOVERY_ATTR_INT_MAX] ||
5471 !tb[NL80211_FILS_DISCOVERY_ATTR_TMPL])
5472 return -EINVAL;
5473
5474 fd->tmpl_len = nla_len(tb[NL80211_FILS_DISCOVERY_ATTR_TMPL]);
5475 fd->tmpl = nla_data(tb[NL80211_FILS_DISCOVERY_ATTR_TMPL]);
5476 fd->min_interval = nla_get_u32(tb[NL80211_FILS_DISCOVERY_ATTR_INT_MIN]);
5477 fd->max_interval = nla_get_u32(tb[NL80211_FILS_DISCOVERY_ATTR_INT_MAX]);
5478
5479 return 0;
5480}
5481
7443dcd1
AD
5482static int
5483nl80211_parse_unsol_bcast_probe_resp(struct cfg80211_registered_device *rdev,
5484 struct nlattr *attrs,
5485 struct cfg80211_ap_settings *params)
5486{
5487 struct nlattr *tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_MAX + 1];
5488 int ret;
5489 struct cfg80211_unsol_bcast_probe_resp *presp =
5490 &params->unsol_bcast_probe_resp;
5491
5492 if (!wiphy_ext_feature_isset(&rdev->wiphy,
5493 NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP))
5494 return -EINVAL;
5495
5496 ret = nla_parse_nested(tb, NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_MAX,
5497 attrs, NULL, NULL);
5498 if (ret)
5499 return ret;
5500
5501 if (!tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INT] ||
5502 !tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL])
5503 return -EINVAL;
5504
5505 presp->tmpl = nla_data(tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL]);
5506 presp->tmpl_len = nla_len(tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL]);
5507 presp->interval = nla_get_u32(tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INT]);
5508 return 0;
5509}
5510
66cd794e 5511static void nl80211_check_ap_rate_selectors(struct cfg80211_ap_settings *params,
153e2a11 5512 const struct element *rates)
66cd794e
JB
5513{
5514 int i;
5515
5516 if (!rates)
5517 return;
5518
153e2a11
JB
5519 for (i = 0; i < rates->datalen; i++) {
5520 if (rates->data[i] == BSS_MEMBERSHIP_SELECTOR_HT_PHY)
66cd794e 5521 params->ht_required = true;
153e2a11 5522 if (rates->data[i] == BSS_MEMBERSHIP_SELECTOR_VHT_PHY)
66cd794e 5523 params->vht_required = true;
153e2a11 5524 if (rates->data[i] == BSS_MEMBERSHIP_SELECTOR_HE_PHY)
2a392596 5525 params->he_required = true;
153e2a11 5526 if (rates->data[i] == BSS_MEMBERSHIP_SELECTOR_SAE_H2E)
d6587602 5527 params->sae_h2e_required = true;
66cd794e
JB
5528 }
5529}
5530
5531/*
5532 * Since the nl80211 API didn't include, from the beginning, attributes about
5533 * HT/VHT requirements/capabilities, we parse them out of the IEs for the
5534 * benefit of drivers that rebuild IEs in the firmware.
5535 */
8bc65d38 5536static int nl80211_calculate_ap_params(struct cfg80211_ap_settings *params)
66cd794e
JB
5537{
5538 const struct cfg80211_beacon_data *bcn = &params->beacon;
ba83bfb1
IM
5539 size_t ies_len = bcn->tail_len;
5540 const u8 *ies = bcn->tail;
153e2a11
JB
5541 const struct element *rates;
5542 const struct element *cap;
66cd794e 5543
153e2a11 5544 rates = cfg80211_find_elem(WLAN_EID_SUPP_RATES, ies, ies_len);
66cd794e
JB
5545 nl80211_check_ap_rate_selectors(params, rates);
5546
153e2a11 5547 rates = cfg80211_find_elem(WLAN_EID_EXT_SUPP_RATES, ies, ies_len);
66cd794e
JB
5548 nl80211_check_ap_rate_selectors(params, rates);
5549
153e2a11
JB
5550 cap = cfg80211_find_elem(WLAN_EID_HT_CAPABILITY, ies, ies_len);
5551 if (cap && cap->datalen >= sizeof(*params->ht_cap))
5552 params->ht_cap = (void *)cap->data;
5553 cap = cfg80211_find_elem(WLAN_EID_VHT_CAPABILITY, ies, ies_len);
5554 if (cap && cap->datalen >= sizeof(*params->vht_cap))
5555 params->vht_cap = (void *)cap->data;
5556 cap = cfg80211_find_ext_elem(WLAN_EID_EXT_HE_CAPABILITY, ies, ies_len);
5557 if (cap && cap->datalen >= sizeof(*params->he_cap) + 1)
5558 params->he_cap = (void *)(cap->data + 1);
5559 cap = cfg80211_find_ext_elem(WLAN_EID_EXT_HE_OPERATION, ies, ies_len);
5560 if (cap && cap->datalen >= sizeof(*params->he_oper) + 1)
5561 params->he_oper = (void *)(cap->data + 1);
8bc65d38
AD
5562 cap = cfg80211_find_ext_elem(WLAN_EID_EXT_EHT_CAPABILITY, ies, ies_len);
5563 if (cap) {
5564 if (!cap->datalen)
5565 return -EINVAL;
5566 params->eht_cap = (void *)(cap->data + 1);
5567 if (!ieee80211_eht_capa_size_ok((const u8 *)params->he_cap,
5568 (const u8 *)params->eht_cap,
5569 cap->datalen - 1))
5570 return -EINVAL;
5571 }
5572 cap = cfg80211_find_ext_elem(WLAN_EID_EXT_EHT_OPERATION, ies, ies_len);
5573 if (cap) {
5574 if (!cap->datalen)
5575 return -EINVAL;
5576 params->eht_oper = (void *)(cap->data + 1);
5577 if (!ieee80211_eht_oper_size_ok((const u8 *)params->eht_oper,
5578 cap->datalen - 1))
5579 return -EINVAL;
5580 }
5581 return 0;
66cd794e
JB
5582}
5583
46c1dd0c
FF
5584static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev,
5585 struct cfg80211_ap_settings *params)
5586{
5587 struct wireless_dev *wdev;
46c1dd0c 5588
53873f13 5589 list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
46c1dd0c
FF
5590 if (wdev->iftype != NL80211_IFTYPE_AP &&
5591 wdev->iftype != NL80211_IFTYPE_P2P_GO)
5592 continue;
5593
7b0a0e3c 5594 if (!wdev->u.ap.preset_chandef.chan)
46c1dd0c
FF
5595 continue;
5596
7b0a0e3c
JB
5597 params->chandef = wdev->u.ap.preset_chandef;
5598 return true;
46c1dd0c
FF
5599 }
5600
7b0a0e3c 5601 return false;
46c1dd0c
FF
5602}
5603
e39e5b5e
JM
5604static bool nl80211_valid_auth_type(struct cfg80211_registered_device *rdev,
5605 enum nl80211_auth_type auth_type,
5606 enum nl80211_commands cmd)
5607{
5608 if (auth_type > NL80211_AUTHTYPE_MAX)
5609 return false;
5610
5611 switch (cmd) {
5612 case NL80211_CMD_AUTHENTICATE:
5613 if (!(rdev->wiphy.features & NL80211_FEATURE_SAE) &&
5614 auth_type == NL80211_AUTHTYPE_SAE)
5615 return false;
63181060
JM
5616 if (!wiphy_ext_feature_isset(&rdev->wiphy,
5617 NL80211_EXT_FEATURE_FILS_STA) &&
5618 (auth_type == NL80211_AUTHTYPE_FILS_SK ||
5619 auth_type == NL80211_AUTHTYPE_FILS_SK_PFS ||
5620 auth_type == NL80211_AUTHTYPE_FILS_PK))
5621 return false;
e39e5b5e
JM
5622 return true;
5623 case NL80211_CMD_CONNECT:
10773a7c 5624 if (!(rdev->wiphy.features & NL80211_FEATURE_SAE) &&
26f7044e
CHH
5625 !wiphy_ext_feature_isset(&rdev->wiphy,
5626 NL80211_EXT_FEATURE_SAE_OFFLOAD) &&
10773a7c 5627 auth_type == NL80211_AUTHTYPE_SAE)
a3caf744 5628 return false;
10773a7c 5629
a3caf744
VK
5630 /* FILS with SK PFS or PK not supported yet */
5631 if (auth_type == NL80211_AUTHTYPE_FILS_SK_PFS ||
5632 auth_type == NL80211_AUTHTYPE_FILS_PK)
5633 return false;
5634 if (!wiphy_ext_feature_isset(
5635 &rdev->wiphy,
5636 NL80211_EXT_FEATURE_FILS_SK_OFFLOAD) &&
5637 auth_type == NL80211_AUTHTYPE_FILS_SK)
5638 return false;
5639 return true;
e39e5b5e 5640 case NL80211_CMD_START_AP:
2831a631
CHH
5641 if (!wiphy_ext_feature_isset(&rdev->wiphy,
5642 NL80211_EXT_FEATURE_SAE_OFFLOAD_AP) &&
5643 auth_type == NL80211_AUTHTYPE_SAE)
e39e5b5e 5644 return false;
63181060
JM
5645 /* FILS not supported yet */
5646 if (auth_type == NL80211_AUTHTYPE_FILS_SK ||
5647 auth_type == NL80211_AUTHTYPE_FILS_SK_PFS ||
5648 auth_type == NL80211_AUTHTYPE_FILS_PK)
5649 return false;
e39e5b5e
JM
5650 return true;
5651 default:
5652 return false;
5653 }
5654}
5655
8860020e
JB
5656static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
5657{
5658 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7b0a0e3c 5659 unsigned int link_id = nl80211_link_id(info->attrs);
8860020e
JB
5660 struct net_device *dev = info->user_ptr[1];
5661 struct wireless_dev *wdev = dev->ieee80211_ptr;
9e263e19 5662 struct cfg80211_ap_settings *params;
8860020e
JB
5663 int err;
5664
5665 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
5666 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
5667 return -EOPNOTSUPP;
5668
5669 if (!rdev->ops->start_ap)
5670 return -EOPNOTSUPP;
5671
7b0a0e3c 5672 if (wdev->links[link_id].ap.beacon_interval)
8860020e
JB
5673 return -EALREADY;
5674
8860020e
JB
5675 /* these are required for START_AP */
5676 if (!info->attrs[NL80211_ATTR_BEACON_INTERVAL] ||
5677 !info->attrs[NL80211_ATTR_DTIM_PERIOD] ||
5678 !info->attrs[NL80211_ATTR_BEACON_HEAD])
5679 return -EINVAL;
5680
9e263e19
JB
5681 params = kzalloc(sizeof(*params), GFP_KERNEL);
5682 if (!params)
5683 return -ENOMEM;
5684
5685 err = nl80211_parse_beacon(rdev, info->attrs, &params->beacon);
8860020e 5686 if (err)
9e263e19 5687 goto out;
8860020e 5688
9e263e19 5689 params->beacon_interval =
8860020e 5690 nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
9e263e19 5691 params->dtim_period =
8860020e
JB
5692 nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);
5693
0c317a02 5694 err = cfg80211_validate_beacon_int(rdev, dev->ieee80211_ptr->iftype,
9e263e19 5695 params->beacon_interval);
8860020e 5696 if (err)
9e263e19 5697 goto out;
8860020e
JB
5698
5699 /*
5700 * In theory, some of these attributes should be required here
5701 * but since they were not used when the command was originally
5702 * added, keep them optional for old user space programs to let
5703 * them continue to work with drivers that do not need the
5704 * additional information -- drivers must check!
5705 */
5706 if (info->attrs[NL80211_ATTR_SSID]) {
9e263e19
JB
5707 params->ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
5708 params->ssid_len =
8860020e 5709 nla_len(info->attrs[NL80211_ATTR_SSID]);
9e263e19
JB
5710 if (params->ssid_len == 0) {
5711 err = -EINVAL;
5712 goto out;
5713 }
7b0a0e3c
JB
5714
5715 if (wdev->u.ap.ssid_len &&
5716 (wdev->u.ap.ssid_len != params->ssid_len ||
5717 memcmp(wdev->u.ap.ssid, params->ssid, params->ssid_len))) {
5718 /* require identical SSID for MLO */
5719 err = -EINVAL;
5720 goto out;
5721 }
5722 } else if (wdev->valid_links) {
5723 /* require SSID for MLO */
5724 err = -EINVAL;
5725 goto out;
8860020e
JB
5726 }
5727
ab0d76f6 5728 if (info->attrs[NL80211_ATTR_HIDDEN_SSID])
9e263e19 5729 params->hidden_ssid = nla_get_u32(
8860020e 5730 info->attrs[NL80211_ATTR_HIDDEN_SSID]);
8860020e 5731
9e263e19 5732 params->privacy = !!info->attrs[NL80211_ATTR_PRIVACY];
8860020e
JB
5733
5734 if (info->attrs[NL80211_ATTR_AUTH_TYPE]) {
9e263e19 5735 params->auth_type = nla_get_u32(
8860020e 5736 info->attrs[NL80211_ATTR_AUTH_TYPE]);
9e263e19
JB
5737 if (!nl80211_valid_auth_type(rdev, params->auth_type,
5738 NL80211_CMD_START_AP)) {
5739 err = -EINVAL;
5740 goto out;
5741 }
8860020e 5742 } else
9e263e19 5743 params->auth_type = NL80211_AUTHTYPE_AUTOMATIC;
8860020e 5744
9e263e19 5745 err = nl80211_crypto_settings(rdev, info, &params->crypto,
8860020e
JB
5746 NL80211_MAX_NR_CIPHER_SUITES);
5747 if (err)
9e263e19 5748 goto out;
8860020e 5749
1b658f11 5750 if (info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]) {
9e263e19
JB
5751 if (!(rdev->wiphy.features & NL80211_FEATURE_INACTIVITY_TIMER)) {
5752 err = -EOPNOTSUPP;
5753 goto out;
5754 }
5755 params->inactivity_timeout = nla_get_u16(
1b658f11
VT
5756 info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]);
5757 }
5758
53cabad7 5759 if (info->attrs[NL80211_ATTR_P2P_CTWINDOW]) {
9e263e19
JB
5760 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
5761 err = -EINVAL;
5762 goto out;
5763 }
5764 params->p2p_ctwindow =
53cabad7 5765 nla_get_u8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]);
9e263e19
JB
5766 if (params->p2p_ctwindow != 0 &&
5767 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN)) {
5768 err = -EINVAL;
5769 goto out;
5770 }
53cabad7
JB
5771 }
5772
5773 if (info->attrs[NL80211_ATTR_P2P_OPPPS]) {
5774 u8 tmp;
5775
9e263e19
JB
5776 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
5777 err = -EINVAL;
5778 goto out;
5779 }
53cabad7 5780 tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]);
9e263e19
JB
5781 params->p2p_opp_ps = tmp;
5782 if (params->p2p_opp_ps != 0 &&
5783 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS)) {
5784 err = -EINVAL;
5785 goto out;
5786 }
53cabad7
JB
5787 }
5788
aa430da4 5789 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
9e263e19 5790 err = nl80211_parse_chandef(rdev, info, &params->chandef);
683b6d3b 5791 if (err)
9e263e19 5792 goto out;
7b0a0e3c
JB
5793 } else if (wdev->valid_links) {
5794 /* with MLD need to specify the channel configuration */
5795 err = -EINVAL;
5796 goto out;
5797 } else if (wdev->u.ap.preset_chandef.chan) {
5798 params->chandef = wdev->u.ap.preset_chandef;
9e263e19
JB
5799 } else if (!nl80211_get_ap_channel(rdev, params)) {
5800 err = -EINVAL;
5801 goto out;
5802 }
aa430da4 5803
9e263e19
JB
5804 if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &params->chandef,
5805 wdev->iftype)) {
5806 err = -EINVAL;
5807 goto out;
5808 }
aa430da4 5809
c2653990
JB
5810 wdev_lock(wdev);
5811
a7c7fbff 5812 if (info->attrs[NL80211_ATTR_TX_RATES]) {
9a5f6488
TC
5813 err = nl80211_parse_tx_bitrate_mask(info, info->attrs,
5814 NL80211_ATTR_TX_RATES,
9e263e19 5815 &params->beacon_rate,
7b0a0e3c 5816 dev, false, link_id);
a7c7fbff 5817 if (err)
c2653990 5818 goto out_unlock;
a7c7fbff 5819
9e263e19
JB
5820 err = validate_beacon_tx_rate(rdev, params->chandef.chan->band,
5821 &params->beacon_rate);
a7c7fbff 5822 if (err)
c2653990 5823 goto out_unlock;
a7c7fbff
PK
5824 }
5825
18998c38 5826 if (info->attrs[NL80211_ATTR_SMPS_MODE]) {
9e263e19 5827 params->smps_mode =
18998c38 5828 nla_get_u8(info->attrs[NL80211_ATTR_SMPS_MODE]);
9e263e19 5829 switch (params->smps_mode) {
18998c38
EP
5830 case NL80211_SMPS_OFF:
5831 break;
5832 case NL80211_SMPS_STATIC:
5833 if (!(rdev->wiphy.features &
9e263e19
JB
5834 NL80211_FEATURE_STATIC_SMPS)) {
5835 err = -EINVAL;
c2653990 5836 goto out_unlock;
9e263e19 5837 }
18998c38
EP
5838 break;
5839 case NL80211_SMPS_DYNAMIC:
5840 if (!(rdev->wiphy.features &
9e263e19
JB
5841 NL80211_FEATURE_DYNAMIC_SMPS)) {
5842 err = -EINVAL;
c2653990 5843 goto out_unlock;
9e263e19 5844 }
18998c38
EP
5845 break;
5846 default:
9e263e19 5847 err = -EINVAL;
c2653990 5848 goto out_unlock;
18998c38
EP
5849 }
5850 } else {
9e263e19 5851 params->smps_mode = NL80211_SMPS_OFF;
18998c38
EP
5852 }
5853
9e263e19
JB
5854 params->pbss = nla_get_flag(info->attrs[NL80211_ATTR_PBSS]);
5855 if (params->pbss && !rdev->wiphy.bands[NL80211_BAND_60GHZ]) {
5856 err = -EOPNOTSUPP;
c2653990 5857 goto out_unlock;
9e263e19 5858 }
6e8ef842 5859
4baf6bea 5860 if (info->attrs[NL80211_ATTR_ACL_POLICY]) {
9e263e19
JB
5861 params->acl = parse_acl_data(&rdev->wiphy, info);
5862 if (IS_ERR(params->acl)) {
5863 err = PTR_ERR(params->acl);
05075fe7 5864 params->acl = NULL;
c2653990 5865 goto out_unlock;
9e263e19 5866 }
4baf6bea
OO
5867 }
5868
9e263e19 5869 params->twt_responder =
a0de1ca3
JC
5870 nla_get_flag(info->attrs[NL80211_ATTR_TWT_RESPONDER]);
5871
796e90f4
JC
5872 if (info->attrs[NL80211_ATTR_HE_OBSS_PD]) {
5873 err = nl80211_parse_he_obss_pd(
5874 info->attrs[NL80211_ATTR_HE_OBSS_PD],
9e263e19 5875 &params->he_obss_pd);
bc7a39b4 5876 if (err)
c2653990 5877 goto out_unlock;
796e90f4
JC
5878 }
5879
291c49de
AD
5880 if (info->attrs[NL80211_ATTR_FILS_DISCOVERY]) {
5881 err = nl80211_parse_fils_discovery(rdev,
5882 info->attrs[NL80211_ATTR_FILS_DISCOVERY],
9e263e19 5883 params);
291c49de 5884 if (err)
c2653990 5885 goto out_unlock;
291c49de
AD
5886 }
5887
7443dcd1
AD
5888 if (info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP]) {
5889 err = nl80211_parse_unsol_bcast_probe_resp(
5890 rdev, info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP],
9e263e19 5891 params);
7443dcd1 5892 if (err)
c2653990 5893 goto out_unlock;
7443dcd1
AD
5894 }
5895
dc1e3cb8
JC
5896 if (info->attrs[NL80211_ATTR_MBSSID_CONFIG]) {
5897 err = nl80211_parse_mbssid_config(&rdev->wiphy, dev,
5898 info->attrs[NL80211_ATTR_MBSSID_CONFIG],
5899 &params->mbssid_config,
5900 params->beacon.mbssid_ies ?
5901 params->beacon.mbssid_ies->cnt :
5902 0);
5903 if (err)
c2653990 5904 goto out_unlock;
dc1e3cb8
JC
5905 }
5906
8bc65d38
AD
5907 err = nl80211_calculate_ap_params(params);
5908 if (err)
5909 goto out_unlock;
66cd794e 5910
47301a74
VJ
5911 if (info->attrs[NL80211_ATTR_AP_SETTINGS_FLAGS])
5912 params->flags = nla_get_u32(
5913 info->attrs[NL80211_ATTR_AP_SETTINGS_FLAGS]);
5914 else if (info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])
5915 params->flags |= NL80211_AP_SETTINGS_EXTERNAL_AUTH_SUPPORT;
fe494370 5916
7b0a0e3c
JB
5917 if (wdev->conn_owner_nlportid &&
5918 info->attrs[NL80211_ATTR_SOCKET_OWNER] &&
5919 wdev->conn_owner_nlportid != info->snd_portid) {
5920 err = -EINVAL;
5921 goto out_unlock;
5922 }
5923
5924 /* FIXME: validate MLO/link-id against driver capabilities */
5925
9e263e19 5926 err = rdev_start_ap(rdev, dev, params);
46c1dd0c 5927 if (!err) {
7b0a0e3c
JB
5928 wdev->links[link_id].ap.beacon_interval = params->beacon_interval;
5929 wdev->links[link_id].ap.chandef = params->chandef;
5930 wdev->u.ap.ssid_len = params->ssid_len;
5931 memcpy(wdev->u.ap.ssid, params->ssid,
5932 params->ssid_len);
466a3061
DK
5933
5934 if (info->attrs[NL80211_ATTR_SOCKET_OWNER])
5935 wdev->conn_owner_nlportid = info->snd_portid;
46c1dd0c 5936 }
7b0a0e3c 5937out_unlock:
c56589ed 5938 wdev_unlock(wdev);
9951ebfc 5939out:
9e263e19 5940 kfree(params->acl);
dc1e3cb8
JC
5941 kfree(params->beacon.mbssid_ies);
5942 if (params->mbssid_config.tx_wdev &&
5943 params->mbssid_config.tx_wdev->netdev &&
5944 params->mbssid_config.tx_wdev->netdev != dev)
5945 dev_put(params->mbssid_config.tx_wdev->netdev);
9e263e19 5946 kfree(params);
77765eaf 5947
56d1893d 5948 return err;
ed1b6cc7
JB
5949}
5950
8860020e
JB
5951static int nl80211_set_beacon(struct sk_buff *skb, struct genl_info *info)
5952{
5953 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7b0a0e3c 5954 unsigned int link_id = nl80211_link_id(info->attrs);
8860020e
JB
5955 struct net_device *dev = info->user_ptr[1];
5956 struct wireless_dev *wdev = dev->ieee80211_ptr;
5957 struct cfg80211_beacon_data params;
5958 int err;
5959
5960 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
5961 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
5962 return -EOPNOTSUPP;
5963
5964 if (!rdev->ops->change_beacon)
5965 return -EOPNOTSUPP;
5966
7b0a0e3c 5967 if (!wdev->links[link_id].ap.beacon_interval)
8860020e
JB
5968 return -EINVAL;
5969
81e54d08 5970 err = nl80211_parse_beacon(rdev, info->attrs, &params);
8860020e 5971 if (err)
dc1e3cb8 5972 goto out;
8860020e 5973
c56589ed
SW
5974 wdev_lock(wdev);
5975 err = rdev_change_beacon(rdev, dev, &params);
5976 wdev_unlock(wdev);
5977
dc1e3cb8
JC
5978out:
5979 kfree(params.mbssid_ies);
c56589ed 5980 return err;
8860020e
JB
5981}
5982
5983static int nl80211_stop_ap(struct sk_buff *skb, struct genl_info *info)
ed1b6cc7 5984{
4c476991 5985 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7b0a0e3c 5986 unsigned int link_id = nl80211_link_id(info->attrs);
4c476991 5987 struct net_device *dev = info->user_ptr[1];
ed1b6cc7 5988
7b0a0e3c 5989 return cfg80211_stop_ap(rdev, dev, link_id, false);
ed1b6cc7
JB
5990}
5991
5727ef1b
JB
5992static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = {
5993 [NL80211_STA_FLAG_AUTHORIZED] = { .type = NLA_FLAG },
5994 [NL80211_STA_FLAG_SHORT_PREAMBLE] = { .type = NLA_FLAG },
5995 [NL80211_STA_FLAG_WME] = { .type = NLA_FLAG },
0e46724a 5996 [NL80211_STA_FLAG_MFP] = { .type = NLA_FLAG },
b39c48fa 5997 [NL80211_STA_FLAG_AUTHENTICATED] = { .type = NLA_FLAG },
d83023da 5998 [NL80211_STA_FLAG_TDLS_PEER] = { .type = NLA_FLAG },
5727ef1b
JB
5999};
6000
eccb8e8f 6001static int parse_station_flags(struct genl_info *info,
bdd3ae3d 6002 enum nl80211_iftype iftype,
eccb8e8f 6003 struct station_parameters *params)
5727ef1b
JB
6004{
6005 struct nlattr *flags[NL80211_STA_FLAG_MAX + 1];
eccb8e8f 6006 struct nlattr *nla;
5727ef1b
JB
6007 int flag;
6008
eccb8e8f
JB
6009 /*
6010 * Try parsing the new attribute first so userspace
6011 * can specify both for older kernels.
6012 */
6013 nla = info->attrs[NL80211_ATTR_STA_FLAGS2];
6014 if (nla) {
6015 struct nl80211_sta_flag_update *sta_flags;
6016
6017 sta_flags = nla_data(nla);
6018 params->sta_flags_mask = sta_flags->mask;
6019 params->sta_flags_set = sta_flags->set;
77ee7c89 6020 params->sta_flags_set &= params->sta_flags_mask;
eccb8e8f
JB
6021 if ((params->sta_flags_mask |
6022 params->sta_flags_set) & BIT(__NL80211_STA_FLAG_INVALID))
6023 return -EINVAL;
6024 return 0;
6025 }
6026
6027 /* if present, parse the old attribute */
5727ef1b 6028
eccb8e8f 6029 nla = info->attrs[NL80211_ATTR_STA_FLAGS];
5727ef1b
JB
6030 if (!nla)
6031 return 0;
6032
8cb08174 6033 if (nla_parse_nested_deprecated(flags, NL80211_STA_FLAG_MAX, nla, sta_flags_policy, info->extack))
5727ef1b
JB
6034 return -EINVAL;
6035
bdd3ae3d
JB
6036 /*
6037 * Only allow certain flags for interface types so that
6038 * other attributes are silently ignored. Remember that
6039 * this is backward compatibility code with old userspace
6040 * and shouldn't be hit in other cases anyway.
6041 */
6042 switch (iftype) {
6043 case NL80211_IFTYPE_AP:
6044 case NL80211_IFTYPE_AP_VLAN:
6045 case NL80211_IFTYPE_P2P_GO:
6046 params->sta_flags_mask = BIT(NL80211_STA_FLAG_AUTHORIZED) |
6047 BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) |
6048 BIT(NL80211_STA_FLAG_WME) |
6049 BIT(NL80211_STA_FLAG_MFP);
6050 break;
6051 case NL80211_IFTYPE_P2P_CLIENT:
6052 case NL80211_IFTYPE_STATION:
6053 params->sta_flags_mask = BIT(NL80211_STA_FLAG_AUTHORIZED) |
6054 BIT(NL80211_STA_FLAG_TDLS_PEER);
6055 break;
6056 case NL80211_IFTYPE_MESH_POINT:
6057 params->sta_flags_mask = BIT(NL80211_STA_FLAG_AUTHENTICATED) |
6058 BIT(NL80211_STA_FLAG_MFP) |
6059 BIT(NL80211_STA_FLAG_AUTHORIZED);
5cf3006c 6060 break;
bdd3ae3d
JB
6061 default:
6062 return -EINVAL;
6063 }
5727ef1b 6064
3383b5a6
JB
6065 for (flag = 1; flag <= NL80211_STA_FLAG_MAX; flag++) {
6066 if (flags[flag]) {
eccb8e8f 6067 params->sta_flags_set |= (1<<flag);
5727ef1b 6068
3383b5a6
JB
6069 /* no longer support new API additions in old API */
6070 if (flag > NL80211_STA_FLAG_MAX_OLD_API)
6071 return -EINVAL;
6072 }
6073 }
6074
5727ef1b
JB
6075 return 0;
6076}
6077
9bb7e0f2 6078bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, int attr)
c8dcfd8a
FF
6079{
6080 struct nlattr *rate;
8eb41c8d
VK
6081 u32 bitrate;
6082 u16 bitrate_compat;
bbf67e45 6083 enum nl80211_rate_info rate_flg;
c8dcfd8a 6084
ae0be8de 6085 rate = nla_nest_start_noflag(msg, attr);
c8dcfd8a 6086 if (!rate)
db9c64cf 6087 return false;
c8dcfd8a
FF
6088
6089 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
6090 bitrate = cfg80211_calculate_bitrate(info);
8eb41c8d
VK
6091 /* report 16-bit bitrate only if we can */
6092 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
db9c64cf
JB
6093 if (bitrate > 0 &&
6094 nla_put_u32(msg, NL80211_RATE_INFO_BITRATE32, bitrate))
6095 return false;
6096 if (bitrate_compat > 0 &&
6097 nla_put_u16(msg, NL80211_RATE_INFO_BITRATE, bitrate_compat))
6098 return false;
6099
b51f3bee
JB
6100 switch (info->bw) {
6101 case RATE_INFO_BW_5:
6102 rate_flg = NL80211_RATE_INFO_5_MHZ_WIDTH;
6103 break;
6104 case RATE_INFO_BW_10:
6105 rate_flg = NL80211_RATE_INFO_10_MHZ_WIDTH;
6106 break;
6107 default:
6108 WARN_ON(1);
7b506ff6 6109 fallthrough;
b51f3bee
JB
6110 case RATE_INFO_BW_20:
6111 rate_flg = 0;
6112 break;
6113 case RATE_INFO_BW_40:
6114 rate_flg = NL80211_RATE_INFO_40_MHZ_WIDTH;
6115 break;
6116 case RATE_INFO_BW_80:
6117 rate_flg = NL80211_RATE_INFO_80_MHZ_WIDTH;
6118 break;
6119 case RATE_INFO_BW_160:
6120 rate_flg = NL80211_RATE_INFO_160_MHZ_WIDTH;
6121 break;
c4cbaf79
LC
6122 case RATE_INFO_BW_HE_RU:
6123 rate_flg = 0;
6124 WARN_ON(!(info->flags & RATE_INFO_FLAGS_HE_MCS));
cfb14110
VJ
6125 break;
6126 case RATE_INFO_BW_320:
6127 rate_flg = NL80211_RATE_INFO_320_MHZ_WIDTH;
6128 break;
6129 case RATE_INFO_BW_EHT_RU:
6130 rate_flg = 0;
6131 WARN_ON(!(info->flags & RATE_INFO_FLAGS_EHT_MCS));
6132 break;
b51f3bee
JB
6133 }
6134
6135 if (rate_flg && nla_put_flag(msg, rate_flg))
6136 return false;
6137
db9c64cf
JB
6138 if (info->flags & RATE_INFO_FLAGS_MCS) {
6139 if (nla_put_u8(msg, NL80211_RATE_INFO_MCS, info->mcs))
6140 return false;
db9c64cf
JB
6141 if (info->flags & RATE_INFO_FLAGS_SHORT_GI &&
6142 nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI))
6143 return false;
6144 } else if (info->flags & RATE_INFO_FLAGS_VHT_MCS) {
6145 if (nla_put_u8(msg, NL80211_RATE_INFO_VHT_MCS, info->mcs))
6146 return false;
6147 if (nla_put_u8(msg, NL80211_RATE_INFO_VHT_NSS, info->nss))
6148 return false;
db9c64cf
JB
6149 if (info->flags & RATE_INFO_FLAGS_SHORT_GI &&
6150 nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI))
6151 return false;
c4cbaf79
LC
6152 } else if (info->flags & RATE_INFO_FLAGS_HE_MCS) {
6153 if (nla_put_u8(msg, NL80211_RATE_INFO_HE_MCS, info->mcs))
6154 return false;
6155 if (nla_put_u8(msg, NL80211_RATE_INFO_HE_NSS, info->nss))
6156 return false;
6157 if (nla_put_u8(msg, NL80211_RATE_INFO_HE_GI, info->he_gi))
6158 return false;
6159 if (nla_put_u8(msg, NL80211_RATE_INFO_HE_DCM, info->he_dcm))
6160 return false;
6161 if (info->bw == RATE_INFO_BW_HE_RU &&
6162 nla_put_u8(msg, NL80211_RATE_INFO_HE_RU_ALLOC,
6163 info->he_ru_alloc))
6164 return false;
cfb14110
VJ
6165 } else if (info->flags & RATE_INFO_FLAGS_EHT_MCS) {
6166 if (nla_put_u8(msg, NL80211_RATE_INFO_EHT_MCS, info->mcs))
6167 return false;
6168 if (nla_put_u8(msg, NL80211_RATE_INFO_EHT_NSS, info->nss))
6169 return false;
6170 if (nla_put_u8(msg, NL80211_RATE_INFO_EHT_GI, info->eht_gi))
6171 return false;
6172 if (info->bw == RATE_INFO_BW_EHT_RU &&
6173 nla_put_u8(msg, NL80211_RATE_INFO_EHT_RU_ALLOC,
6174 info->eht_ru_alloc))
6175 return false;
db9c64cf 6176 }
c8dcfd8a
FF
6177
6178 nla_nest_end(msg, rate);
6179 return true;
c8dcfd8a
FF
6180}
6181
119363c7
FF
6182static bool nl80211_put_signal(struct sk_buff *msg, u8 mask, s8 *signal,
6183 int id)
6184{
6185 void *attr;
6186 int i = 0;
6187
6188 if (!mask)
6189 return true;
6190
ae0be8de 6191 attr = nla_nest_start_noflag(msg, id);
119363c7
FF
6192 if (!attr)
6193 return false;
6194
6195 for (i = 0; i < IEEE80211_MAX_CHAINS; i++) {
6196 if (!(mask & BIT(i)))
6197 continue;
6198
6199 if (nla_put_u8(msg, i, signal[i]))
6200 return false;
6201 }
6202
6203 nla_nest_end(msg, attr);
6204
6205 return true;
6206}
6207
cf5ead82
JB
6208static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
6209 u32 seq, int flags,
66266b3a
JL
6210 struct cfg80211_registered_device *rdev,
6211 struct net_device *dev,
98b62183 6212 const u8 *mac_addr, struct station_info *sinfo)
fd5b74dc
JB
6213{
6214 void *hdr;
f4263c98 6215 struct nlattr *sinfoattr, *bss_param;
fd5b74dc 6216
cf5ead82 6217 hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
f77bf486
AS
6218 if (!hdr) {
6219 cfg80211_sinfo_release_content(sinfo);
fd5b74dc 6220 return -1;
f77bf486 6221 }
fd5b74dc 6222
9360ffd1
DM
6223 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
6224 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr) ||
6225 nla_put_u32(msg, NL80211_ATTR_GENERATION, sinfo->generation))
6226 goto nla_put_failure;
f5ea9120 6227
ae0be8de 6228 sinfoattr = nla_nest_start_noflag(msg, NL80211_ATTR_STA_INFO);
2ec600d6 6229 if (!sinfoattr)
fd5b74dc 6230 goto nla_put_failure;
319090bf
JB
6231
6232#define PUT_SINFO(attr, memb, type) do { \
d686b920 6233 BUILD_BUG_ON(sizeof(type) == sizeof(u64)); \
397c657a 6234 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_ ## attr) && \
319090bf
JB
6235 nla_put_ ## type(msg, NL80211_STA_INFO_ ## attr, \
6236 sinfo->memb)) \
6237 goto nla_put_failure; \
6238 } while (0)
d686b920 6239#define PUT_SINFO_U64(attr, memb) do { \
397c657a 6240 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_ ## attr) && \
d686b920
JB
6241 nla_put_u64_64bit(msg, NL80211_STA_INFO_ ## attr, \
6242 sinfo->memb, NL80211_STA_INFO_PAD)) \
6243 goto nla_put_failure; \
6244 } while (0)
319090bf
JB
6245
6246 PUT_SINFO(CONNECTED_TIME, connected_time, u32);
6247 PUT_SINFO(INACTIVE_TIME, inactive_time, u32);
6c7a0033 6248 PUT_SINFO_U64(ASSOC_AT_BOOTTIME, assoc_at);
319090bf 6249
397c657a
OE
6250 if (sinfo->filled & (BIT_ULL(NL80211_STA_INFO_RX_BYTES) |
6251 BIT_ULL(NL80211_STA_INFO_RX_BYTES64)) &&
9360ffd1 6252 nla_put_u32(msg, NL80211_STA_INFO_RX_BYTES,
42745e03 6253 (u32)sinfo->rx_bytes))
9360ffd1 6254 goto nla_put_failure;
319090bf 6255
397c657a
OE
6256 if (sinfo->filled & (BIT_ULL(NL80211_STA_INFO_TX_BYTES) |
6257 BIT_ULL(NL80211_STA_INFO_TX_BYTES64)) &&
9360ffd1 6258 nla_put_u32(msg, NL80211_STA_INFO_TX_BYTES,
42745e03
VK
6259 (u32)sinfo->tx_bytes))
6260 goto nla_put_failure;
319090bf 6261
d686b920
JB
6262 PUT_SINFO_U64(RX_BYTES64, rx_bytes);
6263 PUT_SINFO_U64(TX_BYTES64, tx_bytes);
319090bf
JB
6264 PUT_SINFO(LLID, llid, u16);
6265 PUT_SINFO(PLID, plid, u16);
6266 PUT_SINFO(PLINK_STATE, plink_state, u8);
d686b920 6267 PUT_SINFO_U64(RX_DURATION, rx_duration);
36647055
THJ
6268 PUT_SINFO_U64(TX_DURATION, tx_duration);
6269
6270 if (wiphy_ext_feature_isset(&rdev->wiphy,
6271 NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))
6272 PUT_SINFO(AIRTIME_WEIGHT, airtime_weight, u16);
319090bf 6273
66266b3a
JL
6274 switch (rdev->wiphy.signal_type) {
6275 case CFG80211_SIGNAL_TYPE_MBM:
319090bf
JB
6276 PUT_SINFO(SIGNAL, signal, u8);
6277 PUT_SINFO(SIGNAL_AVG, signal_avg, u8);
66266b3a
JL
6278 break;
6279 default:
6280 break;
6281 }
397c657a 6282 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL)) {
119363c7
FF
6283 if (!nl80211_put_signal(msg, sinfo->chains,
6284 sinfo->chain_signal,
6285 NL80211_STA_INFO_CHAIN_SIGNAL))
6286 goto nla_put_failure;
6287 }
397c657a 6288 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL_AVG)) {
119363c7
FF
6289 if (!nl80211_put_signal(msg, sinfo->chains,
6290 sinfo->chain_signal_avg,
6291 NL80211_STA_INFO_CHAIN_SIGNAL_AVG))
6292 goto nla_put_failure;
6293 }
397c657a 6294 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_BITRATE)) {
c8dcfd8a
FF
6295 if (!nl80211_put_sta_rate(msg, &sinfo->txrate,
6296 NL80211_STA_INFO_TX_BITRATE))
6297 goto nla_put_failure;
6298 }
397c657a 6299 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_RX_BITRATE)) {
c8dcfd8a
FF
6300 if (!nl80211_put_sta_rate(msg, &sinfo->rxrate,
6301 NL80211_STA_INFO_RX_BITRATE))
420e7fab 6302 goto nla_put_failure;
420e7fab 6303 }
319090bf
JB
6304
6305 PUT_SINFO(RX_PACKETS, rx_packets, u32);
6306 PUT_SINFO(TX_PACKETS, tx_packets, u32);
6307 PUT_SINFO(TX_RETRIES, tx_retries, u32);
6308 PUT_SINFO(TX_FAILED, tx_failed, u32);
6309 PUT_SINFO(EXPECTED_THROUGHPUT, expected_throughput, u32);
ab60633c 6310 PUT_SINFO(AIRTIME_LINK_METRIC, airtime_link_metric, u32);
319090bf
JB
6311 PUT_SINFO(BEACON_LOSS, beacon_loss_count, u32);
6312 PUT_SINFO(LOCAL_PM, local_pm, u32);
6313 PUT_SINFO(PEER_PM, peer_pm, u32);
6314 PUT_SINFO(NONPEER_PM, nonpeer_pm, u32);
dbdaee7a 6315 PUT_SINFO(CONNECTED_TO_GATE, connected_to_gate, u8);
1303a51c 6316 PUT_SINFO(CONNECTED_TO_AS, connected_to_as, u8);
319090bf 6317
397c657a 6318 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_BSS_PARAM)) {
ae0be8de
MK
6319 bss_param = nla_nest_start_noflag(msg,
6320 NL80211_STA_INFO_BSS_PARAM);
f4263c98
PS
6321 if (!bss_param)
6322 goto nla_put_failure;
6323
9360ffd1
DM
6324 if (((sinfo->bss_param.flags & BSS_PARAM_FLAGS_CTS_PROT) &&
6325 nla_put_flag(msg, NL80211_STA_BSS_PARAM_CTS_PROT)) ||
6326 ((sinfo->bss_param.flags & BSS_PARAM_FLAGS_SHORT_PREAMBLE) &&
6327 nla_put_flag(msg, NL80211_STA_BSS_PARAM_SHORT_PREAMBLE)) ||
6328 ((sinfo->bss_param.flags & BSS_PARAM_FLAGS_SHORT_SLOT_TIME) &&
6329 nla_put_flag(msg, NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME)) ||
6330 nla_put_u8(msg, NL80211_STA_BSS_PARAM_DTIM_PERIOD,
6331 sinfo->bss_param.dtim_period) ||
6332 nla_put_u16(msg, NL80211_STA_BSS_PARAM_BEACON_INTERVAL,
6333 sinfo->bss_param.beacon_interval))
6334 goto nla_put_failure;
f4263c98
PS
6335
6336 nla_nest_end(msg, bss_param);
6337 }
397c657a 6338 if ((sinfo->filled & BIT_ULL(NL80211_STA_INFO_STA_FLAGS)) &&
9360ffd1
DM
6339 nla_put(msg, NL80211_STA_INFO_STA_FLAGS,
6340 sizeof(struct nl80211_sta_flag_update),
6341 &sinfo->sta_flags))
6342 goto nla_put_failure;
319090bf 6343
d686b920
JB
6344 PUT_SINFO_U64(T_OFFSET, t_offset);
6345 PUT_SINFO_U64(RX_DROP_MISC, rx_dropped_misc);
6346 PUT_SINFO_U64(BEACON_RX, rx_beacon);
a76b1942 6347 PUT_SINFO(BEACON_SIGNAL_AVG, rx_beacon_signal_avg, u8);
0d4e14a3
AB
6348 PUT_SINFO(RX_MPDUS, rx_mpdu_count, u32);
6349 PUT_SINFO(FCS_ERROR_COUNT, fcs_err_count, u32);
81d5439d 6350 if (wiphy_ext_feature_isset(&rdev->wiphy,
9c06602b
BP
6351 NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT)) {
6352 PUT_SINFO(ACK_SIGNAL, ack_signal, u8);
6353 PUT_SINFO(ACK_SIGNAL_AVG, avg_ack_signal, s8);
6354 }
319090bf
JB
6355
6356#undef PUT_SINFO
d686b920 6357#undef PUT_SINFO_U64
6de39808 6358
8689c051 6359 if (sinfo->pertid) {
6de39808
JB
6360 struct nlattr *tidsattr;
6361 int tid;
6362
ae0be8de
MK
6363 tidsattr = nla_nest_start_noflag(msg,
6364 NL80211_STA_INFO_TID_STATS);
6de39808
JB
6365 if (!tidsattr)
6366 goto nla_put_failure;
6367
6368 for (tid = 0; tid < IEEE80211_NUM_TIDS + 1; tid++) {
6369 struct cfg80211_tid_stats *tidstats;
6370 struct nlattr *tidattr;
6371
6372 tidstats = &sinfo->pertid[tid];
6373
6374 if (!tidstats->filled)
6375 continue;
6376
ae0be8de 6377 tidattr = nla_nest_start_noflag(msg, tid + 1);
6de39808
JB
6378 if (!tidattr)
6379 goto nla_put_failure;
6380
d686b920 6381#define PUT_TIDVAL_U64(attr, memb) do { \
6de39808 6382 if (tidstats->filled & BIT(NL80211_TID_STATS_ ## attr) && \
d686b920
JB
6383 nla_put_u64_64bit(msg, NL80211_TID_STATS_ ## attr, \
6384 tidstats->memb, NL80211_TID_STATS_PAD)) \
6de39808
JB
6385 goto nla_put_failure; \
6386 } while (0)
6387
d686b920
JB
6388 PUT_TIDVAL_U64(RX_MSDU, rx_msdu);
6389 PUT_TIDVAL_U64(TX_MSDU, tx_msdu);
6390 PUT_TIDVAL_U64(TX_MSDU_RETRIES, tx_msdu_retries);
6391 PUT_TIDVAL_U64(TX_MSDU_FAILED, tx_msdu_failed);
6de39808 6392
d686b920 6393#undef PUT_TIDVAL_U64
52539ca8
THJ
6394 if ((tidstats->filled &
6395 BIT(NL80211_TID_STATS_TXQ_STATS)) &&
6396 !nl80211_put_txq_stats(msg, &tidstats->txq_stats,
6397 NL80211_TID_STATS_TXQ_STATS))
6398 goto nla_put_failure;
6399
6de39808
JB
6400 nla_nest_end(msg, tidattr);
6401 }
6402
6403 nla_nest_end(msg, tidsattr);
6404 }
6405
2ec600d6 6406 nla_nest_end(msg, sinfoattr);
fd5b74dc 6407
319090bf 6408 if (sinfo->assoc_req_ies_len &&
9360ffd1
DM
6409 nla_put(msg, NL80211_ATTR_IE, sinfo->assoc_req_ies_len,
6410 sinfo->assoc_req_ies))
6411 goto nla_put_failure;
50d3dfb7 6412
7ea3e110 6413 cfg80211_sinfo_release_content(sinfo);
053c095a
JB
6414 genlmsg_end(msg, hdr);
6415 return 0;
fd5b74dc
JB
6416
6417 nla_put_failure:
7ea3e110 6418 cfg80211_sinfo_release_content(sinfo);
bc3ed28c
TG
6419 genlmsg_cancel(msg, hdr);
6420 return -EMSGSIZE;
fd5b74dc
JB
6421}
6422
2ec600d6 6423static int nl80211_dump_station(struct sk_buff *skb,
bba95fef 6424 struct netlink_callback *cb)
2ec600d6 6425{
73887fd9 6426 struct station_info sinfo;
1b8ec87a 6427 struct cfg80211_registered_device *rdev;
97990a06 6428 struct wireless_dev *wdev;
2ec600d6 6429 u8 mac_addr[ETH_ALEN];
97990a06 6430 int sta_idx = cb->args[2];
2ec600d6 6431 int err;
2ec600d6 6432
ce6b6974 6433 err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev, NULL);
67748893 6434 if (err)
a05829a7
JB
6435 return err;
6436 /* nl80211_prepare_wdev_dump acquired it in the successful case */
6437 __acquire(&rdev->wiphy.mtx);
bba95fef 6438
97990a06
JB
6439 if (!wdev->netdev) {
6440 err = -EINVAL;
6441 goto out_err;
6442 }
6443
1b8ec87a 6444 if (!rdev->ops->dump_station) {
eec60b03 6445 err = -EOPNOTSUPP;
bba95fef
JB
6446 goto out_err;
6447 }
6448
bba95fef 6449 while (1) {
73887fd9 6450 memset(&sinfo, 0, sizeof(sinfo));
1b8ec87a 6451 err = rdev_dump_station(rdev, wdev->netdev, sta_idx,
73887fd9 6452 mac_addr, &sinfo);
bba95fef
JB
6453 if (err == -ENOENT)
6454 break;
6455 if (err)
3b85875a 6456 goto out_err;
bba95fef 6457
cf5ead82 6458 if (nl80211_send_station(skb, NL80211_CMD_NEW_STATION,
15e47304 6459 NETLINK_CB(cb->skb).portid,
bba95fef 6460 cb->nlh->nlmsg_seq, NLM_F_MULTI,
1b8ec87a 6461 rdev, wdev->netdev, mac_addr,
73887fd9 6462 &sinfo) < 0)
bba95fef
JB
6463 goto out;
6464
6465 sta_idx++;
6466 }
6467
bba95fef 6468 out:
97990a06 6469 cb->args[2] = sta_idx;
bba95fef 6470 err = skb->len;
bba95fef 6471 out_err:
a05829a7 6472 wiphy_unlock(&rdev->wiphy);
bba95fef
JB
6473
6474 return err;
2ec600d6 6475}
fd5b74dc 6476
5727ef1b
JB
6477static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
6478{
4c476991
JB
6479 struct cfg80211_registered_device *rdev = info->user_ptr[0];
6480 struct net_device *dev = info->user_ptr[1];
73887fd9 6481 struct station_info sinfo;
fd5b74dc
JB
6482 struct sk_buff *msg;
6483 u8 *mac_addr = NULL;
4c476991 6484 int err;
fd5b74dc 6485
73887fd9 6486 memset(&sinfo, 0, sizeof(sinfo));
fd5b74dc 6487
73887fd9
JB
6488 if (!info->attrs[NL80211_ATTR_MAC])
6489 return -EINVAL;
fd5b74dc
JB
6490
6491 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
6492
73887fd9
JB
6493 if (!rdev->ops->get_station)
6494 return -EOPNOTSUPP;
3b85875a 6495
73887fd9 6496 err = rdev_get_station(rdev, dev, mac_addr, &sinfo);
fd5b74dc 6497 if (err)
73887fd9 6498 return err;
2ec600d6 6499
fd2120ca 6500 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
7ea3e110 6501 if (!msg) {
ba8f566a 6502 cfg80211_sinfo_release_content(&sinfo);
73887fd9 6503 return -ENOMEM;
7ea3e110 6504 }
fd5b74dc 6505
cf5ead82
JB
6506 if (nl80211_send_station(msg, NL80211_CMD_NEW_STATION,
6507 info->snd_portid, info->snd_seq, 0,
73887fd9 6508 rdev, dev, mac_addr, &sinfo) < 0) {
4c476991 6509 nlmsg_free(msg);
73887fd9 6510 return -ENOBUFS;
4c476991 6511 }
3b85875a 6512
73887fd9 6513 return genlmsg_reply(msg, info);
5727ef1b
JB
6514}
6515
77ee7c89
JB
6516int cfg80211_check_station_change(struct wiphy *wiphy,
6517 struct station_parameters *params,
6518 enum cfg80211_station_type statype)
6519{
e4208427
AB
6520 if (params->listen_interval != -1 &&
6521 statype != CFG80211_STA_AP_CLIENT_UNASSOC)
77ee7c89 6522 return -EINVAL;
e4208427 6523
17b94247
AB
6524 if (params->support_p2p_ps != -1 &&
6525 statype != CFG80211_STA_AP_CLIENT_UNASSOC)
6526 return -EINVAL;
6527
c72e1140 6528 if (params->aid &&
e4208427
AB
6529 !(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) &&
6530 statype != CFG80211_STA_AP_CLIENT_UNASSOC)
77ee7c89
JB
6531 return -EINVAL;
6532
6533 /* When you run into this, adjust the code below for the new flag */
6534 BUILD_BUG_ON(NL80211_STA_FLAG_MAX != 7);
6535
6536 switch (statype) {
eef941e6
TP
6537 case CFG80211_STA_MESH_PEER_KERNEL:
6538 case CFG80211_STA_MESH_PEER_USER:
77ee7c89
JB
6539 /*
6540 * No ignoring the TDLS flag here -- the userspace mesh
6541 * code doesn't have the bug of including TDLS in the
6542 * mask everywhere.
6543 */
6544 if (params->sta_flags_mask &
6545 ~(BIT(NL80211_STA_FLAG_AUTHENTICATED) |
6546 BIT(NL80211_STA_FLAG_MFP) |
6547 BIT(NL80211_STA_FLAG_AUTHORIZED)))
6548 return -EINVAL;
6549 break;
6550 case CFG80211_STA_TDLS_PEER_SETUP:
6551 case CFG80211_STA_TDLS_PEER_ACTIVE:
6552 if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))
6553 return -EINVAL;
6554 /* ignore since it can't change */
6555 params->sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
6556 break;
6557 default:
6558 /* disallow mesh-specific things */
6559 if (params->plink_action != NL80211_PLINK_ACTION_NO_ACTION)
6560 return -EINVAL;
6561 if (params->local_pm)
6562 return -EINVAL;
6563 if (params->sta_modify_mask & STATION_PARAM_APPLY_PLINK_STATE)
6564 return -EINVAL;
6565 }
6566
6567 if (statype != CFG80211_STA_TDLS_PEER_SETUP &&
6568 statype != CFG80211_STA_TDLS_PEER_ACTIVE) {
6569 /* TDLS can't be set, ... */
6570 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))
6571 return -EINVAL;
6572 /*
6573 * ... but don't bother the driver with it. This works around
6574 * a hostapd/wpa_supplicant issue -- it always includes the
6575 * TLDS_PEER flag in the mask even for AP mode.
6576 */
6577 params->sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
6578 }
6579
47edb11b
AB
6580 if (statype != CFG80211_STA_TDLS_PEER_SETUP &&
6581 statype != CFG80211_STA_AP_CLIENT_UNASSOC) {
77ee7c89
JB
6582 /* reject other things that can't change */
6583 if (params->sta_modify_mask & STATION_PARAM_APPLY_UAPSD)
6584 return -EINVAL;
6585 if (params->sta_modify_mask & STATION_PARAM_APPLY_CAPABILITY)
6586 return -EINVAL;
b95eb7f0 6587 if (params->link_sta_params.supported_rates)
77ee7c89 6588 return -EINVAL;
b95eb7f0
ST
6589 if (params->ext_capab || params->link_sta_params.ht_capa ||
6590 params->link_sta_params.vht_capa ||
6591 params->link_sta_params.he_capa ||
6592 params->link_sta_params.eht_capa)
77ee7c89
JB
6593 return -EINVAL;
6594 }
6595
47edb11b
AB
6596 if (statype != CFG80211_STA_AP_CLIENT &&
6597 statype != CFG80211_STA_AP_CLIENT_UNASSOC) {
77ee7c89
JB
6598 if (params->vlan)
6599 return -EINVAL;
6600 }
6601
6602 switch (statype) {
6603 case CFG80211_STA_AP_MLME_CLIENT:
6604 /* Use this only for authorizing/unauthorizing a station */
6605 if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)))
6606 return -EOPNOTSUPP;
6607 break;
6608 case CFG80211_STA_AP_CLIENT:
47edb11b 6609 case CFG80211_STA_AP_CLIENT_UNASSOC:
77ee7c89
JB
6610 /* accept only the listed bits */
6611 if (params->sta_flags_mask &
6612 ~(BIT(NL80211_STA_FLAG_AUTHORIZED) |
6613 BIT(NL80211_STA_FLAG_AUTHENTICATED) |
6614 BIT(NL80211_STA_FLAG_ASSOCIATED) |
6615 BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) |
6616 BIT(NL80211_STA_FLAG_WME) |
6617 BIT(NL80211_STA_FLAG_MFP)))
6618 return -EINVAL;
6619
6620 /* but authenticated/associated only if driver handles it */
6621 if (!(wiphy->features & NL80211_FEATURE_FULL_AP_CLIENT_STATE) &&
6622 params->sta_flags_mask &
6623 (BIT(NL80211_STA_FLAG_AUTHENTICATED) |
6624 BIT(NL80211_STA_FLAG_ASSOCIATED)))
6625 return -EINVAL;
6626 break;
6627 case CFG80211_STA_IBSS:
6628 case CFG80211_STA_AP_STA:
6629 /* reject any changes other than AUTHORIZED */
6630 if (params->sta_flags_mask & ~BIT(NL80211_STA_FLAG_AUTHORIZED))
6631 return -EINVAL;
6632 break;
6633 case CFG80211_STA_TDLS_PEER_SETUP:
6634 /* reject any changes other than AUTHORIZED or WME */
6635 if (params->sta_flags_mask & ~(BIT(NL80211_STA_FLAG_AUTHORIZED) |
6636 BIT(NL80211_STA_FLAG_WME)))
6637 return -EINVAL;
6638 /* force (at least) rates when authorizing */
6639 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED) &&
b95eb7f0 6640 !params->link_sta_params.supported_rates)
77ee7c89
JB
6641 return -EINVAL;
6642 break;
6643 case CFG80211_STA_TDLS_PEER_ACTIVE:
6644 /* reject any changes */
6645 return -EINVAL;
eef941e6 6646 case CFG80211_STA_MESH_PEER_KERNEL:
77ee7c89
JB
6647 if (params->sta_modify_mask & STATION_PARAM_APPLY_PLINK_STATE)
6648 return -EINVAL;
6649 break;
eef941e6 6650 case CFG80211_STA_MESH_PEER_USER:
42925040
CYY
6651 if (params->plink_action != NL80211_PLINK_ACTION_NO_ACTION &&
6652 params->plink_action != NL80211_PLINK_ACTION_BLOCK)
77ee7c89
JB
6653 return -EINVAL;
6654 break;
6655 }
6656
06f7c88c
BL
6657 /*
6658 * Older kernel versions ignored this attribute entirely, so don't
6659 * reject attempts to update it but mark it as unused instead so the
6660 * driver won't look at the data.
6661 */
6662 if (statype != CFG80211_STA_AP_CLIENT_UNASSOC &&
6663 statype != CFG80211_STA_TDLS_PEER_SETUP)
b95eb7f0 6664 params->link_sta_params.opmode_notif_used = false;
06f7c88c 6665
77ee7c89
JB
6666 return 0;
6667}
6668EXPORT_SYMBOL(cfg80211_check_station_change);
6669
5727ef1b 6670/*
c258d2de 6671 * Get vlan interface making sure it is running and on the right wiphy.
5727ef1b 6672 */
80b99899
JB
6673static struct net_device *get_vlan(struct genl_info *info,
6674 struct cfg80211_registered_device *rdev)
5727ef1b 6675{
463d0183 6676 struct nlattr *vlanattr = info->attrs[NL80211_ATTR_STA_VLAN];
80b99899
JB
6677 struct net_device *v;
6678 int ret;
6679
6680 if (!vlanattr)
6681 return NULL;
6682
6683 v = dev_get_by_index(genl_info_net(info), nla_get_u32(vlanattr));
6684 if (!v)
6685 return ERR_PTR(-ENODEV);
6686
6687 if (!v->ieee80211_ptr || v->ieee80211_ptr->wiphy != &rdev->wiphy) {
6688 ret = -EINVAL;
6689 goto error;
5727ef1b 6690 }
80b99899 6691
77ee7c89
JB
6692 if (v->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
6693 v->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
6694 v->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
6695 ret = -EINVAL;
6696 goto error;
6697 }
6698
80b99899
JB
6699 if (!netif_running(v)) {
6700 ret = -ENETDOWN;
6701 goto error;
6702 }
6703
6704 return v;
6705 error:
6706 dev_put(v);
6707 return ERR_PTR(ret);
5727ef1b
JB
6708}
6709
94e860f1
JB
6710static const struct nla_policy
6711nl80211_sta_wme_policy[NL80211_STA_WME_MAX + 1] = {
df881293
JM
6712 [NL80211_STA_WME_UAPSD_QUEUES] = { .type = NLA_U8 },
6713 [NL80211_STA_WME_MAX_SP] = { .type = NLA_U8 },
6714};
6715
ff276691
JB
6716static int nl80211_parse_sta_wme(struct genl_info *info,
6717 struct station_parameters *params)
df881293 6718{
df881293
JM
6719 struct nlattr *tb[NL80211_STA_WME_MAX + 1];
6720 struct nlattr *nla;
6721 int err;
6722
df881293
JM
6723 /* parse WME attributes if present */
6724 if (!info->attrs[NL80211_ATTR_STA_WME])
6725 return 0;
6726
6727 nla = info->attrs[NL80211_ATTR_STA_WME];
8cb08174
JB
6728 err = nla_parse_nested_deprecated(tb, NL80211_STA_WME_MAX, nla,
6729 nl80211_sta_wme_policy,
6730 info->extack);
df881293
JM
6731 if (err)
6732 return err;
6733
6734 if (tb[NL80211_STA_WME_UAPSD_QUEUES])
6735 params->uapsd_queues = nla_get_u8(
6736 tb[NL80211_STA_WME_UAPSD_QUEUES]);
6737 if (params->uapsd_queues & ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK)
6738 return -EINVAL;
6739
6740 if (tb[NL80211_STA_WME_MAX_SP])
6741 params->max_sp = nla_get_u8(tb[NL80211_STA_WME_MAX_SP]);
6742
6743 if (params->max_sp & ~IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK)
6744 return -EINVAL;
6745
6746 params->sta_modify_mask |= STATION_PARAM_APPLY_UAPSD;
6747
6748 return 0;
6749}
6750
c01fc9ad
SD
6751static int nl80211_parse_sta_channel_info(struct genl_info *info,
6752 struct station_parameters *params)
6753{
6754 if (info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]) {
6755 params->supported_channels =
6756 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]);
6757 params->supported_channels_len =
6758 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]);
6759 /*
6760 * Need to include at least one (first channel, number of
cb9abd48
JB
6761 * channels) tuple for each subband (checked in policy),
6762 * and must have proper tuples for the rest of the data as well.
c01fc9ad 6763 */
c01fc9ad
SD
6764 if (params->supported_channels_len % 2)
6765 return -EINVAL;
6766 }
6767
6768 if (info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]) {
6769 params->supported_oper_classes =
6770 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]);
6771 params->supported_oper_classes_len =
6772 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]);
c01fc9ad
SD
6773 }
6774 return 0;
6775}
6776
ff276691
JB
6777static int nl80211_set_station_tdls(struct genl_info *info,
6778 struct station_parameters *params)
6779{
c01fc9ad 6780 int err;
ff276691 6781 /* Dummy STA entry gets updated once the peer capabilities are known */
5e4b6f56
JM
6782 if (info->attrs[NL80211_ATTR_PEER_AID])
6783 params->aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]);
ff276691 6784 if (info->attrs[NL80211_ATTR_HT_CAPABILITY])
b95eb7f0 6785 params->link_sta_params.ht_capa =
ff276691
JB
6786 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
6787 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY])
b95eb7f0 6788 params->link_sta_params.vht_capa =
ff276691 6789 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);
c4cbaf79 6790 if (info->attrs[NL80211_ATTR_HE_CAPABILITY]) {
b95eb7f0 6791 params->link_sta_params.he_capa =
c4cbaf79 6792 nla_data(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
b95eb7f0 6793 params->link_sta_params.he_capa_len =
c4cbaf79 6794 nla_len(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
ea05fd35
IP
6795
6796 if (info->attrs[NL80211_ATTR_EHT_CAPABILITY]) {
b95eb7f0 6797 params->link_sta_params.eht_capa =
ea05fd35 6798 nla_data(info->attrs[NL80211_ATTR_EHT_CAPABILITY]);
b95eb7f0 6799 params->link_sta_params.eht_capa_len =
ea05fd35
IP
6800 nla_len(info->attrs[NL80211_ATTR_EHT_CAPABILITY]);
6801
b95eb7f0
ST
6802 if (!ieee80211_eht_capa_size_ok((const u8 *)params->link_sta_params.he_capa,
6803 (const u8 *)params->link_sta_params.eht_capa,
6804 params->link_sta_params.eht_capa_len))
ea05fd35
IP
6805 return -EINVAL;
6806 }
c4cbaf79 6807 }
ff276691 6808
c01fc9ad
SD
6809 err = nl80211_parse_sta_channel_info(info, params);
6810 if (err)
6811 return err;
6812
ff276691
JB
6813 return nl80211_parse_sta_wme(info, params);
6814}
6815
e96d1cd2 6816static int nl80211_parse_sta_txpower_setting(struct genl_info *info,
577e5b8c
ST
6817 struct sta_txpwr *txpwr,
6818 bool *txpwr_set)
e96d1cd2
ARN
6819{
6820 struct cfg80211_registered_device *rdev = info->user_ptr[0];
6821 int idx;
6822
6823 if (info->attrs[NL80211_ATTR_STA_TX_POWER_SETTING]) {
6824 if (!rdev->ops->set_tx_power ||
6825 !wiphy_ext_feature_isset(&rdev->wiphy,
6826 NL80211_EXT_FEATURE_STA_TX_PWR))
6827 return -EOPNOTSUPP;
6828
6829 idx = NL80211_ATTR_STA_TX_POWER_SETTING;
577e5b8c 6830 txpwr->type = nla_get_u8(info->attrs[idx]);
e96d1cd2 6831
577e5b8c 6832 if (txpwr->type == NL80211_TX_POWER_LIMITED) {
e96d1cd2
ARN
6833 idx = NL80211_ATTR_STA_TX_POWER;
6834
6835 if (info->attrs[idx])
577e5b8c 6836 txpwr->power = nla_get_s16(info->attrs[idx]);
e96d1cd2
ARN
6837 else
6838 return -EINVAL;
6839 }
577e5b8c
ST
6840
6841 *txpwr_set = true;
6842 } else {
6843 *txpwr_set = false;
e96d1cd2
ARN
6844 }
6845
6846 return 0;
6847}
6848
5727ef1b
JB
6849static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
6850{
4c476991 6851 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4c476991 6852 struct net_device *dev = info->user_ptr[1];
5727ef1b 6853 struct station_parameters params;
77ee7c89
JB
6854 u8 *mac_addr;
6855 int err;
5727ef1b
JB
6856
6857 memset(&params, 0, sizeof(params));
6858
77ee7c89
JB
6859 if (!rdev->ops->change_station)
6860 return -EOPNOTSUPP;
6861
e4208427
AB
6862 /*
6863 * AID and listen_interval properties can be set only for unassociated
6864 * station. Include these parameters here and will check them in
6865 * cfg80211_check_station_change().
6866 */
a9bc31e4
AB
6867 if (info->attrs[NL80211_ATTR_STA_AID])
6868 params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
e4208427 6869
14f34e36
GG
6870 if (info->attrs[NL80211_ATTR_VLAN_ID])
6871 params.vlan_id = nla_get_u16(info->attrs[NL80211_ATTR_VLAN_ID]);
6872
e4208427
AB
6873 if (info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
6874 params.listen_interval =
6875 nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
6876 else
6877 params.listen_interval = -1;
5727ef1b 6878
ab0d76f6
JB
6879 if (info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS])
6880 params.support_p2p_ps =
6881 nla_get_u8(info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]);
6882 else
17b94247 6883 params.support_p2p_ps = -1;
17b94247 6884
5727ef1b
JB
6885 if (!info->attrs[NL80211_ATTR_MAC])
6886 return -EINVAL;
6887
6888 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
6889
6890 if (info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]) {
b95eb7f0 6891 params.link_sta_params.supported_rates =
5727ef1b 6892 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
b95eb7f0 6893 params.link_sta_params.supported_rates_len =
5727ef1b
JB
6894 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
6895 }
6896
9d62a986
JM
6897 if (info->attrs[NL80211_ATTR_STA_CAPABILITY]) {
6898 params.capability =
6899 nla_get_u16(info->attrs[NL80211_ATTR_STA_CAPABILITY]);
6900 params.sta_modify_mask |= STATION_PARAM_APPLY_CAPABILITY;
6901 }
6902
6903 if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]) {
6904 params.ext_capab =
6905 nla_data(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]);
6906 params.ext_capab_len =
6907 nla_len(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]);
6908 }
6909
bdd3ae3d 6910 if (parse_station_flags(info, dev->ieee80211_ptr->iftype, &params))
5727ef1b
JB
6911 return -EINVAL;
6912
ab0d76f6 6913 if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION])
2ec600d6 6914 params.plink_action =
f8bacc21 6915 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
2ec600d6 6916
f8bacc21 6917 if (info->attrs[NL80211_ATTR_STA_PLINK_STATE]) {
9c3990aa 6918 params.plink_state =
f8bacc21 6919 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_STATE]);
ab0d76f6 6920 if (info->attrs[NL80211_ATTR_MESH_PEER_AID])
7d27a0ba
MH
6921 params.peer_aid = nla_get_u16(
6922 info->attrs[NL80211_ATTR_MESH_PEER_AID]);
f8bacc21
JB
6923 params.sta_modify_mask |= STATION_PARAM_APPLY_PLINK_STATE;
6924 }
9c3990aa 6925
ab0d76f6
JB
6926 if (info->attrs[NL80211_ATTR_LOCAL_MESH_POWER_MODE])
6927 params.local_pm = nla_get_u32(
3b1c5a53
MP
6928 info->attrs[NL80211_ATTR_LOCAL_MESH_POWER_MODE]);
6929
06f7c88c 6930 if (info->attrs[NL80211_ATTR_OPMODE_NOTIF]) {
b95eb7f0
ST
6931 params.link_sta_params.opmode_notif_used = true;
6932 params.link_sta_params.opmode_notif =
06f7c88c
BL
6933 nla_get_u8(info->attrs[NL80211_ATTR_OPMODE_NOTIF]);
6934 }
6935
43e64bf3 6936 if (info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY])
b95eb7f0 6937 params.link_sta_params.he_6ghz_capa =
fce2ff72 6938 nla_data(info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY]);
43e64bf3 6939
36647055
THJ
6940 if (info->attrs[NL80211_ATTR_AIRTIME_WEIGHT])
6941 params.airtime_weight =
6942 nla_get_u16(info->attrs[NL80211_ATTR_AIRTIME_WEIGHT]);
6943
6944 if (params.airtime_weight &&
6945 !wiphy_ext_feature_isset(&rdev->wiphy,
6946 NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))
6947 return -EOPNOTSUPP;
6948
b95eb7f0
ST
6949 err = nl80211_parse_sta_txpower_setting(info,
6950 &params.link_sta_params.txpwr,
6951 &params.link_sta_params.txpwr_set);
e96d1cd2
ARN
6952 if (err)
6953 return err;
6954
77ee7c89
JB
6955 /* Include parameters for TDLS peer (will check later) */
6956 err = nl80211_set_station_tdls(info, &params);
6957 if (err)
6958 return err;
6959
6960 params.vlan = get_vlan(info, rdev);
6961 if (IS_ERR(params.vlan))
6962 return PTR_ERR(params.vlan);
6963
a97f4424
JB
6964 switch (dev->ieee80211_ptr->iftype) {
6965 case NL80211_IFTYPE_AP:
6966 case NL80211_IFTYPE_AP_VLAN:
074ac8df 6967 case NL80211_IFTYPE_P2P_GO:
074ac8df 6968 case NL80211_IFTYPE_P2P_CLIENT:
a97f4424 6969 case NL80211_IFTYPE_STATION:
267335d6 6970 case NL80211_IFTYPE_ADHOC:
a97f4424 6971 case NL80211_IFTYPE_MESH_POINT:
a97f4424
JB
6972 break;
6973 default:
77ee7c89
JB
6974 err = -EOPNOTSUPP;
6975 goto out_put_vlan;
034d655e
JB
6976 }
6977
77ee7c89 6978 /* driver will call cfg80211_check_station_change() */
3d1cc7cd 6979 wdev_lock(dev->ieee80211_ptr);
e35e4d28 6980 err = rdev_change_station(rdev, dev, mac_addr, &params);
3d1cc7cd 6981 wdev_unlock(dev->ieee80211_ptr);
5727ef1b 6982
77ee7c89 6983 out_put_vlan:
1160dfa1 6984 dev_put(params.vlan);
3b85875a 6985
5727ef1b
JB
6986 return err;
6987}
6988
6989static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
6990{
4c476991 6991 struct cfg80211_registered_device *rdev = info->user_ptr[0];
5727ef1b 6992 int err;
4c476991 6993 struct net_device *dev = info->user_ptr[1];
5727ef1b
JB
6994 struct station_parameters params;
6995 u8 *mac_addr = NULL;
bda95eb1
JB
6996 u32 auth_assoc = BIT(NL80211_STA_FLAG_AUTHENTICATED) |
6997 BIT(NL80211_STA_FLAG_ASSOCIATED);
5727ef1b
JB
6998
6999 memset(&params, 0, sizeof(params));
7000
984c311b
JB
7001 if (!rdev->ops->add_station)
7002 return -EOPNOTSUPP;
7003
5727ef1b
JB
7004 if (!info->attrs[NL80211_ATTR_MAC])
7005 return -EINVAL;
7006
5727ef1b
JB
7007 if (!info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
7008 return -EINVAL;
7009
7010 if (!info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES])
7011 return -EINVAL;
7012
5e4b6f56
JM
7013 if (!info->attrs[NL80211_ATTR_STA_AID] &&
7014 !info->attrs[NL80211_ATTR_PEER_AID])
0e956c13
TLSC
7015 return -EINVAL;
7016
b95eb7f0
ST
7017 params.link_sta_params.link_id =
7018 nl80211_link_id_or_invalid(info->attrs);
7019
c0d67012
ST
7020 if (info->attrs[NL80211_ATTR_MLD_ADDR]) {
7021 /* If MLD_ADDR attribute is set then this is an MLD station
7022 * and the MLD_ADDR attribute holds the MLD address and the
7023 * MAC attribute holds for the LINK address.
7024 * In that case, the link_id is also expected to be valid.
7025 */
7026 if (params.link_sta_params.link_id < 0)
7027 return -EINVAL;
7028
7029 mac_addr = nla_data(info->attrs[NL80211_ATTR_MLD_ADDR]);
7030 params.link_sta_params.mld_mac = mac_addr;
7031 params.link_sta_params.link_mac =
7032 nla_data(info->attrs[NL80211_ATTR_MAC]);
7033 if (!is_valid_ether_addr(params.link_sta_params.link_mac))
7034 return -EINVAL;
7035 } else {
7036 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
7037 }
7038
b95eb7f0 7039 params.link_sta_params.supported_rates =
5727ef1b 7040 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
b95eb7f0 7041 params.link_sta_params.supported_rates_len =
5727ef1b
JB
7042 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
7043 params.listen_interval =
7044 nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
51b50fbe 7045
14f34e36
GG
7046 if (info->attrs[NL80211_ATTR_VLAN_ID])
7047 params.vlan_id = nla_get_u16(info->attrs[NL80211_ATTR_VLAN_ID]);
7048
17b94247 7049 if (info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]) {
ab0d76f6
JB
7050 params.support_p2p_ps =
7051 nla_get_u8(info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]);
17b94247
AB
7052 } else {
7053 /*
7054 * if not specified, assume it's supported for P2P GO interface,
7055 * and is NOT supported for AP interface
7056 */
7057 params.support_p2p_ps =
7058 dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO;
7059 }
7060
3d124ea2 7061 if (info->attrs[NL80211_ATTR_PEER_AID])
5e4b6f56 7062 params.aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]);
3d124ea2
JM
7063 else
7064 params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
51b50fbe 7065
9d62a986
JM
7066 if (info->attrs[NL80211_ATTR_STA_CAPABILITY]) {
7067 params.capability =
7068 nla_get_u16(info->attrs[NL80211_ATTR_STA_CAPABILITY]);
7069 params.sta_modify_mask |= STATION_PARAM_APPLY_CAPABILITY;
7070 }
7071
7072 if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]) {
7073 params.ext_capab =
7074 nla_data(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]);
7075 params.ext_capab_len =
7076 nla_len(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]);
7077 }
7078
36aedc90 7079 if (info->attrs[NL80211_ATTR_HT_CAPABILITY])
b95eb7f0 7080 params.link_sta_params.ht_capa =
36aedc90 7081 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
5727ef1b 7082
f461be3e 7083 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY])
b95eb7f0 7084 params.link_sta_params.vht_capa =
f461be3e
MP
7085 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);
7086
c4cbaf79 7087 if (info->attrs[NL80211_ATTR_HE_CAPABILITY]) {
b95eb7f0 7088 params.link_sta_params.he_capa =
c4cbaf79 7089 nla_data(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
b95eb7f0 7090 params.link_sta_params.he_capa_len =
c4cbaf79 7091 nla_len(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
ea05fd35
IP
7092
7093 if (info->attrs[NL80211_ATTR_EHT_CAPABILITY]) {
b95eb7f0 7094 params.link_sta_params.eht_capa =
ea05fd35 7095 nla_data(info->attrs[NL80211_ATTR_EHT_CAPABILITY]);
b95eb7f0 7096 params.link_sta_params.eht_capa_len =
ea05fd35
IP
7097 nla_len(info->attrs[NL80211_ATTR_EHT_CAPABILITY]);
7098
b95eb7f0
ST
7099 if (!ieee80211_eht_capa_size_ok((const u8 *)params.link_sta_params.he_capa,
7100 (const u8 *)params.link_sta_params.eht_capa,
7101 params.link_sta_params.eht_capa_len))
ea05fd35
IP
7102 return -EINVAL;
7103 }
c4cbaf79
LC
7104 }
7105
43e64bf3 7106 if (info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY])
b95eb7f0 7107 params.link_sta_params.he_6ghz_capa =
43e64bf3
RM
7108 nla_data(info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY]);
7109
60f4a7b1 7110 if (info->attrs[NL80211_ATTR_OPMODE_NOTIF]) {
b95eb7f0
ST
7111 params.link_sta_params.opmode_notif_used = true;
7112 params.link_sta_params.opmode_notif =
60f4a7b1
MK
7113 nla_get_u8(info->attrs[NL80211_ATTR_OPMODE_NOTIF]);
7114 }
7115
ab0d76f6 7116 if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION])
96b78dff 7117 params.plink_action =
f8bacc21 7118 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
96b78dff 7119
36647055
THJ
7120 if (info->attrs[NL80211_ATTR_AIRTIME_WEIGHT])
7121 params.airtime_weight =
7122 nla_get_u16(info->attrs[NL80211_ATTR_AIRTIME_WEIGHT]);
7123
7124 if (params.airtime_weight &&
7125 !wiphy_ext_feature_isset(&rdev->wiphy,
7126 NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))
7127 return -EOPNOTSUPP;
7128
b95eb7f0
ST
7129 err = nl80211_parse_sta_txpower_setting(info,
7130 &params.link_sta_params.txpwr,
7131 &params.link_sta_params.txpwr_set);
e96d1cd2
ARN
7132 if (err)
7133 return err;
7134
c01fc9ad
SD
7135 err = nl80211_parse_sta_channel_info(info, &params);
7136 if (err)
7137 return err;
7138
ff276691
JB
7139 err = nl80211_parse_sta_wme(info, &params);
7140 if (err)
7141 return err;
bdd90d5e 7142
bdd3ae3d 7143 if (parse_station_flags(info, dev->ieee80211_ptr->iftype, &params))
5727ef1b
JB
7144 return -EINVAL;
7145
496fcc29
JB
7146 /* HT/VHT requires QoS, but if we don't have that just ignore HT/VHT
7147 * as userspace might just pass through the capabilities from the IEs
7148 * directly, rather than enforcing this restriction and returning an
7149 * error in this case.
7150 */
7151 if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_WME))) {
b95eb7f0
ST
7152 params.link_sta_params.ht_capa = NULL;
7153 params.link_sta_params.vht_capa = NULL;
c4cbaf79 7154
ea05fd35 7155 /* HE and EHT require WME */
b95eb7f0
ST
7156 if (params.link_sta_params.he_capa_len ||
7157 params.link_sta_params.he_6ghz_capa ||
7158 params.link_sta_params.eht_capa_len)
c4cbaf79 7159 return -EINVAL;
496fcc29
JB
7160 }
7161
43e64bf3 7162 /* Ensure that HT/VHT capabilities are not set for 6 GHz HE STA */
b95eb7f0
ST
7163 if (params.link_sta_params.he_6ghz_capa &&
7164 (params.link_sta_params.ht_capa || params.link_sta_params.vht_capa))
43e64bf3
RM
7165 return -EINVAL;
7166
77ee7c89
JB
7167 /* When you run into this, adjust the code below for the new flag */
7168 BUILD_BUG_ON(NL80211_STA_FLAG_MAX != 7);
7169
bdd90d5e
JB
7170 switch (dev->ieee80211_ptr->iftype) {
7171 case NL80211_IFTYPE_AP:
7172 case NL80211_IFTYPE_AP_VLAN:
7173 case NL80211_IFTYPE_P2P_GO:
984c311b
JB
7174 /* ignore WME attributes if iface/sta is not capable */
7175 if (!(rdev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) ||
7176 !(params.sta_flags_set & BIT(NL80211_STA_FLAG_WME)))
7177 params.sta_modify_mask &= ~STATION_PARAM_APPLY_UAPSD;
c75786c9 7178
bdd90d5e 7179 /* TDLS peers cannot be added */
3d124ea2
JM
7180 if ((params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) ||
7181 info->attrs[NL80211_ATTR_PEER_AID])
4319e193 7182 return -EINVAL;
bdd90d5e
JB
7183 /* but don't bother the driver with it */
7184 params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
3b9ce80c 7185
d582cffb
JB
7186 /* allow authenticated/associated only if driver handles it */
7187 if (!(rdev->wiphy.features &
7188 NL80211_FEATURE_FULL_AP_CLIENT_STATE) &&
bda95eb1 7189 params.sta_flags_mask & auth_assoc)
d582cffb
JB
7190 return -EINVAL;
7191
bda95eb1
JB
7192 /* Older userspace, or userspace wanting to be compatible with
7193 * !NL80211_FEATURE_FULL_AP_CLIENT_STATE, will not set the auth
7194 * and assoc flags in the mask, but assumes the station will be
7195 * added as associated anyway since this was the required driver
7196 * behaviour before NL80211_FEATURE_FULL_AP_CLIENT_STATE was
7197 * introduced.
7198 * In order to not bother drivers with this quirk in the API
7199 * set the flags in both the mask and set for new stations in
7200 * this case.
7201 */
7202 if (!(params.sta_flags_mask & auth_assoc)) {
7203 params.sta_flags_mask |= auth_assoc;
7204 params.sta_flags_set |= auth_assoc;
7205 }
7206
bdd90d5e
JB
7207 /* must be last in here for error handling */
7208 params.vlan = get_vlan(info, rdev);
7209 if (IS_ERR(params.vlan))
7210 return PTR_ERR(params.vlan);
7211 break;
7212 case NL80211_IFTYPE_MESH_POINT:
984c311b
JB
7213 /* ignore uAPSD data */
7214 params.sta_modify_mask &= ~STATION_PARAM_APPLY_UAPSD;
7215
d582cffb
JB
7216 /* associated is disallowed */
7217 if (params.sta_flags_mask & BIT(NL80211_STA_FLAG_ASSOCIATED))
7218 return -EINVAL;
bdd90d5e 7219 /* TDLS peers cannot be added */
3d124ea2
JM
7220 if ((params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) ||
7221 info->attrs[NL80211_ATTR_PEER_AID])
bdd90d5e
JB
7222 return -EINVAL;
7223 break;
7224 case NL80211_IFTYPE_STATION:
93d08f0b 7225 case NL80211_IFTYPE_P2P_CLIENT:
984c311b
JB
7226 /* ignore uAPSD data */
7227 params.sta_modify_mask &= ~STATION_PARAM_APPLY_UAPSD;
7228
77ee7c89
JB
7229 /* these are disallowed */
7230 if (params.sta_flags_mask &
7231 (BIT(NL80211_STA_FLAG_ASSOCIATED) |
7232 BIT(NL80211_STA_FLAG_AUTHENTICATED)))
d582cffb 7233 return -EINVAL;
bdd90d5e
JB
7234 /* Only TDLS peers can be added */
7235 if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))
7236 return -EINVAL;
7237 /* Can only add if TDLS ... */
7238 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS))
7239 return -EOPNOTSUPP;
7240 /* ... with external setup is supported */
7241 if (!(rdev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP))
7242 return -EOPNOTSUPP;
77ee7c89
JB
7243 /*
7244 * Older wpa_supplicant versions always mark the TDLS peer
7245 * as authorized, but it shouldn't yet be.
7246 */
7247 params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_AUTHORIZED);
bdd90d5e
JB
7248 break;
7249 default:
7250 return -EOPNOTSUPP;
c75786c9
EP
7251 }
7252
bdd90d5e 7253 /* be aware of params.vlan when changing code here */
5727ef1b 7254
3d1cc7cd 7255 wdev_lock(dev->ieee80211_ptr);
e35e4d28 7256 err = rdev_add_station(rdev, dev, mac_addr, &params);
3d1cc7cd 7257 wdev_unlock(dev->ieee80211_ptr);
5727ef1b 7258
1160dfa1 7259 dev_put(params.vlan);
5727ef1b
JB
7260 return err;
7261}
7262
7263static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info)
7264{
4c476991
JB
7265 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7266 struct net_device *dev = info->user_ptr[1];
89c771e5 7267 struct station_del_parameters params;
3d1cc7cd 7268 int ret;
89c771e5
JM
7269
7270 memset(&params, 0, sizeof(params));
5727ef1b
JB
7271
7272 if (info->attrs[NL80211_ATTR_MAC])
89c771e5 7273 params.mac = nla_data(info->attrs[NL80211_ATTR_MAC]);
5727ef1b 7274
306b79ea
JB
7275 switch (dev->ieee80211_ptr->iftype) {
7276 case NL80211_IFTYPE_AP:
7277 case NL80211_IFTYPE_AP_VLAN:
7278 case NL80211_IFTYPE_MESH_POINT:
7279 case NL80211_IFTYPE_P2P_GO:
7280 /* always accept these */
7281 break;
7282 case NL80211_IFTYPE_ADHOC:
7283 /* conditionally accept */
7284 if (wiphy_ext_feature_isset(&rdev->wiphy,
7285 NL80211_EXT_FEATURE_DEL_IBSS_STA))
7286 break;
edafcf42 7287 return -EINVAL;
306b79ea 7288 default:
4c476991 7289 return -EINVAL;
306b79ea 7290 }
5727ef1b 7291
4c476991
JB
7292 if (!rdev->ops->del_station)
7293 return -EOPNOTSUPP;
3b85875a 7294
98856866
JM
7295 if (info->attrs[NL80211_ATTR_MGMT_SUBTYPE]) {
7296 params.subtype =
7297 nla_get_u8(info->attrs[NL80211_ATTR_MGMT_SUBTYPE]);
7298 if (params.subtype != IEEE80211_STYPE_DISASSOC >> 4 &&
7299 params.subtype != IEEE80211_STYPE_DEAUTH >> 4)
7300 return -EINVAL;
7301 } else {
7302 /* Default to Deauthentication frame */
7303 params.subtype = IEEE80211_STYPE_DEAUTH >> 4;
7304 }
7305
7306 if (info->attrs[NL80211_ATTR_REASON_CODE]) {
7307 params.reason_code =
7308 nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
7309 if (params.reason_code == 0)
7310 return -EINVAL; /* 0 is reserved */
7311 } else {
7312 /* Default to reason code 2 */
7313 params.reason_code = WLAN_REASON_PREV_AUTH_NOT_VALID;
7314 }
7315
3d1cc7cd
JB
7316 wdev_lock(dev->ieee80211_ptr);
7317 ret = rdev_del_station(rdev, dev, &params);
7318 wdev_unlock(dev->ieee80211_ptr);
7319
7320 return ret;
5727ef1b
JB
7321}
7322
15e47304 7323static int nl80211_send_mpath(struct sk_buff *msg, u32 portid, u32 seq,
2ec600d6
LCC
7324 int flags, struct net_device *dev,
7325 u8 *dst, u8 *next_hop,
7326 struct mpath_info *pinfo)
7327{
7328 void *hdr;
7329 struct nlattr *pinfoattr;
7330
1ef4c850 7331 hdr = nl80211hdr_put(msg, portid, seq, flags, NL80211_CMD_NEW_MPATH);
2ec600d6
LCC
7332 if (!hdr)
7333 return -1;
7334
9360ffd1
DM
7335 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
7336 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, dst) ||
7337 nla_put(msg, NL80211_ATTR_MPATH_NEXT_HOP, ETH_ALEN, next_hop) ||
7338 nla_put_u32(msg, NL80211_ATTR_GENERATION, pinfo->generation))
7339 goto nla_put_failure;
f5ea9120 7340
ae0be8de 7341 pinfoattr = nla_nest_start_noflag(msg, NL80211_ATTR_MPATH_INFO);
2ec600d6
LCC
7342 if (!pinfoattr)
7343 goto nla_put_failure;
9360ffd1
DM
7344 if ((pinfo->filled & MPATH_INFO_FRAME_QLEN) &&
7345 nla_put_u32(msg, NL80211_MPATH_INFO_FRAME_QLEN,
7346 pinfo->frame_qlen))
7347 goto nla_put_failure;
7348 if (((pinfo->filled & MPATH_INFO_SN) &&
7349 nla_put_u32(msg, NL80211_MPATH_INFO_SN, pinfo->sn)) ||
7350 ((pinfo->filled & MPATH_INFO_METRIC) &&
7351 nla_put_u32(msg, NL80211_MPATH_INFO_METRIC,
7352 pinfo->metric)) ||
7353 ((pinfo->filled & MPATH_INFO_EXPTIME) &&
7354 nla_put_u32(msg, NL80211_MPATH_INFO_EXPTIME,
7355 pinfo->exptime)) ||
7356 ((pinfo->filled & MPATH_INFO_FLAGS) &&
7357 nla_put_u8(msg, NL80211_MPATH_INFO_FLAGS,
7358 pinfo->flags)) ||
7359 ((pinfo->filled & MPATH_INFO_DISCOVERY_TIMEOUT) &&
7360 nla_put_u32(msg, NL80211_MPATH_INFO_DISCOVERY_TIMEOUT,
7361 pinfo->discovery_timeout)) ||
7362 ((pinfo->filled & MPATH_INFO_DISCOVERY_RETRIES) &&
7363 nla_put_u8(msg, NL80211_MPATH_INFO_DISCOVERY_RETRIES,
cc241636
JH
7364 pinfo->discovery_retries)) ||
7365 ((pinfo->filled & MPATH_INFO_HOP_COUNT) &&
7366 nla_put_u8(msg, NL80211_MPATH_INFO_HOP_COUNT,
540bbcb9
JH
7367 pinfo->hop_count)) ||
7368 ((pinfo->filled & MPATH_INFO_PATH_CHANGE) &&
7369 nla_put_u32(msg, NL80211_MPATH_INFO_PATH_CHANGE,
7370 pinfo->path_change_count)))
9360ffd1 7371 goto nla_put_failure;
2ec600d6
LCC
7372
7373 nla_nest_end(msg, pinfoattr);
7374
053c095a
JB
7375 genlmsg_end(msg, hdr);
7376 return 0;
2ec600d6
LCC
7377
7378 nla_put_failure:
bc3ed28c
TG
7379 genlmsg_cancel(msg, hdr);
7380 return -EMSGSIZE;
2ec600d6
LCC
7381}
7382
7383static int nl80211_dump_mpath(struct sk_buff *skb,
bba95fef 7384 struct netlink_callback *cb)
2ec600d6 7385{
2ec600d6 7386 struct mpath_info pinfo;
1b8ec87a 7387 struct cfg80211_registered_device *rdev;
97990a06 7388 struct wireless_dev *wdev;
2ec600d6
LCC
7389 u8 dst[ETH_ALEN];
7390 u8 next_hop[ETH_ALEN];
97990a06 7391 int path_idx = cb->args[2];
2ec600d6 7392 int err;
2ec600d6 7393
ce6b6974 7394 err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev, NULL);
67748893 7395 if (err)
a05829a7
JB
7396 return err;
7397 /* nl80211_prepare_wdev_dump acquired it in the successful case */
7398 __acquire(&rdev->wiphy.mtx);
bba95fef 7399
1b8ec87a 7400 if (!rdev->ops->dump_mpath) {
eec60b03 7401 err = -EOPNOTSUPP;
bba95fef
JB
7402 goto out_err;
7403 }
7404
97990a06 7405 if (wdev->iftype != NL80211_IFTYPE_MESH_POINT) {
eec60b03 7406 err = -EOPNOTSUPP;
0448b5fc 7407 goto out_err;
eec60b03
JM
7408 }
7409
bba95fef 7410 while (1) {
1b8ec87a 7411 err = rdev_dump_mpath(rdev, wdev->netdev, path_idx, dst,
97990a06 7412 next_hop, &pinfo);
bba95fef 7413 if (err == -ENOENT)
2ec600d6 7414 break;
bba95fef 7415 if (err)
3b85875a 7416 goto out_err;
2ec600d6 7417
15e47304 7418 if (nl80211_send_mpath(skb, NETLINK_CB(cb->skb).portid,
bba95fef 7419 cb->nlh->nlmsg_seq, NLM_F_MULTI,
97990a06 7420 wdev->netdev, dst, next_hop,
bba95fef
JB
7421 &pinfo) < 0)
7422 goto out;
2ec600d6 7423
bba95fef 7424 path_idx++;
2ec600d6 7425 }
2ec600d6 7426
bba95fef 7427 out:
97990a06 7428 cb->args[2] = path_idx;
bba95fef 7429 err = skb->len;
bba95fef 7430 out_err:
a05829a7 7431 wiphy_unlock(&rdev->wiphy);
bba95fef 7432 return err;
2ec600d6
LCC
7433}
7434
7435static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info)
7436{
4c476991 7437 struct cfg80211_registered_device *rdev = info->user_ptr[0];
2ec600d6 7438 int err;
4c476991 7439 struct net_device *dev = info->user_ptr[1];
2ec600d6
LCC
7440 struct mpath_info pinfo;
7441 struct sk_buff *msg;
7442 u8 *dst = NULL;
7443 u8 next_hop[ETH_ALEN];
7444
7445 memset(&pinfo, 0, sizeof(pinfo));
7446
7447 if (!info->attrs[NL80211_ATTR_MAC])
7448 return -EINVAL;
7449
7450 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
7451
4c476991
JB
7452 if (!rdev->ops->get_mpath)
7453 return -EOPNOTSUPP;
2ec600d6 7454
4c476991
JB
7455 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
7456 return -EOPNOTSUPP;
eec60b03 7457
e35e4d28 7458 err = rdev_get_mpath(rdev, dev, dst, next_hop, &pinfo);
2ec600d6 7459 if (err)
4c476991 7460 return err;
2ec600d6 7461
fd2120ca 7462 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2ec600d6 7463 if (!msg)
4c476991 7464 return -ENOMEM;
2ec600d6 7465
15e47304 7466 if (nl80211_send_mpath(msg, info->snd_portid, info->snd_seq, 0,
4c476991
JB
7467 dev, dst, next_hop, &pinfo) < 0) {
7468 nlmsg_free(msg);
7469 return -ENOBUFS;
7470 }
3b85875a 7471
4c476991 7472 return genlmsg_reply(msg, info);
2ec600d6
LCC
7473}
7474
7475static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info)
7476{
4c476991
JB
7477 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7478 struct net_device *dev = info->user_ptr[1];
2ec600d6
LCC
7479 u8 *dst = NULL;
7480 u8 *next_hop = NULL;
7481
7482 if (!info->attrs[NL80211_ATTR_MAC])
7483 return -EINVAL;
7484
7485 if (!info->attrs[NL80211_ATTR_MPATH_NEXT_HOP])
7486 return -EINVAL;
7487
7488 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
7489 next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);
7490
4c476991
JB
7491 if (!rdev->ops->change_mpath)
7492 return -EOPNOTSUPP;
35a8efe1 7493
4c476991
JB
7494 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
7495 return -EOPNOTSUPP;
2ec600d6 7496
e35e4d28 7497 return rdev_change_mpath(rdev, dev, dst, next_hop);
2ec600d6 7498}
4c476991 7499
2ec600d6
LCC
7500static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info)
7501{
4c476991
JB
7502 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7503 struct net_device *dev = info->user_ptr[1];
2ec600d6
LCC
7504 u8 *dst = NULL;
7505 u8 *next_hop = NULL;
7506
7507 if (!info->attrs[NL80211_ATTR_MAC])
7508 return -EINVAL;
7509
7510 if (!info->attrs[NL80211_ATTR_MPATH_NEXT_HOP])
7511 return -EINVAL;
7512
7513 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
7514 next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);
7515
4c476991
JB
7516 if (!rdev->ops->add_mpath)
7517 return -EOPNOTSUPP;
35a8efe1 7518
4c476991
JB
7519 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
7520 return -EOPNOTSUPP;
2ec600d6 7521
e35e4d28 7522 return rdev_add_mpath(rdev, dev, dst, next_hop);
2ec600d6
LCC
7523}
7524
7525static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info)
7526{
4c476991
JB
7527 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7528 struct net_device *dev = info->user_ptr[1];
2ec600d6
LCC
7529 u8 *dst = NULL;
7530
7531 if (info->attrs[NL80211_ATTR_MAC])
7532 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
7533
4c476991
JB
7534 if (!rdev->ops->del_mpath)
7535 return -EOPNOTSUPP;
3b85875a 7536
b501426c
MP
7537 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
7538 return -EOPNOTSUPP;
7539
e35e4d28 7540 return rdev_del_mpath(rdev, dev, dst);
2ec600d6
LCC
7541}
7542
66be7d2b
HR
7543static int nl80211_get_mpp(struct sk_buff *skb, struct genl_info *info)
7544{
7545 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7546 int err;
7547 struct net_device *dev = info->user_ptr[1];
7548 struct mpath_info pinfo;
7549 struct sk_buff *msg;
7550 u8 *dst = NULL;
7551 u8 mpp[ETH_ALEN];
7552
7553 memset(&pinfo, 0, sizeof(pinfo));
7554
7555 if (!info->attrs[NL80211_ATTR_MAC])
7556 return -EINVAL;
7557
7558 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
7559
7560 if (!rdev->ops->get_mpp)
7561 return -EOPNOTSUPP;
7562
7563 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
7564 return -EOPNOTSUPP;
7565
7566 err = rdev_get_mpp(rdev, dev, dst, mpp, &pinfo);
7567 if (err)
7568 return err;
7569
7570 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
7571 if (!msg)
7572 return -ENOMEM;
7573
7574 if (nl80211_send_mpath(msg, info->snd_portid, info->snd_seq, 0,
7575 dev, dst, mpp, &pinfo) < 0) {
7576 nlmsg_free(msg);
7577 return -ENOBUFS;
7578 }
7579
7580 return genlmsg_reply(msg, info);
7581}
7582
7583static int nl80211_dump_mpp(struct sk_buff *skb,
7584 struct netlink_callback *cb)
7585{
7586 struct mpath_info pinfo;
7587 struct cfg80211_registered_device *rdev;
7588 struct wireless_dev *wdev;
7589 u8 dst[ETH_ALEN];
7590 u8 mpp[ETH_ALEN];
7591 int path_idx = cb->args[2];
7592 int err;
7593
ce6b6974 7594 err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev, NULL);
66be7d2b 7595 if (err)
a05829a7
JB
7596 return err;
7597 /* nl80211_prepare_wdev_dump acquired it in the successful case */
7598 __acquire(&rdev->wiphy.mtx);
66be7d2b
HR
7599
7600 if (!rdev->ops->dump_mpp) {
7601 err = -EOPNOTSUPP;
7602 goto out_err;
7603 }
7604
7605 if (wdev->iftype != NL80211_IFTYPE_MESH_POINT) {
7606 err = -EOPNOTSUPP;
7607 goto out_err;
7608 }
7609
7610 while (1) {
7611 err = rdev_dump_mpp(rdev, wdev->netdev, path_idx, dst,
7612 mpp, &pinfo);
7613 if (err == -ENOENT)
7614 break;
7615 if (err)
7616 goto out_err;
7617
7618 if (nl80211_send_mpath(skb, NETLINK_CB(cb->skb).portid,
7619 cb->nlh->nlmsg_seq, NLM_F_MULTI,
7620 wdev->netdev, dst, mpp,
7621 &pinfo) < 0)
7622 goto out;
7623
7624 path_idx++;
7625 }
7626
7627 out:
7628 cb->args[2] = path_idx;
7629 err = skb->len;
7630 out_err:
a05829a7 7631 wiphy_unlock(&rdev->wiphy);
66be7d2b
HR
7632 return err;
7633}
7634
9f1ba906
JM
7635static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
7636{
4c476991
JB
7637 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7638 struct net_device *dev = info->user_ptr[1];
c56589ed 7639 struct wireless_dev *wdev = dev->ieee80211_ptr;
9f1ba906 7640 struct bss_parameters params;
c56589ed 7641 int err;
9f1ba906
JM
7642
7643 memset(&params, 0, sizeof(params));
7644 /* default to not changing parameters */
7645 params.use_cts_prot = -1;
7646 params.use_short_preamble = -1;
7647 params.use_short_slot_time = -1;
fd8aaaf3 7648 params.ap_isolate = -1;
50b12f59 7649 params.ht_opmode = -1;
53cabad7
JB
7650 params.p2p_ctwindow = -1;
7651 params.p2p_opp_ps = -1;
9f1ba906
JM
7652
7653 if (info->attrs[NL80211_ATTR_BSS_CTS_PROT])
7654 params.use_cts_prot =
7655 nla_get_u8(info->attrs[NL80211_ATTR_BSS_CTS_PROT]);
7656 if (info->attrs[NL80211_ATTR_BSS_SHORT_PREAMBLE])
7657 params.use_short_preamble =
7658 nla_get_u8(info->attrs[NL80211_ATTR_BSS_SHORT_PREAMBLE]);
7659 if (info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME])
7660 params.use_short_slot_time =
7661 nla_get_u8(info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME]);
90c97a04
JM
7662 if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) {
7663 params.basic_rates =
7664 nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
7665 params.basic_rates_len =
7666 nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
7667 }
fd8aaaf3
FF
7668 if (info->attrs[NL80211_ATTR_AP_ISOLATE])
7669 params.ap_isolate = !!nla_get_u8(info->attrs[NL80211_ATTR_AP_ISOLATE]);
50b12f59
HS
7670 if (info->attrs[NL80211_ATTR_BSS_HT_OPMODE])
7671 params.ht_opmode =
7672 nla_get_u16(info->attrs[NL80211_ATTR_BSS_HT_OPMODE]);
9f1ba906 7673
53cabad7
JB
7674 if (info->attrs[NL80211_ATTR_P2P_CTWINDOW]) {
7675 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
7676 return -EINVAL;
7677 params.p2p_ctwindow =
ab0d76f6 7678 nla_get_u8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]);
53cabad7
JB
7679 if (params.p2p_ctwindow != 0 &&
7680 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN))
7681 return -EINVAL;
7682 }
7683
7684 if (info->attrs[NL80211_ATTR_P2P_OPPPS]) {
7685 u8 tmp;
7686
7687 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
7688 return -EINVAL;
7689 tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]);
53cabad7
JB
7690 params.p2p_opp_ps = tmp;
7691 if (params.p2p_opp_ps &&
7692 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS))
7693 return -EINVAL;
7694 }
7695
4c476991
JB
7696 if (!rdev->ops->change_bss)
7697 return -EOPNOTSUPP;
9f1ba906 7698
074ac8df 7699 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
4c476991
JB
7700 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
7701 return -EOPNOTSUPP;
3b85875a 7702
c56589ed
SW
7703 wdev_lock(wdev);
7704 err = rdev_change_bss(rdev, dev, &params);
7705 wdev_unlock(wdev);
7706
7707 return err;
9f1ba906
JM
7708}
7709
b2e1b302
LR
7710static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info)
7711{
b2e1b302 7712 char *data = NULL;
05050753 7713 bool is_indoor;
57b5ce07 7714 enum nl80211_user_reg_hint_type user_reg_hint_type;
05050753
I
7715 u32 owner_nlportid;
7716
80778f18
LR
7717 /*
7718 * You should only get this when cfg80211 hasn't yet initialized
7719 * completely when built-in to the kernel right between the time
7720 * window between nl80211_init() and regulatory_init(), if that is
7721 * even possible.
7722 */
458f4f9e 7723 if (unlikely(!rcu_access_pointer(cfg80211_regdomain)))
fe33eb39 7724 return -EINPROGRESS;
80778f18 7725
57b5ce07
LR
7726 if (info->attrs[NL80211_ATTR_USER_REG_HINT_TYPE])
7727 user_reg_hint_type =
7728 nla_get_u32(info->attrs[NL80211_ATTR_USER_REG_HINT_TYPE]);
7729 else
7730 user_reg_hint_type = NL80211_USER_REG_HINT_USER;
7731
7732 switch (user_reg_hint_type) {
7733 case NL80211_USER_REG_HINT_USER:
7734 case NL80211_USER_REG_HINT_CELL_BASE:
52616f2b
IP
7735 if (!info->attrs[NL80211_ATTR_REG_ALPHA2])
7736 return -EINVAL;
7737
7738 data = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]);
7739 return regulatory_hint_user(data, user_reg_hint_type);
7740 case NL80211_USER_REG_HINT_INDOOR:
05050753
I
7741 if (info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
7742 owner_nlportid = info->snd_portid;
7743 is_indoor = !!info->attrs[NL80211_ATTR_REG_INDOOR];
7744 } else {
7745 owner_nlportid = 0;
7746 is_indoor = true;
7747 }
7748
7749 return regulatory_hint_indoor(is_indoor, owner_nlportid);
57b5ce07
LR
7750 default:
7751 return -EINVAL;
7752 }
b2e1b302
LR
7753}
7754
1ea4ff3e
JB
7755static int nl80211_reload_regdb(struct sk_buff *skb, struct genl_info *info)
7756{
7757 return reg_reload_regdb();
7758}
7759
24bdd9f4 7760static int nl80211_get_mesh_config(struct sk_buff *skb,
29cbe68c 7761 struct genl_info *info)
93da9cc1 7762{
4c476991 7763 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4c476991 7764 struct net_device *dev = info->user_ptr[1];
29cbe68c
JB
7765 struct wireless_dev *wdev = dev->ieee80211_ptr;
7766 struct mesh_config cur_params;
7767 int err = 0;
93da9cc1 7768 void *hdr;
7769 struct nlattr *pinfoattr;
7770 struct sk_buff *msg;
7771
29cbe68c
JB
7772 if (wdev->iftype != NL80211_IFTYPE_MESH_POINT)
7773 return -EOPNOTSUPP;
7774
24bdd9f4 7775 if (!rdev->ops->get_mesh_config)
4c476991 7776 return -EOPNOTSUPP;
f3f92586 7777
29cbe68c
JB
7778 wdev_lock(wdev);
7779 /* If not connected, get default parameters */
7b0a0e3c 7780 if (!wdev->u.mesh.id_len)
29cbe68c
JB
7781 memcpy(&cur_params, &default_mesh_config, sizeof(cur_params));
7782 else
e35e4d28 7783 err = rdev_get_mesh_config(rdev, dev, &cur_params);
29cbe68c
JB
7784 wdev_unlock(wdev);
7785
93da9cc1 7786 if (err)
4c476991 7787 return err;
93da9cc1 7788
7789 /* Draw up a netlink message to send back */
fd2120ca 7790 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4c476991
JB
7791 if (!msg)
7792 return -ENOMEM;
15e47304 7793 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
24bdd9f4 7794 NL80211_CMD_GET_MESH_CONFIG);
93da9cc1 7795 if (!hdr)
efe1cf0c 7796 goto out;
ae0be8de 7797 pinfoattr = nla_nest_start_noflag(msg, NL80211_ATTR_MESH_CONFIG);
93da9cc1 7798 if (!pinfoattr)
7799 goto nla_put_failure;
9360ffd1
DM
7800 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
7801 nla_put_u16(msg, NL80211_MESHCONF_RETRY_TIMEOUT,
7802 cur_params.dot11MeshRetryTimeout) ||
7803 nla_put_u16(msg, NL80211_MESHCONF_CONFIRM_TIMEOUT,
7804 cur_params.dot11MeshConfirmTimeout) ||
7805 nla_put_u16(msg, NL80211_MESHCONF_HOLDING_TIMEOUT,
7806 cur_params.dot11MeshHoldingTimeout) ||
7807 nla_put_u16(msg, NL80211_MESHCONF_MAX_PEER_LINKS,
7808 cur_params.dot11MeshMaxPeerLinks) ||
7809 nla_put_u8(msg, NL80211_MESHCONF_MAX_RETRIES,
7810 cur_params.dot11MeshMaxRetries) ||
7811 nla_put_u8(msg, NL80211_MESHCONF_TTL,
7812 cur_params.dot11MeshTTL) ||
7813 nla_put_u8(msg, NL80211_MESHCONF_ELEMENT_TTL,
7814 cur_params.element_ttl) ||
7815 nla_put_u8(msg, NL80211_MESHCONF_AUTO_OPEN_PLINKS,
7816 cur_params.auto_open_plinks) ||
7eab0f64
JL
7817 nla_put_u32(msg, NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR,
7818 cur_params.dot11MeshNbrOffsetMaxNeighbor) ||
9360ffd1
DM
7819 nla_put_u8(msg, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES,
7820 cur_params.dot11MeshHWMPmaxPREQretries) ||
7821 nla_put_u32(msg, NL80211_MESHCONF_PATH_REFRESH_TIME,
7822 cur_params.path_refresh_time) ||
7823 nla_put_u16(msg, NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT,
7824 cur_params.min_discovery_timeout) ||
7825 nla_put_u32(msg, NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT,
7826 cur_params.dot11MeshHWMPactivePathTimeout) ||
7827 nla_put_u16(msg, NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL,
7828 cur_params.dot11MeshHWMPpreqMinInterval) ||
7829 nla_put_u16(msg, NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL,
7830 cur_params.dot11MeshHWMPperrMinInterval) ||
7831 nla_put_u16(msg, NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
7832 cur_params.dot11MeshHWMPnetDiameterTraversalTime) ||
7833 nla_put_u8(msg, NL80211_MESHCONF_HWMP_ROOTMODE,
7834 cur_params.dot11MeshHWMPRootMode) ||
7835 nla_put_u16(msg, NL80211_MESHCONF_HWMP_RANN_INTERVAL,
7836 cur_params.dot11MeshHWMPRannInterval) ||
7837 nla_put_u8(msg, NL80211_MESHCONF_GATE_ANNOUNCEMENTS,
7838 cur_params.dot11MeshGateAnnouncementProtocol) ||
7839 nla_put_u8(msg, NL80211_MESHCONF_FORWARDING,
7840 cur_params.dot11MeshForwarding) ||
335d5349 7841 nla_put_s32(msg, NL80211_MESHCONF_RSSI_THRESHOLD,
70c33eaa
AN
7842 cur_params.rssi_threshold) ||
7843 nla_put_u32(msg, NL80211_MESHCONF_HT_OPMODE,
ac1073a6
CYY
7844 cur_params.ht_opmode) ||
7845 nla_put_u32(msg, NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT,
7846 cur_params.dot11MeshHWMPactivePathToRootTimeout) ||
7847 nla_put_u16(msg, NL80211_MESHCONF_HWMP_ROOT_INTERVAL,
728b19e5
CYY
7848 cur_params.dot11MeshHWMProotInterval) ||
7849 nla_put_u16(msg, NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL,
3b1c5a53
MP
7850 cur_params.dot11MeshHWMPconfirmationInterval) ||
7851 nla_put_u32(msg, NL80211_MESHCONF_POWER_MODE,
7852 cur_params.power_mode) ||
7853 nla_put_u16(msg, NL80211_MESHCONF_AWAKE_WINDOW,
8e7c0538
CT
7854 cur_params.dot11MeshAwakeWindowDuration) ||
7855 nla_put_u32(msg, NL80211_MESHCONF_PLINK_TIMEOUT,
01d66fbd
BC
7856 cur_params.plink_timeout) ||
7857 nla_put_u8(msg, NL80211_MESHCONF_CONNECTED_TO_GATE,
e3718a61
LL
7858 cur_params.dot11MeshConnectedToMeshGate) ||
7859 nla_put_u8(msg, NL80211_MESHCONF_NOLEARN,
184eebe6
MT
7860 cur_params.dot11MeshNolearn) ||
7861 nla_put_u8(msg, NL80211_MESHCONF_CONNECTED_TO_AS,
7862 cur_params.dot11MeshConnectedToAuthServer))
9360ffd1 7863 goto nla_put_failure;
93da9cc1 7864 nla_nest_end(msg, pinfoattr);
7865 genlmsg_end(msg, hdr);
4c476991 7866 return genlmsg_reply(msg, info);
93da9cc1 7867
3b85875a 7868 nla_put_failure:
efe1cf0c 7869 out:
d080e275 7870 nlmsg_free(msg);
4c476991 7871 return -ENOBUFS;
93da9cc1 7872}
7873
ab0d76f6
JB
7874static const struct nla_policy
7875nl80211_meshconf_params_policy[NL80211_MESHCONF_ATTR_MAX+1] = {
7876 [NL80211_MESHCONF_RETRY_TIMEOUT] =
7877 NLA_POLICY_RANGE(NLA_U16, 1, 255),
7878 [NL80211_MESHCONF_CONFIRM_TIMEOUT] =
7879 NLA_POLICY_RANGE(NLA_U16, 1, 255),
7880 [NL80211_MESHCONF_HOLDING_TIMEOUT] =
7881 NLA_POLICY_RANGE(NLA_U16, 1, 255),
7882 [NL80211_MESHCONF_MAX_PEER_LINKS] =
7883 NLA_POLICY_RANGE(NLA_U16, 0, 255),
7884 [NL80211_MESHCONF_MAX_RETRIES] = NLA_POLICY_MAX(NLA_U8, 16),
7885 [NL80211_MESHCONF_TTL] = NLA_POLICY_MIN(NLA_U8, 1),
7886 [NL80211_MESHCONF_ELEMENT_TTL] = NLA_POLICY_MIN(NLA_U8, 1),
7887 [NL80211_MESHCONF_AUTO_OPEN_PLINKS] = NLA_POLICY_MAX(NLA_U8, 1),
7888 [NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR] =
7889 NLA_POLICY_RANGE(NLA_U32, 1, 255),
93da9cc1 7890 [NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES] = { .type = NLA_U8 },
7891 [NL80211_MESHCONF_PATH_REFRESH_TIME] = { .type = NLA_U32 },
ab0d76f6 7892 [NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT] = NLA_POLICY_MIN(NLA_U16, 1),
93da9cc1 7893 [NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT] = { .type = NLA_U32 },
ab0d76f6
JB
7894 [NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL] =
7895 NLA_POLICY_MIN(NLA_U16, 1),
7896 [NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL] =
7897 NLA_POLICY_MIN(NLA_U16, 1),
7898 [NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME] =
7899 NLA_POLICY_MIN(NLA_U16, 1),
7900 [NL80211_MESHCONF_HWMP_ROOTMODE] = NLA_POLICY_MAX(NLA_U8, 4),
7901 [NL80211_MESHCONF_HWMP_RANN_INTERVAL] =
7902 NLA_POLICY_MIN(NLA_U16, 1),
7903 [NL80211_MESHCONF_GATE_ANNOUNCEMENTS] = NLA_POLICY_MAX(NLA_U8, 1),
7904 [NL80211_MESHCONF_FORWARDING] = NLA_POLICY_MAX(NLA_U8, 1),
7905 [NL80211_MESHCONF_RSSI_THRESHOLD] =
7906 NLA_POLICY_RANGE(NLA_S32, -255, 0),
a4f606ea 7907 [NL80211_MESHCONF_HT_OPMODE] = { .type = NLA_U16 },
ac1073a6 7908 [NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT] = { .type = NLA_U32 },
ab0d76f6
JB
7909 [NL80211_MESHCONF_HWMP_ROOT_INTERVAL] =
7910 NLA_POLICY_MIN(NLA_U16, 1),
7911 [NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL] =
7912 NLA_POLICY_MIN(NLA_U16, 1),
7913 [NL80211_MESHCONF_POWER_MODE] =
7914 NLA_POLICY_RANGE(NLA_U32,
7915 NL80211_MESH_POWER_ACTIVE,
7916 NL80211_MESH_POWER_MAX),
3b1c5a53 7917 [NL80211_MESHCONF_AWAKE_WINDOW] = { .type = NLA_U16 },
8e7c0538 7918 [NL80211_MESHCONF_PLINK_TIMEOUT] = { .type = NLA_U32 },
01d66fbd 7919 [NL80211_MESHCONF_CONNECTED_TO_GATE] = NLA_POLICY_RANGE(NLA_U8, 0, 1),
e3718a61 7920 [NL80211_MESHCONF_NOLEARN] = NLA_POLICY_RANGE(NLA_U8, 0, 1),
184eebe6 7921 [NL80211_MESHCONF_CONNECTED_TO_AS] = NLA_POLICY_RANGE(NLA_U8, 0, 1),
93da9cc1 7922};
7923
c80d545d
JC
7924static const struct nla_policy
7925 nl80211_mesh_setup_params_policy[NL80211_MESH_SETUP_ATTR_MAX+1] = {
d299a1f2 7926 [NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC] = { .type = NLA_U8 },
c80d545d
JC
7927 [NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL] = { .type = NLA_U8 },
7928 [NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC] = { .type = NLA_U8 },
15d5dda6 7929 [NL80211_MESH_SETUP_USERSPACE_AUTH] = { .type = NLA_FLAG },
6e16d90b 7930 [NL80211_MESH_SETUP_AUTH_PROTOCOL] = { .type = NLA_U8 },
bb2798d4 7931 [NL80211_MESH_SETUP_USERSPACE_MPM] = { .type = NLA_FLAG },
3d7af878
JB
7932 [NL80211_MESH_SETUP_IE] =
7933 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr,
7934 IEEE80211_MAX_DATA_LEN),
b130e5ce 7935 [NL80211_MESH_SETUP_USERSPACE_AMPE] = { .type = NLA_FLAG },
c80d545d
JC
7936};
7937
24bdd9f4 7938static int nl80211_parse_mesh_config(struct genl_info *info,
bd90fdcc
JB
7939 struct mesh_config *cfg,
7940 u32 *mask_out)
93da9cc1 7941{
93da9cc1 7942 struct nlattr *tb[NL80211_MESHCONF_ATTR_MAX + 1];
bd90fdcc 7943 u32 mask = 0;
9757235f 7944 u16 ht_opmode;
93da9cc1 7945
ab0d76f6
JB
7946#define FILL_IN_MESH_PARAM_IF_SET(tb, cfg, param, mask, attr, fn) \
7947do { \
7948 if (tb[attr]) { \
7949 cfg->param = fn(tb[attr]); \
7950 mask |= BIT((attr) - 1); \
7951 } \
ea54fba2 7952} while (0)
bd90fdcc 7953
24bdd9f4 7954 if (!info->attrs[NL80211_ATTR_MESH_CONFIG])
93da9cc1 7955 return -EINVAL;
8cb08174 7956 if (nla_parse_nested_deprecated(tb, NL80211_MESHCONF_ATTR_MAX, info->attrs[NL80211_ATTR_MESH_CONFIG], nl80211_meshconf_params_policy, info->extack))
93da9cc1 7957 return -EINVAL;
7958
93da9cc1 7959 /* This makes sure that there aren't more than 32 mesh config
7960 * parameters (otherwise our bitfield scheme would not work.) */
7961 BUILD_BUG_ON(NL80211_MESHCONF_ATTR_MAX > 32);
7962
7963 /* Fill in the params struct */
ab0d76f6
JB
7964 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshRetryTimeout, mask,
7965 NL80211_MESHCONF_RETRY_TIMEOUT, nla_get_u16);
7966 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConfirmTimeout, mask,
7967 NL80211_MESHCONF_CONFIRM_TIMEOUT,
7968 nla_get_u16);
7969 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHoldingTimeout, mask,
7970 NL80211_MESHCONF_HOLDING_TIMEOUT,
7971 nla_get_u16);
7972 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxPeerLinks, mask,
7973 NL80211_MESHCONF_MAX_PEER_LINKS,
7974 nla_get_u16);
7975 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxRetries, mask,
7976 NL80211_MESHCONF_MAX_RETRIES, nla_get_u8);
7977 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshTTL, mask,
7978 NL80211_MESHCONF_TTL, nla_get_u8);
7979 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, element_ttl, mask,
7980 NL80211_MESHCONF_ELEMENT_TTL, nla_get_u8);
7981 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, auto_open_plinks, mask,
7982 NL80211_MESHCONF_AUTO_OPEN_PLINKS,
7983 nla_get_u8);
ea54fba2 7984 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshNbrOffsetMaxNeighbor,
ab0d76f6 7985 mask,
a4f606ea 7986 NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR,
ab0d76f6
JB
7987 nla_get_u32);
7988 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPmaxPREQretries, mask,
7989 NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES,
7990 nla_get_u8);
7991 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, path_refresh_time, mask,
7992 NL80211_MESHCONF_PATH_REFRESH_TIME,
7993 nla_get_u32);
7994 if (mask & BIT(NL80211_MESHCONF_PATH_REFRESH_TIME) &&
7995 (cfg->path_refresh_time < 1 || cfg->path_refresh_time > 65535))
7996 return -EINVAL;
7997 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, min_discovery_timeout, mask,
7998 NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT,
7999 nla_get_u16);
ea54fba2 8000 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathTimeout,
ab0d76f6 8001 mask,
a4f606ea 8002 NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT,
ab0d76f6
JB
8003 nla_get_u32);
8004 if (mask & BIT(NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT) &&
8005 (cfg->dot11MeshHWMPactivePathTimeout < 1 ||
8006 cfg->dot11MeshHWMPactivePathTimeout > 65535))
8007 return -EINVAL;
8008 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPpreqMinInterval, mask,
ea54fba2 8009 NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL,
ab0d76f6
JB
8010 nla_get_u16);
8011 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPperrMinInterval, mask,
ea54fba2 8012 NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL,
ab0d76f6 8013 nla_get_u16);
93da9cc1 8014 FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
ab0d76f6 8015 dot11MeshHWMPnetDiameterTraversalTime, mask,
a4f606ea 8016 NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
ab0d76f6
JB
8017 nla_get_u16);
8018 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRootMode, mask,
8019 NL80211_MESHCONF_HWMP_ROOTMODE, nla_get_u8);
8020 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRannInterval, mask,
8021 NL80211_MESHCONF_HWMP_RANN_INTERVAL,
8022 nla_get_u16);
8023 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshGateAnnouncementProtocol,
ea54fba2 8024 mask, NL80211_MESHCONF_GATE_ANNOUNCEMENTS,
ab0d76f6
JB
8025 nla_get_u8);
8026 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshForwarding, mask,
8027 NL80211_MESHCONF_FORWARDING, nla_get_u8);
8028 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, rssi_threshold, mask,
8029 NL80211_MESHCONF_RSSI_THRESHOLD,
8030 nla_get_s32);
01d66fbd
BC
8031 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConnectedToMeshGate, mask,
8032 NL80211_MESHCONF_CONNECTED_TO_GATE,
8033 nla_get_u8);
184eebe6
MT
8034 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConnectedToAuthServer, mask,
8035 NL80211_MESHCONF_CONNECTED_TO_AS,
8036 nla_get_u8);
9757235f
MH
8037 /*
8038 * Check HT operation mode based on
188f60ab 8039 * IEEE 802.11-2016 9.4.2.57 HT Operation element.
9757235f
MH
8040 */
8041 if (tb[NL80211_MESHCONF_HT_OPMODE]) {
8042 ht_opmode = nla_get_u16(tb[NL80211_MESHCONF_HT_OPMODE]);
8043
8044 if (ht_opmode & ~(IEEE80211_HT_OP_MODE_PROTECTION |
8045 IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT |
8046 IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT))
8047 return -EINVAL;
8048
188f60ab
BC
8049 /* NON_HT_STA bit is reserved, but some programs set it */
8050 ht_opmode &= ~IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT;
9757235f 8051
9757235f 8052 cfg->ht_opmode = ht_opmode;
fd551bac 8053 mask |= (1 << (NL80211_MESHCONF_HT_OPMODE - 1));
9757235f 8054 }
728b19e5 8055 FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
ab0d76f6
JB
8056 dot11MeshHWMPactivePathToRootTimeout, mask,
8057 NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT,
8058 nla_get_u32);
8059 if (mask & BIT(NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT) &&
8060 (cfg->dot11MeshHWMPactivePathToRootTimeout < 1 ||
8061 cfg->dot11MeshHWMPactivePathToRootTimeout > 65535))
8062 return -EINVAL;
8063 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMProotInterval, mask,
8064 NL80211_MESHCONF_HWMP_ROOT_INTERVAL,
8065 nla_get_u16);
8066 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPconfirmationInterval,
8067 mask,
728b19e5 8068 NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL,
ab0d76f6
JB
8069 nla_get_u16);
8070 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, power_mode, mask,
8071 NL80211_MESHCONF_POWER_MODE, nla_get_u32);
8072 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshAwakeWindowDuration, mask,
8073 NL80211_MESHCONF_AWAKE_WINDOW, nla_get_u16);
8074 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, plink_timeout, mask,
8075 NL80211_MESHCONF_PLINK_TIMEOUT, nla_get_u32);
e3718a61
LL
8076 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshNolearn, mask,
8077 NL80211_MESHCONF_NOLEARN, nla_get_u8);
bd90fdcc
JB
8078 if (mask_out)
8079 *mask_out = mask;
c80d545d 8080
bd90fdcc
JB
8081 return 0;
8082
8083#undef FILL_IN_MESH_PARAM_IF_SET
8084}
8085
c80d545d
JC
8086static int nl80211_parse_mesh_setup(struct genl_info *info,
8087 struct mesh_setup *setup)
8088{
bb2798d4 8089 struct cfg80211_registered_device *rdev = info->user_ptr[0];
c80d545d
JC
8090 struct nlattr *tb[NL80211_MESH_SETUP_ATTR_MAX + 1];
8091
8092 if (!info->attrs[NL80211_ATTR_MESH_SETUP])
8093 return -EINVAL;
8cb08174 8094 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
8095 return -EINVAL;
8096
d299a1f2
JC
8097 if (tb[NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC])
8098 setup->sync_method =
8099 (nla_get_u8(tb[NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC])) ?
8100 IEEE80211_SYNC_METHOD_VENDOR :
8101 IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET;
8102
c80d545d
JC
8103 if (tb[NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL])
8104 setup->path_sel_proto =
8105 (nla_get_u8(tb[NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL])) ?
8106 IEEE80211_PATH_PROTOCOL_VENDOR :
8107 IEEE80211_PATH_PROTOCOL_HWMP;
8108
8109 if (tb[NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC])
8110 setup->path_metric =
8111 (nla_get_u8(tb[NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC])) ?
8112 IEEE80211_PATH_METRIC_VENDOR :
8113 IEEE80211_PATH_METRIC_AIRTIME;
8114
581a8b0f 8115 if (tb[NL80211_MESH_SETUP_IE]) {
c80d545d 8116 struct nlattr *ieattr =
581a8b0f 8117 tb[NL80211_MESH_SETUP_IE];
581a8b0f
JC
8118 setup->ie = nla_data(ieattr);
8119 setup->ie_len = nla_len(ieattr);
c80d545d 8120 }
bb2798d4
TP
8121 if (tb[NL80211_MESH_SETUP_USERSPACE_MPM] &&
8122 !(rdev->wiphy.features & NL80211_FEATURE_USERSPACE_MPM))
8123 return -EINVAL;
8124 setup->user_mpm = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_MPM]);
b130e5ce
JC
8125 setup->is_authenticated = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AUTH]);
8126 setup->is_secure = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AMPE]);
bb2798d4
TP
8127 if (setup->is_secure)
8128 setup->user_mpm = true;
c80d545d 8129
6e16d90b
CT
8130 if (tb[NL80211_MESH_SETUP_AUTH_PROTOCOL]) {
8131 if (!setup->user_mpm)
8132 return -EINVAL;
8133 setup->auth_id =
8134 nla_get_u8(tb[NL80211_MESH_SETUP_AUTH_PROTOCOL]);
8135 }
8136
c80d545d
JC
8137 return 0;
8138}
8139
24bdd9f4 8140static int nl80211_update_mesh_config(struct sk_buff *skb,
29cbe68c 8141 struct genl_info *info)
bd90fdcc
JB
8142{
8143 struct cfg80211_registered_device *rdev = info->user_ptr[0];
8144 struct net_device *dev = info->user_ptr[1];
29cbe68c 8145 struct wireless_dev *wdev = dev->ieee80211_ptr;
bd90fdcc
JB
8146 struct mesh_config cfg;
8147 u32 mask;
8148 int err;
8149
29cbe68c
JB
8150 if (wdev->iftype != NL80211_IFTYPE_MESH_POINT)
8151 return -EOPNOTSUPP;
8152
24bdd9f4 8153 if (!rdev->ops->update_mesh_config)
bd90fdcc
JB
8154 return -EOPNOTSUPP;
8155
24bdd9f4 8156 err = nl80211_parse_mesh_config(info, &cfg, &mask);
bd90fdcc
JB
8157 if (err)
8158 return err;
8159
29cbe68c 8160 wdev_lock(wdev);
7b0a0e3c 8161 if (!wdev->u.mesh.id_len)
29cbe68c
JB
8162 err = -ENOLINK;
8163
8164 if (!err)
e35e4d28 8165 err = rdev_update_mesh_config(rdev, dev, mask, &cfg);
29cbe68c
JB
8166
8167 wdev_unlock(wdev);
8168
8169 return err;
93da9cc1 8170}
8171
ad30ca2c
AN
8172static int nl80211_put_regdom(const struct ieee80211_regdomain *regdom,
8173 struct sk_buff *msg)
f130347c 8174{
f130347c
LR
8175 struct nlattr *nl_reg_rules;
8176 unsigned int i;
f130347c 8177
458f4f9e
JB
8178 if (nla_put_string(msg, NL80211_ATTR_REG_ALPHA2, regdom->alpha2) ||
8179 (regdom->dfs_region &&
8180 nla_put_u8(msg, NL80211_ATTR_DFS_REGION, regdom->dfs_region)))
ad30ca2c 8181 goto nla_put_failure;
458f4f9e 8182
ae0be8de 8183 nl_reg_rules = nla_nest_start_noflag(msg, NL80211_ATTR_REG_RULES);
f130347c 8184 if (!nl_reg_rules)
ad30ca2c 8185 goto nla_put_failure;
f130347c 8186
458f4f9e 8187 for (i = 0; i < regdom->n_reg_rules; i++) {
f130347c
LR
8188 struct nlattr *nl_reg_rule;
8189 const struct ieee80211_reg_rule *reg_rule;
8190 const struct ieee80211_freq_range *freq_range;
8191 const struct ieee80211_power_rule *power_rule;
97524820 8192 unsigned int max_bandwidth_khz;
f130347c 8193
458f4f9e 8194 reg_rule = &regdom->reg_rules[i];
f130347c
LR
8195 freq_range = &reg_rule->freq_range;
8196 power_rule = &reg_rule->power_rule;
8197
ae0be8de 8198 nl_reg_rule = nla_nest_start_noflag(msg, i);
f130347c 8199 if (!nl_reg_rule)
ad30ca2c 8200 goto nla_put_failure;
f130347c 8201
97524820
JD
8202 max_bandwidth_khz = freq_range->max_bandwidth_khz;
8203 if (!max_bandwidth_khz)
8204 max_bandwidth_khz = reg_get_max_bandwidth(regdom,
8205 reg_rule);
8206
9360ffd1
DM
8207 if (nla_put_u32(msg, NL80211_ATTR_REG_RULE_FLAGS,
8208 reg_rule->flags) ||
8209 nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_START,
8210 freq_range->start_freq_khz) ||
8211 nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_END,
8212 freq_range->end_freq_khz) ||
8213 nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_MAX_BW,
97524820 8214 max_bandwidth_khz) ||
9360ffd1
DM
8215 nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN,
8216 power_rule->max_antenna_gain) ||
8217 nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_EIRP,
089027e5
JD
8218 power_rule->max_eirp) ||
8219 nla_put_u32(msg, NL80211_ATTR_DFS_CAC_TIME,
8220 reg_rule->dfs_cac_ms))
ad30ca2c 8221 goto nla_put_failure;
f130347c
LR
8222
8223 nla_nest_end(msg, nl_reg_rule);
8224 }
8225
8226 nla_nest_end(msg, nl_reg_rules);
ad30ca2c
AN
8227 return 0;
8228
8229nla_put_failure:
8230 return -EMSGSIZE;
8231}
8232
8233static int nl80211_get_reg_do(struct sk_buff *skb, struct genl_info *info)
8234{
8235 const struct ieee80211_regdomain *regdom = NULL;
8236 struct cfg80211_registered_device *rdev;
8237 struct wiphy *wiphy = NULL;
8238 struct sk_buff *msg;
024fcf5e 8239 int err = -EMSGSIZE;
ad30ca2c
AN
8240 void *hdr;
8241
8242 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
8243 if (!msg)
8244 return -ENOBUFS;
8245
8246 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
8247 NL80211_CMD_GET_REG);
8248 if (!hdr)
8249 goto put_failure;
8250
a05829a7
JB
8251 rtnl_lock();
8252
ad30ca2c 8253 if (info->attrs[NL80211_ATTR_WIPHY]) {
1bdd716c
AN
8254 bool self_managed;
8255
ad30ca2c
AN
8256 rdev = cfg80211_get_dev_from_info(genl_info_net(info), info);
8257 if (IS_ERR(rdev)) {
024fcf5e
JB
8258 err = PTR_ERR(rdev);
8259 goto nla_put_failure;
ad30ca2c
AN
8260 }
8261
8262 wiphy = &rdev->wiphy;
1bdd716c
AN
8263 self_managed = wiphy->regulatory_flags &
8264 REGULATORY_WIPHY_SELF_MANAGED;
024fcf5e
JB
8265
8266 rcu_read_lock();
8267
ad30ca2c
AN
8268 regdom = get_wiphy_regdom(wiphy);
8269
1bdd716c
AN
8270 /* a self-managed-reg device must have a private regdom */
8271 if (WARN_ON(!regdom && self_managed)) {
024fcf5e
JB
8272 err = -EINVAL;
8273 goto nla_put_failure_rcu;
1bdd716c
AN
8274 }
8275
ad30ca2c
AN
8276 if (regdom &&
8277 nla_put_u32(msg, NL80211_ATTR_WIPHY, get_wiphy_idx(wiphy)))
024fcf5e
JB
8278 goto nla_put_failure_rcu;
8279 } else {
8280 rcu_read_lock();
ad30ca2c
AN
8281 }
8282
8283 if (!wiphy && reg_last_request_cell_base() &&
8284 nla_put_u32(msg, NL80211_ATTR_USER_REG_HINT_TYPE,
8285 NL80211_USER_REG_HINT_CELL_BASE))
024fcf5e 8286 goto nla_put_failure_rcu;
ad30ca2c
AN
8287
8288 if (!regdom)
8289 regdom = rcu_dereference(cfg80211_regdomain);
8290
8291 if (nl80211_put_regdom(regdom, msg))
8292 goto nla_put_failure_rcu;
8293
8294 rcu_read_unlock();
f130347c
LR
8295
8296 genlmsg_end(msg, hdr);
a05829a7 8297 rtnl_unlock();
5fe231e8 8298 return genlmsg_reply(msg, info);
f130347c 8299
458f4f9e
JB
8300nla_put_failure_rcu:
8301 rcu_read_unlock();
f130347c 8302nla_put_failure:
a05829a7 8303 rtnl_unlock();
efe1cf0c 8304put_failure:
d080e275 8305 nlmsg_free(msg);
024fcf5e 8306 return err;
f130347c
LR
8307}
8308
ad30ca2c
AN
8309static int nl80211_send_regdom(struct sk_buff *msg, struct netlink_callback *cb,
8310 u32 seq, int flags, struct wiphy *wiphy,
8311 const struct ieee80211_regdomain *regdom)
8312{
8313 void *hdr = nl80211hdr_put(msg, NETLINK_CB(cb->skb).portid, seq, flags,
8314 NL80211_CMD_GET_REG);
8315
8316 if (!hdr)
8317 return -1;
8318
0a833c29 8319 genl_dump_check_consistent(cb, hdr);
ad30ca2c
AN
8320
8321 if (nl80211_put_regdom(regdom, msg))
8322 goto nla_put_failure;
8323
8324 if (!wiphy && reg_last_request_cell_base() &&
8325 nla_put_u32(msg, NL80211_ATTR_USER_REG_HINT_TYPE,
8326 NL80211_USER_REG_HINT_CELL_BASE))
8327 goto nla_put_failure;
8328
8329 if (wiphy &&
8330 nla_put_u32(msg, NL80211_ATTR_WIPHY, get_wiphy_idx(wiphy)))
8331 goto nla_put_failure;
8332
1bdd716c
AN
8333 if (wiphy && wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED &&
8334 nla_put_flag(msg, NL80211_ATTR_WIPHY_SELF_MANAGED_REG))
8335 goto nla_put_failure;
8336
053c095a
JB
8337 genlmsg_end(msg, hdr);
8338 return 0;
ad30ca2c
AN
8339
8340nla_put_failure:
8341 genlmsg_cancel(msg, hdr);
8342 return -EMSGSIZE;
8343}
8344
8345static int nl80211_get_reg_dump(struct sk_buff *skb,
8346 struct netlink_callback *cb)
8347{
8348 const struct ieee80211_regdomain *regdom = NULL;
8349 struct cfg80211_registered_device *rdev;
8350 int err, reg_idx, start = cb->args[2];
8351
024fcf5e 8352 rcu_read_lock();
ad30ca2c
AN
8353
8354 if (cfg80211_regdomain && start == 0) {
8355 err = nl80211_send_regdom(skb, cb, cb->nlh->nlmsg_seq,
8356 NLM_F_MULTI, NULL,
024fcf5e 8357 rcu_dereference(cfg80211_regdomain));
ad30ca2c
AN
8358 if (err < 0)
8359 goto out_err;
8360 }
8361
8362 /* the global regdom is idx 0 */
8363 reg_idx = 1;
024fcf5e 8364 list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) {
ad30ca2c
AN
8365 regdom = get_wiphy_regdom(&rdev->wiphy);
8366 if (!regdom)
8367 continue;
8368
8369 if (++reg_idx <= start)
8370 continue;
8371
8372 err = nl80211_send_regdom(skb, cb, cb->nlh->nlmsg_seq,
8373 NLM_F_MULTI, &rdev->wiphy, regdom);
8374 if (err < 0) {
8375 reg_idx--;
8376 break;
8377 }
8378 }
8379
8380 cb->args[2] = reg_idx;
8381 err = skb->len;
8382out_err:
024fcf5e 8383 rcu_read_unlock();
ad30ca2c
AN
8384 return err;
8385}
8386
b6863036
JB
8387#ifdef CONFIG_CFG80211_CRDA_SUPPORT
8388static const struct nla_policy reg_rule_policy[NL80211_REG_RULE_ATTR_MAX + 1] = {
8389 [NL80211_ATTR_REG_RULE_FLAGS] = { .type = NLA_U32 },
8390 [NL80211_ATTR_FREQ_RANGE_START] = { .type = NLA_U32 },
8391 [NL80211_ATTR_FREQ_RANGE_END] = { .type = NLA_U32 },
8392 [NL80211_ATTR_FREQ_RANGE_MAX_BW] = { .type = NLA_U32 },
8393 [NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN] = { .type = NLA_U32 },
8394 [NL80211_ATTR_POWER_RULE_MAX_EIRP] = { .type = NLA_U32 },
8395 [NL80211_ATTR_DFS_CAC_TIME] = { .type = NLA_U32 },
8396};
8397
8398static int parse_reg_rule(struct nlattr *tb[],
8399 struct ieee80211_reg_rule *reg_rule)
8400{
8401 struct ieee80211_freq_range *freq_range = &reg_rule->freq_range;
8402 struct ieee80211_power_rule *power_rule = &reg_rule->power_rule;
8403
8404 if (!tb[NL80211_ATTR_REG_RULE_FLAGS])
8405 return -EINVAL;
8406 if (!tb[NL80211_ATTR_FREQ_RANGE_START])
8407 return -EINVAL;
8408 if (!tb[NL80211_ATTR_FREQ_RANGE_END])
8409 return -EINVAL;
8410 if (!tb[NL80211_ATTR_FREQ_RANGE_MAX_BW])
8411 return -EINVAL;
8412 if (!tb[NL80211_ATTR_POWER_RULE_MAX_EIRP])
8413 return -EINVAL;
8414
8415 reg_rule->flags = nla_get_u32(tb[NL80211_ATTR_REG_RULE_FLAGS]);
8416
8417 freq_range->start_freq_khz =
8418 nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]);
8419 freq_range->end_freq_khz =
8420 nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]);
8421 freq_range->max_bandwidth_khz =
8422 nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]);
8423
8424 power_rule->max_eirp =
8425 nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_EIRP]);
8426
8427 if (tb[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN])
8428 power_rule->max_antenna_gain =
8429 nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN]);
8430
8431 if (tb[NL80211_ATTR_DFS_CAC_TIME])
8432 reg_rule->dfs_cac_ms =
8433 nla_get_u32(tb[NL80211_ATTR_DFS_CAC_TIME]);
8434
8435 return 0;
8436}
8437
b2e1b302
LR
8438static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
8439{
8440 struct nlattr *tb[NL80211_REG_RULE_ATTR_MAX + 1];
8441 struct nlattr *nl_reg_rule;
ea372c54
JB
8442 char *alpha2;
8443 int rem_reg_rules, r;
391d132c 8444 u32 num_rules = 0, rule_idx = 0;
4c7d3982 8445 enum nl80211_dfs_regions dfs_region = NL80211_DFS_UNSET;
ea372c54 8446 struct ieee80211_regdomain *rd;
b2e1b302
LR
8447
8448 if (!info->attrs[NL80211_ATTR_REG_ALPHA2])
8449 return -EINVAL;
8450
8451 if (!info->attrs[NL80211_ATTR_REG_RULES])
8452 return -EINVAL;
8453
8454 alpha2 = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]);
8455
8b60b078
LR
8456 if (info->attrs[NL80211_ATTR_DFS_REGION])
8457 dfs_region = nla_get_u8(info->attrs[NL80211_ATTR_DFS_REGION]);
8458
b2e1b302 8459 nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES],
1a919318 8460 rem_reg_rules) {
b2e1b302
LR
8461 num_rules++;
8462 if (num_rules > NL80211_MAX_SUPP_REG_RULES)
4776c6e7 8463 return -EINVAL;
b2e1b302
LR
8464 }
8465
a05829a7
JB
8466 rtnl_lock();
8467 if (!reg_is_valid_request(alpha2)) {
8468 r = -EINVAL;
8469 goto out;
8470 }
e438768f 8471
391d132c 8472 rd = kzalloc(struct_size(rd, reg_rules, num_rules), GFP_KERNEL);
a05829a7
JB
8473 if (!rd) {
8474 r = -ENOMEM;
8475 goto out;
8476 }
b2e1b302
LR
8477
8478 rd->n_reg_rules = num_rules;
8479 rd->alpha2[0] = alpha2[0];
8480 rd->alpha2[1] = alpha2[1];
8481
8b60b078
LR
8482 /*
8483 * Disable DFS master mode if the DFS region was
8484 * not supported or known on this kernel.
8485 */
8486 if (reg_supported_dfs_region(dfs_region))
8487 rd->dfs_region = dfs_region;
8488
b2e1b302 8489 nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES],
1a919318 8490 rem_reg_rules) {
8cb08174
JB
8491 r = nla_parse_nested_deprecated(tb, NL80211_REG_RULE_ATTR_MAX,
8492 nl_reg_rule, reg_rule_policy,
8493 info->extack);
ae811e21
JB
8494 if (r)
8495 goto bad_reg;
b2e1b302
LR
8496 r = parse_reg_rule(tb, &rd->reg_rules[rule_idx]);
8497 if (r)
8498 goto bad_reg;
8499
8500 rule_idx++;
8501
d0e18f83
LR
8502 if (rule_idx > NL80211_MAX_SUPP_REG_RULES) {
8503 r = -EINVAL;
b2e1b302 8504 goto bad_reg;
d0e18f83 8505 }
b2e1b302
LR
8506 }
8507
a05829a7 8508 r = set_regdom(rd, REGD_SOURCE_CRDA);
06627990 8509 /* set_regdom takes ownership of rd */
a05829a7 8510 rd = NULL;
d2372b31 8511 bad_reg:
b2e1b302 8512 kfree(rd);
a05829a7
JB
8513 out:
8514 rtnl_unlock();
d0e18f83 8515 return r;
b2e1b302 8516}
b6863036 8517#endif /* CONFIG_CFG80211_CRDA_SUPPORT */
b2e1b302 8518
83f5e2cf
JB
8519static int validate_scan_freqs(struct nlattr *freqs)
8520{
8521 struct nlattr *attr1, *attr2;
8522 int n_channels = 0, tmp1, tmp2;
8523
d7f13f74
SD
8524 nla_for_each_nested(attr1, freqs, tmp1)
8525 if (nla_len(attr1) != sizeof(u32))
8526 return 0;
8527
83f5e2cf
JB
8528 nla_for_each_nested(attr1, freqs, tmp1) {
8529 n_channels++;
8530 /*
8531 * Some hardware has a limited channel list for
8532 * scanning, and it is pretty much nonsensical
8533 * to scan for a channel twice, so disallow that
8534 * and don't require drivers to check that the
8535 * channel list they get isn't longer than what
8536 * they can scan, as long as they can scan all
8537 * the channels they registered at once.
8538 */
8539 nla_for_each_nested(attr2, freqs, tmp2)
8540 if (attr1 != attr2 &&
8541 nla_get_u32(attr1) == nla_get_u32(attr2))
8542 return 0;
8543 }
8544
8545 return n_channels;
8546}
8547
57fbcce3 8548static bool is_band_valid(struct wiphy *wiphy, enum nl80211_band b)
38de03d2 8549{
57fbcce3 8550 return b < NUM_NL80211_BANDS && wiphy->bands[b];
38de03d2
AS
8551}
8552
8553static int parse_bss_select(struct nlattr *nla, struct wiphy *wiphy,
8554 struct cfg80211_bss_selection *bss_select)
8555{
8556 struct nlattr *attr[NL80211_BSS_SELECT_ATTR_MAX + 1];
8557 struct nlattr *nest;
8558 int err;
8559 bool found = false;
8560 int i;
8561
8562 /* only process one nested attribute */
8563 nest = nla_data(nla);
8564 if (!nla_ok(nest, nla_len(nest)))
8565 return -EINVAL;
8566
8cb08174
JB
8567 err = nla_parse_nested_deprecated(attr, NL80211_BSS_SELECT_ATTR_MAX,
8568 nest, nl80211_bss_select_policy,
8569 NULL);
38de03d2
AS
8570 if (err)
8571 return err;
8572
8573 /* only one attribute may be given */
8574 for (i = 0; i <= NL80211_BSS_SELECT_ATTR_MAX; i++) {
8575 if (attr[i]) {
8576 if (found)
8577 return -EINVAL;
8578 found = true;
8579 }
8580 }
8581
8582 bss_select->behaviour = __NL80211_BSS_SELECT_ATTR_INVALID;
8583
8584 if (attr[NL80211_BSS_SELECT_ATTR_RSSI])
8585 bss_select->behaviour = NL80211_BSS_SELECT_ATTR_RSSI;
8586
8587 if (attr[NL80211_BSS_SELECT_ATTR_BAND_PREF]) {
8588 bss_select->behaviour = NL80211_BSS_SELECT_ATTR_BAND_PREF;
8589 bss_select->param.band_pref =
8590 nla_get_u32(attr[NL80211_BSS_SELECT_ATTR_BAND_PREF]);
8591 if (!is_band_valid(wiphy, bss_select->param.band_pref))
8592 return -EINVAL;
8593 }
8594
8595 if (attr[NL80211_BSS_SELECT_ATTR_RSSI_ADJUST]) {
8596 struct nl80211_bss_select_rssi_adjust *adj_param;
8597
8598 adj_param = nla_data(attr[NL80211_BSS_SELECT_ATTR_RSSI_ADJUST]);
8599 bss_select->behaviour = NL80211_BSS_SELECT_ATTR_RSSI_ADJUST;
8600 bss_select->param.adjust.band = adj_param->band;
8601 bss_select->param.adjust.delta = adj_param->delta;
8602 if (!is_band_valid(wiphy, bss_select->param.adjust.band))
8603 return -EINVAL;
8604 }
8605
8606 /* user-space did not provide behaviour attribute */
8607 if (bss_select->behaviour == __NL80211_BSS_SELECT_ATTR_INVALID)
8608 return -EINVAL;
8609
8610 if (!(wiphy->bss_select_support & BIT(bss_select->behaviour)))
8611 return -EINVAL;
8612
8613 return 0;
8614}
8615
9bb7e0f2
JB
8616int nl80211_parse_random_mac(struct nlattr **attrs,
8617 u8 *mac_addr, u8 *mac_addr_mask)
ad2b26ab
JB
8618{
8619 int i;
8620
8621 if (!attrs[NL80211_ATTR_MAC] && !attrs[NL80211_ATTR_MAC_MASK]) {
d2beae10
JP
8622 eth_zero_addr(mac_addr);
8623 eth_zero_addr(mac_addr_mask);
ad2b26ab
JB
8624 mac_addr[0] = 0x2;
8625 mac_addr_mask[0] = 0x3;
8626
8627 return 0;
8628 }
8629
8630 /* need both or none */
8631 if (!attrs[NL80211_ATTR_MAC] || !attrs[NL80211_ATTR_MAC_MASK])
8632 return -EINVAL;
8633
8634 memcpy(mac_addr, nla_data(attrs[NL80211_ATTR_MAC]), ETH_ALEN);
8635 memcpy(mac_addr_mask, nla_data(attrs[NL80211_ATTR_MAC_MASK]), ETH_ALEN);
8636
8637 /* don't allow or configure an mcast address */
8638 if (!is_multicast_ether_addr(mac_addr_mask) ||
8639 is_multicast_ether_addr(mac_addr))
8640 return -EINVAL;
8641
8642 /*
8643 * allow users to pass a MAC address that has bits set outside
8644 * of the mask, but don't bother drivers with having to deal
8645 * with such bits
8646 */
8647 for (i = 0; i < ETH_ALEN; i++)
8648 mac_addr[i] &= mac_addr_mask[i];
8649
8650 return 0;
8651}
8652
7b0a0e3c
JB
8653static bool cfg80211_off_channel_oper_allowed(struct wireless_dev *wdev,
8654 struct ieee80211_channel *chan)
34373d12 8655{
7b0a0e3c
JB
8656 unsigned int link_id;
8657 bool all_ok = true;
8658
34373d12
VT
8659 ASSERT_WDEV_LOCK(wdev);
8660
8661 if (!cfg80211_beaconing_iface_active(wdev))
8662 return true;
8663
7b0a0e3c
JB
8664 /*
8665 * FIXME: check if we have a free HW resource/link for chan
8666 *
8667 * This, as well as the FIXME below, requires knowing the link
8668 * capabilities of the hardware.
8669 */
8670
8671 /* we cannot leave radar channels */
8672 for_each_valid_link(wdev, link_id) {
8673 struct cfg80211_chan_def *chandef;
8674
8675 chandef = wdev_chandef(wdev, link_id);
8676 if (!chandef)
8677 continue;
8678
8679 /*
8680 * FIXME: don't require all_ok, but rather check only the
8681 * correct HW resource/link onto which 'chan' falls,
8682 * as only that link leaves the channel for doing
8683 * the off-channel operation.
8684 */
8685
8686 if (chandef->chan->flags & IEEE80211_CHAN_RADAR)
8687 all_ok = false;
8688 }
8689
8690 if (all_ok)
34373d12
VT
8691 return true;
8692
8693 return regulatory_pre_cac_allowed(wdev->wiphy);
8694}
8695
db0a4ad8
JB
8696static bool nl80211_check_scan_feat(struct wiphy *wiphy, u32 flags, u32 flag,
8697 enum nl80211_ext_feature_index feat)
8698{
8699 if (!(flags & flag))
8700 return true;
8701 if (wiphy_ext_feature_isset(wiphy, feat))
8702 return true;
8703 return false;
8704}
8705
2d23d073
RZ
8706static int
8707nl80211_check_scan_flags(struct wiphy *wiphy, struct wireless_dev *wdev,
8708 void *request, struct nlattr **attrs,
8709 bool is_sched_scan)
8710{
8711 u8 *mac_addr, *mac_addr_mask;
8712 u32 *flags;
8713 enum nl80211_feature_flags randomness_flag;
8714
8715 if (!attrs[NL80211_ATTR_SCAN_FLAGS])
8716 return 0;
8717
8718 if (is_sched_scan) {
8719 struct cfg80211_sched_scan_request *req = request;
8720
8721 randomness_flag = wdev ?
8722 NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR :
8723 NL80211_FEATURE_ND_RANDOM_MAC_ADDR;
8724 flags = &req->flags;
8725 mac_addr = req->mac_addr;
8726 mac_addr_mask = req->mac_addr_mask;
8727 } else {
8728 struct cfg80211_scan_request *req = request;
8729
8730 randomness_flag = NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
8731 flags = &req->flags;
8732 mac_addr = req->mac_addr;
8733 mac_addr_mask = req->mac_addr_mask;
8734 }
8735
8736 *flags = nla_get_u32(attrs[NL80211_ATTR_SCAN_FLAGS]);
8737
5037a009
SD
8738 if (((*flags & NL80211_SCAN_FLAG_LOW_PRIORITY) &&
8739 !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) ||
db0a4ad8
JB
8740 !nl80211_check_scan_feat(wiphy, *flags,
8741 NL80211_SCAN_FLAG_LOW_SPAN,
8742 NL80211_EXT_FEATURE_LOW_SPAN_SCAN) ||
8743 !nl80211_check_scan_feat(wiphy, *flags,
8744 NL80211_SCAN_FLAG_LOW_POWER,
8745 NL80211_EXT_FEATURE_LOW_POWER_SCAN) ||
8746 !nl80211_check_scan_feat(wiphy, *flags,
8747 NL80211_SCAN_FLAG_HIGH_ACCURACY,
8748 NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN) ||
8749 !nl80211_check_scan_feat(wiphy, *flags,
8750 NL80211_SCAN_FLAG_FILS_MAX_CHANNEL_TIME,
8751 NL80211_EXT_FEATURE_FILS_MAX_CHANNEL_TIME) ||
8752 !nl80211_check_scan_feat(wiphy, *flags,
8753 NL80211_SCAN_FLAG_ACCEPT_BCAST_PROBE_RESP,
8754 NL80211_EXT_FEATURE_ACCEPT_BCAST_PROBE_RESP) ||
8755 !nl80211_check_scan_feat(wiphy, *flags,
8756 NL80211_SCAN_FLAG_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION,
8757 NL80211_EXT_FEATURE_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION) ||
8758 !nl80211_check_scan_feat(wiphy, *flags,
8759 NL80211_SCAN_FLAG_OCE_PROBE_REQ_HIGH_TX_RATE,
2e076f19
JB
8760 NL80211_EXT_FEATURE_OCE_PROBE_REQ_HIGH_TX_RATE) ||
8761 !nl80211_check_scan_feat(wiphy, *flags,
8762 NL80211_SCAN_FLAG_RANDOM_SN,
8763 NL80211_EXT_FEATURE_SCAN_RANDOM_SN) ||
8764 !nl80211_check_scan_feat(wiphy, *flags,
8765 NL80211_SCAN_FLAG_MIN_PREQ_CONTENT,
8766 NL80211_EXT_FEATURE_SCAN_MIN_PREQ_CONTENT))
2d23d073
RZ
8767 return -EOPNOTSUPP;
8768
8769 if (*flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
8770 int err;
8771
8772 if (!(wiphy->features & randomness_flag) ||
7b0a0e3c 8773 (wdev && wdev->connected))
2d23d073
RZ
8774 return -EOPNOTSUPP;
8775
8776 err = nl80211_parse_random_mac(attrs, mac_addr, mac_addr_mask);
8777 if (err)
8778 return err;
8779 }
8780
2d23d073
RZ
8781 return 0;
8782}
8783
2a519311
JB
8784static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
8785{
4c476991 8786 struct cfg80211_registered_device *rdev = info->user_ptr[0];
fd014284 8787 struct wireless_dev *wdev = info->user_ptr[1];
2a519311 8788 struct cfg80211_scan_request *request;
2032f3b2
TP
8789 struct nlattr *scan_freqs = NULL;
8790 bool scan_freqs_khz = false;
2a519311
JB
8791 struct nlattr *attr;
8792 struct wiphy *wiphy;
83f5e2cf 8793 int err, tmp, n_ssids = 0, n_channels, i;
70692ad2 8794 size_t ie_len;
2a519311 8795
79c97e97 8796 wiphy = &rdev->wiphy;
2a519311 8797
cb3b7d87
AB
8798 if (wdev->iftype == NL80211_IFTYPE_NAN)
8799 return -EOPNOTSUPP;
8800
4c476991
JB
8801 if (!rdev->ops->scan)
8802 return -EOPNOTSUPP;
2a519311 8803
83286856
CJ
8804 if (rdev->scan_req || rdev->scan_msg)
8805 return -EBUSY;
2a519311 8806
2032f3b2
TP
8807 if (info->attrs[NL80211_ATTR_SCAN_FREQ_KHZ]) {
8808 if (!wiphy_ext_feature_isset(wiphy,
8809 NL80211_EXT_FEATURE_SCAN_FREQ_KHZ))
8810 return -EOPNOTSUPP;
8811 scan_freqs = info->attrs[NL80211_ATTR_SCAN_FREQ_KHZ];
8812 scan_freqs_khz = true;
8813 } else if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES])
8814 scan_freqs = info->attrs[NL80211_ATTR_SCAN_FREQUENCIES];
8815
8816 if (scan_freqs) {
8817 n_channels = validate_scan_freqs(scan_freqs);
83286856
CJ
8818 if (!n_channels)
8819 return -EINVAL;
2a519311 8820 } else {
bdfbec2d 8821 n_channels = ieee80211_get_num_supported_channels(wiphy);
2a519311
JB
8822 }
8823
8824 if (info->attrs[NL80211_ATTR_SCAN_SSIDS])
8825 nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp)
8826 n_ssids++;
8827
83286856
CJ
8828 if (n_ssids > wiphy->max_scan_ssids)
8829 return -EINVAL;
2a519311 8830
70692ad2
JM
8831 if (info->attrs[NL80211_ATTR_IE])
8832 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
8833 else
8834 ie_len = 0;
8835
83286856
CJ
8836 if (ie_len > wiphy->max_scan_ie_len)
8837 return -EINVAL;
18a83659 8838
2a519311 8839 request = kzalloc(sizeof(*request)
a2cd43c5
LC
8840 + sizeof(*request->ssids) * n_ssids
8841 + sizeof(*request->channels) * n_channels
70692ad2 8842 + ie_len, GFP_KERNEL);
83286856
CJ
8843 if (!request)
8844 return -ENOMEM;
2a519311 8845
2a519311 8846 if (n_ssids)
5ba63533 8847 request->ssids = (void *)&request->channels[n_channels];
2a519311 8848 request->n_ssids = n_ssids;
70692ad2 8849 if (ie_len) {
13874e4b 8850 if (n_ssids)
70692ad2
JM
8851 request->ie = (void *)(request->ssids + n_ssids);
8852 else
8853 request->ie = (void *)(request->channels + n_channels);
8854 }
2a519311 8855
584991dc 8856 i = 0;
2032f3b2 8857 if (scan_freqs) {
2a519311 8858 /* user specified, bail out if channel not found */
2032f3b2 8859 nla_for_each_nested(attr, scan_freqs, tmp) {
584991dc 8860 struct ieee80211_channel *chan;
2032f3b2 8861 int freq = nla_get_u32(attr);
584991dc 8862
2032f3b2
TP
8863 if (!scan_freqs_khz)
8864 freq = MHZ_TO_KHZ(freq);
584991dc 8865
2032f3b2 8866 chan = ieee80211_get_channel_khz(wiphy, freq);
584991dc 8867 if (!chan) {
2a519311
JB
8868 err = -EINVAL;
8869 goto out_free;
8870 }
584991dc
JB
8871
8872 /* ignore disabled channels */
8873 if (chan->flags & IEEE80211_CHAN_DISABLED)
8874 continue;
8875
8876 request->channels[i] = chan;
2a519311
JB
8877 i++;
8878 }
8879 } else {
57fbcce3 8880 enum nl80211_band band;
34850ab2 8881
2a519311 8882 /* all channels */
57fbcce3 8883 for (band = 0; band < NUM_NL80211_BANDS; band++) {
2a519311 8884 int j;
7a087e74 8885
2a519311
JB
8886 if (!wiphy->bands[band])
8887 continue;
8888 for (j = 0; j < wiphy->bands[band]->n_channels; j++) {
584991dc
JB
8889 struct ieee80211_channel *chan;
8890
8891 chan = &wiphy->bands[band]->channels[j];
8892
8893 if (chan->flags & IEEE80211_CHAN_DISABLED)
8894 continue;
8895
8896 request->channels[i] = chan;
2a519311
JB
8897 i++;
8898 }
8899 }
8900 }
8901
584991dc
JB
8902 if (!i) {
8903 err = -EINVAL;
8904 goto out_free;
8905 }
8906
8907 request->n_channels = i;
8908
34373d12 8909 wdev_lock(wdev);
7b0a0e3c
JB
8910 for (i = 0; i < request->n_channels; i++) {
8911 struct ieee80211_channel *chan = request->channels[i];
34373d12 8912
7b0a0e3c
JB
8913 /* if we can go off-channel to the target channel we're good */
8914 if (cfg80211_off_channel_oper_allowed(wdev, chan))
8915 continue;
34373d12 8916
7b0a0e3c 8917 if (!cfg80211_wdev_on_sub_chan(wdev, chan, true)) {
34373d12
VT
8918 wdev_unlock(wdev);
8919 err = -EBUSY;
8920 goto out_free;
8921 }
8922 }
8923 wdev_unlock(wdev);
8924
2a519311 8925 i = 0;
13874e4b 8926 if (n_ssids) {
2a519311 8927 nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) {
57a27e1d 8928 if (nla_len(attr) > IEEE80211_MAX_SSID_LEN) {
2a519311
JB
8929 err = -EINVAL;
8930 goto out_free;
8931 }
57a27e1d 8932 request->ssids[i].ssid_len = nla_len(attr);
2a519311 8933 memcpy(request->ssids[i].ssid, nla_data(attr), nla_len(attr));
2a519311
JB
8934 i++;
8935 }
8936 }
8937
70692ad2
JM
8938 if (info->attrs[NL80211_ATTR_IE]) {
8939 request->ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
de95a54b
JB
8940 memcpy((void *)request->ie,
8941 nla_data(info->attrs[NL80211_ATTR_IE]),
70692ad2
JM
8942 request->ie_len);
8943 }
8944
57fbcce3 8945 for (i = 0; i < NUM_NL80211_BANDS; i++)
a401d2bb
JB
8946 if (wiphy->bands[i])
8947 request->rates[i] =
8948 (1 << wiphy->bands[i]->n_bitrates) - 1;
34850ab2
JB
8949
8950 if (info->attrs[NL80211_ATTR_SCAN_SUPP_RATES]) {
8951 nla_for_each_nested(attr,
8952 info->attrs[NL80211_ATTR_SCAN_SUPP_RATES],
8953 tmp) {
57fbcce3 8954 enum nl80211_band band = nla_type(attr);
34850ab2 8955
57fbcce3 8956 if (band < 0 || band >= NUM_NL80211_BANDS) {
34850ab2
JB
8957 err = -EINVAL;
8958 goto out_free;
8959 }
1b09cd82
FF
8960
8961 if (!wiphy->bands[band])
8962 continue;
8963
34850ab2
JB
8964 err = ieee80211_get_ratemask(wiphy->bands[band],
8965 nla_data(attr),
8966 nla_len(attr),
8967 &request->rates[band]);
8968 if (err)
8969 goto out_free;
8970 }
8971 }
8972
1d76250b 8973 if (info->attrs[NL80211_ATTR_MEASUREMENT_DURATION]) {
1d76250b
AS
8974 request->duration =
8975 nla_get_u16(info->attrs[NL80211_ATTR_MEASUREMENT_DURATION]);
8976 request->duration_mandatory =
8977 nla_get_flag(info->attrs[NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY]);
8978 }
8979
2d23d073
RZ
8980 err = nl80211_check_scan_flags(wiphy, wdev, request, info->attrs,
8981 false);
8982 if (err)
8983 goto out_free;
ed473771 8984
e9f935e3
RM
8985 request->no_cck =
8986 nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]);
8987
2fa436b3
VK
8988 /* Initial implementation used NL80211_ATTR_MAC to set the specific
8989 * BSSID to scan for. This was problematic because that same attribute
8990 * was already used for another purpose (local random MAC address). The
8991 * NL80211_ATTR_BSSID attribute was added to fix this. For backwards
8992 * compatibility with older userspace components, also use the
8993 * NL80211_ATTR_MAC value here if it can be determined to be used for
8994 * the specific BSSID use case instead of the random MAC address
8995 * (NL80211_ATTR_SCAN_FLAGS is used to enable random MAC address use).
8996 */
8997 if (info->attrs[NL80211_ATTR_BSSID])
8998 memcpy(request->bssid,
8999 nla_data(info->attrs[NL80211_ATTR_BSSID]), ETH_ALEN);
9000 else if (!(request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) &&
9001 info->attrs[NL80211_ATTR_MAC])
818965d3
JM
9002 memcpy(request->bssid, nla_data(info->attrs[NL80211_ATTR_MAC]),
9003 ETH_ALEN);
9004 else
9005 eth_broadcast_addr(request->bssid);
9006
fd014284 9007 request->wdev = wdev;
79c97e97 9008 request->wiphy = &rdev->wiphy;
15d6030b 9009 request->scan_start = jiffies;
2a519311 9010
79c97e97 9011 rdev->scan_req = request;
c8cb5b85 9012 err = cfg80211_scan(rdev);
2a519311 9013
504776be
CJ
9014 if (err)
9015 goto out_free;
9016
9017 nl80211_send_scan_start(rdev, wdev);
1160dfa1 9018 dev_hold(wdev->netdev);
504776be
CJ
9019
9020 return 0;
9021
2a519311 9022 out_free:
504776be
CJ
9023 rdev->scan_req = NULL;
9024 kfree(request);
3b85875a 9025
2a519311
JB
9026 return err;
9027}
9028
91d3ab46
VK
9029static int nl80211_abort_scan(struct sk_buff *skb, struct genl_info *info)
9030{
9031 struct cfg80211_registered_device *rdev = info->user_ptr[0];
9032 struct wireless_dev *wdev = info->user_ptr[1];
9033
9034 if (!rdev->ops->abort_scan)
9035 return -EOPNOTSUPP;
9036
9037 if (rdev->scan_msg)
9038 return 0;
9039
9040 if (!rdev->scan_req)
9041 return -ENOENT;
9042
9043 rdev_abort_scan(rdev, wdev);
9044 return 0;
9045}
9046
3b06d277
AS
9047static int
9048nl80211_parse_sched_scan_plans(struct wiphy *wiphy, int n_plans,
9049 struct cfg80211_sched_scan_request *request,
9050 struct nlattr **attrs)
9051{
9052 int tmp, err, i = 0;
9053 struct nlattr *attr;
9054
9055 if (!attrs[NL80211_ATTR_SCHED_SCAN_PLANS]) {
9056 u32 interval;
9057
9058 /*
9059 * If scan plans are not specified,
5a88de53 9060 * %NL80211_ATTR_SCHED_SCAN_INTERVAL will be specified. In this
3b06d277
AS
9061 * case one scan plan will be set with the specified scan
9062 * interval and infinite number of iterations.
9063 */
3b06d277
AS
9064 interval = nla_get_u32(attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL]);
9065 if (!interval)
9066 return -EINVAL;
9067
9068 request->scan_plans[0].interval =
9069 DIV_ROUND_UP(interval, MSEC_PER_SEC);
9070 if (!request->scan_plans[0].interval)
9071 return -EINVAL;
9072
9073 if (request->scan_plans[0].interval >
9074 wiphy->max_sched_scan_plan_interval)
9075 request->scan_plans[0].interval =
9076 wiphy->max_sched_scan_plan_interval;
9077
9078 return 0;
9079 }
9080
9081 nla_for_each_nested(attr, attrs[NL80211_ATTR_SCHED_SCAN_PLANS], tmp) {
9082 struct nlattr *plan[NL80211_SCHED_SCAN_PLAN_MAX + 1];
9083
9084 if (WARN_ON(i >= n_plans))
9085 return -EINVAL;
9086
8cb08174
JB
9087 err = nla_parse_nested_deprecated(plan,
9088 NL80211_SCHED_SCAN_PLAN_MAX,
9089 attr, nl80211_plan_policy,
9090 NULL);
3b06d277
AS
9091 if (err)
9092 return err;
9093
9094 if (!plan[NL80211_SCHED_SCAN_PLAN_INTERVAL])
9095 return -EINVAL;
9096
9097 request->scan_plans[i].interval =
9098 nla_get_u32(plan[NL80211_SCHED_SCAN_PLAN_INTERVAL]);
9099 if (!request->scan_plans[i].interval ||
9100 request->scan_plans[i].interval >
9101 wiphy->max_sched_scan_plan_interval)
9102 return -EINVAL;
9103
9104 if (plan[NL80211_SCHED_SCAN_PLAN_ITERATIONS]) {
9105 request->scan_plans[i].iterations =
9106 nla_get_u32(plan[NL80211_SCHED_SCAN_PLAN_ITERATIONS]);
9107 if (!request->scan_plans[i].iterations ||
9108 (request->scan_plans[i].iterations >
9109 wiphy->max_sched_scan_plan_iterations))
9110 return -EINVAL;
9111 } else if (i < n_plans - 1) {
9112 /*
9113 * All scan plans but the last one must specify
9114 * a finite number of iterations
9115 */
9116 return -EINVAL;
9117 }
9118
9119 i++;
9120 }
9121
9122 /*
9123 * The last scan plan must not specify the number of
9124 * iterations, it is supposed to run infinitely
9125 */
9126 if (request->scan_plans[n_plans - 1].iterations)
9127 return -EINVAL;
9128
9129 return 0;
9130}
9131
1e1b11b6 9132static int
9133nl80211_parse_sched_scan_per_band_rssi(struct wiphy *wiphy,
9134 struct cfg80211_match_set *match_sets,
9135 struct nlattr *tb_band_rssi,
9136 s32 rssi_thold)
9137{
9138 struct nlattr *attr;
9139 int i, tmp, ret = 0;
9140
9141 if (!wiphy_ext_feature_isset(wiphy,
9142 NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD)) {
9143 if (tb_band_rssi)
9144 ret = -EOPNOTSUPP;
9145 else
9146 for (i = 0; i < NUM_NL80211_BANDS; i++)
9147 match_sets->per_band_rssi_thold[i] =
9148 NL80211_SCAN_RSSI_THOLD_OFF;
9149 return ret;
9150 }
9151
9152 for (i = 0; i < NUM_NL80211_BANDS; i++)
9153 match_sets->per_band_rssi_thold[i] = rssi_thold;
9154
9155 nla_for_each_nested(attr, tb_band_rssi, tmp) {
9156 enum nl80211_band band = nla_type(attr);
9157
9158 if (band < 0 || band >= NUM_NL80211_BANDS)
9159 return -EINVAL;
9160
9161 match_sets->per_band_rssi_thold[band] = nla_get_s32(attr);
9162 }
9163
9164 return 0;
9165}
9166
256da02d 9167static struct cfg80211_sched_scan_request *
ad2b26ab 9168nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev,
aad1e812 9169 struct nlattr **attrs, int max_match_sets)
807f8a8c
LC
9170{
9171 struct cfg80211_sched_scan_request *request;
807f8a8c 9172 struct nlattr *attr;
3b06d277 9173 int err, tmp, n_ssids = 0, n_match_sets = 0, n_channels, i, n_plans = 0;
57fbcce3 9174 enum nl80211_band band;
807f8a8c 9175 size_t ie_len;
a1f1c21c 9176 struct nlattr *tb[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1];
ea73cbce 9177 s32 default_match_rssi = NL80211_SCAN_RSSI_THOLD_OFF;
807f8a8c 9178
256da02d 9179 if (attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
807f8a8c 9180 n_channels = validate_scan_freqs(
256da02d 9181 attrs[NL80211_ATTR_SCAN_FREQUENCIES]);
807f8a8c 9182 if (!n_channels)
256da02d 9183 return ERR_PTR(-EINVAL);
807f8a8c 9184 } else {
bdfbec2d 9185 n_channels = ieee80211_get_num_supported_channels(wiphy);
807f8a8c
LC
9186 }
9187
256da02d
LC
9188 if (attrs[NL80211_ATTR_SCAN_SSIDS])
9189 nla_for_each_nested(attr, attrs[NL80211_ATTR_SCAN_SSIDS],
807f8a8c
LC
9190 tmp)
9191 n_ssids++;
9192
93b6aa69 9193 if (n_ssids > wiphy->max_sched_scan_ssids)
256da02d 9194 return ERR_PTR(-EINVAL);
807f8a8c 9195
ea73cbce
JB
9196 /*
9197 * First, count the number of 'real' matchsets. Due to an issue with
9198 * the old implementation, matchsets containing only the RSSI attribute
9199 * (NL80211_SCHED_SCAN_MATCH_ATTR_RSSI) are considered as the 'default'
9200 * RSSI for all matchsets, rather than their own matchset for reporting
9201 * all APs with a strong RSSI. This is needed to be compatible with
9202 * older userspace that treated a matchset with only the RSSI as the
9203 * global RSSI for all other matchsets - if there are other matchsets.
9204 */
256da02d 9205 if (attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) {
a1f1c21c 9206 nla_for_each_nested(attr,
256da02d 9207 attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
ea73cbce
JB
9208 tmp) {
9209 struct nlattr *rssi;
9210
8cb08174
JB
9211 err = nla_parse_nested_deprecated(tb,
9212 NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
9213 attr,
9214 nl80211_match_policy,
9215 NULL);
ea73cbce 9216 if (err)
256da02d 9217 return ERR_PTR(err);
3007e352
AVS
9218
9219 /* SSID and BSSID are mutually exclusive */
9220 if (tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID] &&
9221 tb[NL80211_SCHED_SCAN_MATCH_ATTR_BSSID])
9222 return ERR_PTR(-EINVAL);
9223
ea73cbce 9224 /* add other standalone attributes here */
3007e352
AVS
9225 if (tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID] ||
9226 tb[NL80211_SCHED_SCAN_MATCH_ATTR_BSSID]) {
ea73cbce
JB
9227 n_match_sets++;
9228 continue;
9229 }
9230 rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI];
9231 if (rssi)
9232 default_match_rssi = nla_get_s32(rssi);
9233 }
9234 }
9235
9236 /* However, if there's no other matchset, add the RSSI one */
9237 if (!n_match_sets && default_match_rssi != NL80211_SCAN_RSSI_THOLD_OFF)
9238 n_match_sets = 1;
a1f1c21c 9239
aad1e812 9240 if (n_match_sets > max_match_sets)
256da02d 9241 return ERR_PTR(-EINVAL);
a1f1c21c 9242
256da02d
LC
9243 if (attrs[NL80211_ATTR_IE])
9244 ie_len = nla_len(attrs[NL80211_ATTR_IE]);
807f8a8c
LC
9245 else
9246 ie_len = 0;
9247
5a865bad 9248 if (ie_len > wiphy->max_sched_scan_ie_len)
256da02d 9249 return ERR_PTR(-EINVAL);
c10841ca 9250
3b06d277
AS
9251 if (attrs[NL80211_ATTR_SCHED_SCAN_PLANS]) {
9252 /*
9253 * NL80211_ATTR_SCHED_SCAN_INTERVAL must not be specified since
9254 * each scan plan already specifies its own interval
9255 */
9256 if (attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL])
9257 return ERR_PTR(-EINVAL);
9258
9259 nla_for_each_nested(attr,
9260 attrs[NL80211_ATTR_SCHED_SCAN_PLANS], tmp)
9261 n_plans++;
9262 } else {
9263 /*
9264 * The scan interval attribute is kept for backward
9265 * compatibility. If no scan plans are specified and sched scan
9266 * interval is specified, one scan plan will be set with this
9267 * scan interval and infinite number of iterations.
9268 */
9269 if (!attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL])
9270 return ERR_PTR(-EINVAL);
9271
9272 n_plans = 1;
9273 }
9274
9275 if (!n_plans || n_plans > wiphy->max_sched_scan_plans)
9276 return ERR_PTR(-EINVAL);
9277
bf95ecdb 9278 if (!wiphy_ext_feature_isset(
9279 wiphy, NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI) &&
9280 (attrs[NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI] ||
9281 attrs[NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST]))
9282 return ERR_PTR(-EINVAL);
9283
807f8a8c 9284 request = kzalloc(sizeof(*request)
a2cd43c5 9285 + sizeof(*request->ssids) * n_ssids
a1f1c21c 9286 + sizeof(*request->match_sets) * n_match_sets
3b06d277 9287 + sizeof(*request->scan_plans) * n_plans
a2cd43c5 9288 + sizeof(*request->channels) * n_channels
807f8a8c 9289 + ie_len, GFP_KERNEL);
256da02d
LC
9290 if (!request)
9291 return ERR_PTR(-ENOMEM);
807f8a8c
LC
9292
9293 if (n_ssids)
9294 request->ssids = (void *)&request->channels[n_channels];
9295 request->n_ssids = n_ssids;
9296 if (ie_len) {
13874e4b 9297 if (n_ssids)
807f8a8c
LC
9298 request->ie = (void *)(request->ssids + n_ssids);
9299 else
9300 request->ie = (void *)(request->channels + n_channels);
9301 }
9302
a1f1c21c
LC
9303 if (n_match_sets) {
9304 if (request->ie)
9305 request->match_sets = (void *)(request->ie + ie_len);
13874e4b 9306 else if (n_ssids)
a1f1c21c
LC
9307 request->match_sets =
9308 (void *)(request->ssids + n_ssids);
9309 else
9310 request->match_sets =
9311 (void *)(request->channels + n_channels);
9312 }
9313 request->n_match_sets = n_match_sets;
9314
3b06d277
AS
9315 if (n_match_sets)
9316 request->scan_plans = (void *)(request->match_sets +
9317 n_match_sets);
9318 else if (request->ie)
9319 request->scan_plans = (void *)(request->ie + ie_len);
9320 else if (n_ssids)
9321 request->scan_plans = (void *)(request->ssids + n_ssids);
9322 else
9323 request->scan_plans = (void *)(request->channels + n_channels);
9324
9325 request->n_scan_plans = n_plans;
9326
807f8a8c 9327 i = 0;
256da02d 9328 if (attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
807f8a8c
LC
9329 /* user specified, bail out if channel not found */
9330 nla_for_each_nested(attr,
256da02d 9331 attrs[NL80211_ATTR_SCAN_FREQUENCIES],
807f8a8c
LC
9332 tmp) {
9333 struct ieee80211_channel *chan;
9334
9335 chan = ieee80211_get_channel(wiphy, nla_get_u32(attr));
9336
9337 if (!chan) {
9338 err = -EINVAL;
9339 goto out_free;
9340 }
9341
9342 /* ignore disabled channels */
9343 if (chan->flags & IEEE80211_CHAN_DISABLED)
9344 continue;
9345
9346 request->channels[i] = chan;
9347 i++;
9348 }
9349 } else {
9350 /* all channels */
57fbcce3 9351 for (band = 0; band < NUM_NL80211_BANDS; band++) {
807f8a8c 9352 int j;
7a087e74 9353
807f8a8c
LC
9354 if (!wiphy->bands[band])
9355 continue;
9356 for (j = 0; j < wiphy->bands[band]->n_channels; j++) {
9357 struct ieee80211_channel *chan;
9358
9359 chan = &wiphy->bands[band]->channels[j];
9360
9361 if (chan->flags & IEEE80211_CHAN_DISABLED)
9362 continue;
9363
9364 request->channels[i] = chan;
9365 i++;
9366 }
9367 }
9368 }
9369
9370 if (!i) {
9371 err = -EINVAL;
9372 goto out_free;
9373 }
9374
9375 request->n_channels = i;
9376
9377 i = 0;
13874e4b 9378 if (n_ssids) {
256da02d 9379 nla_for_each_nested(attr, attrs[NL80211_ATTR_SCAN_SSIDS],
807f8a8c 9380 tmp) {
57a27e1d 9381 if (nla_len(attr) > IEEE80211_MAX_SSID_LEN) {
807f8a8c
LC
9382 err = -EINVAL;
9383 goto out_free;
9384 }
57a27e1d 9385 request->ssids[i].ssid_len = nla_len(attr);
807f8a8c
LC
9386 memcpy(request->ssids[i].ssid, nla_data(attr),
9387 nla_len(attr));
807f8a8c
LC
9388 i++;
9389 }
9390 }
9391
a1f1c21c 9392 i = 0;
256da02d 9393 if (attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) {
a1f1c21c 9394 nla_for_each_nested(attr,
256da02d 9395 attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
a1f1c21c 9396 tmp) {
3007e352 9397 struct nlattr *ssid, *bssid, *rssi;
a1f1c21c 9398
8cb08174
JB
9399 err = nla_parse_nested_deprecated(tb,
9400 NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
9401 attr,
9402 nl80211_match_policy,
9403 NULL);
ae811e21
JB
9404 if (err)
9405 goto out_free;
4a4ab0d7 9406 ssid = tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID];
3007e352 9407 bssid = tb[NL80211_SCHED_SCAN_MATCH_ATTR_BSSID];
d39f3b4f
JB
9408
9409 if (!ssid && !bssid) {
9410 i++;
9411 continue;
9412 }
9413
9414 if (WARN_ON(i >= n_match_sets)) {
9415 /* this indicates a programming error,
9416 * the loop above should have verified
9417 * things properly
9418 */
9419 err = -EINVAL;
9420 goto out_free;
9421 }
9422
9423 if (ssid) {
d39f3b4f
JB
9424 memcpy(request->match_sets[i].ssid.ssid,
9425 nla_data(ssid), nla_len(ssid));
9426 request->match_sets[i].ssid.ssid_len =
9427 nla_len(ssid);
9428 }
cb9abd48 9429 if (bssid)
d39f3b4f
JB
9430 memcpy(request->match_sets[i].bssid,
9431 nla_data(bssid), ETH_ALEN);
3007e352 9432
d39f3b4f
JB
9433 /* special attribute - old implementation w/a */
9434 request->match_sets[i].rssi_thold = default_match_rssi;
9435 rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI];
9436 if (rssi)
ea73cbce 9437 request->match_sets[i].rssi_thold =
d39f3b4f 9438 nla_get_s32(rssi);
1e1b11b6 9439
9440 /* Parse per band RSSI attribute */
9441 err = nl80211_parse_sched_scan_per_band_rssi(wiphy,
9442 &request->match_sets[i],
9443 tb[NL80211_SCHED_SCAN_MATCH_PER_BAND_RSSI],
9444 request->match_sets[i].rssi_thold);
9445 if (err)
9446 goto out_free;
9447
a1f1c21c
LC
9448 i++;
9449 }
ea73cbce
JB
9450
9451 /* there was no other matchset, so the RSSI one is alone */
f89f46cf 9452 if (i == 0 && n_match_sets)
ea73cbce
JB
9453 request->match_sets[0].rssi_thold = default_match_rssi;
9454
9455 request->min_rssi_thold = INT_MAX;
9456 for (i = 0; i < n_match_sets; i++)
9457 request->min_rssi_thold =
9458 min(request->match_sets[i].rssi_thold,
9459 request->min_rssi_thold);
9460 } else {
9461 request->min_rssi_thold = NL80211_SCAN_RSSI_THOLD_OFF;
a1f1c21c
LC
9462 }
9463
9900e484
JB
9464 if (ie_len) {
9465 request->ie_len = ie_len;
807f8a8c 9466 memcpy((void *)request->ie,
256da02d 9467 nla_data(attrs[NL80211_ATTR_IE]),
807f8a8c
LC
9468 request->ie_len);
9469 }
9470
2d23d073
RZ
9471 err = nl80211_check_scan_flags(wiphy, wdev, request, attrs, true);
9472 if (err)
9473 goto out_free;
ed473771 9474
9c748934
LC
9475 if (attrs[NL80211_ATTR_SCHED_SCAN_DELAY])
9476 request->delay =
9477 nla_get_u32(attrs[NL80211_ATTR_SCHED_SCAN_DELAY]);
9478
bf95ecdb 9479 if (attrs[NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI]) {
9480 request->relative_rssi = nla_get_s8(
9481 attrs[NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI]);
9482 request->relative_rssi_set = true;
9483 }
9484
9485 if (request->relative_rssi_set &&
9486 attrs[NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST]) {
9487 struct nl80211_bss_select_rssi_adjust *rssi_adjust;
9488
9489 rssi_adjust = nla_data(
9490 attrs[NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST]);
9491 request->rssi_adjust.band = rssi_adjust->band;
9492 request->rssi_adjust.delta = rssi_adjust->delta;
9493 if (!is_band_valid(wiphy, request->rssi_adjust.band)) {
9494 err = -EINVAL;
9495 goto out_free;
9496 }
9497 }
9498
3b06d277
AS
9499 err = nl80211_parse_sched_scan_plans(wiphy, n_plans, request, attrs);
9500 if (err)
9501 goto out_free;
9502
15d6030b 9503 request->scan_start = jiffies;
807f8a8c 9504
256da02d 9505 return request;
807f8a8c
LC
9506
9507out_free:
9508 kfree(request);
256da02d
LC
9509 return ERR_PTR(err);
9510}
9511
9512static int nl80211_start_sched_scan(struct sk_buff *skb,
9513 struct genl_info *info)
9514{
9515 struct cfg80211_registered_device *rdev = info->user_ptr[0];
9516 struct net_device *dev = info->user_ptr[1];
ad2b26ab 9517 struct wireless_dev *wdev = dev->ieee80211_ptr;
31a60ed1 9518 struct cfg80211_sched_scan_request *sched_scan_req;
ca986ad9 9519 bool want_multi;
256da02d
LC
9520 int err;
9521
ca986ad9 9522 if (!rdev->wiphy.max_sched_scan_reqs || !rdev->ops->sched_scan_start)
256da02d
LC
9523 return -EOPNOTSUPP;
9524
ca986ad9
AVS
9525 want_multi = info->attrs[NL80211_ATTR_SCHED_SCAN_MULTI];
9526 err = cfg80211_sched_scan_req_possible(rdev, want_multi);
9527 if (err)
9528 return err;
256da02d 9529
31a60ed1 9530 sched_scan_req = nl80211_parse_sched_scan(&rdev->wiphy, wdev,
aad1e812
AVS
9531 info->attrs,
9532 rdev->wiphy.max_match_sets);
31a60ed1
JR
9533
9534 err = PTR_ERR_OR_ZERO(sched_scan_req);
256da02d
LC
9535 if (err)
9536 goto out_err;
9537
ca986ad9
AVS
9538 /* leave request id zero for legacy request
9539 * or if driver does not support multi-scheduled scan
9540 */
2fd351a8
DK
9541 if (want_multi && rdev->wiphy.max_sched_scan_reqs > 1)
9542 sched_scan_req->reqid = cfg80211_assign_cookie(rdev);
ca986ad9 9543
31a60ed1 9544 err = rdev_sched_scan_start(rdev, dev, sched_scan_req);
256da02d
LC
9545 if (err)
9546 goto out_free;
9547
31a60ed1
JR
9548 sched_scan_req->dev = dev;
9549 sched_scan_req->wiphy = &rdev->wiphy;
9550
93a1e86c
JR
9551 if (info->attrs[NL80211_ATTR_SOCKET_OWNER])
9552 sched_scan_req->owner_nlportid = info->snd_portid;
9553
ca986ad9 9554 cfg80211_add_sched_scan_req(rdev, sched_scan_req);
256da02d 9555
96b08fd6 9556 nl80211_send_sched_scan(sched_scan_req, NL80211_CMD_START_SCHED_SCAN);
256da02d
LC
9557 return 0;
9558
9559out_free:
31a60ed1 9560 kfree(sched_scan_req);
256da02d 9561out_err:
807f8a8c
LC
9562 return err;
9563}
9564
9565static int nl80211_stop_sched_scan(struct sk_buff *skb,
9566 struct genl_info *info)
9567{
ca986ad9 9568 struct cfg80211_sched_scan_request *req;
807f8a8c 9569 struct cfg80211_registered_device *rdev = info->user_ptr[0];
ca986ad9 9570 u64 cookie;
807f8a8c 9571
ca986ad9 9572 if (!rdev->wiphy.max_sched_scan_reqs || !rdev->ops->sched_scan_stop)
807f8a8c
LC
9573 return -EOPNOTSUPP;
9574
ca986ad9
AVS
9575 if (info->attrs[NL80211_ATTR_COOKIE]) {
9576 cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);
9577 return __cfg80211_stop_sched_scan(rdev, cookie, false);
9578 }
9579
9580 req = list_first_or_null_rcu(&rdev->sched_scan_req_list,
9581 struct cfg80211_sched_scan_request,
9582 list);
9583 if (!req || req->reqid ||
9584 (req->owner_nlportid &&
9585 req->owner_nlportid != info->snd_portid))
9586 return -ENOENT;
9587
9588 return cfg80211_stop_sched_scan_req(rdev, req, false);
807f8a8c
LC
9589}
9590
04f39047
SW
9591static int nl80211_start_radar_detection(struct sk_buff *skb,
9592 struct genl_info *info)
9593{
9594 struct cfg80211_registered_device *rdev = info->user_ptr[0];
9595 struct net_device *dev = info->user_ptr[1];
9596 struct wireless_dev *wdev = dev->ieee80211_ptr;
13cf6dec 9597 struct wiphy *wiphy = wdev->wiphy;
04f39047 9598 struct cfg80211_chan_def chandef;
55f7435c 9599 enum nl80211_dfs_regions dfs_region;
31559f35 9600 unsigned int cac_time_ms;
84158164
LB
9601 int err = -EINVAL;
9602
9603 flush_delayed_work(&rdev->dfs_update_channels_wk);
9604
9605 wiphy_lock(wiphy);
04f39047 9606
13cf6dec 9607 dfs_region = reg_get_dfs_region(wiphy);
55f7435c 9608 if (dfs_region == NL80211_DFS_UNSET)
84158164 9609 goto unlock;
55f7435c 9610
04f39047
SW
9611 err = nl80211_parse_chandef(rdev, info, &chandef);
9612 if (err)
84158164 9613 goto unlock;
04f39047 9614
13cf6dec 9615 err = cfg80211_chandef_dfs_required(wiphy, &chandef, wdev->iftype);
04f39047 9616 if (err < 0)
84158164 9617 goto unlock;
04f39047 9618
84158164
LB
9619 if (err == 0) {
9620 err = -EINVAL;
9621 goto unlock;
9622 }
04f39047 9623
84158164
LB
9624 if (!cfg80211_chandef_dfs_usable(wiphy, &chandef)) {
9625 err = -EINVAL;
9626 goto unlock;
9627 }
04f39047 9628
a95bfb87
LB
9629 if (nla_get_flag(info->attrs[NL80211_ATTR_RADAR_BACKGROUND])) {
9630 err = cfg80211_start_background_radar_detection(rdev, wdev,
9631 &chandef);
84158164
LB
9632 goto unlock;
9633 }
bc2dfc02 9634
84158164
LB
9635 if (netif_carrier_ok(dev)) {
9636 err = -EBUSY;
9637 goto unlock;
9638 }
bc2dfc02 9639
84158164
LB
9640 if (wdev->cac_started) {
9641 err = -EBUSY;
9642 goto unlock;
9643 }
bc2dfc02 9644
13cf6dec 9645 /* CAC start is offloaded to HW and can't be started manually */
84158164
LB
9646 if (wiphy_ext_feature_isset(wiphy, NL80211_EXT_FEATURE_DFS_OFFLOAD)) {
9647 err = -EOPNOTSUPP;
9648 goto unlock;
9649 }
13cf6dec 9650
84158164
LB
9651 if (!rdev->ops->start_radar_detection) {
9652 err = -EOPNOTSUPP;
9653 goto unlock;
9654 }
04f39047 9655
31559f35
JD
9656 cac_time_ms = cfg80211_chandef_dfs_cac_time(&rdev->wiphy, &chandef);
9657 if (WARN_ON(!cac_time_ms))
9658 cac_time_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
9659
a1056b1b 9660 err = rdev_start_radar_detection(rdev, dev, &chandef, cac_time_ms);
04f39047 9661 if (!err) {
7b0a0e3c 9662 wdev->links[0].ap.chandef = chandef;
04f39047
SW
9663 wdev->cac_started = true;
9664 wdev->cac_start_time = jiffies;
31559f35 9665 wdev->cac_time_ms = cac_time_ms;
04f39047 9666 }
84158164
LB
9667unlock:
9668 wiphy_unlock(wiphy);
9669
04f39047
SW
9670 return err;
9671}
9672
30c63115
S
9673static int nl80211_notify_radar_detection(struct sk_buff *skb,
9674 struct genl_info *info)
9675{
9676 struct cfg80211_registered_device *rdev = info->user_ptr[0];
9677 struct net_device *dev = info->user_ptr[1];
9678 struct wireless_dev *wdev = dev->ieee80211_ptr;
9679 struct wiphy *wiphy = wdev->wiphy;
9680 struct cfg80211_chan_def chandef;
9681 enum nl80211_dfs_regions dfs_region;
9682 int err;
9683
9684 dfs_region = reg_get_dfs_region(wiphy);
9685 if (dfs_region == NL80211_DFS_UNSET) {
9686 GENL_SET_ERR_MSG(info,
9687 "DFS Region is not set. Unexpected Radar indication");
9688 return -EINVAL;
9689 }
9690
9691 err = nl80211_parse_chandef(rdev, info, &chandef);
9692 if (err) {
9693 GENL_SET_ERR_MSG(info, "Unable to extract chandef info");
9694 return err;
9695 }
9696
9697 err = cfg80211_chandef_dfs_required(wiphy, &chandef, wdev->iftype);
9698 if (err < 0) {
9699 GENL_SET_ERR_MSG(info, "chandef is invalid");
9700 return err;
9701 }
9702
9703 if (err == 0) {
9704 GENL_SET_ERR_MSG(info,
9705 "Unexpected Radar indication for chandef/iftype");
9706 return -EINVAL;
9707 }
9708
9709 /* Do not process this notification if radar is already detected
9710 * by kernel on this channel, and return success.
9711 */
9712 if (chandef.chan->dfs_state == NL80211_DFS_UNAVAILABLE)
9713 return 0;
9714
9715 cfg80211_set_dfs_state(wiphy, &chandef, NL80211_DFS_UNAVAILABLE);
9716
9717 cfg80211_sched_dfs_chan_update(rdev);
9718
a680fe46 9719 rdev->radar_chandef = chandef;
30c63115
S
9720
9721 /* Propagate this notification to other radios as well */
9722 queue_work(cfg80211_wq, &rdev->propagate_radar_detect_wk);
9723
9724 return 0;
9725}
9726
16ef1fe2
SW
9727static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
9728{
9729 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7b0a0e3c 9730 unsigned int link_id = nl80211_link_id(info->attrs);
16ef1fe2
SW
9731 struct net_device *dev = info->user_ptr[1];
9732 struct wireless_dev *wdev = dev->ieee80211_ptr;
9733 struct cfg80211_csa_settings params;
a05829a7 9734 struct nlattr **csa_attrs = NULL;
16ef1fe2 9735 int err;
ee4bc9e7 9736 bool need_new_beacon = false;
8d9de16f 9737 bool need_handle_dfs_flag = true;
9a774c78 9738 int len, i;
252e07ca 9739 u32 cs_count;
16ef1fe2
SW
9740
9741 if (!rdev->ops->channel_switch ||
9742 !(rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH))
9743 return -EOPNOTSUPP;
9744
ee4bc9e7
SW
9745 switch (dev->ieee80211_ptr->iftype) {
9746 case NL80211_IFTYPE_AP:
9747 case NL80211_IFTYPE_P2P_GO:
9748 need_new_beacon = true;
8d9de16f
BB
9749 /* For all modes except AP the handle_dfs flag needs to be
9750 * supplied to tell the kernel that userspace will handle radar
9751 * events when they happen. Otherwise a switch to a channel
9752 * requiring DFS will be rejected.
9753 */
9754 need_handle_dfs_flag = false;
ee4bc9e7
SW
9755
9756 /* useless if AP is not running */
7b0a0e3c 9757 if (!wdev->links[link_id].ap.beacon_interval)
1ff79dfa 9758 return -ENOTCONN;
ee4bc9e7
SW
9759 break;
9760 case NL80211_IFTYPE_ADHOC:
7b0a0e3c 9761 if (!wdev->u.ibss.ssid_len)
1ff79dfa
JB
9762 return -ENOTCONN;
9763 break;
c6da674a 9764 case NL80211_IFTYPE_MESH_POINT:
7b0a0e3c 9765 if (!wdev->u.mesh.id_len)
1ff79dfa 9766 return -ENOTCONN;
ee4bc9e7
SW
9767 break;
9768 default:
16ef1fe2 9769 return -EOPNOTSUPP;
ee4bc9e7 9770 }
16ef1fe2
SW
9771
9772 memset(&params, 0, sizeof(params));
c177db2d 9773 params.beacon_csa.ftm_responder = -1;
16ef1fe2
SW
9774
9775 if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] ||
9776 !info->attrs[NL80211_ATTR_CH_SWITCH_COUNT])
9777 return -EINVAL;
9778
9779 /* only important for AP, IBSS and mesh create IEs internally */
d0a361a5 9780 if (need_new_beacon && !info->attrs[NL80211_ATTR_CSA_IES])
16ef1fe2
SW
9781 return -EINVAL;
9782
252e07ca
LC
9783 /* Even though the attribute is u32, the specification says
9784 * u8, so let's make sure we don't overflow.
9785 */
9786 cs_count = nla_get_u32(info->attrs[NL80211_ATTR_CH_SWITCH_COUNT]);
9787 if (cs_count > 255)
9788 return -EINVAL;
9789
9790 params.count = cs_count;
16ef1fe2 9791
ee4bc9e7
SW
9792 if (!need_new_beacon)
9793 goto skip_beacons;
9794
81e54d08 9795 err = nl80211_parse_beacon(rdev, info->attrs, &params.beacon_after);
16ef1fe2 9796 if (err)
dc1e3cb8 9797 goto free;
16ef1fe2 9798
a05829a7
JB
9799 csa_attrs = kcalloc(NL80211_ATTR_MAX + 1, sizeof(*csa_attrs),
9800 GFP_KERNEL);
dc1e3cb8
JC
9801 if (!csa_attrs) {
9802 err = -ENOMEM;
9803 goto free;
9804 }
a05829a7 9805
8cb08174
JB
9806 err = nla_parse_nested_deprecated(csa_attrs, NL80211_ATTR_MAX,
9807 info->attrs[NL80211_ATTR_CSA_IES],
9808 nl80211_policy, info->extack);
16ef1fe2 9809 if (err)
a05829a7 9810 goto free;
16ef1fe2 9811
81e54d08 9812 err = nl80211_parse_beacon(rdev, csa_attrs, &params.beacon_csa);
16ef1fe2 9813 if (err)
a05829a7 9814 goto free;
16ef1fe2 9815
a05829a7
JB
9816 if (!csa_attrs[NL80211_ATTR_CNTDWN_OFFS_BEACON]) {
9817 err = -EINVAL;
9818 goto free;
9819 }
16ef1fe2 9820
00c207ed 9821 len = nla_len(csa_attrs[NL80211_ATTR_CNTDWN_OFFS_BEACON]);
a05829a7
JB
9822 if (!len || (len % sizeof(u16))) {
9823 err = -EINVAL;
9824 goto free;
9825 }
16ef1fe2 9826
9a774c78
AO
9827 params.n_counter_offsets_beacon = len / sizeof(u16);
9828 if (rdev->wiphy.max_num_csa_counters &&
9829 (params.n_counter_offsets_beacon >
a05829a7
JB
9830 rdev->wiphy.max_num_csa_counters)) {
9831 err = -EINVAL;
9832 goto free;
9833 }
16ef1fe2 9834
9a774c78 9835 params.counter_offsets_beacon =
00c207ed 9836 nla_data(csa_attrs[NL80211_ATTR_CNTDWN_OFFS_BEACON]);
9a774c78
AO
9837
9838 /* sanity checks - counters should fit and be the same */
9839 for (i = 0; i < params.n_counter_offsets_beacon; i++) {
9840 u16 offset = params.counter_offsets_beacon[i];
9841
a05829a7
JB
9842 if (offset >= params.beacon_csa.tail_len) {
9843 err = -EINVAL;
9844 goto free;
9845 }
9a774c78 9846
a05829a7
JB
9847 if (params.beacon_csa.tail[offset] != params.count) {
9848 err = -EINVAL;
9849 goto free;
9850 }
9a774c78
AO
9851 }
9852
00c207ed
JC
9853 if (csa_attrs[NL80211_ATTR_CNTDWN_OFFS_PRESP]) {
9854 len = nla_len(csa_attrs[NL80211_ATTR_CNTDWN_OFFS_PRESP]);
a05829a7
JB
9855 if (!len || (len % sizeof(u16))) {
9856 err = -EINVAL;
9857 goto free;
9858 }
16ef1fe2 9859
9a774c78
AO
9860 params.n_counter_offsets_presp = len / sizeof(u16);
9861 if (rdev->wiphy.max_num_csa_counters &&
ad5987b4 9862 (params.n_counter_offsets_presp >
a05829a7
JB
9863 rdev->wiphy.max_num_csa_counters)) {
9864 err = -EINVAL;
9865 goto free;
9866 }
9a774c78
AO
9867
9868 params.counter_offsets_presp =
00c207ed 9869 nla_data(csa_attrs[NL80211_ATTR_CNTDWN_OFFS_PRESP]);
9a774c78
AO
9870
9871 /* sanity checks - counters should fit and be the same */
9872 for (i = 0; i < params.n_counter_offsets_presp; i++) {
9873 u16 offset = params.counter_offsets_presp[i];
9874
a05829a7
JB
9875 if (offset >= params.beacon_csa.probe_resp_len) {
9876 err = -EINVAL;
9877 goto free;
9878 }
9a774c78
AO
9879
9880 if (params.beacon_csa.probe_resp[offset] !=
a05829a7
JB
9881 params.count) {
9882 err = -EINVAL;
9883 goto free;
9884 }
9a774c78 9885 }
16ef1fe2
SW
9886 }
9887
ee4bc9e7 9888skip_beacons:
16ef1fe2
SW
9889 err = nl80211_parse_chandef(rdev, info, &params.chandef);
9890 if (err)
a05829a7 9891 goto free;
16ef1fe2 9892
923b352f 9893 if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &params.chandef,
a05829a7
JB
9894 wdev->iftype)) {
9895 err = -EINVAL;
9896 goto free;
9897 }
16ef1fe2 9898
2beb6dab
LC
9899 err = cfg80211_chandef_dfs_required(wdev->wiphy,
9900 &params.chandef,
9901 wdev->iftype);
9902 if (err < 0)
a05829a7 9903 goto free;
2beb6dab 9904
8d9de16f 9905 if (err > 0) {
2beb6dab 9906 params.radar_required = true;
8d9de16f
BB
9907 if (need_handle_dfs_flag &&
9908 !nla_get_flag(info->attrs[NL80211_ATTR_HANDLE_DFS])) {
a05829a7
JB
9909 err = -EINVAL;
9910 goto free;
8d9de16f
BB
9911 }
9912 }
16ef1fe2 9913
16ef1fe2
SW
9914 if (info->attrs[NL80211_ATTR_CH_SWITCH_BLOCK_TX])
9915 params.block_tx = true;
9916
c56589ed
SW
9917 wdev_lock(wdev);
9918 err = rdev_channel_switch(rdev, dev, &params);
9919 wdev_unlock(wdev);
9920
a05829a7 9921free:
dc1e3cb8
JC
9922 kfree(params.beacon_after.mbssid_ies);
9923 kfree(params.beacon_csa.mbssid_ies);
a05829a7 9924 kfree(csa_attrs);
c56589ed 9925 return err;
16ef1fe2
SW
9926}
9927
9720bb3a
JB
9928static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
9929 u32 seq, int flags,
2a519311 9930 struct cfg80211_registered_device *rdev,
48ab905d
JB
9931 struct wireless_dev *wdev,
9932 struct cfg80211_internal_bss *intbss)
2a519311 9933{
48ab905d 9934 struct cfg80211_bss *res = &intbss->pub;
9caf0364 9935 const struct cfg80211_bss_ies *ies;
7b0a0e3c 9936 unsigned int link_id;
2a519311
JB
9937 void *hdr;
9938 struct nlattr *bss;
48ab905d
JB
9939
9940 ASSERT_WDEV_LOCK(wdev);
2a519311 9941
15e47304 9942 hdr = nl80211hdr_put(msg, NETLINK_CB(cb->skb).portid, seq, flags,
2a519311
JB
9943 NL80211_CMD_NEW_SCAN_RESULTS);
9944 if (!hdr)
9945 return -1;
9946
0a833c29 9947 genl_dump_check_consistent(cb, hdr);
9720bb3a 9948
97990a06
JB
9949 if (nla_put_u32(msg, NL80211_ATTR_GENERATION, rdev->bss_generation))
9950 goto nla_put_failure;
9951 if (wdev->netdev &&
9360ffd1
DM
9952 nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex))
9953 goto nla_put_failure;
2dad624e
ND
9954 if (nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
9955 NL80211_ATTR_PAD))
97990a06 9956 goto nla_put_failure;
2a519311 9957
ae0be8de 9958 bss = nla_nest_start_noflag(msg, NL80211_ATTR_BSS);
2a519311
JB
9959 if (!bss)
9960 goto nla_put_failure;
9360ffd1 9961 if ((!is_zero_ether_addr(res->bssid) &&
9caf0364 9962 nla_put(msg, NL80211_BSS_BSSID, ETH_ALEN, res->bssid)))
9360ffd1 9963 goto nla_put_failure;
9caf0364
JB
9964
9965 rcu_read_lock();
0e227084
JB
9966 /* indicate whether we have probe response data or not */
9967 if (rcu_access_pointer(res->proberesp_ies) &&
9968 nla_put_flag(msg, NL80211_BSS_PRESP_DATA))
9969 goto fail_unlock_rcu;
9970
9971 /* this pointer prefers to be pointed to probe response data
9972 * but is always valid
9973 */
9caf0364 9974 ies = rcu_dereference(res->ies);
8cef2c9d 9975 if (ies) {
2dad624e
ND
9976 if (nla_put_u64_64bit(msg, NL80211_BSS_TSF, ies->tsf,
9977 NL80211_BSS_PAD))
8cef2c9d 9978 goto fail_unlock_rcu;
8cef2c9d
JB
9979 if (ies->len && nla_put(msg, NL80211_BSS_INFORMATION_ELEMENTS,
9980 ies->len, ies->data))
9981 goto fail_unlock_rcu;
9caf0364 9982 }
0e227084
JB
9983
9984 /* and this pointer is always (unless driver didn't know) beacon data */
9caf0364 9985 ies = rcu_dereference(res->beacon_ies);
0e227084 9986 if (ies && ies->from_beacon) {
2dad624e
ND
9987 if (nla_put_u64_64bit(msg, NL80211_BSS_BEACON_TSF, ies->tsf,
9988 NL80211_BSS_PAD))
8cef2c9d
JB
9989 goto fail_unlock_rcu;
9990 if (ies->len && nla_put(msg, NL80211_BSS_BEACON_IES,
9991 ies->len, ies->data))
9992 goto fail_unlock_rcu;
9caf0364
JB
9993 }
9994 rcu_read_unlock();
9995
9360ffd1
DM
9996 if (res->beacon_interval &&
9997 nla_put_u16(msg, NL80211_BSS_BEACON_INTERVAL, res->beacon_interval))
9998 goto nla_put_failure;
9999 if (nla_put_u16(msg, NL80211_BSS_CAPABILITY, res->capability) ||
10000 nla_put_u32(msg, NL80211_BSS_FREQUENCY, res->channel->center_freq) ||
942ba88b
TP
10001 nla_put_u32(msg, NL80211_BSS_FREQUENCY_OFFSET,
10002 res->channel->freq_offset) ||
dcd6eac1 10003 nla_put_u32(msg, NL80211_BSS_CHAN_WIDTH, res->scan_width) ||
9360ffd1
DM
10004 nla_put_u32(msg, NL80211_BSS_SEEN_MS_AGO,
10005 jiffies_to_msecs(jiffies - intbss->ts)))
10006 goto nla_put_failure;
2a519311 10007
1d76250b
AS
10008 if (intbss->parent_tsf &&
10009 (nla_put_u64_64bit(msg, NL80211_BSS_PARENT_TSF,
10010 intbss->parent_tsf, NL80211_BSS_PAD) ||
10011 nla_put(msg, NL80211_BSS_PARENT_BSSID, ETH_ALEN,
10012 intbss->parent_bssid)))
10013 goto nla_put_failure;
10014
6e19bc4b 10015 if (intbss->ts_boottime &&
2dad624e
ND
10016 nla_put_u64_64bit(msg, NL80211_BSS_LAST_SEEN_BOOTTIME,
10017 intbss->ts_boottime, NL80211_BSS_PAD))
6e19bc4b
DS
10018 goto nla_put_failure;
10019
983dafaa
SD
10020 if (!nl80211_put_signal(msg, intbss->pub.chains,
10021 intbss->pub.chain_signal,
10022 NL80211_BSS_CHAIN_SIGNAL))
10023 goto nla_put_failure;
10024
77965c97 10025 switch (rdev->wiphy.signal_type) {
2a519311 10026 case CFG80211_SIGNAL_TYPE_MBM:
9360ffd1
DM
10027 if (nla_put_u32(msg, NL80211_BSS_SIGNAL_MBM, res->signal))
10028 goto nla_put_failure;
2a519311
JB
10029 break;
10030 case CFG80211_SIGNAL_TYPE_UNSPEC:
9360ffd1
DM
10031 if (nla_put_u8(msg, NL80211_BSS_SIGNAL_UNSPEC, res->signal))
10032 goto nla_put_failure;
2a519311
JB
10033 break;
10034 default:
10035 break;
10036 }
10037
48ab905d 10038 switch (wdev->iftype) {
074ac8df 10039 case NL80211_IFTYPE_P2P_CLIENT:
48ab905d 10040 case NL80211_IFTYPE_STATION:
7b0a0e3c
JB
10041 for_each_valid_link(wdev, link_id) {
10042 if (intbss == wdev->links[link_id].client.current_bss &&
dd374f84
JB
10043 (nla_put_u32(msg, NL80211_BSS_STATUS,
10044 NL80211_BSS_STATUS_ASSOCIATED) ||
10045 (wdev->valid_links &&
3c512307
VJ
10046 nla_put_u8(msg, NL80211_BSS_MLO_LINK_ID,
10047 link_id))))
7b0a0e3c
JB
10048 goto nla_put_failure;
10049 }
48ab905d
JB
10050 break;
10051 case NL80211_IFTYPE_ADHOC:
7b0a0e3c 10052 if (intbss == wdev->u.ibss.current_bss &&
9360ffd1
DM
10053 nla_put_u32(msg, NL80211_BSS_STATUS,
10054 NL80211_BSS_STATUS_IBSS_JOINED))
10055 goto nla_put_failure;
48ab905d
JB
10056 break;
10057 default:
10058 break;
10059 }
10060
2a519311
JB
10061 nla_nest_end(msg, bss);
10062
053c095a
JB
10063 genlmsg_end(msg, hdr);
10064 return 0;
2a519311 10065
8cef2c9d
JB
10066 fail_unlock_rcu:
10067 rcu_read_unlock();
2a519311
JB
10068 nla_put_failure:
10069 genlmsg_cancel(msg, hdr);
10070 return -EMSGSIZE;
10071}
10072
97990a06 10073static int nl80211_dump_scan(struct sk_buff *skb, struct netlink_callback *cb)
2a519311 10074{
48ab905d 10075 struct cfg80211_registered_device *rdev;
2a519311 10076 struct cfg80211_internal_bss *scan;
48ab905d 10077 struct wireless_dev *wdev;
97990a06 10078 int start = cb->args[2], idx = 0;
2a519311
JB
10079 int err;
10080
ce6b6974 10081 err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev, NULL);
a05829a7 10082 if (err)
67748893 10083 return err;
a05829a7
JB
10084 /* nl80211_prepare_wdev_dump acquired it in the successful case */
10085 __acquire(&rdev->wiphy.mtx);
2a519311 10086
48ab905d
JB
10087 wdev_lock(wdev);
10088 spin_lock_bh(&rdev->bss_lock);
d1e23c94
DK
10089
10090 /*
10091 * dump_scan will be called multiple times to break up the scan results
10092 * into multiple messages. It is unlikely that any more bss-es will be
10093 * expired after the first call, so only call only call this on the
10094 * first dump_scan invocation.
10095 */
10096 if (start == 0)
10097 cfg80211_bss_expire(rdev);
48ab905d 10098
9720bb3a
JB
10099 cb->seq = rdev->bss_generation;
10100
48ab905d 10101 list_for_each_entry(scan, &rdev->bss_list, list) {
2a519311
JB
10102 if (++idx <= start)
10103 continue;
9720bb3a 10104 if (nl80211_send_bss(skb, cb,
2a519311 10105 cb->nlh->nlmsg_seq, NLM_F_MULTI,
48ab905d 10106 rdev, wdev, scan) < 0) {
2a519311 10107 idx--;
67748893 10108 break;
2a519311
JB
10109 }
10110 }
10111
48ab905d
JB
10112 spin_unlock_bh(&rdev->bss_lock);
10113 wdev_unlock(wdev);
2a519311 10114
97990a06 10115 cb->args[2] = idx;
a05829a7 10116 wiphy_unlock(&rdev->wiphy);
2a519311 10117
67748893 10118 return skb->len;
2a519311
JB
10119}
10120
15e47304 10121static int nl80211_send_survey(struct sk_buff *msg, u32 portid, u32 seq,
11f78ac3
JB
10122 int flags, struct net_device *dev,
10123 bool allow_radio_stats,
10124 struct survey_info *survey)
61fa713c
HS
10125{
10126 void *hdr;
10127 struct nlattr *infoattr;
10128
11f78ac3
JB
10129 /* skip radio stats if userspace didn't request them */
10130 if (!survey->channel && !allow_radio_stats)
10131 return 0;
10132
15e47304 10133 hdr = nl80211hdr_put(msg, portid, seq, flags,
61fa713c
HS
10134 NL80211_CMD_NEW_SURVEY_RESULTS);
10135 if (!hdr)
10136 return -ENOMEM;
10137
9360ffd1
DM
10138 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
10139 goto nla_put_failure;
61fa713c 10140
ae0be8de 10141 infoattr = nla_nest_start_noflag(msg, NL80211_ATTR_SURVEY_INFO);
61fa713c
HS
10142 if (!infoattr)
10143 goto nla_put_failure;
10144
11f78ac3
JB
10145 if (survey->channel &&
10146 nla_put_u32(msg, NL80211_SURVEY_INFO_FREQUENCY,
9360ffd1
DM
10147 survey->channel->center_freq))
10148 goto nla_put_failure;
58ef7c1b
TP
10149
10150 if (survey->channel && survey->channel->freq_offset &&
10151 nla_put_u32(msg, NL80211_SURVEY_INFO_FREQUENCY_OFFSET,
10152 survey->channel->freq_offset))
10153 goto nla_put_failure;
9360ffd1
DM
10154
10155 if ((survey->filled & SURVEY_INFO_NOISE_DBM) &&
10156 nla_put_u8(msg, NL80211_SURVEY_INFO_NOISE, survey->noise))
10157 goto nla_put_failure;
10158 if ((survey->filled & SURVEY_INFO_IN_USE) &&
10159 nla_put_flag(msg, NL80211_SURVEY_INFO_IN_USE))
10160 goto nla_put_failure;
4ed20beb 10161 if ((survey->filled & SURVEY_INFO_TIME) &&
2dad624e
ND
10162 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME,
10163 survey->time, NL80211_SURVEY_INFO_PAD))
9360ffd1 10164 goto nla_put_failure;
4ed20beb 10165 if ((survey->filled & SURVEY_INFO_TIME_BUSY) &&
2dad624e
ND
10166 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_BUSY,
10167 survey->time_busy, NL80211_SURVEY_INFO_PAD))
9360ffd1 10168 goto nla_put_failure;
4ed20beb 10169 if ((survey->filled & SURVEY_INFO_TIME_EXT_BUSY) &&
2dad624e
ND
10170 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_EXT_BUSY,
10171 survey->time_ext_busy, NL80211_SURVEY_INFO_PAD))
9360ffd1 10172 goto nla_put_failure;
4ed20beb 10173 if ((survey->filled & SURVEY_INFO_TIME_RX) &&
2dad624e
ND
10174 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_RX,
10175 survey->time_rx, NL80211_SURVEY_INFO_PAD))
9360ffd1 10176 goto nla_put_failure;
4ed20beb 10177 if ((survey->filled & SURVEY_INFO_TIME_TX) &&
2dad624e
ND
10178 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_TX,
10179 survey->time_tx, NL80211_SURVEY_INFO_PAD))
9360ffd1 10180 goto nla_put_failure;
052536ab 10181 if ((survey->filled & SURVEY_INFO_TIME_SCAN) &&
2dad624e
ND
10182 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_SCAN,
10183 survey->time_scan, NL80211_SURVEY_INFO_PAD))
052536ab 10184 goto nla_put_failure;
c8cd6e7f
FF
10185 if ((survey->filled & SURVEY_INFO_TIME_BSS_RX) &&
10186 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_BSS_RX,
10187 survey->time_bss_rx, NL80211_SURVEY_INFO_PAD))
10188 goto nla_put_failure;
61fa713c
HS
10189
10190 nla_nest_end(msg, infoattr);
10191
053c095a
JB
10192 genlmsg_end(msg, hdr);
10193 return 0;
61fa713c
HS
10194
10195 nla_put_failure:
10196 genlmsg_cancel(msg, hdr);
10197 return -EMSGSIZE;
10198}
10199
11f78ac3 10200static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb)
61fa713c 10201{
50508d94 10202 struct nlattr **attrbuf;
61fa713c 10203 struct survey_info survey;
1b8ec87a 10204 struct cfg80211_registered_device *rdev;
97990a06
JB
10205 struct wireless_dev *wdev;
10206 int survey_idx = cb->args[2];
61fa713c 10207 int res;
11f78ac3 10208 bool radio_stats;
61fa713c 10209
50508d94
JB
10210 attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf), GFP_KERNEL);
10211 if (!attrbuf)
10212 return -ENOMEM;
10213
ce6b6974 10214 res = nl80211_prepare_wdev_dump(cb, &rdev, &wdev, attrbuf);
a05829a7
JB
10215 if (res) {
10216 kfree(attrbuf);
10217 return res;
10218 }
10219 /* nl80211_prepare_wdev_dump acquired it in the successful case */
10220 __acquire(&rdev->wiphy.mtx);
61fa713c 10221
11f78ac3 10222 /* prepare_wdev_dump parsed the attributes */
c90c39da 10223 radio_stats = attrbuf[NL80211_ATTR_SURVEY_RADIO_STATS];
11f78ac3 10224
97990a06
JB
10225 if (!wdev->netdev) {
10226 res = -EINVAL;
10227 goto out_err;
10228 }
10229
1b8ec87a 10230 if (!rdev->ops->dump_survey) {
61fa713c
HS
10231 res = -EOPNOTSUPP;
10232 goto out_err;
10233 }
10234
10235 while (1) {
284b38b6 10236 wdev_lock(wdev);
1b8ec87a 10237 res = rdev_dump_survey(rdev, wdev->netdev, survey_idx, &survey);
284b38b6 10238 wdev_unlock(wdev);
61fa713c
HS
10239 if (res == -ENOENT)
10240 break;
10241 if (res)
10242 goto out_err;
10243
11f78ac3
JB
10244 /* don't send disabled channels, but do send non-channel data */
10245 if (survey.channel &&
10246 survey.channel->flags & IEEE80211_CHAN_DISABLED) {
180cdc79
LR
10247 survey_idx++;
10248 continue;
10249 }
10250
61fa713c 10251 if (nl80211_send_survey(skb,
15e47304 10252 NETLINK_CB(cb->skb).portid,
61fa713c 10253 cb->nlh->nlmsg_seq, NLM_F_MULTI,
11f78ac3 10254 wdev->netdev, radio_stats, &survey) < 0)
61fa713c
HS
10255 goto out;
10256 survey_idx++;
10257 }
10258
10259 out:
97990a06 10260 cb->args[2] = survey_idx;
61fa713c
HS
10261 res = skb->len;
10262 out_err:
50508d94 10263 kfree(attrbuf);
a05829a7 10264 wiphy_unlock(&rdev->wiphy);
61fa713c
HS
10265 return res;
10266}
10267
b23aa676
SO
10268static bool nl80211_valid_wpa_versions(u32 wpa_versions)
10269{
10270 return !(wpa_versions & ~(NL80211_WPA_VERSION_1 |
cc3e14c2
CHH
10271 NL80211_WPA_VERSION_2 |
10272 NL80211_WPA_VERSION_3));
b23aa676
SO
10273}
10274
636a5d36
JM
10275static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
10276{
4c476991
JB
10277 struct cfg80211_registered_device *rdev = info->user_ptr[0];
10278 struct net_device *dev = info->user_ptr[1];
19957bb3 10279 struct ieee80211_channel *chan;
325839da
JB
10280 const u8 *bssid, *ssid;
10281 int err, ssid_len;
19957bb3 10282 enum nl80211_auth_type auth_type;
fffd0934 10283 struct key_parse key;
d5cdfacb 10284 bool local_state_change;
325839da 10285 struct cfg80211_auth_request req = {};
942ba88b 10286 u32 freq;
636a5d36 10287
f4a11bb0
JB
10288 if (!info->attrs[NL80211_ATTR_MAC])
10289 return -EINVAL;
10290
1778092e
JM
10291 if (!info->attrs[NL80211_ATTR_AUTH_TYPE])
10292 return -EINVAL;
10293
19957bb3
JB
10294 if (!info->attrs[NL80211_ATTR_SSID])
10295 return -EINVAL;
10296
10297 if (!info->attrs[NL80211_ATTR_WIPHY_FREQ])
10298 return -EINVAL;
10299
fffd0934
JB
10300 err = nl80211_parse_key(info, &key);
10301 if (err)
10302 return err;
10303
10304 if (key.idx >= 0) {
e31b8213
JB
10305 if (key.type != -1 && key.type != NL80211_KEYTYPE_GROUP)
10306 return -EINVAL;
fffd0934
JB
10307 if (!key.p.key || !key.p.key_len)
10308 return -EINVAL;
10309 if ((key.p.cipher != WLAN_CIPHER_SUITE_WEP40 ||
10310 key.p.key_len != WLAN_KEY_LEN_WEP40) &&
10311 (key.p.cipher != WLAN_CIPHER_SUITE_WEP104 ||
10312 key.p.key_len != WLAN_KEY_LEN_WEP104))
10313 return -EINVAL;
b6b5555b 10314 if (key.idx > 3)
fffd0934
JB
10315 return -EINVAL;
10316 } else {
10317 key.p.key_len = 0;
10318 key.p.key = NULL;
10319 }
10320
afea0b7a
JB
10321 if (key.idx >= 0) {
10322 int i;
10323 bool ok = false;
7a087e74 10324
afea0b7a
JB
10325 for (i = 0; i < rdev->wiphy.n_cipher_suites; i++) {
10326 if (key.p.cipher == rdev->wiphy.cipher_suites[i]) {
10327 ok = true;
10328 break;
10329 }
10330 }
4c476991
JB
10331 if (!ok)
10332 return -EINVAL;
afea0b7a
JB
10333 }
10334
4c476991
JB
10335 if (!rdev->ops->auth)
10336 return -EOPNOTSUPP;
636a5d36 10337
074ac8df 10338 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
10339 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
10340 return -EOPNOTSUPP;
eec60b03 10341
19957bb3 10342 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
942ba88b
TP
10343 freq = MHZ_TO_KHZ(nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
10344 if (info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET])
10345 freq +=
10346 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET]);
10347
10348 chan = nl80211_get_valid_chan(&rdev->wiphy, freq);
664834de 10349 if (!chan)
4c476991 10350 return -EINVAL;
636a5d36 10351
19957bb3
JB
10352 ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
10353 ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
636a5d36
JM
10354
10355 if (info->attrs[NL80211_ATTR_IE]) {
325839da
JB
10356 req.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
10357 req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
636a5d36
JM
10358 }
10359
19957bb3 10360 auth_type = nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
e39e5b5e 10361 if (!nl80211_valid_auth_type(rdev, auth_type, NL80211_CMD_AUTHENTICATE))
4c476991 10362 return -EINVAL;
636a5d36 10363
63181060
JM
10364 if ((auth_type == NL80211_AUTHTYPE_SAE ||
10365 auth_type == NL80211_AUTHTYPE_FILS_SK ||
10366 auth_type == NL80211_AUTHTYPE_FILS_SK_PFS ||
10367 auth_type == NL80211_AUTHTYPE_FILS_PK) &&
11b6b5a4 10368 !info->attrs[NL80211_ATTR_AUTH_DATA])
e39e5b5e
JM
10369 return -EINVAL;
10370
11b6b5a4 10371 if (info->attrs[NL80211_ATTR_AUTH_DATA]) {
63181060
JM
10372 if (auth_type != NL80211_AUTHTYPE_SAE &&
10373 auth_type != NL80211_AUTHTYPE_FILS_SK &&
10374 auth_type != NL80211_AUTHTYPE_FILS_SK_PFS &&
10375 auth_type != NL80211_AUTHTYPE_FILS_PK)
e39e5b5e 10376 return -EINVAL;
325839da
JB
10377 req.auth_data = nla_data(info->attrs[NL80211_ATTR_AUTH_DATA]);
10378 req.auth_data_len = nla_len(info->attrs[NL80211_ATTR_AUTH_DATA]);
e39e5b5e
JM
10379 }
10380
d5cdfacb
JM
10381 local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
10382
95de817b
JB
10383 /*
10384 * Since we no longer track auth state, ignore
10385 * requests to only change local state.
10386 */
10387 if (local_state_change)
10388 return 0;
10389
325839da
JB
10390 req.auth_type = auth_type;
10391 req.key = key.p.key;
10392 req.key_len = key.p.key_len;
10393 req.key_idx = key.idx;
d648c230
JB
10394 req.link_id = nl80211_link_id_or_invalid(info->attrs);
10395 if (req.link_id >= 0) {
10396 if (!info->attrs[NL80211_ATTR_MLD_ADDR])
10397 return -EINVAL;
10398 req.ap_mld_addr = nla_data(info->attrs[NL80211_ATTR_MLD_ADDR]);
10399 }
325839da
JB
10400
10401 req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
10402 IEEE80211_BSS_TYPE_ESS,
10403 IEEE80211_PRIVACY_ANY);
10404 if (!req.bss)
10405 return -ENOENT;
10406
91bf9b26 10407 wdev_lock(dev->ieee80211_ptr);
325839da 10408 err = cfg80211_mlme_auth(rdev, dev, &req);
91bf9b26 10409 wdev_unlock(dev->ieee80211_ptr);
325839da
JB
10410
10411 cfg80211_put_bss(&rdev->wiphy, req.bss);
10412
91bf9b26 10413 return err;
636a5d36
JM
10414}
10415
64bf3d4b
DK
10416static int validate_pae_over_nl80211(struct cfg80211_registered_device *rdev,
10417 struct genl_info *info)
10418{
10419 if (!info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
10420 GENL_SET_ERR_MSG(info, "SOCKET_OWNER not set");
10421 return -EINVAL;
10422 }
10423
10424 if (!rdev->ops->tx_control_port ||
10425 !wiphy_ext_feature_isset(&rdev->wiphy,
10426 NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211))
10427 return -EOPNOTSUPP;
10428
10429 return 0;
10430}
10431
c0692b8f
JB
10432static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev,
10433 struct genl_info *info,
3dc27d25
JB
10434 struct cfg80211_crypto_settings *settings,
10435 int cipher_limit)
b23aa676 10436{
c0b2bbd8
JB
10437 memset(settings, 0, sizeof(*settings));
10438
b23aa676
SO
10439 settings->control_port = info->attrs[NL80211_ATTR_CONTROL_PORT];
10440
c0692b8f
JB
10441 if (info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]) {
10442 u16 proto;
7a087e74 10443
c0692b8f
JB
10444 proto = nla_get_u16(
10445 info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]);
10446 settings->control_port_ethertype = cpu_to_be16(proto);
10447 if (!(rdev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) &&
10448 proto != ETH_P_PAE)
10449 return -EINVAL;
10450 if (info->attrs[NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT])
10451 settings->control_port_no_encrypt = true;
10452 } else
10453 settings->control_port_ethertype = cpu_to_be16(ETH_P_PAE);
10454
64bf3d4b
DK
10455 if (info->attrs[NL80211_ATTR_CONTROL_PORT_OVER_NL80211]) {
10456 int r = validate_pae_over_nl80211(rdev, info);
10457
10458 if (r < 0)
10459 return r;
10460
10461 settings->control_port_over_nl80211 = true;
7f3f96ce
MT
10462
10463 if (info->attrs[NL80211_ATTR_CONTROL_PORT_NO_PREAUTH])
10464 settings->control_port_no_preauth = true;
64bf3d4b
DK
10465 }
10466
b23aa676
SO
10467 if (info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE]) {
10468 void *data;
10469 int len, i;
10470
10471 data = nla_data(info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE]);
10472 len = nla_len(info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE]);
10473 settings->n_ciphers_pairwise = len / sizeof(u32);
10474
10475 if (len % sizeof(u32))
10476 return -EINVAL;
10477
3dc27d25 10478 if (settings->n_ciphers_pairwise > cipher_limit)
b23aa676
SO
10479 return -EINVAL;
10480
10481 memcpy(settings->ciphers_pairwise, data, len);
10482
10483 for (i = 0; i < settings->n_ciphers_pairwise; i++)
38ba3c57
JM
10484 if (!cfg80211_supported_cipher_suite(
10485 &rdev->wiphy,
b23aa676
SO
10486 settings->ciphers_pairwise[i]))
10487 return -EINVAL;
10488 }
10489
10490 if (info->attrs[NL80211_ATTR_CIPHER_SUITE_GROUP]) {
10491 settings->cipher_group =
10492 nla_get_u32(info->attrs[NL80211_ATTR_CIPHER_SUITE_GROUP]);
38ba3c57
JM
10493 if (!cfg80211_supported_cipher_suite(&rdev->wiphy,
10494 settings->cipher_group))
b23aa676
SO
10495 return -EINVAL;
10496 }
10497
10498 if (info->attrs[NL80211_ATTR_WPA_VERSIONS]) {
10499 settings->wpa_versions =
10500 nla_get_u32(info->attrs[NL80211_ATTR_WPA_VERSIONS]);
10501 if (!nl80211_valid_wpa_versions(settings->wpa_versions))
10502 return -EINVAL;
10503 }
10504
10505 if (info->attrs[NL80211_ATTR_AKM_SUITES]) {
10506 void *data;
6d30240e 10507 int len;
b23aa676
SO
10508
10509 data = nla_data(info->attrs[NL80211_ATTR_AKM_SUITES]);
10510 len = nla_len(info->attrs[NL80211_ATTR_AKM_SUITES]);
10511 settings->n_akm_suites = len / sizeof(u32);
10512
10513 if (len % sizeof(u32))
10514 return -EINVAL;
10515
ecad3b0b 10516 if (settings->n_akm_suites > rdev->wiphy.max_num_akm_suites)
1b9ca027
JM
10517 return -EINVAL;
10518
b23aa676 10519 memcpy(settings->akm_suites, data, len);
b23aa676
SO
10520 }
10521
91b5ab62
EP
10522 if (info->attrs[NL80211_ATTR_PMK]) {
10523 if (nla_len(info->attrs[NL80211_ATTR_PMK]) != WLAN_PMK_LEN)
10524 return -EINVAL;
10525 if (!wiphy_ext_feature_isset(&rdev->wiphy,
f9662274
CHH
10526 NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK) &&
10527 !wiphy_ext_feature_isset(&rdev->wiphy,
10528 NL80211_EXT_FEATURE_4WAY_HANDSHAKE_AP_PSK))
91b5ab62
EP
10529 return -EINVAL;
10530 settings->psk = nla_data(info->attrs[NL80211_ATTR_PMK]);
10531 }
10532
26f7044e
CHH
10533 if (info->attrs[NL80211_ATTR_SAE_PASSWORD]) {
10534 if (!wiphy_ext_feature_isset(&rdev->wiphy,
2831a631
CHH
10535 NL80211_EXT_FEATURE_SAE_OFFLOAD) &&
10536 !wiphy_ext_feature_isset(&rdev->wiphy,
10537 NL80211_EXT_FEATURE_SAE_OFFLOAD_AP))
26f7044e
CHH
10538 return -EINVAL;
10539 settings->sae_pwd =
10540 nla_data(info->attrs[NL80211_ATTR_SAE_PASSWORD]);
10541 settings->sae_pwd_len =
10542 nla_len(info->attrs[NL80211_ATTR_SAE_PASSWORD]);
10543 }
10544
9f0ffa41
RD
10545 if (info->attrs[NL80211_ATTR_SAE_PWE])
10546 settings->sae_pwe =
10547 nla_get_u8(info->attrs[NL80211_ATTR_SAE_PWE]);
10548 else
10549 settings->sae_pwe = NL80211_SAE_PWE_UNSPECIFIED;
10550
b23aa676
SO
10551 return 0;
10552}
10553
9ecff10e
JB
10554static struct cfg80211_bss *nl80211_assoc_bss(struct cfg80211_registered_device *rdev,
10555 const u8 *ssid, int ssid_len,
10556 struct nlattr **attrs,
10557 const u8 **bssid_out)
10558{
10559 struct ieee80211_channel *chan;
10560 struct cfg80211_bss *bss;
10561 const u8 *bssid;
10562 u32 freq;
10563
10564 if (!attrs[NL80211_ATTR_MAC] || !attrs[NL80211_ATTR_WIPHY_FREQ])
10565 return ERR_PTR(-EINVAL);
10566
10567 bssid = nla_data(attrs[NL80211_ATTR_MAC]);
10568
10569 freq = MHZ_TO_KHZ(nla_get_u32(attrs[NL80211_ATTR_WIPHY_FREQ]));
10570 if (attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET])
10571 freq += nla_get_u32(attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET]);
10572
10573 chan = nl80211_get_valid_chan(&rdev->wiphy, freq);
10574 if (!chan)
10575 return ERR_PTR(-EINVAL);
10576
10577 bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid,
10578 ssid, ssid_len,
10579 IEEE80211_BSS_TYPE_ESS,
10580 IEEE80211_PRIVACY_ANY);
10581 if (!bss)
10582 return ERR_PTR(-ENOENT);
10583
10584 *bssid_out = bssid;
10585 return bss;
10586}
10587
636a5d36
JM
10588static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
10589{
4c476991
JB
10590 struct cfg80211_registered_device *rdev = info->user_ptr[0];
10591 struct net_device *dev = info->user_ptr[1];
f62fab73 10592 struct cfg80211_assoc_request req = {};
d648c230 10593 struct nlattr **attrs = NULL;
f62fab73 10594 const u8 *bssid, *ssid;
d648c230 10595 unsigned int link_id;
0f759448 10596 int err, ssid_len;
636a5d36 10597
bad29297
AZ
10598 if (dev->ieee80211_ptr->conn_owner_nlportid &&
10599 dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)
10600 return -EPERM;
10601
9ecff10e 10602 if (!info->attrs[NL80211_ATTR_SSID])
f4a11bb0
JB
10603 return -EINVAL;
10604
4c476991
JB
10605 if (!rdev->ops->assoc)
10606 return -EOPNOTSUPP;
636a5d36 10607
074ac8df 10608 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
10609 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
10610 return -EOPNOTSUPP;
eec60b03 10611
19957bb3
JB
10612 ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
10613 ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
636a5d36
JM
10614
10615 if (info->attrs[NL80211_ATTR_IE]) {
f62fab73
JB
10616 req.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
10617 req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
636a5d36
JM
10618 }
10619
dc6382ce 10620 if (info->attrs[NL80211_ATTR_USE_MFP]) {
4f5dadce 10621 enum nl80211_mfp mfp =
dc6382ce 10622 nla_get_u32(info->attrs[NL80211_ATTR_USE_MFP]);
4f5dadce 10623 if (mfp == NL80211_MFP_REQUIRED)
f62fab73 10624 req.use_mfp = true;
4c476991
JB
10625 else if (mfp != NL80211_MFP_NO)
10626 return -EINVAL;
dc6382ce
JM
10627 }
10628
3e5d7649 10629 if (info->attrs[NL80211_ATTR_PREV_BSSID])
f62fab73 10630 req.prev_bssid = nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]);
3e5d7649 10631
7e7c8926 10632 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HT]))
f62fab73 10633 req.flags |= ASSOC_REQ_DISABLE_HT;
7e7c8926
BG
10634
10635 if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
f62fab73
JB
10636 memcpy(&req.ht_capa_mask,
10637 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]),
10638 sizeof(req.ht_capa_mask));
7e7c8926
BG
10639
10640 if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
f62fab73 10641 if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
7e7c8926 10642 return -EINVAL;
f62fab73
JB
10643 memcpy(&req.ht_capa,
10644 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]),
10645 sizeof(req.ht_capa));
7e7c8926
BG
10646 }
10647
ee2aca34 10648 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_VHT]))
f62fab73 10649 req.flags |= ASSOC_REQ_DISABLE_VHT;
ee2aca34 10650
b6db0f89
BG
10651 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HE]))
10652 req.flags |= ASSOC_REQ_DISABLE_HE;
10653
36f84235
MS
10654 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_EHT]))
10655 req.flags |= ASSOC_REQ_DISABLE_EHT;
10656
ee2aca34 10657 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK])
f62fab73
JB
10658 memcpy(&req.vht_capa_mask,
10659 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]),
10660 sizeof(req.vht_capa_mask));
ee2aca34
JB
10661
10662 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY]) {
f62fab73 10663 if (!info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK])
ee2aca34 10664 return -EINVAL;
f62fab73
JB
10665 memcpy(&req.vht_capa,
10666 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]),
10667 sizeof(req.vht_capa));
ee2aca34
JB
10668 }
10669
bab5ab7d 10670 if (nla_get_flag(info->attrs[NL80211_ATTR_USE_RRM])) {
0c9ca11b
BL
10671 if (!((rdev->wiphy.features &
10672 NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES) &&
10673 (rdev->wiphy.features & NL80211_FEATURE_QUIET)) &&
10674 !wiphy_ext_feature_isset(&rdev->wiphy,
10675 NL80211_EXT_FEATURE_RRM))
bab5ab7d
AK
10676 return -EINVAL;
10677 req.flags |= ASSOC_REQ_USE_RRM;
10678 }
10679
348bd456
JM
10680 if (info->attrs[NL80211_ATTR_FILS_KEK]) {
10681 req.fils_kek = nla_data(info->attrs[NL80211_ATTR_FILS_KEK]);
10682 req.fils_kek_len = nla_len(info->attrs[NL80211_ATTR_FILS_KEK]);
10683 if (!info->attrs[NL80211_ATTR_FILS_NONCES])
10684 return -EINVAL;
10685 req.fils_nonces =
10686 nla_data(info->attrs[NL80211_ATTR_FILS_NONCES]);
10687 }
10688
d2b7588a
TP
10689 if (info->attrs[NL80211_ATTR_S1G_CAPABILITY_MASK]) {
10690 if (!info->attrs[NL80211_ATTR_S1G_CAPABILITY])
10691 return -EINVAL;
10692 memcpy(&req.s1g_capa_mask,
10693 nla_data(info->attrs[NL80211_ATTR_S1G_CAPABILITY_MASK]),
10694 sizeof(req.s1g_capa_mask));
10695 }
10696
10697 if (info->attrs[NL80211_ATTR_S1G_CAPABILITY]) {
10698 if (!info->attrs[NL80211_ATTR_S1G_CAPABILITY_MASK])
10699 return -EINVAL;
10700 memcpy(&req.s1g_capa,
10701 nla_data(info->attrs[NL80211_ATTR_S1G_CAPABILITY]),
10702 sizeof(req.s1g_capa));
10703 }
10704
d648c230
JB
10705 req.link_id = nl80211_link_id_or_invalid(info->attrs);
10706
10707 if (info->attrs[NL80211_ATTR_MLO_LINKS]) {
10708 unsigned int attrsize = NUM_NL80211_ATTR * sizeof(*attrs);
10709 struct nlattr *link;
10710 int rem = 0;
10711
10712 if (req.link_id < 0)
10713 return -EINVAL;
10714
10715 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_MLO))
10716 return -EINVAL;
10717
10718 if (info->attrs[NL80211_ATTR_MAC] ||
10719 info->attrs[NL80211_ATTR_WIPHY_FREQ] ||
10720 !info->attrs[NL80211_ATTR_MLD_ADDR])
10721 return -EINVAL;
10722
10723 req.ap_mld_addr = nla_data(info->attrs[NL80211_ATTR_MLD_ADDR]);
10724
10725 attrs = kzalloc(attrsize, GFP_KERNEL);
10726 if (!attrs)
10727 return -ENOMEM;
10728
10729 nla_for_each_nested(link,
10730 info->attrs[NL80211_ATTR_MLO_LINKS],
10731 rem) {
10732 memset(attrs, 0, attrsize);
10733
10734 nla_parse_nested(attrs, NL80211_ATTR_MAX,
10735 link, NULL, NULL);
10736
10737 if (!attrs[NL80211_ATTR_MLO_LINK_ID]) {
10738 err = -EINVAL;
10739 goto free;
10740 }
10741
10742 link_id = nla_get_u8(attrs[NL80211_ATTR_MLO_LINK_ID]);
10743 /* cannot use the same link ID again */
10744 if (req.links[link_id].bss) {
10745 err = -EINVAL;
10746 goto free;
10747 }
10748 req.links[link_id].bss =
10749 nl80211_assoc_bss(rdev, ssid, ssid_len, attrs,
10750 &bssid);
10751 if (IS_ERR(req.links[link_id].bss)) {
10752 err = PTR_ERR(req.links[link_id].bss);
10753 goto free;
10754 }
10755
10756 if (attrs[NL80211_ATTR_IE]) {
10757 req.links[link_id].elems =
10758 nla_data(attrs[NL80211_ATTR_IE]);
10759 req.links[link_id].elems_len =
10760 nla_len(attrs[NL80211_ATTR_IE]);
10761 }
10762 }
10763
10764 if (!req.links[req.link_id].bss) {
10765 err = -EINVAL;
10766 goto free;
10767 }
10768
10769 kfree(attrs);
10770 attrs = NULL;
10771 } else {
10772 if (req.link_id >= 0)
10773 return -EINVAL;
10774
10775 req.bss = nl80211_assoc_bss(rdev, ssid, ssid_len, info->attrs,
10776 &bssid);
10777 if (IS_ERR(req.bss))
10778 return PTR_ERR(req.bss);
10779 }
0f759448 10780
f62fab73 10781 err = nl80211_crypto_settings(rdev, info, &req.crypto, 1);
91bf9b26
JB
10782 if (!err) {
10783 wdev_lock(dev->ieee80211_ptr);
bd2522b1 10784
0f759448 10785 err = cfg80211_mlme_assoc(rdev, dev, &req);
bd2522b1
AZ
10786
10787 if (!err && info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
10788 dev->ieee80211_ptr->conn_owner_nlportid =
10789 info->snd_portid;
10790 memcpy(dev->ieee80211_ptr->disconnect_bssid,
10791 bssid, ETH_ALEN);
10792 }
10793
91bf9b26
JB
10794 wdev_unlock(dev->ieee80211_ptr);
10795 }
636a5d36 10796
d648c230
JB
10797free:
10798 for (link_id = 0; link_id < ARRAY_SIZE(req.links); link_id++)
10799 cfg80211_put_bss(&rdev->wiphy, req.links[link_id].bss);
0f759448 10800 cfg80211_put_bss(&rdev->wiphy, req.bss);
d648c230 10801 kfree(attrs);
0f759448 10802
636a5d36
JM
10803 return err;
10804}
10805
10806static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info)
10807{
4c476991
JB
10808 struct cfg80211_registered_device *rdev = info->user_ptr[0];
10809 struct net_device *dev = info->user_ptr[1];
19957bb3 10810 const u8 *ie = NULL, *bssid;
91bf9b26 10811 int ie_len = 0, err;
19957bb3 10812 u16 reason_code;
d5cdfacb 10813 bool local_state_change;
636a5d36 10814
bad29297
AZ
10815 if (dev->ieee80211_ptr->conn_owner_nlportid &&
10816 dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)
10817 return -EPERM;
10818
f4a11bb0
JB
10819 if (!info->attrs[NL80211_ATTR_MAC])
10820 return -EINVAL;
10821
10822 if (!info->attrs[NL80211_ATTR_REASON_CODE])
10823 return -EINVAL;
10824
4c476991
JB
10825 if (!rdev->ops->deauth)
10826 return -EOPNOTSUPP;
636a5d36 10827
074ac8df 10828 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
10829 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
10830 return -EOPNOTSUPP;
eec60b03 10831
19957bb3 10832 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
636a5d36 10833
19957bb3
JB
10834 reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
10835 if (reason_code == 0) {
f4a11bb0 10836 /* Reason Code 0 is reserved */
4c476991 10837 return -EINVAL;
255e737e 10838 }
636a5d36
JM
10839
10840 if (info->attrs[NL80211_ATTR_IE]) {
19957bb3
JB
10841 ie = nla_data(info->attrs[NL80211_ATTR_IE]);
10842 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
636a5d36
JM
10843 }
10844
d5cdfacb
JM
10845 local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
10846
91bf9b26
JB
10847 wdev_lock(dev->ieee80211_ptr);
10848 err = cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code,
10849 local_state_change);
10850 wdev_unlock(dev->ieee80211_ptr);
10851 return err;
636a5d36
JM
10852}
10853
10854static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info)
10855{
4c476991
JB
10856 struct cfg80211_registered_device *rdev = info->user_ptr[0];
10857 struct net_device *dev = info->user_ptr[1];
19957bb3 10858 const u8 *ie = NULL, *bssid;
91bf9b26 10859 int ie_len = 0, err;
19957bb3 10860 u16 reason_code;
d5cdfacb 10861 bool local_state_change;
636a5d36 10862
bad29297
AZ
10863 if (dev->ieee80211_ptr->conn_owner_nlportid &&
10864 dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)
10865 return -EPERM;
10866
f4a11bb0
JB
10867 if (!info->attrs[NL80211_ATTR_MAC])
10868 return -EINVAL;
10869
10870 if (!info->attrs[NL80211_ATTR_REASON_CODE])
10871 return -EINVAL;
10872
4c476991
JB
10873 if (!rdev->ops->disassoc)
10874 return -EOPNOTSUPP;
636a5d36 10875
074ac8df 10876 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
10877 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
10878 return -EOPNOTSUPP;
eec60b03 10879
19957bb3 10880 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
636a5d36 10881
19957bb3
JB
10882 reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
10883 if (reason_code == 0) {
f4a11bb0 10884 /* Reason Code 0 is reserved */
4c476991 10885 return -EINVAL;
255e737e 10886 }
636a5d36
JM
10887
10888 if (info->attrs[NL80211_ATTR_IE]) {
19957bb3
JB
10889 ie = nla_data(info->attrs[NL80211_ATTR_IE]);
10890 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
636a5d36
JM
10891 }
10892
d5cdfacb
JM
10893 local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
10894
91bf9b26
JB
10895 wdev_lock(dev->ieee80211_ptr);
10896 err = cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code,
10897 local_state_change);
10898 wdev_unlock(dev->ieee80211_ptr);
10899 return err;
636a5d36
JM
10900}
10901
dd5b4cc7
FF
10902static bool
10903nl80211_parse_mcast_rate(struct cfg80211_registered_device *rdev,
57fbcce3 10904 int mcast_rate[NUM_NL80211_BANDS],
dd5b4cc7
FF
10905 int rateval)
10906{
10907 struct wiphy *wiphy = &rdev->wiphy;
10908 bool found = false;
10909 int band, i;
10910
57fbcce3 10911 for (band = 0; band < NUM_NL80211_BANDS; band++) {
dd5b4cc7
FF
10912 struct ieee80211_supported_band *sband;
10913
10914 sband = wiphy->bands[band];
10915 if (!sband)
10916 continue;
10917
10918 for (i = 0; i < sband->n_bitrates; i++) {
10919 if (sband->bitrates[i].bitrate == rateval) {
10920 mcast_rate[band] = i + 1;
10921 found = true;
10922 break;
10923 }
10924 }
10925 }
10926
10927 return found;
10928}
10929
04a773ad
JB
10930static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
10931{
4c476991
JB
10932 struct cfg80211_registered_device *rdev = info->user_ptr[0];
10933 struct net_device *dev = info->user_ptr[1];
04a773ad
JB
10934 struct cfg80211_ibss_params ibss;
10935 struct wiphy *wiphy;
fffd0934 10936 struct cfg80211_cached_keys *connkeys = NULL;
04a773ad
JB
10937 int err;
10938
8e30bc55
JB
10939 memset(&ibss, 0, sizeof(ibss));
10940
683b6d3b 10941 if (!info->attrs[NL80211_ATTR_SSID] ||
04a773ad
JB
10942 !nla_len(info->attrs[NL80211_ATTR_SSID]))
10943 return -EINVAL;
10944
8e30bc55
JB
10945 ibss.beacon_interval = 100;
10946
12d20fc9 10947 if (info->attrs[NL80211_ATTR_BEACON_INTERVAL])
8e30bc55
JB
10948 ibss.beacon_interval =
10949 nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
12d20fc9 10950
0c317a02
PK
10951 err = cfg80211_validate_beacon_int(rdev, NL80211_IFTYPE_ADHOC,
10952 ibss.beacon_interval);
12d20fc9
PK
10953 if (err)
10954 return err;
8e30bc55 10955
4c476991
JB
10956 if (!rdev->ops->join_ibss)
10957 return -EOPNOTSUPP;
04a773ad 10958
4c476991
JB
10959 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC)
10960 return -EOPNOTSUPP;
04a773ad 10961
79c97e97 10962 wiphy = &rdev->wiphy;
04a773ad 10963
39193498 10964 if (info->attrs[NL80211_ATTR_MAC]) {
04a773ad 10965 ibss.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
39193498
JB
10966
10967 if (!is_valid_ether_addr(ibss.bssid))
10968 return -EINVAL;
10969 }
04a773ad
JB
10970 ibss.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
10971 ibss.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
10972
10973 if (info->attrs[NL80211_ATTR_IE]) {
10974 ibss.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
10975 ibss.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
10976 }
10977
683b6d3b
JB
10978 err = nl80211_parse_chandef(rdev, info, &ibss.chandef);
10979 if (err)
10980 return err;
04a773ad 10981
174e0cd2
IP
10982 if (!cfg80211_reg_can_beacon(&rdev->wiphy, &ibss.chandef,
10983 NL80211_IFTYPE_ADHOC))
54858ee5
AS
10984 return -EINVAL;
10985
2f301ab2 10986 switch (ibss.chandef.width) {
bf372645
SW
10987 case NL80211_CHAN_WIDTH_5:
10988 case NL80211_CHAN_WIDTH_10:
2f301ab2
SW
10989 case NL80211_CHAN_WIDTH_20_NOHT:
10990 break;
10991 case NL80211_CHAN_WIDTH_20:
10992 case NL80211_CHAN_WIDTH_40:
ffc11991
JD
10993 if (!(rdev->wiphy.features & NL80211_FEATURE_HT_IBSS))
10994 return -EINVAL;
10995 break;
10996 case NL80211_CHAN_WIDTH_80:
10997 case NL80211_CHAN_WIDTH_80P80:
10998 case NL80211_CHAN_WIDTH_160:
10999 if (!(rdev->wiphy.features & NL80211_FEATURE_HT_IBSS))
11000 return -EINVAL;
11001 if (!wiphy_ext_feature_isset(&rdev->wiphy,
11002 NL80211_EXT_FEATURE_VHT_IBSS))
11003 return -EINVAL;
11004 break;
3743bec6
JD
11005 case NL80211_CHAN_WIDTH_320:
11006 return -EINVAL;
2f301ab2 11007 default:
c04d6150 11008 return -EINVAL;
2f301ab2 11009 }
db9c64cf 11010
04a773ad 11011 ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED];
fffd0934
JB
11012 ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY];
11013
fbd2c8dc
TP
11014 if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) {
11015 u8 *rates =
11016 nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
11017 int n_rates =
11018 nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
11019 struct ieee80211_supported_band *sband =
683b6d3b 11020 wiphy->bands[ibss.chandef.chan->band];
fbd2c8dc 11021
34850ab2
JB
11022 err = ieee80211_get_ratemask(sband, rates, n_rates,
11023 &ibss.basic_rates);
11024 if (err)
11025 return err;
fbd2c8dc 11026 }
dd5b4cc7 11027
803768f5
SW
11028 if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
11029 memcpy(&ibss.ht_capa_mask,
11030 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]),
11031 sizeof(ibss.ht_capa_mask));
11032
11033 if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
11034 if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
11035 return -EINVAL;
11036 memcpy(&ibss.ht_capa,
11037 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]),
11038 sizeof(ibss.ht_capa));
11039 }
11040
dd5b4cc7
FF
11041 if (info->attrs[NL80211_ATTR_MCAST_RATE] &&
11042 !nl80211_parse_mcast_rate(rdev, ibss.mcast_rate,
11043 nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE])))
11044 return -EINVAL;
fbd2c8dc 11045
4c476991 11046 if (ibss.privacy && info->attrs[NL80211_ATTR_KEYS]) {
de7044ee
SM
11047 bool no_ht = false;
11048
768075eb 11049 connkeys = nl80211_parse_connkeys(rdev, info, &no_ht);
4c476991
JB
11050 if (IS_ERR(connkeys))
11051 return PTR_ERR(connkeys);
de7044ee 11052
3d9d1d66
JB
11053 if ((ibss.chandef.width != NL80211_CHAN_WIDTH_20_NOHT) &&
11054 no_ht) {
453431a5 11055 kfree_sensitive(connkeys);
de7044ee
SM
11056 return -EINVAL;
11057 }
4c476991 11058 }
04a773ad 11059
267335d6
AQ
11060 ibss.control_port =
11061 nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT]);
11062
c3bfe1f6
DK
11063 if (info->attrs[NL80211_ATTR_CONTROL_PORT_OVER_NL80211]) {
11064 int r = validate_pae_over_nl80211(rdev, info);
11065
d350a0f4 11066 if (r < 0) {
453431a5 11067 kfree_sensitive(connkeys);
c3bfe1f6 11068 return r;
d350a0f4 11069 }
c3bfe1f6
DK
11070
11071 ibss.control_port_over_nl80211 = true;
11072 }
11073
5336fa88
SW
11074 ibss.userspace_handles_dfs =
11075 nla_get_flag(info->attrs[NL80211_ATTR_HANDLE_DFS]);
11076
f8d16d3e
DK
11077 wdev_lock(dev->ieee80211_ptr);
11078 err = __cfg80211_join_ibss(rdev, dev, &ibss, connkeys);
fffd0934 11079 if (err)
453431a5 11080 kfree_sensitive(connkeys);
f8d16d3e
DK
11081 else if (info->attrs[NL80211_ATTR_SOCKET_OWNER])
11082 dev->ieee80211_ptr->conn_owner_nlportid = info->snd_portid;
11083 wdev_unlock(dev->ieee80211_ptr);
11084
04a773ad
JB
11085 return err;
11086}
11087
11088static int nl80211_leave_ibss(struct sk_buff *skb, struct genl_info *info)
11089{
4c476991
JB
11090 struct cfg80211_registered_device *rdev = info->user_ptr[0];
11091 struct net_device *dev = info->user_ptr[1];
04a773ad 11092
4c476991
JB
11093 if (!rdev->ops->leave_ibss)
11094 return -EOPNOTSUPP;
04a773ad 11095
4c476991
JB
11096 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC)
11097 return -EOPNOTSUPP;
04a773ad 11098
4c476991 11099 return cfg80211_leave_ibss(rdev, dev, false);
04a773ad
JB
11100}
11101
f4e583c8
AQ
11102static int nl80211_set_mcast_rate(struct sk_buff *skb, struct genl_info *info)
11103{
11104 struct cfg80211_registered_device *rdev = info->user_ptr[0];
11105 struct net_device *dev = info->user_ptr[1];
57fbcce3 11106 int mcast_rate[NUM_NL80211_BANDS];
f4e583c8
AQ
11107 u32 nla_rate;
11108 int err;
11109
11110 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC &&
876dc930
BVB
11111 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT &&
11112 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_OCB)
f4e583c8
AQ
11113 return -EOPNOTSUPP;
11114
11115 if (!rdev->ops->set_mcast_rate)
11116 return -EOPNOTSUPP;
11117
11118 memset(mcast_rate, 0, sizeof(mcast_rate));
11119
11120 if (!info->attrs[NL80211_ATTR_MCAST_RATE])
11121 return -EINVAL;
11122
11123 nla_rate = nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE]);
11124 if (!nl80211_parse_mcast_rate(rdev, mcast_rate, nla_rate))
11125 return -EINVAL;
11126
a1056b1b 11127 err = rdev_set_mcast_rate(rdev, dev, mcast_rate);
f4e583c8
AQ
11128
11129 return err;
11130}
11131
ad7e718c
JB
11132static struct sk_buff *
11133__cfg80211_alloc_vendor_skb(struct cfg80211_registered_device *rdev,
6c09e791
AK
11134 struct wireless_dev *wdev, int approxlen,
11135 u32 portid, u32 seq, enum nl80211_commands cmd,
567ffc35
JB
11136 enum nl80211_attrs attr,
11137 const struct nl80211_vendor_cmd_info *info,
11138 gfp_t gfp)
ad7e718c
JB
11139{
11140 struct sk_buff *skb;
11141 void *hdr;
11142 struct nlattr *data;
11143
11144 skb = nlmsg_new(approxlen + 100, gfp);
11145 if (!skb)
11146 return NULL;
11147
11148 hdr = nl80211hdr_put(skb, portid, seq, 0, cmd);
11149 if (!hdr) {
11150 kfree_skb(skb);
11151 return NULL;
11152 }
11153
11154 if (nla_put_u32(skb, NL80211_ATTR_WIPHY, rdev->wiphy_idx))
11155 goto nla_put_failure;
567ffc35
JB
11156
11157 if (info) {
11158 if (nla_put_u32(skb, NL80211_ATTR_VENDOR_ID,
11159 info->vendor_id))
11160 goto nla_put_failure;
11161 if (nla_put_u32(skb, NL80211_ATTR_VENDOR_SUBCMD,
11162 info->subcmd))
11163 goto nla_put_failure;
11164 }
11165
6c09e791 11166 if (wdev) {
2dad624e
ND
11167 if (nla_put_u64_64bit(skb, NL80211_ATTR_WDEV,
11168 wdev_id(wdev), NL80211_ATTR_PAD))
6c09e791
AK
11169 goto nla_put_failure;
11170 if (wdev->netdev &&
11171 nla_put_u32(skb, NL80211_ATTR_IFINDEX,
11172 wdev->netdev->ifindex))
11173 goto nla_put_failure;
11174 }
11175
ae0be8de 11176 data = nla_nest_start_noflag(skb, attr);
76e1fb4b
JB
11177 if (!data)
11178 goto nla_put_failure;
ad7e718c
JB
11179
11180 ((void **)skb->cb)[0] = rdev;
11181 ((void **)skb->cb)[1] = hdr;
11182 ((void **)skb->cb)[2] = data;
11183
11184 return skb;
11185
11186 nla_put_failure:
11187 kfree_skb(skb);
11188 return NULL;
11189}
f4e583c8 11190
e03ad6ea 11191struct sk_buff *__cfg80211_alloc_event_skb(struct wiphy *wiphy,
6c09e791 11192 struct wireless_dev *wdev,
e03ad6ea
JB
11193 enum nl80211_commands cmd,
11194 enum nl80211_attrs attr,
55c1fdf0 11195 unsigned int portid,
e03ad6ea
JB
11196 int vendor_event_idx,
11197 int approxlen, gfp_t gfp)
11198{
f26cbf40 11199 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
e03ad6ea
JB
11200 const struct nl80211_vendor_cmd_info *info;
11201
11202 switch (cmd) {
11203 case NL80211_CMD_TESTMODE:
11204 if (WARN_ON(vendor_event_idx != -1))
11205 return NULL;
11206 info = NULL;
11207 break;
11208 case NL80211_CMD_VENDOR:
11209 if (WARN_ON(vendor_event_idx < 0 ||
11210 vendor_event_idx >= wiphy->n_vendor_events))
11211 return NULL;
11212 info = &wiphy->vendor_events[vendor_event_idx];
11213 break;
11214 default:
11215 WARN_ON(1);
11216 return NULL;
11217 }
11218
55c1fdf0 11219 return __cfg80211_alloc_vendor_skb(rdev, wdev, approxlen, portid, 0,
e03ad6ea
JB
11220 cmd, attr, info, gfp);
11221}
11222EXPORT_SYMBOL(__cfg80211_alloc_event_skb);
11223
11224void __cfg80211_send_event_skb(struct sk_buff *skb, gfp_t gfp)
11225{
11226 struct cfg80211_registered_device *rdev = ((void **)skb->cb)[0];
11227 void *hdr = ((void **)skb->cb)[1];
55c1fdf0 11228 struct nlmsghdr *nlhdr = nlmsg_hdr(skb);
e03ad6ea
JB
11229 struct nlattr *data = ((void **)skb->cb)[2];
11230 enum nl80211_multicast_groups mcgrp = NL80211_MCGRP_TESTMODE;
11231
bd8c78e7
JB
11232 /* clear CB data for netlink core to own from now on */
11233 memset(skb->cb, 0, sizeof(skb->cb));
11234
e03ad6ea
JB
11235 nla_nest_end(skb, data);
11236 genlmsg_end(skb, hdr);
11237
55c1fdf0
JB
11238 if (nlhdr->nlmsg_pid) {
11239 genlmsg_unicast(wiphy_net(&rdev->wiphy), skb,
11240 nlhdr->nlmsg_pid);
11241 } else {
11242 if (data->nla_type == NL80211_ATTR_VENDOR_DATA)
11243 mcgrp = NL80211_MCGRP_VENDOR;
e03ad6ea 11244
55c1fdf0
JB
11245 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
11246 skb, 0, mcgrp, gfp);
11247 }
e03ad6ea
JB
11248}
11249EXPORT_SYMBOL(__cfg80211_send_event_skb);
11250
aff89a9b 11251#ifdef CONFIG_NL80211_TESTMODE
aff89a9b
JB
11252static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info)
11253{
4c476991 11254 struct cfg80211_registered_device *rdev = info->user_ptr[0];
a05829a7 11255 struct wireless_dev *wdev;
aff89a9b
JB
11256 int err;
11257
a05829a7
JB
11258 lockdep_assert_held(&rdev->wiphy.mtx);
11259
11260 wdev = __cfg80211_wdev_from_attrs(rdev, genl_info_net(info),
11261 info->attrs);
11262
fc73f11f
DS
11263 if (!rdev->ops->testmode_cmd)
11264 return -EOPNOTSUPP;
11265
11266 if (IS_ERR(wdev)) {
11267 err = PTR_ERR(wdev);
11268 if (err != -EINVAL)
11269 return err;
11270 wdev = NULL;
11271 } else if (wdev->wiphy != &rdev->wiphy) {
11272 return -EINVAL;
11273 }
11274
aff89a9b
JB
11275 if (!info->attrs[NL80211_ATTR_TESTDATA])
11276 return -EINVAL;
11277
ad7e718c 11278 rdev->cur_cmd_info = info;
fc73f11f 11279 err = rdev_testmode_cmd(rdev, wdev,
aff89a9b
JB
11280 nla_data(info->attrs[NL80211_ATTR_TESTDATA]),
11281 nla_len(info->attrs[NL80211_ATTR_TESTDATA]));
ad7e718c 11282 rdev->cur_cmd_info = NULL;
aff89a9b 11283
aff89a9b
JB
11284 return err;
11285}
11286
71063f0e
WYG
11287static int nl80211_testmode_dump(struct sk_buff *skb,
11288 struct netlink_callback *cb)
11289{
00918d33 11290 struct cfg80211_registered_device *rdev;
50508d94 11291 struct nlattr **attrbuf = NULL;
71063f0e
WYG
11292 int err;
11293 long phy_idx;
11294 void *data = NULL;
11295 int data_len = 0;
11296
5fe231e8
JB
11297 rtnl_lock();
11298
71063f0e
WYG
11299 if (cb->args[0]) {
11300 /*
11301 * 0 is a valid index, but not valid for args[0],
11302 * so we need to offset by 1.
11303 */
11304 phy_idx = cb->args[0] - 1;
a4956dca
LC
11305
11306 rdev = cfg80211_rdev_by_wiphy_idx(phy_idx);
11307 if (!rdev) {
11308 err = -ENOENT;
11309 goto out_err;
11310 }
71063f0e 11311 } else {
50508d94
JB
11312 attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf),
11313 GFP_KERNEL);
11314 if (!attrbuf) {
11315 err = -ENOMEM;
11316 goto out_err;
11317 }
c90c39da 11318
8cb08174
JB
11319 err = nlmsg_parse_deprecated(cb->nlh,
11320 GENL_HDRLEN + nl80211_fam.hdrsize,
11321 attrbuf, nl80211_fam.maxattr,
11322 nl80211_policy, NULL);
71063f0e 11323 if (err)
5fe231e8 11324 goto out_err;
00918d33 11325
c90c39da 11326 rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk), attrbuf);
2bd7e35d 11327 if (IS_ERR(rdev)) {
5fe231e8
JB
11328 err = PTR_ERR(rdev);
11329 goto out_err;
00918d33 11330 }
2bd7e35d 11331 phy_idx = rdev->wiphy_idx;
2bd7e35d 11332
c90c39da
JB
11333 if (attrbuf[NL80211_ATTR_TESTDATA])
11334 cb->args[1] = (long)attrbuf[NL80211_ATTR_TESTDATA];
71063f0e
WYG
11335 }
11336
11337 if (cb->args[1]) {
11338 data = nla_data((void *)cb->args[1]);
11339 data_len = nla_len((void *)cb->args[1]);
11340 }
11341
00918d33 11342 if (!rdev->ops->testmode_dump) {
71063f0e
WYG
11343 err = -EOPNOTSUPP;
11344 goto out_err;
11345 }
11346
11347 while (1) {
15e47304 11348 void *hdr = nl80211hdr_put(skb, NETLINK_CB(cb->skb).portid,
71063f0e
WYG
11349 cb->nlh->nlmsg_seq, NLM_F_MULTI,
11350 NL80211_CMD_TESTMODE);
11351 struct nlattr *tmdata;
11352
cb35fba3
DC
11353 if (!hdr)
11354 break;
11355
9360ffd1 11356 if (nla_put_u32(skb, NL80211_ATTR_WIPHY, phy_idx)) {
71063f0e
WYG
11357 genlmsg_cancel(skb, hdr);
11358 break;
11359 }
11360
ae0be8de 11361 tmdata = nla_nest_start_noflag(skb, NL80211_ATTR_TESTDATA);
71063f0e
WYG
11362 if (!tmdata) {
11363 genlmsg_cancel(skb, hdr);
11364 break;
11365 }
e35e4d28 11366 err = rdev_testmode_dump(rdev, skb, cb, data, data_len);
71063f0e
WYG
11367 nla_nest_end(skb, tmdata);
11368
11369 if (err == -ENOBUFS || err == -ENOENT) {
11370 genlmsg_cancel(skb, hdr);
11371 break;
11372 } else if (err) {
11373 genlmsg_cancel(skb, hdr);
11374 goto out_err;
11375 }
11376
11377 genlmsg_end(skb, hdr);
11378 }
11379
11380 err = skb->len;
11381 /* see above */
11382 cb->args[0] = phy_idx + 1;
11383 out_err:
50508d94 11384 kfree(attrbuf);
5fe231e8 11385 rtnl_unlock();
71063f0e
WYG
11386 return err;
11387}
aff89a9b
JB
11388#endif
11389
b23aa676
SO
11390static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
11391{
4c476991
JB
11392 struct cfg80211_registered_device *rdev = info->user_ptr[0];
11393 struct net_device *dev = info->user_ptr[1];
b23aa676
SO
11394 struct cfg80211_connect_params connect;
11395 struct wiphy *wiphy;
fffd0934 11396 struct cfg80211_cached_keys *connkeys = NULL;
942ba88b 11397 u32 freq = 0;
b23aa676
SO
11398 int err;
11399
11400 memset(&connect, 0, sizeof(connect));
11401
b23aa676
SO
11402 if (!info->attrs[NL80211_ATTR_SSID] ||
11403 !nla_len(info->attrs[NL80211_ATTR_SSID]))
11404 return -EINVAL;
11405
11406 if (info->attrs[NL80211_ATTR_AUTH_TYPE]) {
11407 connect.auth_type =
11408 nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
e39e5b5e
JM
11409 if (!nl80211_valid_auth_type(rdev, connect.auth_type,
11410 NL80211_CMD_CONNECT))
b23aa676
SO
11411 return -EINVAL;
11412 } else
11413 connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
11414
11415 connect.privacy = info->attrs[NL80211_ATTR_PRIVACY];
11416
3a00df57
AS
11417 if (info->attrs[NL80211_ATTR_WANT_1X_4WAY_HS] &&
11418 !wiphy_ext_feature_isset(&rdev->wiphy,
11419 NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X))
11420 return -EINVAL;
11421 connect.want_1x = info->attrs[NL80211_ATTR_WANT_1X_4WAY_HS];
11422
c0692b8f 11423 err = nl80211_crypto_settings(rdev, info, &connect.crypto,
3dc27d25 11424 NL80211_MAX_NR_CIPHER_SUITES);
b23aa676
SO
11425 if (err)
11426 return err;
b23aa676 11427
074ac8df 11428 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
11429 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
11430 return -EOPNOTSUPP;
b23aa676 11431
79c97e97 11432 wiphy = &rdev->wiphy;
b23aa676 11433
4486ea98
BS
11434 connect.bg_scan_period = -1;
11435 if (info->attrs[NL80211_ATTR_BG_SCAN_PERIOD] &&
11436 (wiphy->flags & WIPHY_FLAG_SUPPORTS_FW_ROAM)) {
11437 connect.bg_scan_period =
11438 nla_get_u16(info->attrs[NL80211_ATTR_BG_SCAN_PERIOD]);
11439 }
11440
b23aa676
SO
11441 if (info->attrs[NL80211_ATTR_MAC])
11442 connect.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
1df4a510
JM
11443 else if (info->attrs[NL80211_ATTR_MAC_HINT])
11444 connect.bssid_hint =
11445 nla_data(info->attrs[NL80211_ATTR_MAC_HINT]);
b23aa676
SO
11446 connect.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
11447 connect.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
11448
11449 if (info->attrs[NL80211_ATTR_IE]) {
11450 connect.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
11451 connect.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
11452 }
11453
cee00a95
JM
11454 if (info->attrs[NL80211_ATTR_USE_MFP]) {
11455 connect.mfp = nla_get_u32(info->attrs[NL80211_ATTR_USE_MFP]);
65026002
EG
11456 if (connect.mfp == NL80211_MFP_OPTIONAL &&
11457 !wiphy_ext_feature_isset(&rdev->wiphy,
11458 NL80211_EXT_FEATURE_MFP_OPTIONAL))
11459 return -EOPNOTSUPP;
cee00a95
JM
11460 } else {
11461 connect.mfp = NL80211_MFP_NO;
11462 }
11463
ba6fbacf
JM
11464 if (info->attrs[NL80211_ATTR_PREV_BSSID])
11465 connect.prev_bssid =
11466 nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]);
11467
942ba88b
TP
11468 if (info->attrs[NL80211_ATTR_WIPHY_FREQ])
11469 freq = MHZ_TO_KHZ(nla_get_u32(
11470 info->attrs[NL80211_ATTR_WIPHY_FREQ]));
11471 if (info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET])
11472 freq +=
11473 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET]);
11474
11475 if (freq) {
11476 connect.channel = nl80211_get_valid_chan(wiphy, freq);
664834de 11477 if (!connect.channel)
1df4a510
JM
11478 return -EINVAL;
11479 } else if (info->attrs[NL80211_ATTR_WIPHY_FREQ_HINT]) {
942ba88b
TP
11480 freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ_HINT]);
11481 freq = MHZ_TO_KHZ(freq);
11482 connect.channel_hint = nl80211_get_valid_chan(wiphy, freq);
664834de 11483 if (!connect.channel_hint)
4c476991 11484 return -EINVAL;
b23aa676
SO
11485 }
11486
2a38075c
AAL
11487 if (info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]) {
11488 connect.edmg.channels =
11489 nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]);
11490
11491 if (info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG])
11492 connect.edmg.bw_config =
11493 nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG]);
11494 }
11495
fffd0934 11496 if (connect.privacy && info->attrs[NL80211_ATTR_KEYS]) {
768075eb 11497 connkeys = nl80211_parse_connkeys(rdev, info, NULL);
4c476991
JB
11498 if (IS_ERR(connkeys))
11499 return PTR_ERR(connkeys);
fffd0934
JB
11500 }
11501
7e7c8926
BG
11502 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HT]))
11503 connect.flags |= ASSOC_REQ_DISABLE_HT;
11504
11505 if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
11506 memcpy(&connect.ht_capa_mask,
11507 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]),
11508 sizeof(connect.ht_capa_mask));
11509
11510 if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
b4e4f47e 11511 if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]) {
453431a5 11512 kfree_sensitive(connkeys);
7e7c8926 11513 return -EINVAL;
b4e4f47e 11514 }
7e7c8926
BG
11515 memcpy(&connect.ht_capa,
11516 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]),
11517 sizeof(connect.ht_capa));
11518 }
11519
ee2aca34
JB
11520 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_VHT]))
11521 connect.flags |= ASSOC_REQ_DISABLE_VHT;
11522
b6db0f89
BG
11523 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HE]))
11524 connect.flags |= ASSOC_REQ_DISABLE_HE;
11525
36f84235
MS
11526 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_EHT]))
11527 connect.flags |= ASSOC_REQ_DISABLE_EHT;
11528
ee2aca34
JB
11529 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK])
11530 memcpy(&connect.vht_capa_mask,
11531 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]),
11532 sizeof(connect.vht_capa_mask));
11533
11534 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY]) {
11535 if (!info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]) {
453431a5 11536 kfree_sensitive(connkeys);
ee2aca34
JB
11537 return -EINVAL;
11538 }
11539 memcpy(&connect.vht_capa,
11540 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]),
11541 sizeof(connect.vht_capa));
11542 }
11543
bab5ab7d 11544 if (nla_get_flag(info->attrs[NL80211_ATTR_USE_RRM])) {
0c9ca11b
BL
11545 if (!((rdev->wiphy.features &
11546 NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES) &&
11547 (rdev->wiphy.features & NL80211_FEATURE_QUIET)) &&
11548 !wiphy_ext_feature_isset(&rdev->wiphy,
11549 NL80211_EXT_FEATURE_RRM)) {
453431a5 11550 kfree_sensitive(connkeys);
bab5ab7d 11551 return -EINVAL;
707554b4 11552 }
bab5ab7d
AK
11553 connect.flags |= ASSOC_REQ_USE_RRM;
11554 }
11555
34d50519 11556 connect.pbss = nla_get_flag(info->attrs[NL80211_ATTR_PBSS]);
57fbcce3 11557 if (connect.pbss && !rdev->wiphy.bands[NL80211_BAND_60GHZ]) {
453431a5 11558 kfree_sensitive(connkeys);
34d50519
LD
11559 return -EOPNOTSUPP;
11560 }
11561
38de03d2
AS
11562 if (info->attrs[NL80211_ATTR_BSS_SELECT]) {
11563 /* bss selection makes no sense if bssid is set */
11564 if (connect.bssid) {
453431a5 11565 kfree_sensitive(connkeys);
38de03d2
AS
11566 return -EINVAL;
11567 }
11568
11569 err = parse_bss_select(info->attrs[NL80211_ATTR_BSS_SELECT],
11570 wiphy, &connect.bss_select);
11571 if (err) {
453431a5 11572 kfree_sensitive(connkeys);
38de03d2
AS
11573 return err;
11574 }
11575 }
11576
a3caf744
VK
11577 if (wiphy_ext_feature_isset(&rdev->wiphy,
11578 NL80211_EXT_FEATURE_FILS_SK_OFFLOAD) &&
11579 info->attrs[NL80211_ATTR_FILS_ERP_USERNAME] &&
11580 info->attrs[NL80211_ATTR_FILS_ERP_REALM] &&
11581 info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] &&
11582 info->attrs[NL80211_ATTR_FILS_ERP_RRK]) {
11583 connect.fils_erp_username =
11584 nla_data(info->attrs[NL80211_ATTR_FILS_ERP_USERNAME]);
11585 connect.fils_erp_username_len =
11586 nla_len(info->attrs[NL80211_ATTR_FILS_ERP_USERNAME]);
11587 connect.fils_erp_realm =
11588 nla_data(info->attrs[NL80211_ATTR_FILS_ERP_REALM]);
11589 connect.fils_erp_realm_len =
11590 nla_len(info->attrs[NL80211_ATTR_FILS_ERP_REALM]);
11591 connect.fils_erp_next_seq_num =
11592 nla_get_u16(
11593 info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM]);
11594 connect.fils_erp_rrk =
11595 nla_data(info->attrs[NL80211_ATTR_FILS_ERP_RRK]);
11596 connect.fils_erp_rrk_len =
11597 nla_len(info->attrs[NL80211_ATTR_FILS_ERP_RRK]);
11598 } else if (info->attrs[NL80211_ATTR_FILS_ERP_USERNAME] ||
11599 info->attrs[NL80211_ATTR_FILS_ERP_REALM] ||
11600 info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] ||
11601 info->attrs[NL80211_ATTR_FILS_ERP_RRK]) {
453431a5 11602 kfree_sensitive(connkeys);
a3caf744
VK
11603 return -EINVAL;
11604 }
11605
40cbfa90
SD
11606 if (nla_get_flag(info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])) {
11607 if (!info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
453431a5 11608 kfree_sensitive(connkeys);
40cbfa90
SD
11609 GENL_SET_ERR_MSG(info,
11610 "external auth requires connection ownership");
11611 return -EINVAL;
11612 }
11613 connect.flags |= CONNECT_REQ_EXTERNAL_AUTH_SUPPORT;
11614 }
11615
efbabc11
VJ
11616 if (nla_get_flag(info->attrs[NL80211_ATTR_MLO_SUPPORT]))
11617 connect.flags |= CONNECT_REQ_MLO_SUPPORT;
11618
83739b03 11619 wdev_lock(dev->ieee80211_ptr);
bd2522b1 11620
4ce2bd9c
JM
11621 err = cfg80211_connect(rdev, dev, &connect, connkeys,
11622 connect.prev_bssid);
fffd0934 11623 if (err)
453431a5 11624 kfree_sensitive(connkeys);
bd2522b1
AZ
11625
11626 if (!err && info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
11627 dev->ieee80211_ptr->conn_owner_nlportid = info->snd_portid;
11628 if (connect.bssid)
11629 memcpy(dev->ieee80211_ptr->disconnect_bssid,
11630 connect.bssid, ETH_ALEN);
11631 else
3b1648f1 11632 eth_zero_addr(dev->ieee80211_ptr->disconnect_bssid);
bd2522b1
AZ
11633 }
11634
11635 wdev_unlock(dev->ieee80211_ptr);
11636
b23aa676
SO
11637 return err;
11638}
11639
088e8df8 11640static int nl80211_update_connect_params(struct sk_buff *skb,
11641 struct genl_info *info)
11642{
11643 struct cfg80211_connect_params connect = {};
11644 struct cfg80211_registered_device *rdev = info->user_ptr[0];
11645 struct net_device *dev = info->user_ptr[1];
11646 struct wireless_dev *wdev = dev->ieee80211_ptr;
7f9a3e15
VK
11647 bool fils_sk_offload;
11648 u32 auth_type;
088e8df8 11649 u32 changed = 0;
11650 int ret;
11651
11652 if (!rdev->ops->update_connect_params)
11653 return -EOPNOTSUPP;
11654
11655 if (info->attrs[NL80211_ATTR_IE]) {
088e8df8 11656 connect.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
11657 connect.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
11658 changed |= UPDATE_ASSOC_IES;
11659 }
11660
7f9a3e15
VK
11661 fils_sk_offload = wiphy_ext_feature_isset(&rdev->wiphy,
11662 NL80211_EXT_FEATURE_FILS_SK_OFFLOAD);
11663
11664 /*
11665 * when driver supports fils-sk offload all attributes must be
11666 * provided. So the else covers "fils-sk-not-all" and
11667 * "no-fils-sk-any".
11668 */
11669 if (fils_sk_offload &&
11670 info->attrs[NL80211_ATTR_FILS_ERP_USERNAME] &&
11671 info->attrs[NL80211_ATTR_FILS_ERP_REALM] &&
11672 info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] &&
11673 info->attrs[NL80211_ATTR_FILS_ERP_RRK]) {
11674 connect.fils_erp_username =
11675 nla_data(info->attrs[NL80211_ATTR_FILS_ERP_USERNAME]);
11676 connect.fils_erp_username_len =
11677 nla_len(info->attrs[NL80211_ATTR_FILS_ERP_USERNAME]);
11678 connect.fils_erp_realm =
11679 nla_data(info->attrs[NL80211_ATTR_FILS_ERP_REALM]);
11680 connect.fils_erp_realm_len =
11681 nla_len(info->attrs[NL80211_ATTR_FILS_ERP_REALM]);
11682 connect.fils_erp_next_seq_num =
11683 nla_get_u16(
11684 info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM]);
11685 connect.fils_erp_rrk =
11686 nla_data(info->attrs[NL80211_ATTR_FILS_ERP_RRK]);
11687 connect.fils_erp_rrk_len =
11688 nla_len(info->attrs[NL80211_ATTR_FILS_ERP_RRK]);
11689 changed |= UPDATE_FILS_ERP_INFO;
11690 } else if (info->attrs[NL80211_ATTR_FILS_ERP_USERNAME] ||
11691 info->attrs[NL80211_ATTR_FILS_ERP_REALM] ||
11692 info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] ||
11693 info->attrs[NL80211_ATTR_FILS_ERP_RRK]) {
11694 return -EINVAL;
11695 }
11696
11697 if (info->attrs[NL80211_ATTR_AUTH_TYPE]) {
11698 auth_type = nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
11699 if (!nl80211_valid_auth_type(rdev, auth_type,
11700 NL80211_CMD_CONNECT))
11701 return -EINVAL;
11702
11703 if (auth_type == NL80211_AUTHTYPE_FILS_SK &&
11704 fils_sk_offload && !(changed & UPDATE_FILS_ERP_INFO))
11705 return -EINVAL;
11706
11707 connect.auth_type = auth_type;
11708 changed |= UPDATE_AUTH_TYPE;
11709 }
11710
088e8df8 11711 wdev_lock(dev->ieee80211_ptr);
7b0a0e3c 11712 if (!wdev->connected)
088e8df8 11713 ret = -ENOLINK;
11714 else
11715 ret = rdev_update_connect_params(rdev, dev, &connect, changed);
11716 wdev_unlock(dev->ieee80211_ptr);
11717
11718 return ret;
11719}
11720
b23aa676
SO
11721static int nl80211_disconnect(struct sk_buff *skb, struct genl_info *info)
11722{
4c476991
JB
11723 struct cfg80211_registered_device *rdev = info->user_ptr[0];
11724 struct net_device *dev = info->user_ptr[1];
b23aa676 11725 u16 reason;
83739b03 11726 int ret;
b23aa676 11727
bad29297
AZ
11728 if (dev->ieee80211_ptr->conn_owner_nlportid &&
11729 dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)
11730 return -EPERM;
11731
b23aa676
SO
11732 if (!info->attrs[NL80211_ATTR_REASON_CODE])
11733 reason = WLAN_REASON_DEAUTH_LEAVING;
11734 else
11735 reason = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
11736
11737 if (reason == 0)
11738 return -EINVAL;
11739
074ac8df 11740 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
11741 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
11742 return -EOPNOTSUPP;
b23aa676 11743
83739b03
JB
11744 wdev_lock(dev->ieee80211_ptr);
11745 ret = cfg80211_disconnect(rdev, dev, reason, true);
11746 wdev_unlock(dev->ieee80211_ptr);
11747 return ret;
b23aa676
SO
11748}
11749
463d0183
JB
11750static int nl80211_wiphy_netns(struct sk_buff *skb, struct genl_info *info)
11751{
4c476991 11752 struct cfg80211_registered_device *rdev = info->user_ptr[0];
463d0183
JB
11753 struct net *net;
11754 int err;
463d0183 11755
4b681c82
VK
11756 if (info->attrs[NL80211_ATTR_PID]) {
11757 u32 pid = nla_get_u32(info->attrs[NL80211_ATTR_PID]);
11758
11759 net = get_net_ns_by_pid(pid);
11760 } else if (info->attrs[NL80211_ATTR_NETNS_FD]) {
11761 u32 fd = nla_get_u32(info->attrs[NL80211_ATTR_NETNS_FD]);
463d0183 11762
4b681c82
VK
11763 net = get_net_ns_by_fd(fd);
11764 } else {
11765 return -EINVAL;
11766 }
463d0183 11767
4c476991
JB
11768 if (IS_ERR(net))
11769 return PTR_ERR(net);
463d0183
JB
11770
11771 err = 0;
11772
11773 /* check if anything to do */
4c476991
JB
11774 if (!net_eq(wiphy_net(&rdev->wiphy), net))
11775 err = cfg80211_switch_netns(rdev, net);
463d0183 11776
463d0183 11777 put_net(net);
463d0183
JB
11778 return err;
11779}
11780
67fbb16b
SO
11781static int nl80211_setdel_pmksa(struct sk_buff *skb, struct genl_info *info)
11782{
4c476991 11783 struct cfg80211_registered_device *rdev = info->user_ptr[0];
67fbb16b
SO
11784 int (*rdev_ops)(struct wiphy *wiphy, struct net_device *dev,
11785 struct cfg80211_pmksa *pmksa) = NULL;
4c476991 11786 struct net_device *dev = info->user_ptr[1];
67fbb16b
SO
11787 struct cfg80211_pmksa pmksa;
11788
11789 memset(&pmksa, 0, sizeof(struct cfg80211_pmksa));
11790
67fbb16b
SO
11791 if (!info->attrs[NL80211_ATTR_PMKID])
11792 return -EINVAL;
11793
67fbb16b 11794 pmksa.pmkid = nla_data(info->attrs[NL80211_ATTR_PMKID]);
a3caf744
VK
11795
11796 if (info->attrs[NL80211_ATTR_MAC]) {
11797 pmksa.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
11798 } else if (info->attrs[NL80211_ATTR_SSID] &&
11799 info->attrs[NL80211_ATTR_FILS_CACHE_ID] &&
11800 (info->genlhdr->cmd == NL80211_CMD_DEL_PMKSA ||
11801 info->attrs[NL80211_ATTR_PMK])) {
11802 pmksa.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
11803 pmksa.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
11804 pmksa.cache_id =
11805 nla_data(info->attrs[NL80211_ATTR_FILS_CACHE_ID]);
11806 } else {
11807 return -EINVAL;
11808 }
11809 if (info->attrs[NL80211_ATTR_PMK]) {
11810 pmksa.pmk = nla_data(info->attrs[NL80211_ATTR_PMK]);
11811 pmksa.pmk_len = nla_len(info->attrs[NL80211_ATTR_PMK]);
11812 }
67fbb16b 11813
7fc82af8
VJ
11814 if (info->attrs[NL80211_ATTR_PMK_LIFETIME])
11815 pmksa.pmk_lifetime =
11816 nla_get_u32(info->attrs[NL80211_ATTR_PMK_LIFETIME]);
11817
11818 if (info->attrs[NL80211_ATTR_PMK_REAUTH_THRESHOLD])
11819 pmksa.pmk_reauth_threshold =
11820 nla_get_u8(
11821 info->attrs[NL80211_ATTR_PMK_REAUTH_THRESHOLD]);
11822
074ac8df 11823 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
6c900360
LD
11824 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT &&
11825 !(dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP &&
11826 wiphy_ext_feature_isset(&rdev->wiphy,
11827 NL80211_EXT_FEATURE_AP_PMKSA_CACHING)))
4c476991 11828 return -EOPNOTSUPP;
67fbb16b
SO
11829
11830 switch (info->genlhdr->cmd) {
11831 case NL80211_CMD_SET_PMKSA:
11832 rdev_ops = rdev->ops->set_pmksa;
11833 break;
11834 case NL80211_CMD_DEL_PMKSA:
11835 rdev_ops = rdev->ops->del_pmksa;
11836 break;
11837 default:
11838 WARN_ON(1);
11839 break;
11840 }
11841
4c476991
JB
11842 if (!rdev_ops)
11843 return -EOPNOTSUPP;
67fbb16b 11844
4c476991 11845 return rdev_ops(&rdev->wiphy, dev, &pmksa);
67fbb16b
SO
11846}
11847
11848static int nl80211_flush_pmksa(struct sk_buff *skb, struct genl_info *info)
11849{
4c476991
JB
11850 struct cfg80211_registered_device *rdev = info->user_ptr[0];
11851 struct net_device *dev = info->user_ptr[1];
67fbb16b 11852
074ac8df 11853 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
11854 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
11855 return -EOPNOTSUPP;
67fbb16b 11856
4c476991
JB
11857 if (!rdev->ops->flush_pmksa)
11858 return -EOPNOTSUPP;
67fbb16b 11859
e35e4d28 11860 return rdev_flush_pmksa(rdev, dev);
67fbb16b
SO
11861}
11862
109086ce
AN
11863static int nl80211_tdls_mgmt(struct sk_buff *skb, struct genl_info *info)
11864{
11865 struct cfg80211_registered_device *rdev = info->user_ptr[0];
11866 struct net_device *dev = info->user_ptr[1];
11867 u8 action_code, dialog_token;
df942e7b 11868 u32 peer_capability = 0;
109086ce
AN
11869 u16 status_code;
11870 u8 *peer;
31fa97c5 11871 bool initiator;
109086ce
AN
11872
11873 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) ||
11874 !rdev->ops->tdls_mgmt)
11875 return -EOPNOTSUPP;
11876
11877 if (!info->attrs[NL80211_ATTR_TDLS_ACTION] ||
11878 !info->attrs[NL80211_ATTR_STATUS_CODE] ||
11879 !info->attrs[NL80211_ATTR_TDLS_DIALOG_TOKEN] ||
11880 !info->attrs[NL80211_ATTR_IE] ||
11881 !info->attrs[NL80211_ATTR_MAC])
11882 return -EINVAL;
11883
11884 peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
11885 action_code = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_ACTION]);
11886 status_code = nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]);
11887 dialog_token = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_DIALOG_TOKEN]);
31fa97c5 11888 initiator = nla_get_flag(info->attrs[NL80211_ATTR_TDLS_INITIATOR]);
df942e7b
SDU
11889 if (info->attrs[NL80211_ATTR_TDLS_PEER_CAPABILITY])
11890 peer_capability =
11891 nla_get_u32(info->attrs[NL80211_ATTR_TDLS_PEER_CAPABILITY]);
109086ce 11892
e35e4d28 11893 return rdev_tdls_mgmt(rdev, dev, peer, action_code,
df942e7b 11894 dialog_token, status_code, peer_capability,
31fa97c5 11895 initiator,
e35e4d28
HG
11896 nla_data(info->attrs[NL80211_ATTR_IE]),
11897 nla_len(info->attrs[NL80211_ATTR_IE]));
109086ce
AN
11898}
11899
11900static int nl80211_tdls_oper(struct sk_buff *skb, struct genl_info *info)
11901{
11902 struct cfg80211_registered_device *rdev = info->user_ptr[0];
11903 struct net_device *dev = info->user_ptr[1];
11904 enum nl80211_tdls_operation operation;
11905 u8 *peer;
11906
11907 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) ||
11908 !rdev->ops->tdls_oper)
11909 return -EOPNOTSUPP;
11910
11911 if (!info->attrs[NL80211_ATTR_TDLS_OPERATION] ||
11912 !info->attrs[NL80211_ATTR_MAC])
11913 return -EINVAL;
11914
11915 operation = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_OPERATION]);
11916 peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
11917
e35e4d28 11918 return rdev_tdls_oper(rdev, dev, peer, operation);
109086ce
AN
11919}
11920
9588bbd5
JM
11921static int nl80211_remain_on_channel(struct sk_buff *skb,
11922 struct genl_info *info)
11923{
4c476991 11924 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7b0a0e3c 11925 unsigned int link_id = nl80211_link_id(info->attrs);
71bbc994 11926 struct wireless_dev *wdev = info->user_ptr[1];
683b6d3b 11927 struct cfg80211_chan_def chandef;
9588bbd5
JM
11928 struct sk_buff *msg;
11929 void *hdr;
11930 u64 cookie;
683b6d3b 11931 u32 duration;
9588bbd5
JM
11932 int err;
11933
11934 if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] ||
11935 !info->attrs[NL80211_ATTR_DURATION])
11936 return -EINVAL;
11937
11938 duration = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]);
11939
ebf348fc
JB
11940 if (!rdev->ops->remain_on_channel ||
11941 !(rdev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL))
11942 return -EOPNOTSUPP;
11943
9588bbd5 11944 /*
ebf348fc
JB
11945 * We should be on that channel for at least a minimum amount of
11946 * time (10ms) but no longer than the driver supports.
9588bbd5 11947 */
ebf348fc 11948 if (duration < NL80211_MIN_REMAIN_ON_CHANNEL_TIME ||
a293911d 11949 duration > rdev->wiphy.max_remain_on_channel_duration)
9588bbd5
JM
11950 return -EINVAL;
11951
683b6d3b
JB
11952 err = nl80211_parse_chandef(rdev, info, &chandef);
11953 if (err)
11954 return err;
9588bbd5 11955
34373d12 11956 wdev_lock(wdev);
7b0a0e3c
JB
11957 if (!cfg80211_off_channel_oper_allowed(wdev, chandef.chan)) {
11958 const struct cfg80211_chan_def *oper_chandef, *compat_chandef;
11959
11960 oper_chandef = wdev_chandef(wdev, link_id);
11961
11962 if (WARN_ON(!oper_chandef)) {
11963 /* cannot happen since we must beacon to get here */
11964 WARN_ON(1);
11965 wdev_unlock(wdev);
11966 return -EBUSY;
11967 }
11968
11969 /* note: returns first one if identical chandefs */
11970 compat_chandef = cfg80211_chandef_compatible(&chandef,
11971 oper_chandef);
11972
34373d12
VT
11973 if (compat_chandef != &chandef) {
11974 wdev_unlock(wdev);
11975 return -EBUSY;
11976 }
11977 }
11978 wdev_unlock(wdev);
11979
9588bbd5 11980 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4c476991
JB
11981 if (!msg)
11982 return -ENOMEM;
9588bbd5 11983
15e47304 11984 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
9588bbd5 11985 NL80211_CMD_REMAIN_ON_CHANNEL);
cb35fba3
DC
11986 if (!hdr) {
11987 err = -ENOBUFS;
9588bbd5
JM
11988 goto free_msg;
11989 }
11990
683b6d3b
JB
11991 err = rdev_remain_on_channel(rdev, wdev, chandef.chan,
11992 duration, &cookie);
9588bbd5
JM
11993
11994 if (err)
11995 goto free_msg;
11996
2dad624e
ND
11997 if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
11998 NL80211_ATTR_PAD))
9360ffd1 11999 goto nla_put_failure;
9588bbd5
JM
12000
12001 genlmsg_end(msg, hdr);
4c476991
JB
12002
12003 return genlmsg_reply(msg, info);
9588bbd5
JM
12004
12005 nla_put_failure:
12006 err = -ENOBUFS;
12007 free_msg:
12008 nlmsg_free(msg);
9588bbd5
JM
12009 return err;
12010}
12011
12012static int nl80211_cancel_remain_on_channel(struct sk_buff *skb,
12013 struct genl_info *info)
12014{
4c476991 12015 struct cfg80211_registered_device *rdev = info->user_ptr[0];
71bbc994 12016 struct wireless_dev *wdev = info->user_ptr[1];
9588bbd5 12017 u64 cookie;
9588bbd5
JM
12018
12019 if (!info->attrs[NL80211_ATTR_COOKIE])
12020 return -EINVAL;
12021
4c476991
JB
12022 if (!rdev->ops->cancel_remain_on_channel)
12023 return -EOPNOTSUPP;
9588bbd5 12024
9588bbd5
JM
12025 cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);
12026
e35e4d28 12027 return rdev_cancel_remain_on_channel(rdev, wdev, cookie);
9588bbd5
JM
12028}
12029
13ae75b1
JM
12030static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
12031 struct genl_info *info)
12032{
13ae75b1 12033 struct cfg80211_bitrate_mask mask;
7b0a0e3c 12034 unsigned int link_id = nl80211_link_id(info->attrs);
a7c7fbff 12035 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4c476991 12036 struct net_device *dev = info->user_ptr[1];
f971e188 12037 struct wireless_dev *wdev = dev->ieee80211_ptr;
a7c7fbff 12038 int err;
13ae75b1 12039
4c476991
JB
12040 if (!rdev->ops->set_bitrate_mask)
12041 return -EOPNOTSUPP;
13ae75b1 12042
f971e188 12043 wdev_lock(wdev);
9a5f6488 12044 err = nl80211_parse_tx_bitrate_mask(info, info->attrs,
eb89a6a6 12045 NL80211_ATTR_TX_RATES, &mask,
7b0a0e3c 12046 dev, true, link_id);
a7c7fbff 12047 if (err)
f971e188 12048 goto out;
13ae75b1 12049
7b0a0e3c 12050 err = rdev_set_bitrate_mask(rdev, dev, link_id, NULL, &mask);
f971e188
JB
12051out:
12052 wdev_unlock(wdev);
12053 return err;
13ae75b1
JM
12054}
12055
2e161f78 12056static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info)
026331c4 12057{
4c476991 12058 struct cfg80211_registered_device *rdev = info->user_ptr[0];
71bbc994 12059 struct wireless_dev *wdev = info->user_ptr[1];
2e161f78 12060 u16 frame_type = IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION;
026331c4
JM
12061
12062 if (!info->attrs[NL80211_ATTR_FRAME_MATCH])
12063 return -EINVAL;
12064
2e161f78
JB
12065 if (info->attrs[NL80211_ATTR_FRAME_TYPE])
12066 frame_type = nla_get_u16(info->attrs[NL80211_ATTR_FRAME_TYPE]);
026331c4 12067
71bbc994
JB
12068 switch (wdev->iftype) {
12069 case NL80211_IFTYPE_STATION:
12070 case NL80211_IFTYPE_ADHOC:
12071 case NL80211_IFTYPE_P2P_CLIENT:
12072 case NL80211_IFTYPE_AP:
12073 case NL80211_IFTYPE_AP_VLAN:
12074 case NL80211_IFTYPE_MESH_POINT:
12075 case NL80211_IFTYPE_P2P_GO:
98104fde 12076 case NL80211_IFTYPE_P2P_DEVICE:
71bbc994 12077 break;
cb3b7d87 12078 case NL80211_IFTYPE_NAN:
71bbc994 12079 default:
4c476991 12080 return -EOPNOTSUPP;
71bbc994 12081 }
026331c4
JM
12082
12083 /* not much point in registering if we can't reply */
4c476991
JB
12084 if (!rdev->ops->mgmt_tx)
12085 return -EOPNOTSUPP;
026331c4 12086
9dba48a6
JB
12087 if (info->attrs[NL80211_ATTR_RECEIVE_MULTICAST] &&
12088 !wiphy_ext_feature_isset(&rdev->wiphy,
12089 NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS)) {
12090 GENL_SET_ERR_MSG(info,
12091 "multicast RX registrations are not supported");
12092 return -EOPNOTSUPP;
12093 }
12094
15e47304 12095 return cfg80211_mlme_register_mgmt(wdev, info->snd_portid, frame_type,
ff74c51e
IP
12096 nla_data(info->attrs[NL80211_ATTR_FRAME_MATCH]),
12097 nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH]),
9dba48a6 12098 info->attrs[NL80211_ATTR_RECEIVE_MULTICAST],
ff74c51e 12099 info->extack);
026331c4
JM
12100}
12101
2e161f78 12102static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
026331c4 12103{
4c476991 12104 struct cfg80211_registered_device *rdev = info->user_ptr[0];
71bbc994 12105 struct wireless_dev *wdev = info->user_ptr[1];
683b6d3b 12106 struct cfg80211_chan_def chandef;
026331c4 12107 int err;
d64d373f 12108 void *hdr = NULL;
026331c4 12109 u64 cookie;
e247bd90 12110 struct sk_buff *msg = NULL;
b176e629
AO
12111 struct cfg80211_mgmt_tx_params params = {
12112 .dont_wait_for_ack =
12113 info->attrs[NL80211_ATTR_DONT_WAIT_FOR_ACK],
12114 };
026331c4 12115
683b6d3b 12116 if (!info->attrs[NL80211_ATTR_FRAME])
026331c4
JM
12117 return -EINVAL;
12118
4c476991
JB
12119 if (!rdev->ops->mgmt_tx)
12120 return -EOPNOTSUPP;
026331c4 12121
71bbc994 12122 switch (wdev->iftype) {
ea141b75
AQ
12123 case NL80211_IFTYPE_P2P_DEVICE:
12124 if (!info->attrs[NL80211_ATTR_WIPHY_FREQ])
12125 return -EINVAL;
d7832c71 12126 break;
71bbc994
JB
12127 case NL80211_IFTYPE_STATION:
12128 case NL80211_IFTYPE_ADHOC:
12129 case NL80211_IFTYPE_P2P_CLIENT:
12130 case NL80211_IFTYPE_AP:
12131 case NL80211_IFTYPE_AP_VLAN:
12132 case NL80211_IFTYPE_MESH_POINT:
12133 case NL80211_IFTYPE_P2P_GO:
12134 break;
cb3b7d87 12135 case NL80211_IFTYPE_NAN:
71bbc994 12136 default:
4c476991 12137 return -EOPNOTSUPP;
71bbc994 12138 }
026331c4 12139
f7ca38df 12140 if (info->attrs[NL80211_ATTR_DURATION]) {
7c4ef712 12141 if (!(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX))
f7ca38df 12142 return -EINVAL;
b176e629 12143 params.wait = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]);
ebf348fc
JB
12144
12145 /*
12146 * We should wait on the channel for at least a minimum amount
12147 * of time (10ms) but no longer than the driver supports.
12148 */
b176e629
AO
12149 if (params.wait < NL80211_MIN_REMAIN_ON_CHANNEL_TIME ||
12150 params.wait > rdev->wiphy.max_remain_on_channel_duration)
ebf348fc 12151 return -EINVAL;
f7ca38df
JB
12152 }
12153
b176e629 12154 params.offchan = info->attrs[NL80211_ATTR_OFFCHANNEL_TX_OK];
f7ca38df 12155
b176e629 12156 if (params.offchan && !(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX))
7c4ef712
JB
12157 return -EINVAL;
12158
b176e629 12159 params.no_cck = nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]);
e9f935e3 12160
ea141b75
AQ
12161 /* get the channel if any has been specified, otherwise pass NULL to
12162 * the driver. The latter will use the current one
12163 */
12164 chandef.chan = NULL;
12165 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
12166 err = nl80211_parse_chandef(rdev, info, &chandef);
12167 if (err)
12168 return err;
12169 }
12170
b176e629 12171 if (!chandef.chan && params.offchan)
ea141b75 12172 return -EINVAL;
026331c4 12173
34373d12 12174 wdev_lock(wdev);
7b0a0e3c
JB
12175 if (params.offchan &&
12176 !cfg80211_off_channel_oper_allowed(wdev, chandef.chan)) {
34373d12
VT
12177 wdev_unlock(wdev);
12178 return -EBUSY;
12179 }
12180 wdev_unlock(wdev);
12181
34d22ce2
AO
12182 params.buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
12183 params.len = nla_len(info->attrs[NL80211_ATTR_FRAME]);
12184
12185 if (info->attrs[NL80211_ATTR_CSA_C_OFFSETS_TX]) {
12186 int len = nla_len(info->attrs[NL80211_ATTR_CSA_C_OFFSETS_TX]);
12187 int i;
12188
12189 if (len % sizeof(u16))
12190 return -EINVAL;
12191
12192 params.n_csa_offsets = len / sizeof(u16);
12193 params.csa_offsets =
12194 nla_data(info->attrs[NL80211_ATTR_CSA_C_OFFSETS_TX]);
12195
12196 /* check that all the offsets fit the frame */
12197 for (i = 0; i < params.n_csa_offsets; i++) {
12198 if (params.csa_offsets[i] >= params.len)
12199 return -EINVAL;
12200 }
12201 }
12202
b176e629 12203 if (!params.dont_wait_for_ack) {
e247bd90
JB
12204 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
12205 if (!msg)
12206 return -ENOMEM;
026331c4 12207
15e47304 12208 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
e247bd90 12209 NL80211_CMD_FRAME);
cb35fba3
DC
12210 if (!hdr) {
12211 err = -ENOBUFS;
e247bd90
JB
12212 goto free_msg;
12213 }
026331c4 12214 }
e247bd90 12215
b176e629
AO
12216 params.chan = chandef.chan;
12217 err = cfg80211_mlme_mgmt_tx(rdev, wdev, &params, &cookie);
026331c4
JM
12218 if (err)
12219 goto free_msg;
12220
e247bd90 12221 if (msg) {
2dad624e
ND
12222 if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
12223 NL80211_ATTR_PAD))
9360ffd1 12224 goto nla_put_failure;
026331c4 12225
e247bd90
JB
12226 genlmsg_end(msg, hdr);
12227 return genlmsg_reply(msg, info);
12228 }
12229
12230 return 0;
026331c4
JM
12231
12232 nla_put_failure:
12233 err = -ENOBUFS;
12234 free_msg:
12235 nlmsg_free(msg);
026331c4
JM
12236 return err;
12237}
12238
f7ca38df
JB
12239static int nl80211_tx_mgmt_cancel_wait(struct sk_buff *skb, struct genl_info *info)
12240{
12241 struct cfg80211_registered_device *rdev = info->user_ptr[0];
71bbc994 12242 struct wireless_dev *wdev = info->user_ptr[1];
f7ca38df
JB
12243 u64 cookie;
12244
12245 if (!info->attrs[NL80211_ATTR_COOKIE])
12246 return -EINVAL;
12247
12248 if (!rdev->ops->mgmt_tx_cancel_wait)
12249 return -EOPNOTSUPP;
12250
71bbc994
JB
12251 switch (wdev->iftype) {
12252 case NL80211_IFTYPE_STATION:
12253 case NL80211_IFTYPE_ADHOC:
12254 case NL80211_IFTYPE_P2P_CLIENT:
12255 case NL80211_IFTYPE_AP:
12256 case NL80211_IFTYPE_AP_VLAN:
12257 case NL80211_IFTYPE_P2P_GO:
98104fde 12258 case NL80211_IFTYPE_P2P_DEVICE:
71bbc994 12259 break;
cb3b7d87 12260 case NL80211_IFTYPE_NAN:
71bbc994 12261 default:
f7ca38df 12262 return -EOPNOTSUPP;
71bbc994 12263 }
f7ca38df
JB
12264
12265 cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);
12266
e35e4d28 12267 return rdev_mgmt_tx_cancel_wait(rdev, wdev, cookie);
f7ca38df
JB
12268}
12269
ffb9eb3d
KV
12270static int nl80211_set_power_save(struct sk_buff *skb, struct genl_info *info)
12271{
4c476991 12272 struct cfg80211_registered_device *rdev = info->user_ptr[0];
ffb9eb3d 12273 struct wireless_dev *wdev;
4c476991 12274 struct net_device *dev = info->user_ptr[1];
ffb9eb3d
KV
12275 u8 ps_state;
12276 bool state;
12277 int err;
12278
4c476991
JB
12279 if (!info->attrs[NL80211_ATTR_PS_STATE])
12280 return -EINVAL;
ffb9eb3d
KV
12281
12282 ps_state = nla_get_u32(info->attrs[NL80211_ATTR_PS_STATE]);
12283
ffb9eb3d
KV
12284 wdev = dev->ieee80211_ptr;
12285
4c476991
JB
12286 if (!rdev->ops->set_power_mgmt)
12287 return -EOPNOTSUPP;
ffb9eb3d
KV
12288
12289 state = (ps_state == NL80211_PS_ENABLED) ? true : false;
12290
12291 if (state == wdev->ps)
4c476991 12292 return 0;
ffb9eb3d 12293
e35e4d28 12294 err = rdev_set_power_mgmt(rdev, dev, state, wdev->ps_timeout);
4c476991
JB
12295 if (!err)
12296 wdev->ps = state;
ffb9eb3d
KV
12297 return err;
12298}
12299
12300static int nl80211_get_power_save(struct sk_buff *skb, struct genl_info *info)
12301{
4c476991 12302 struct cfg80211_registered_device *rdev = info->user_ptr[0];
ffb9eb3d
KV
12303 enum nl80211_ps_state ps_state;
12304 struct wireless_dev *wdev;
4c476991 12305 struct net_device *dev = info->user_ptr[1];
ffb9eb3d
KV
12306 struct sk_buff *msg;
12307 void *hdr;
12308 int err;
12309
ffb9eb3d
KV
12310 wdev = dev->ieee80211_ptr;
12311
4c476991
JB
12312 if (!rdev->ops->set_power_mgmt)
12313 return -EOPNOTSUPP;
ffb9eb3d
KV
12314
12315 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4c476991
JB
12316 if (!msg)
12317 return -ENOMEM;
ffb9eb3d 12318
15e47304 12319 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
ffb9eb3d
KV
12320 NL80211_CMD_GET_POWER_SAVE);
12321 if (!hdr) {
4c476991 12322 err = -ENOBUFS;
ffb9eb3d
KV
12323 goto free_msg;
12324 }
12325
12326 if (wdev->ps)
12327 ps_state = NL80211_PS_ENABLED;
12328 else
12329 ps_state = NL80211_PS_DISABLED;
12330
9360ffd1
DM
12331 if (nla_put_u32(msg, NL80211_ATTR_PS_STATE, ps_state))
12332 goto nla_put_failure;
ffb9eb3d
KV
12333
12334 genlmsg_end(msg, hdr);
4c476991 12335 return genlmsg_reply(msg, info);
ffb9eb3d 12336
4c476991 12337 nla_put_failure:
ffb9eb3d 12338 err = -ENOBUFS;
4c476991 12339 free_msg:
ffb9eb3d 12340 nlmsg_free(msg);
ffb9eb3d
KV
12341 return err;
12342}
12343
94e860f1
JB
12344static const struct nla_policy
12345nl80211_attr_cqm_policy[NL80211_ATTR_CQM_MAX + 1] = {
4a4b8169 12346 [NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_BINARY },
d6dc1a38
JO
12347 [NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U32 },
12348 [NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 },
84f10708
TP
12349 [NL80211_ATTR_CQM_TXE_RATE] = { .type = NLA_U32 },
12350 [NL80211_ATTR_CQM_TXE_PKTS] = { .type = NLA_U32 },
12351 [NL80211_ATTR_CQM_TXE_INTVL] = { .type = NLA_U32 },
bee427b8 12352 [NL80211_ATTR_CQM_RSSI_LEVEL] = { .type = NLA_S32 },
d6dc1a38
JO
12353};
12354
84f10708 12355static int nl80211_set_cqm_txe(struct genl_info *info,
d9d8b019 12356 u32 rate, u32 pkts, u32 intvl)
84f10708
TP
12357{
12358 struct cfg80211_registered_device *rdev = info->user_ptr[0];
84f10708 12359 struct net_device *dev = info->user_ptr[1];
1da5fcc8 12360 struct wireless_dev *wdev = dev->ieee80211_ptr;
84f10708 12361
d9d8b019 12362 if (rate > 100 || intvl > NL80211_CQM_TXE_MAX_INTVL)
84f10708
TP
12363 return -EINVAL;
12364
84f10708
TP
12365 if (!rdev->ops->set_cqm_txe_config)
12366 return -EOPNOTSUPP;
12367
12368 if (wdev->iftype != NL80211_IFTYPE_STATION &&
12369 wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
12370 return -EOPNOTSUPP;
12371
e35e4d28 12372 return rdev_set_cqm_txe_config(rdev, dev, rate, pkts, intvl);
84f10708
TP
12373}
12374
4a4b8169
AZ
12375static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev,
12376 struct net_device *dev)
12377{
12378 struct wireless_dev *wdev = dev->ieee80211_ptr;
12379 s32 last, low, high;
12380 u32 hyst;
1222a160 12381 int i, n, low_index;
4a4b8169
AZ
12382 int err;
12383
12384 /* RSSI reporting disabled? */
12385 if (!wdev->cqm_config)
12386 return rdev_set_cqm_rssi_range_config(rdev, dev, 0, 0);
12387
12388 /*
12389 * Obtain current RSSI value if possible, if not and no RSSI threshold
12390 * event has been received yet, we should receive an event after a
12391 * connection is established and enough beacons received to calculate
12392 * the average.
12393 */
7b0a0e3c
JB
12394 if (!wdev->cqm_config->last_rssi_event_value &&
12395 wdev->links[0].client.current_bss &&
4a4b8169 12396 rdev->ops->get_station) {
73887fd9 12397 struct station_info sinfo = {};
4a4b8169
AZ
12398 u8 *mac_addr;
12399
7b0a0e3c 12400 mac_addr = wdev->links[0].client.current_bss->pub.bssid;
4a4b8169 12401
73887fd9
JB
12402 err = rdev_get_station(rdev, dev, mac_addr, &sinfo);
12403 if (err)
4a4b8169
AZ
12404 return err;
12405
df16737d 12406 cfg80211_sinfo_release_content(&sinfo);
397c657a 12407 if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_BEACON_SIGNAL_AVG))
4a4b8169 12408 wdev->cqm_config->last_rssi_event_value =
73887fd9 12409 (s8) sinfo.rx_beacon_signal_avg;
4a4b8169
AZ
12410 }
12411
12412 last = wdev->cqm_config->last_rssi_event_value;
12413 hyst = wdev->cqm_config->rssi_hyst;
12414 n = wdev->cqm_config->n_rssi_thresholds;
12415
4b2c5a14
MH
12416 for (i = 0; i < n; i++) {
12417 i = array_index_nospec(i, n);
4a4b8169
AZ
12418 if (last < wdev->cqm_config->rssi_thresholds[i])
12419 break;
4b2c5a14 12420 }
4a4b8169 12421
1222a160
MH
12422 low_index = i - 1;
12423 if (low_index >= 0) {
12424 low_index = array_index_nospec(low_index, n);
12425 low = wdev->cqm_config->rssi_thresholds[low_index] - hyst;
12426 } else {
12427 low = S32_MIN;
12428 }
12429 if (i < n) {
12430 i = array_index_nospec(i, n);
12431 high = wdev->cqm_config->rssi_thresholds[i] + hyst - 1;
12432 } else {
12433 high = S32_MAX;
12434 }
4a4b8169
AZ
12435
12436 return rdev_set_cqm_rssi_range_config(rdev, dev, low, high);
12437}
12438
d6dc1a38 12439static int nl80211_set_cqm_rssi(struct genl_info *info,
4a4b8169
AZ
12440 const s32 *thresholds, int n_thresholds,
12441 u32 hysteresis)
d6dc1a38 12442{
4c476991 12443 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4c476991 12444 struct net_device *dev = info->user_ptr[1];
1da5fcc8 12445 struct wireless_dev *wdev = dev->ieee80211_ptr;
4a4b8169
AZ
12446 int i, err;
12447 s32 prev = S32_MIN;
d6dc1a38 12448
4a4b8169
AZ
12449 /* Check all values negative and sorted */
12450 for (i = 0; i < n_thresholds; i++) {
12451 if (thresholds[i] > 0 || thresholds[i] <= prev)
12452 return -EINVAL;
d6dc1a38 12453
4a4b8169
AZ
12454 prev = thresholds[i];
12455 }
d6dc1a38 12456
074ac8df 12457 if (wdev->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
12458 wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
12459 return -EOPNOTSUPP;
d6dc1a38 12460
4a4b8169
AZ
12461 wdev_lock(wdev);
12462 cfg80211_cqm_config_free(wdev);
12463 wdev_unlock(wdev);
12464
12465 if (n_thresholds <= 1 && rdev->ops->set_cqm_rssi_config) {
12466 if (n_thresholds == 0 || thresholds[0] == 0) /* Disabling */
12467 return rdev_set_cqm_rssi_config(rdev, dev, 0, 0);
12468
12469 return rdev_set_cqm_rssi_config(rdev, dev,
12470 thresholds[0], hysteresis);
12471 }
12472
12473 if (!wiphy_ext_feature_isset(&rdev->wiphy,
12474 NL80211_EXT_FEATURE_CQM_RSSI_LIST))
12475 return -EOPNOTSUPP;
12476
12477 if (n_thresholds == 1 && thresholds[0] == 0) /* Disabling */
12478 n_thresholds = 0;
12479
12480 wdev_lock(wdev);
12481 if (n_thresholds) {
12482 struct cfg80211_cqm_config *cqm_config;
12483
40f231e7
LB
12484 cqm_config = kzalloc(struct_size(cqm_config, rssi_thresholds,
12485 n_thresholds),
12486 GFP_KERNEL);
4a4b8169
AZ
12487 if (!cqm_config) {
12488 err = -ENOMEM;
12489 goto unlock;
12490 }
12491
12492 cqm_config->rssi_hyst = hysteresis;
12493 cqm_config->n_rssi_thresholds = n_thresholds;
12494 memcpy(cqm_config->rssi_thresholds, thresholds,
40f231e7
LB
12495 flex_array_size(cqm_config, rssi_thresholds,
12496 n_thresholds));
4a4b8169
AZ
12497
12498 wdev->cqm_config = cqm_config;
12499 }
12500
12501 err = cfg80211_cqm_rssi_update(rdev, dev);
12502
12503unlock:
12504 wdev_unlock(wdev);
12505
12506 return err;
d6dc1a38
JO
12507}
12508
12509static int nl80211_set_cqm(struct sk_buff *skb, struct genl_info *info)
12510{
12511 struct nlattr *attrs[NL80211_ATTR_CQM_MAX + 1];
12512 struct nlattr *cqm;
12513 int err;
12514
12515 cqm = info->attrs[NL80211_ATTR_CQM];
1da5fcc8
JB
12516 if (!cqm)
12517 return -EINVAL;
d6dc1a38 12518
8cb08174
JB
12519 err = nla_parse_nested_deprecated(attrs, NL80211_ATTR_CQM_MAX, cqm,
12520 nl80211_attr_cqm_policy,
12521 info->extack);
d6dc1a38 12522 if (err)
1da5fcc8 12523 return err;
d6dc1a38
JO
12524
12525 if (attrs[NL80211_ATTR_CQM_RSSI_THOLD] &&
12526 attrs[NL80211_ATTR_CQM_RSSI_HYST]) {
4a4b8169
AZ
12527 const s32 *thresholds =
12528 nla_data(attrs[NL80211_ATTR_CQM_RSSI_THOLD]);
12529 int len = nla_len(attrs[NL80211_ATTR_CQM_RSSI_THOLD]);
1da5fcc8 12530 u32 hysteresis = nla_get_u32(attrs[NL80211_ATTR_CQM_RSSI_HYST]);
d6dc1a38 12531
4a4b8169
AZ
12532 if (len % 4)
12533 return -EINVAL;
12534
12535 return nl80211_set_cqm_rssi(info, thresholds, len / 4,
12536 hysteresis);
1da5fcc8
JB
12537 }
12538
12539 if (attrs[NL80211_ATTR_CQM_TXE_RATE] &&
12540 attrs[NL80211_ATTR_CQM_TXE_PKTS] &&
12541 attrs[NL80211_ATTR_CQM_TXE_INTVL]) {
12542 u32 rate = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_RATE]);
12543 u32 pkts = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_PKTS]);
12544 u32 intvl = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_INTVL]);
12545
12546 return nl80211_set_cqm_txe(info, rate, pkts, intvl);
12547 }
12548
12549 return -EINVAL;
d6dc1a38
JO
12550}
12551
6e0bd6c3
RL
12552static int nl80211_join_ocb(struct sk_buff *skb, struct genl_info *info)
12553{
12554 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12555 struct net_device *dev = info->user_ptr[1];
12556 struct ocb_setup setup = {};
12557 int err;
12558
12559 err = nl80211_parse_chandef(rdev, info, &setup.chandef);
12560 if (err)
12561 return err;
12562
12563 return cfg80211_join_ocb(rdev, dev, &setup);
12564}
12565
12566static int nl80211_leave_ocb(struct sk_buff *skb, struct genl_info *info)
12567{
12568 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12569 struct net_device *dev = info->user_ptr[1];
12570
12571 return cfg80211_leave_ocb(rdev, dev);
12572}
12573
29cbe68c
JB
12574static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info)
12575{
12576 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12577 struct net_device *dev = info->user_ptr[1];
12578 struct mesh_config cfg;
c80d545d 12579 struct mesh_setup setup;
29cbe68c
JB
12580 int err;
12581
12582 /* start with default */
12583 memcpy(&cfg, &default_mesh_config, sizeof(cfg));
c80d545d 12584 memcpy(&setup, &default_mesh_setup, sizeof(setup));
29cbe68c 12585
24bdd9f4 12586 if (info->attrs[NL80211_ATTR_MESH_CONFIG]) {
29cbe68c 12587 /* and parse parameters if given */
24bdd9f4 12588 err = nl80211_parse_mesh_config(info, &cfg, NULL);
29cbe68c
JB
12589 if (err)
12590 return err;
12591 }
12592
12593 if (!info->attrs[NL80211_ATTR_MESH_ID] ||
12594 !nla_len(info->attrs[NL80211_ATTR_MESH_ID]))
12595 return -EINVAL;
12596
c80d545d
JC
12597 setup.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]);
12598 setup.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
12599
4bb62344
CYY
12600 if (info->attrs[NL80211_ATTR_MCAST_RATE] &&
12601 !nl80211_parse_mcast_rate(rdev, setup.mcast_rate,
12602 nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE])))
12603 return -EINVAL;
12604
9bdbf04d
MP
12605 if (info->attrs[NL80211_ATTR_BEACON_INTERVAL]) {
12606 setup.beacon_interval =
12607 nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
12d20fc9 12608
0c317a02
PK
12609 err = cfg80211_validate_beacon_int(rdev,
12610 NL80211_IFTYPE_MESH_POINT,
12611 setup.beacon_interval);
12d20fc9
PK
12612 if (err)
12613 return err;
9bdbf04d
MP
12614 }
12615
12616 if (info->attrs[NL80211_ATTR_DTIM_PERIOD]) {
12617 setup.dtim_period =
12618 nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);
12619 if (setup.dtim_period < 1 || setup.dtim_period > 100)
12620 return -EINVAL;
12621 }
12622
c80d545d
JC
12623 if (info->attrs[NL80211_ATTR_MESH_SETUP]) {
12624 /* parse additional setup parameters if given */
12625 err = nl80211_parse_mesh_setup(info, &setup);
12626 if (err)
12627 return err;
12628 }
12629
d37bb18a
TP
12630 if (setup.user_mpm)
12631 cfg.auto_open_plinks = false;
12632
cc1d2806 12633 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
683b6d3b
JB
12634 err = nl80211_parse_chandef(rdev, info, &setup.chandef);
12635 if (err)
12636 return err;
cc1d2806 12637 } else {
188c1b3c 12638 /* __cfg80211_join_mesh() will sort it out */
683b6d3b 12639 setup.chandef.chan = NULL;
cc1d2806
JB
12640 }
12641
ffb3cf30
AN
12642 if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) {
12643 u8 *rates = nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
12644 int n_rates =
12645 nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
12646 struct ieee80211_supported_band *sband;
12647
12648 if (!setup.chandef.chan)
12649 return -EINVAL;
12650
12651 sband = rdev->wiphy.bands[setup.chandef.chan->band];
12652
12653 err = ieee80211_get_ratemask(sband, rates, n_rates,
12654 &setup.basic_rates);
12655 if (err)
12656 return err;
12657 }
12658
8564e382 12659 if (info->attrs[NL80211_ATTR_TX_RATES]) {
9a5f6488
TC
12660 err = nl80211_parse_tx_bitrate_mask(info, info->attrs,
12661 NL80211_ATTR_TX_RATES,
eb89a6a6 12662 &setup.beacon_rate,
7b0a0e3c 12663 dev, false, 0);
8564e382
JB
12664 if (err)
12665 return err;
12666
265698d7
JB
12667 if (!setup.chandef.chan)
12668 return -EINVAL;
12669
8564e382
JB
12670 err = validate_beacon_tx_rate(rdev, setup.chandef.chan->band,
12671 &setup.beacon_rate);
12672 if (err)
12673 return err;
12674 }
12675
d37d49c2
BB
12676 setup.userspace_handles_dfs =
12677 nla_get_flag(info->attrs[NL80211_ATTR_HANDLE_DFS]);
12678
1224f583
DK
12679 if (info->attrs[NL80211_ATTR_CONTROL_PORT_OVER_NL80211]) {
12680 int r = validate_pae_over_nl80211(rdev, info);
12681
12682 if (r < 0)
12683 return r;
12684
12685 setup.control_port_over_nl80211 = true;
12686 }
12687
188c1b3c
DK
12688 wdev_lock(dev->ieee80211_ptr);
12689 err = __cfg80211_join_mesh(rdev, dev, &setup, &cfg);
12690 if (!err && info->attrs[NL80211_ATTR_SOCKET_OWNER])
12691 dev->ieee80211_ptr->conn_owner_nlportid = info->snd_portid;
12692 wdev_unlock(dev->ieee80211_ptr);
12693
12694 return err;
29cbe68c
JB
12695}
12696
12697static int nl80211_leave_mesh(struct sk_buff *skb, struct genl_info *info)
12698{
12699 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12700 struct net_device *dev = info->user_ptr[1];
12701
12702 return cfg80211_leave_mesh(rdev, dev);
12703}
12704
dfb89c56 12705#ifdef CONFIG_PM
bb92d199
AK
12706static int nl80211_send_wowlan_patterns(struct sk_buff *msg,
12707 struct cfg80211_registered_device *rdev)
12708{
6abb9cb9 12709 struct cfg80211_wowlan *wowlan = rdev->wiphy.wowlan_config;
bb92d199
AK
12710 struct nlattr *nl_pats, *nl_pat;
12711 int i, pat_len;
12712
6abb9cb9 12713 if (!wowlan->n_patterns)
bb92d199
AK
12714 return 0;
12715
ae0be8de 12716 nl_pats = nla_nest_start_noflag(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN);
bb92d199
AK
12717 if (!nl_pats)
12718 return -ENOBUFS;
12719
6abb9cb9 12720 for (i = 0; i < wowlan->n_patterns; i++) {
ae0be8de 12721 nl_pat = nla_nest_start_noflag(msg, i + 1);
bb92d199
AK
12722 if (!nl_pat)
12723 return -ENOBUFS;
6abb9cb9 12724 pat_len = wowlan->patterns[i].pattern_len;
50ac6607 12725 if (nla_put(msg, NL80211_PKTPAT_MASK, DIV_ROUND_UP(pat_len, 8),
6abb9cb9 12726 wowlan->patterns[i].mask) ||
50ac6607
AK
12727 nla_put(msg, NL80211_PKTPAT_PATTERN, pat_len,
12728 wowlan->patterns[i].pattern) ||
12729 nla_put_u32(msg, NL80211_PKTPAT_OFFSET,
6abb9cb9 12730 wowlan->patterns[i].pkt_offset))
bb92d199
AK
12731 return -ENOBUFS;
12732 nla_nest_end(msg, nl_pat);
12733 }
12734 nla_nest_end(msg, nl_pats);
12735
12736 return 0;
12737}
12738
2a0e047e
JB
12739static int nl80211_send_wowlan_tcp(struct sk_buff *msg,
12740 struct cfg80211_wowlan_tcp *tcp)
12741{
12742 struct nlattr *nl_tcp;
12743
12744 if (!tcp)
12745 return 0;
12746
ae0be8de
MK
12747 nl_tcp = nla_nest_start_noflag(msg,
12748 NL80211_WOWLAN_TRIG_TCP_CONNECTION);
2a0e047e
JB
12749 if (!nl_tcp)
12750 return -ENOBUFS;
12751
930345ea
JB
12752 if (nla_put_in_addr(msg, NL80211_WOWLAN_TCP_SRC_IPV4, tcp->src) ||
12753 nla_put_in_addr(msg, NL80211_WOWLAN_TCP_DST_IPV4, tcp->dst) ||
2a0e047e
JB
12754 nla_put(msg, NL80211_WOWLAN_TCP_DST_MAC, ETH_ALEN, tcp->dst_mac) ||
12755 nla_put_u16(msg, NL80211_WOWLAN_TCP_SRC_PORT, tcp->src_port) ||
12756 nla_put_u16(msg, NL80211_WOWLAN_TCP_DST_PORT, tcp->dst_port) ||
12757 nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD,
12758 tcp->payload_len, tcp->payload) ||
12759 nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_INTERVAL,
12760 tcp->data_interval) ||
12761 nla_put(msg, NL80211_WOWLAN_TCP_WAKE_PAYLOAD,
12762 tcp->wake_len, tcp->wake_data) ||
12763 nla_put(msg, NL80211_WOWLAN_TCP_WAKE_MASK,
12764 DIV_ROUND_UP(tcp->wake_len, 8), tcp->wake_mask))
12765 return -ENOBUFS;
12766
12767 if (tcp->payload_seq.len &&
12768 nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ,
12769 sizeof(tcp->payload_seq), &tcp->payload_seq))
12770 return -ENOBUFS;
12771
12772 if (tcp->payload_tok.len &&
12773 nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN,
12774 sizeof(tcp->payload_tok) + tcp->tokens_size,
12775 &tcp->payload_tok))
12776 return -ENOBUFS;
12777
e248ad30
JB
12778 nla_nest_end(msg, nl_tcp);
12779
2a0e047e
JB
12780 return 0;
12781}
12782
75453ccb
LC
12783static int nl80211_send_wowlan_nd(struct sk_buff *msg,
12784 struct cfg80211_sched_scan_request *req)
12785{
3b06d277 12786 struct nlattr *nd, *freqs, *matches, *match, *scan_plans, *scan_plan;
75453ccb
LC
12787 int i;
12788
12789 if (!req)
12790 return 0;
12791
ae0be8de 12792 nd = nla_nest_start_noflag(msg, NL80211_WOWLAN_TRIG_NET_DETECT);
75453ccb
LC
12793 if (!nd)
12794 return -ENOBUFS;
12795
3b06d277
AS
12796 if (req->n_scan_plans == 1 &&
12797 nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_INTERVAL,
12798 req->scan_plans[0].interval * 1000))
75453ccb
LC
12799 return -ENOBUFS;
12800
21fea567
LC
12801 if (nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_DELAY, req->delay))
12802 return -ENOBUFS;
12803
bf95ecdb 12804 if (req->relative_rssi_set) {
12805 struct nl80211_bss_select_rssi_adjust rssi_adjust;
12806
12807 if (nla_put_s8(msg, NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI,
12808 req->relative_rssi))
12809 return -ENOBUFS;
12810
12811 rssi_adjust.band = req->rssi_adjust.band;
12812 rssi_adjust.delta = req->rssi_adjust.delta;
12813 if (nla_put(msg, NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST,
12814 sizeof(rssi_adjust), &rssi_adjust))
12815 return -ENOBUFS;
12816 }
12817
ae0be8de 12818 freqs = nla_nest_start_noflag(msg, NL80211_ATTR_SCAN_FREQUENCIES);
75453ccb
LC
12819 if (!freqs)
12820 return -ENOBUFS;
12821
53b18980
JB
12822 for (i = 0; i < req->n_channels; i++) {
12823 if (nla_put_u32(msg, i, req->channels[i]->center_freq))
12824 return -ENOBUFS;
12825 }
75453ccb
LC
12826
12827 nla_nest_end(msg, freqs);
12828
12829 if (req->n_match_sets) {
ae0be8de
MK
12830 matches = nla_nest_start_noflag(msg,
12831 NL80211_ATTR_SCHED_SCAN_MATCH);
76e1fb4b
JB
12832 if (!matches)
12833 return -ENOBUFS;
12834
75453ccb 12835 for (i = 0; i < req->n_match_sets; i++) {
ae0be8de 12836 match = nla_nest_start_noflag(msg, i);
76e1fb4b
JB
12837 if (!match)
12838 return -ENOBUFS;
12839
53b18980
JB
12840 if (nla_put(msg, NL80211_SCHED_SCAN_MATCH_ATTR_SSID,
12841 req->match_sets[i].ssid.ssid_len,
12842 req->match_sets[i].ssid.ssid))
12843 return -ENOBUFS;
75453ccb
LC
12844 nla_nest_end(msg, match);
12845 }
12846 nla_nest_end(msg, matches);
12847 }
12848
ae0be8de 12849 scan_plans = nla_nest_start_noflag(msg, NL80211_ATTR_SCHED_SCAN_PLANS);
3b06d277
AS
12850 if (!scan_plans)
12851 return -ENOBUFS;
12852
12853 for (i = 0; i < req->n_scan_plans; i++) {
ae0be8de 12854 scan_plan = nla_nest_start_noflag(msg, i + 1);
76e1fb4b
JB
12855 if (!scan_plan)
12856 return -ENOBUFS;
12857
67626964 12858 if (nla_put_u32(msg, NL80211_SCHED_SCAN_PLAN_INTERVAL,
3b06d277
AS
12859 req->scan_plans[i].interval) ||
12860 (req->scan_plans[i].iterations &&
12861 nla_put_u32(msg, NL80211_SCHED_SCAN_PLAN_ITERATIONS,
12862 req->scan_plans[i].iterations)))
12863 return -ENOBUFS;
12864 nla_nest_end(msg, scan_plan);
12865 }
12866 nla_nest_end(msg, scan_plans);
12867
75453ccb
LC
12868 nla_nest_end(msg, nd);
12869
12870 return 0;
12871}
12872
ff1b6e69
JB
12873static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info)
12874{
12875 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12876 struct sk_buff *msg;
12877 void *hdr;
2a0e047e 12878 u32 size = NLMSG_DEFAULT_SIZE;
ff1b6e69 12879
964dc9e2 12880 if (!rdev->wiphy.wowlan)
ff1b6e69
JB
12881 return -EOPNOTSUPP;
12882
6abb9cb9 12883 if (rdev->wiphy.wowlan_config && rdev->wiphy.wowlan_config->tcp) {
2a0e047e 12884 /* adjust size to have room for all the data */
6abb9cb9
JB
12885 size += rdev->wiphy.wowlan_config->tcp->tokens_size +
12886 rdev->wiphy.wowlan_config->tcp->payload_len +
12887 rdev->wiphy.wowlan_config->tcp->wake_len +
12888 rdev->wiphy.wowlan_config->tcp->wake_len / 8;
2a0e047e
JB
12889 }
12890
12891 msg = nlmsg_new(size, GFP_KERNEL);
ff1b6e69
JB
12892 if (!msg)
12893 return -ENOMEM;
12894
15e47304 12895 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
ff1b6e69
JB
12896 NL80211_CMD_GET_WOWLAN);
12897 if (!hdr)
12898 goto nla_put_failure;
12899
6abb9cb9 12900 if (rdev->wiphy.wowlan_config) {
ff1b6e69
JB
12901 struct nlattr *nl_wowlan;
12902
ae0be8de
MK
12903 nl_wowlan = nla_nest_start_noflag(msg,
12904 NL80211_ATTR_WOWLAN_TRIGGERS);
ff1b6e69
JB
12905 if (!nl_wowlan)
12906 goto nla_put_failure;
12907
6abb9cb9 12908 if ((rdev->wiphy.wowlan_config->any &&
9360ffd1 12909 nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) ||
6abb9cb9 12910 (rdev->wiphy.wowlan_config->disconnect &&
9360ffd1 12911 nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) ||
6abb9cb9 12912 (rdev->wiphy.wowlan_config->magic_pkt &&
9360ffd1 12913 nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) ||
6abb9cb9 12914 (rdev->wiphy.wowlan_config->gtk_rekey_failure &&
9360ffd1 12915 nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) ||
6abb9cb9 12916 (rdev->wiphy.wowlan_config->eap_identity_req &&
9360ffd1 12917 nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) ||
6abb9cb9 12918 (rdev->wiphy.wowlan_config->four_way_handshake &&
9360ffd1 12919 nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) ||
6abb9cb9 12920 (rdev->wiphy.wowlan_config->rfkill_release &&
9360ffd1
DM
12921 nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE)))
12922 goto nla_put_failure;
2a0e047e 12923
bb92d199
AK
12924 if (nl80211_send_wowlan_patterns(msg, rdev))
12925 goto nla_put_failure;
2a0e047e 12926
6abb9cb9
JB
12927 if (nl80211_send_wowlan_tcp(msg,
12928 rdev->wiphy.wowlan_config->tcp))
2a0e047e 12929 goto nla_put_failure;
75453ccb
LC
12930
12931 if (nl80211_send_wowlan_nd(
12932 msg,
12933 rdev->wiphy.wowlan_config->nd_config))
12934 goto nla_put_failure;
2a0e047e 12935
ff1b6e69
JB
12936 nla_nest_end(msg, nl_wowlan);
12937 }
12938
12939 genlmsg_end(msg, hdr);
12940 return genlmsg_reply(msg, info);
12941
12942nla_put_failure:
12943 nlmsg_free(msg);
12944 return -ENOBUFS;
12945}
12946
2a0e047e
JB
12947static int nl80211_parse_wowlan_tcp(struct cfg80211_registered_device *rdev,
12948 struct nlattr *attr,
12949 struct cfg80211_wowlan *trig)
12950{
12951 struct nlattr *tb[NUM_NL80211_WOWLAN_TCP];
12952 struct cfg80211_wowlan_tcp *cfg;
12953 struct nl80211_wowlan_tcp_data_token *tok = NULL;
12954 struct nl80211_wowlan_tcp_data_seq *seq = NULL;
12955 u32 size;
12956 u32 data_size, wake_size, tokens_size = 0, wake_mask_size;
12957 int err, port;
12958
964dc9e2 12959 if (!rdev->wiphy.wowlan->tcp)
2a0e047e
JB
12960 return -EINVAL;
12961
8cb08174
JB
12962 err = nla_parse_nested_deprecated(tb, MAX_NL80211_WOWLAN_TCP, attr,
12963 nl80211_wowlan_tcp_policy, NULL);
2a0e047e
JB
12964 if (err)
12965 return err;
12966
12967 if (!tb[NL80211_WOWLAN_TCP_SRC_IPV4] ||
12968 !tb[NL80211_WOWLAN_TCP_DST_IPV4] ||
12969 !tb[NL80211_WOWLAN_TCP_DST_MAC] ||
12970 !tb[NL80211_WOWLAN_TCP_DST_PORT] ||
12971 !tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD] ||
12972 !tb[NL80211_WOWLAN_TCP_DATA_INTERVAL] ||
12973 !tb[NL80211_WOWLAN_TCP_WAKE_PAYLOAD] ||
12974 !tb[NL80211_WOWLAN_TCP_WAKE_MASK])
12975 return -EINVAL;
12976
12977 data_size = nla_len(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD]);
964dc9e2 12978 if (data_size > rdev->wiphy.wowlan->tcp->data_payload_max)
2a0e047e
JB
12979 return -EINVAL;
12980
12981 if (nla_get_u32(tb[NL80211_WOWLAN_TCP_DATA_INTERVAL]) >
964dc9e2 12982 rdev->wiphy.wowlan->tcp->data_interval_max ||
723d568a 12983 nla_get_u32(tb[NL80211_WOWLAN_TCP_DATA_INTERVAL]) == 0)
2a0e047e
JB
12984 return -EINVAL;
12985
12986 wake_size = nla_len(tb[NL80211_WOWLAN_TCP_WAKE_PAYLOAD]);
964dc9e2 12987 if (wake_size > rdev->wiphy.wowlan->tcp->wake_payload_max)
2a0e047e
JB
12988 return -EINVAL;
12989
12990 wake_mask_size = nla_len(tb[NL80211_WOWLAN_TCP_WAKE_MASK]);
12991 if (wake_mask_size != DIV_ROUND_UP(wake_size, 8))
12992 return -EINVAL;
12993
12994 if (tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN]) {
12995 u32 tokln = nla_len(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN]);
12996
12997 tok = nla_data(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN]);
12998 tokens_size = tokln - sizeof(*tok);
12999
13000 if (!tok->len || tokens_size % tok->len)
13001 return -EINVAL;
964dc9e2 13002 if (!rdev->wiphy.wowlan->tcp->tok)
2a0e047e 13003 return -EINVAL;
964dc9e2 13004 if (tok->len > rdev->wiphy.wowlan->tcp->tok->max_len)
2a0e047e 13005 return -EINVAL;
964dc9e2 13006 if (tok->len < rdev->wiphy.wowlan->tcp->tok->min_len)
2a0e047e 13007 return -EINVAL;
964dc9e2 13008 if (tokens_size > rdev->wiphy.wowlan->tcp->tok->bufsize)
2a0e047e
JB
13009 return -EINVAL;
13010 if (tok->offset + tok->len > data_size)
13011 return -EINVAL;
13012 }
13013
13014 if (tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ]) {
13015 seq = nla_data(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ]);
964dc9e2 13016 if (!rdev->wiphy.wowlan->tcp->seq)
2a0e047e
JB
13017 return -EINVAL;
13018 if (seq->len == 0 || seq->len > 4)
13019 return -EINVAL;
13020 if (seq->len + seq->offset > data_size)
13021 return -EINVAL;
13022 }
13023
13024 size = sizeof(*cfg);
13025 size += data_size;
13026 size += wake_size + wake_mask_size;
13027 size += tokens_size;
13028
13029 cfg = kzalloc(size, GFP_KERNEL);
13030 if (!cfg)
13031 return -ENOMEM;
67b61f6c
JB
13032 cfg->src = nla_get_in_addr(tb[NL80211_WOWLAN_TCP_SRC_IPV4]);
13033 cfg->dst = nla_get_in_addr(tb[NL80211_WOWLAN_TCP_DST_IPV4]);
2a0e047e
JB
13034 memcpy(cfg->dst_mac, nla_data(tb[NL80211_WOWLAN_TCP_DST_MAC]),
13035 ETH_ALEN);
13036 if (tb[NL80211_WOWLAN_TCP_SRC_PORT])
13037 port = nla_get_u16(tb[NL80211_WOWLAN_TCP_SRC_PORT]);
13038 else
13039 port = 0;
13040#ifdef CONFIG_INET
13041 /* allocate a socket and port for it and use it */
13042 err = __sock_create(wiphy_net(&rdev->wiphy), PF_INET, SOCK_STREAM,
13043 IPPROTO_TCP, &cfg->sock, 1);
13044 if (err) {
13045 kfree(cfg);
13046 return err;
13047 }
13048 if (inet_csk_get_port(cfg->sock->sk, port)) {
13049 sock_release(cfg->sock);
13050 kfree(cfg);
13051 return -EADDRINUSE;
13052 }
13053 cfg->src_port = inet_sk(cfg->sock->sk)->inet_num;
13054#else
13055 if (!port) {
13056 kfree(cfg);
13057 return -EINVAL;
13058 }
13059 cfg->src_port = port;
13060#endif
13061
13062 cfg->dst_port = nla_get_u16(tb[NL80211_WOWLAN_TCP_DST_PORT]);
13063 cfg->payload_len = data_size;
13064 cfg->payload = (u8 *)cfg + sizeof(*cfg) + tokens_size;
13065 memcpy((void *)cfg->payload,
13066 nla_data(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD]),
13067 data_size);
13068 if (seq)
13069 cfg->payload_seq = *seq;
13070 cfg->data_interval = nla_get_u32(tb[NL80211_WOWLAN_TCP_DATA_INTERVAL]);
13071 cfg->wake_len = wake_size;
13072 cfg->wake_data = (u8 *)cfg + sizeof(*cfg) + tokens_size + data_size;
13073 memcpy((void *)cfg->wake_data,
13074 nla_data(tb[NL80211_WOWLAN_TCP_WAKE_PAYLOAD]),
13075 wake_size);
13076 cfg->wake_mask = (u8 *)cfg + sizeof(*cfg) + tokens_size +
13077 data_size + wake_size;
13078 memcpy((void *)cfg->wake_mask,
13079 nla_data(tb[NL80211_WOWLAN_TCP_WAKE_MASK]),
13080 wake_mask_size);
13081 if (tok) {
13082 cfg->tokens_size = tokens_size;
13083 memcpy(&cfg->payload_tok, tok, sizeof(*tok) + tokens_size);
13084 }
13085
13086 trig->tcp = cfg;
13087
13088 return 0;
13089}
13090
8cd4d456
LC
13091static int nl80211_parse_wowlan_nd(struct cfg80211_registered_device *rdev,
13092 const struct wiphy_wowlan_support *wowlan,
13093 struct nlattr *attr,
13094 struct cfg80211_wowlan *trig)
13095{
13096 struct nlattr **tb;
13097 int err;
13098
6396bb22 13099 tb = kcalloc(NUM_NL80211_ATTR, sizeof(*tb), GFP_KERNEL);
8cd4d456
LC
13100 if (!tb)
13101 return -ENOMEM;
13102
13103 if (!(wowlan->flags & WIPHY_WOWLAN_NET_DETECT)) {
13104 err = -EOPNOTSUPP;
13105 goto out;
13106 }
13107
8cb08174
JB
13108 err = nla_parse_nested_deprecated(tb, NL80211_ATTR_MAX, attr,
13109 nl80211_policy, NULL);
8cd4d456
LC
13110 if (err)
13111 goto out;
13112
aad1e812
AVS
13113 trig->nd_config = nl80211_parse_sched_scan(&rdev->wiphy, NULL, tb,
13114 wowlan->max_nd_match_sets);
8cd4d456
LC
13115 err = PTR_ERR_OR_ZERO(trig->nd_config);
13116 if (err)
13117 trig->nd_config = NULL;
13118
13119out:
13120 kfree(tb);
13121 return err;
13122}
13123
ff1b6e69
JB
13124static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
13125{
13126 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13127 struct nlattr *tb[NUM_NL80211_WOWLAN_TRIG];
ff1b6e69 13128 struct cfg80211_wowlan new_triggers = {};
ae33bd81 13129 struct cfg80211_wowlan *ntrig;
964dc9e2 13130 const struct wiphy_wowlan_support *wowlan = rdev->wiphy.wowlan;
ff1b6e69 13131 int err, i;
6abb9cb9 13132 bool prev_enabled = rdev->wiphy.wowlan_config;
98fc4386 13133 bool regular = false;
ff1b6e69 13134
964dc9e2 13135 if (!wowlan)
ff1b6e69
JB
13136 return -EOPNOTSUPP;
13137
ae33bd81
JB
13138 if (!info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS]) {
13139 cfg80211_rdev_free_wowlan(rdev);
6abb9cb9 13140 rdev->wiphy.wowlan_config = NULL;
ae33bd81
JB
13141 goto set_wakeup;
13142 }
ff1b6e69 13143
8cb08174
JB
13144 err = nla_parse_nested_deprecated(tb, MAX_NL80211_WOWLAN_TRIG,
13145 info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS],
13146 nl80211_wowlan_policy, info->extack);
ff1b6e69
JB
13147 if (err)
13148 return err;
13149
13150 if (tb[NL80211_WOWLAN_TRIG_ANY]) {
13151 if (!(wowlan->flags & WIPHY_WOWLAN_ANY))
13152 return -EINVAL;
13153 new_triggers.any = true;
13154 }
13155
13156 if (tb[NL80211_WOWLAN_TRIG_DISCONNECT]) {
13157 if (!(wowlan->flags & WIPHY_WOWLAN_DISCONNECT))
13158 return -EINVAL;
13159 new_triggers.disconnect = true;
98fc4386 13160 regular = true;
ff1b6e69
JB
13161 }
13162
13163 if (tb[NL80211_WOWLAN_TRIG_MAGIC_PKT]) {
13164 if (!(wowlan->flags & WIPHY_WOWLAN_MAGIC_PKT))
13165 return -EINVAL;
13166 new_triggers.magic_pkt = true;
98fc4386 13167 regular = true;
ff1b6e69
JB
13168 }
13169
77dbbb13
JB
13170 if (tb[NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED])
13171 return -EINVAL;
13172
13173 if (tb[NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE]) {
13174 if (!(wowlan->flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE))
13175 return -EINVAL;
13176 new_triggers.gtk_rekey_failure = true;
98fc4386 13177 regular = true;
77dbbb13
JB
13178 }
13179
13180 if (tb[NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST]) {
13181 if (!(wowlan->flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ))
13182 return -EINVAL;
13183 new_triggers.eap_identity_req = true;
98fc4386 13184 regular = true;
77dbbb13
JB
13185 }
13186
13187 if (tb[NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE]) {
13188 if (!(wowlan->flags & WIPHY_WOWLAN_4WAY_HANDSHAKE))
13189 return -EINVAL;
13190 new_triggers.four_way_handshake = true;
98fc4386 13191 regular = true;
77dbbb13
JB
13192 }
13193
13194 if (tb[NL80211_WOWLAN_TRIG_RFKILL_RELEASE]) {
13195 if (!(wowlan->flags & WIPHY_WOWLAN_RFKILL_RELEASE))
13196 return -EINVAL;
13197 new_triggers.rfkill_release = true;
98fc4386 13198 regular = true;
77dbbb13
JB
13199 }
13200
ff1b6e69
JB
13201 if (tb[NL80211_WOWLAN_TRIG_PKT_PATTERN]) {
13202 struct nlattr *pat;
13203 int n_patterns = 0;
bb92d199 13204 int rem, pat_len, mask_len, pkt_offset;
50ac6607 13205 struct nlattr *pat_tb[NUM_NL80211_PKTPAT];
ff1b6e69 13206
98fc4386
JB
13207 regular = true;
13208
ff1b6e69
JB
13209 nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN],
13210 rem)
13211 n_patterns++;
13212 if (n_patterns > wowlan->n_patterns)
13213 return -EINVAL;
13214
13215 new_triggers.patterns = kcalloc(n_patterns,
13216 sizeof(new_triggers.patterns[0]),
13217 GFP_KERNEL);
13218 if (!new_triggers.patterns)
13219 return -ENOMEM;
13220
13221 new_triggers.n_patterns = n_patterns;
13222 i = 0;
13223
13224 nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN],
13225 rem) {
922bd80f
JB
13226 u8 *mask_pat;
13227
8cb08174
JB
13228 err = nla_parse_nested_deprecated(pat_tb,
13229 MAX_NL80211_PKTPAT,
13230 pat,
13231 nl80211_packet_pattern_policy,
13232 info->extack);
95bca62f
JB
13233 if (err)
13234 goto error;
13235
ff1b6e69 13236 err = -EINVAL;
50ac6607
AK
13237 if (!pat_tb[NL80211_PKTPAT_MASK] ||
13238 !pat_tb[NL80211_PKTPAT_PATTERN])
ff1b6e69 13239 goto error;
50ac6607 13240 pat_len = nla_len(pat_tb[NL80211_PKTPAT_PATTERN]);
ff1b6e69 13241 mask_len = DIV_ROUND_UP(pat_len, 8);
50ac6607 13242 if (nla_len(pat_tb[NL80211_PKTPAT_MASK]) != mask_len)
ff1b6e69
JB
13243 goto error;
13244 if (pat_len > wowlan->pattern_max_len ||
13245 pat_len < wowlan->pattern_min_len)
13246 goto error;
13247
50ac6607 13248 if (!pat_tb[NL80211_PKTPAT_OFFSET])
bb92d199
AK
13249 pkt_offset = 0;
13250 else
13251 pkt_offset = nla_get_u32(
50ac6607 13252 pat_tb[NL80211_PKTPAT_OFFSET]);
bb92d199
AK
13253 if (pkt_offset > wowlan->max_pkt_offset)
13254 goto error;
13255 new_triggers.patterns[i].pkt_offset = pkt_offset;
13256
922bd80f
JB
13257 mask_pat = kmalloc(mask_len + pat_len, GFP_KERNEL);
13258 if (!mask_pat) {
ff1b6e69
JB
13259 err = -ENOMEM;
13260 goto error;
13261 }
922bd80f
JB
13262 new_triggers.patterns[i].mask = mask_pat;
13263 memcpy(mask_pat, nla_data(pat_tb[NL80211_PKTPAT_MASK]),
ff1b6e69 13264 mask_len);
922bd80f
JB
13265 mask_pat += mask_len;
13266 new_triggers.patterns[i].pattern = mask_pat;
ff1b6e69 13267 new_triggers.patterns[i].pattern_len = pat_len;
922bd80f 13268 memcpy(mask_pat,
50ac6607 13269 nla_data(pat_tb[NL80211_PKTPAT_PATTERN]),
ff1b6e69
JB
13270 pat_len);
13271 i++;
13272 }
13273 }
13274
2a0e047e 13275 if (tb[NL80211_WOWLAN_TRIG_TCP_CONNECTION]) {
98fc4386 13276 regular = true;
2a0e047e
JB
13277 err = nl80211_parse_wowlan_tcp(
13278 rdev, tb[NL80211_WOWLAN_TRIG_TCP_CONNECTION],
13279 &new_triggers);
13280 if (err)
13281 goto error;
13282 }
13283
8cd4d456 13284 if (tb[NL80211_WOWLAN_TRIG_NET_DETECT]) {
98fc4386 13285 regular = true;
8cd4d456
LC
13286 err = nl80211_parse_wowlan_nd(
13287 rdev, wowlan, tb[NL80211_WOWLAN_TRIG_NET_DETECT],
13288 &new_triggers);
13289 if (err)
13290 goto error;
13291 }
13292
98fc4386
JB
13293 /* The 'any' trigger means the device continues operating more or less
13294 * as in its normal operation mode and wakes up the host on most of the
13295 * normal interrupts (like packet RX, ...)
13296 * It therefore makes little sense to combine with the more constrained
13297 * wakeup trigger modes.
13298 */
13299 if (new_triggers.any && regular) {
13300 err = -EINVAL;
13301 goto error;
13302 }
13303
ae33bd81
JB
13304 ntrig = kmemdup(&new_triggers, sizeof(new_triggers), GFP_KERNEL);
13305 if (!ntrig) {
13306 err = -ENOMEM;
13307 goto error;
ff1b6e69 13308 }
ae33bd81 13309 cfg80211_rdev_free_wowlan(rdev);
6abb9cb9 13310 rdev->wiphy.wowlan_config = ntrig;
ff1b6e69 13311
ae33bd81 13312 set_wakeup:
6abb9cb9
JB
13313 if (rdev->ops->set_wakeup &&
13314 prev_enabled != !!rdev->wiphy.wowlan_config)
13315 rdev_set_wakeup(rdev, rdev->wiphy.wowlan_config);
6d52563f 13316
ff1b6e69
JB
13317 return 0;
13318 error:
13319 for (i = 0; i < new_triggers.n_patterns; i++)
13320 kfree(new_triggers.patterns[i].mask);
13321 kfree(new_triggers.patterns);
2a0e047e
JB
13322 if (new_triggers.tcp && new_triggers.tcp->sock)
13323 sock_release(new_triggers.tcp->sock);
13324 kfree(new_triggers.tcp);
e5dbe070 13325 kfree(new_triggers.nd_config);
ff1b6e69
JB
13326 return err;
13327}
dfb89c56 13328#endif
ff1b6e69 13329
be29b99a
AK
13330static int nl80211_send_coalesce_rules(struct sk_buff *msg,
13331 struct cfg80211_registered_device *rdev)
13332{
13333 struct nlattr *nl_pats, *nl_pat, *nl_rule, *nl_rules;
13334 int i, j, pat_len;
13335 struct cfg80211_coalesce_rules *rule;
13336
13337 if (!rdev->coalesce->n_rules)
13338 return 0;
13339
ae0be8de 13340 nl_rules = nla_nest_start_noflag(msg, NL80211_ATTR_COALESCE_RULE);
be29b99a
AK
13341 if (!nl_rules)
13342 return -ENOBUFS;
13343
13344 for (i = 0; i < rdev->coalesce->n_rules; i++) {
ae0be8de 13345 nl_rule = nla_nest_start_noflag(msg, i + 1);
be29b99a
AK
13346 if (!nl_rule)
13347 return -ENOBUFS;
13348
13349 rule = &rdev->coalesce->rules[i];
13350 if (nla_put_u32(msg, NL80211_ATTR_COALESCE_RULE_DELAY,
13351 rule->delay))
13352 return -ENOBUFS;
13353
13354 if (nla_put_u32(msg, NL80211_ATTR_COALESCE_RULE_CONDITION,
13355 rule->condition))
13356 return -ENOBUFS;
13357
ae0be8de
MK
13358 nl_pats = nla_nest_start_noflag(msg,
13359 NL80211_ATTR_COALESCE_RULE_PKT_PATTERN);
be29b99a
AK
13360 if (!nl_pats)
13361 return -ENOBUFS;
13362
13363 for (j = 0; j < rule->n_patterns; j++) {
ae0be8de 13364 nl_pat = nla_nest_start_noflag(msg, j + 1);
be29b99a
AK
13365 if (!nl_pat)
13366 return -ENOBUFS;
13367 pat_len = rule->patterns[j].pattern_len;
13368 if (nla_put(msg, NL80211_PKTPAT_MASK,
13369 DIV_ROUND_UP(pat_len, 8),
13370 rule->patterns[j].mask) ||
13371 nla_put(msg, NL80211_PKTPAT_PATTERN, pat_len,
13372 rule->patterns[j].pattern) ||
13373 nla_put_u32(msg, NL80211_PKTPAT_OFFSET,
13374 rule->patterns[j].pkt_offset))
13375 return -ENOBUFS;
13376 nla_nest_end(msg, nl_pat);
13377 }
13378 nla_nest_end(msg, nl_pats);
13379 nla_nest_end(msg, nl_rule);
13380 }
13381 nla_nest_end(msg, nl_rules);
13382
13383 return 0;
13384}
13385
13386static int nl80211_get_coalesce(struct sk_buff *skb, struct genl_info *info)
13387{
13388 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13389 struct sk_buff *msg;
13390 void *hdr;
13391
13392 if (!rdev->wiphy.coalesce)
13393 return -EOPNOTSUPP;
13394
13395 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
13396 if (!msg)
13397 return -ENOMEM;
13398
13399 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
13400 NL80211_CMD_GET_COALESCE);
13401 if (!hdr)
13402 goto nla_put_failure;
13403
13404 if (rdev->coalesce && nl80211_send_coalesce_rules(msg, rdev))
13405 goto nla_put_failure;
13406
13407 genlmsg_end(msg, hdr);
13408 return genlmsg_reply(msg, info);
13409
13410nla_put_failure:
13411 nlmsg_free(msg);
13412 return -ENOBUFS;
13413}
13414
13415void cfg80211_rdev_free_coalesce(struct cfg80211_registered_device *rdev)
13416{
13417 struct cfg80211_coalesce *coalesce = rdev->coalesce;
13418 int i, j;
13419 struct cfg80211_coalesce_rules *rule;
13420
13421 if (!coalesce)
13422 return;
13423
13424 for (i = 0; i < coalesce->n_rules; i++) {
13425 rule = &coalesce->rules[i];
13426 for (j = 0; j < rule->n_patterns; j++)
13427 kfree(rule->patterns[j].mask);
13428 kfree(rule->patterns);
13429 }
13430 kfree(coalesce->rules);
13431 kfree(coalesce);
13432 rdev->coalesce = NULL;
13433}
13434
13435static int nl80211_parse_coalesce_rule(struct cfg80211_registered_device *rdev,
13436 struct nlattr *rule,
13437 struct cfg80211_coalesce_rules *new_rule)
13438{
13439 int err, i;
13440 const struct wiphy_coalesce_support *coalesce = rdev->wiphy.coalesce;
13441 struct nlattr *tb[NUM_NL80211_ATTR_COALESCE_RULE], *pat;
13442 int rem, pat_len, mask_len, pkt_offset, n_patterns = 0;
13443 struct nlattr *pat_tb[NUM_NL80211_PKTPAT];
13444
8cb08174
JB
13445 err = nla_parse_nested_deprecated(tb, NL80211_ATTR_COALESCE_RULE_MAX,
13446 rule, nl80211_coalesce_policy, NULL);
be29b99a
AK
13447 if (err)
13448 return err;
13449
13450 if (tb[NL80211_ATTR_COALESCE_RULE_DELAY])
13451 new_rule->delay =
13452 nla_get_u32(tb[NL80211_ATTR_COALESCE_RULE_DELAY]);
13453 if (new_rule->delay > coalesce->max_delay)
13454 return -EINVAL;
13455
13456 if (tb[NL80211_ATTR_COALESCE_RULE_CONDITION])
13457 new_rule->condition =
13458 nla_get_u32(tb[NL80211_ATTR_COALESCE_RULE_CONDITION]);
be29b99a
AK
13459
13460 if (!tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN])
13461 return -EINVAL;
13462
13463 nla_for_each_nested(pat, tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN],
13464 rem)
13465 n_patterns++;
13466 if (n_patterns > coalesce->n_patterns)
13467 return -EINVAL;
13468
13469 new_rule->patterns = kcalloc(n_patterns, sizeof(new_rule->patterns[0]),
13470 GFP_KERNEL);
13471 if (!new_rule->patterns)
13472 return -ENOMEM;
13473
13474 new_rule->n_patterns = n_patterns;
13475 i = 0;
13476
13477 nla_for_each_nested(pat, tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN],
13478 rem) {
922bd80f
JB
13479 u8 *mask_pat;
13480
8cb08174
JB
13481 err = nla_parse_nested_deprecated(pat_tb, MAX_NL80211_PKTPAT,
13482 pat,
13483 nl80211_packet_pattern_policy,
13484 NULL);
95bca62f
JB
13485 if (err)
13486 return err;
13487
be29b99a
AK
13488 if (!pat_tb[NL80211_PKTPAT_MASK] ||
13489 !pat_tb[NL80211_PKTPAT_PATTERN])
13490 return -EINVAL;
13491 pat_len = nla_len(pat_tb[NL80211_PKTPAT_PATTERN]);
13492 mask_len = DIV_ROUND_UP(pat_len, 8);
13493 if (nla_len(pat_tb[NL80211_PKTPAT_MASK]) != mask_len)
13494 return -EINVAL;
13495 if (pat_len > coalesce->pattern_max_len ||
13496 pat_len < coalesce->pattern_min_len)
13497 return -EINVAL;
13498
13499 if (!pat_tb[NL80211_PKTPAT_OFFSET])
13500 pkt_offset = 0;
13501 else
13502 pkt_offset = nla_get_u32(pat_tb[NL80211_PKTPAT_OFFSET]);
13503 if (pkt_offset > coalesce->max_pkt_offset)
13504 return -EINVAL;
13505 new_rule->patterns[i].pkt_offset = pkt_offset;
13506
922bd80f
JB
13507 mask_pat = kmalloc(mask_len + pat_len, GFP_KERNEL);
13508 if (!mask_pat)
be29b99a 13509 return -ENOMEM;
922bd80f
JB
13510
13511 new_rule->patterns[i].mask = mask_pat;
13512 memcpy(mask_pat, nla_data(pat_tb[NL80211_PKTPAT_MASK]),
13513 mask_len);
13514
13515 mask_pat += mask_len;
13516 new_rule->patterns[i].pattern = mask_pat;
be29b99a 13517 new_rule->patterns[i].pattern_len = pat_len;
922bd80f
JB
13518 memcpy(mask_pat, nla_data(pat_tb[NL80211_PKTPAT_PATTERN]),
13519 pat_len);
be29b99a
AK
13520 i++;
13521 }
13522
13523 return 0;
13524}
13525
13526static int nl80211_set_coalesce(struct sk_buff *skb, struct genl_info *info)
13527{
13528 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13529 const struct wiphy_coalesce_support *coalesce = rdev->wiphy.coalesce;
13530 struct cfg80211_coalesce new_coalesce = {};
13531 struct cfg80211_coalesce *n_coalesce;
13532 int err, rem_rule, n_rules = 0, i, j;
13533 struct nlattr *rule;
13534 struct cfg80211_coalesce_rules *tmp_rule;
13535
13536 if (!rdev->wiphy.coalesce || !rdev->ops->set_coalesce)
13537 return -EOPNOTSUPP;
13538
13539 if (!info->attrs[NL80211_ATTR_COALESCE_RULE]) {
13540 cfg80211_rdev_free_coalesce(rdev);
a1056b1b 13541 rdev_set_coalesce(rdev, NULL);
be29b99a
AK
13542 return 0;
13543 }
13544
13545 nla_for_each_nested(rule, info->attrs[NL80211_ATTR_COALESCE_RULE],
13546 rem_rule)
13547 n_rules++;
13548 if (n_rules > coalesce->n_rules)
13549 return -EINVAL;
13550
13551 new_coalesce.rules = kcalloc(n_rules, sizeof(new_coalesce.rules[0]),
13552 GFP_KERNEL);
13553 if (!new_coalesce.rules)
13554 return -ENOMEM;
13555
13556 new_coalesce.n_rules = n_rules;
13557 i = 0;
13558
13559 nla_for_each_nested(rule, info->attrs[NL80211_ATTR_COALESCE_RULE],
13560 rem_rule) {
13561 err = nl80211_parse_coalesce_rule(rdev, rule,
13562 &new_coalesce.rules[i]);
13563 if (err)
13564 goto error;
13565
13566 i++;
13567 }
13568
a1056b1b 13569 err = rdev_set_coalesce(rdev, &new_coalesce);
be29b99a
AK
13570 if (err)
13571 goto error;
13572
13573 n_coalesce = kmemdup(&new_coalesce, sizeof(new_coalesce), GFP_KERNEL);
13574 if (!n_coalesce) {
13575 err = -ENOMEM;
13576 goto error;
13577 }
13578 cfg80211_rdev_free_coalesce(rdev);
13579 rdev->coalesce = n_coalesce;
13580
13581 return 0;
13582error:
13583 for (i = 0; i < new_coalesce.n_rules; i++) {
13584 tmp_rule = &new_coalesce.rules[i];
13585 for (j = 0; j < tmp_rule->n_patterns; j++)
13586 kfree(tmp_rule->patterns[j].mask);
13587 kfree(tmp_rule->patterns);
13588 }
13589 kfree(new_coalesce.rules);
13590
13591 return err;
13592}
13593
e5497d76
JB
13594static int nl80211_set_rekey_data(struct sk_buff *skb, struct genl_info *info)
13595{
13596 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13597 struct net_device *dev = info->user_ptr[1];
13598 struct wireless_dev *wdev = dev->ieee80211_ptr;
13599 struct nlattr *tb[NUM_NL80211_REKEY_DATA];
f495acd8 13600 struct cfg80211_gtk_rekey_data rekey_data = {};
e5497d76
JB
13601 int err;
13602
13603 if (!info->attrs[NL80211_ATTR_REKEY_DATA])
13604 return -EINVAL;
13605
8cb08174
JB
13606 err = nla_parse_nested_deprecated(tb, MAX_NL80211_REKEY_DATA,
13607 info->attrs[NL80211_ATTR_REKEY_DATA],
13608 nl80211_rekey_policy, info->extack);
e5497d76
JB
13609 if (err)
13610 return err;
13611
e785fa0a
VD
13612 if (!tb[NL80211_REKEY_DATA_REPLAY_CTR] || !tb[NL80211_REKEY_DATA_KEK] ||
13613 !tb[NL80211_REKEY_DATA_KCK])
13614 return -EINVAL;
093a48d2
NE
13615 if (nla_len(tb[NL80211_REKEY_DATA_KEK]) != NL80211_KEK_LEN &&
13616 !(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_EXT_KEK_KCK &&
13617 nla_len(tb[NL80211_REKEY_DATA_KEK]) == NL80211_KEK_EXT_LEN))
e5497d76 13618 return -ERANGE;
093a48d2
NE
13619 if (nla_len(tb[NL80211_REKEY_DATA_KCK]) != NL80211_KCK_LEN &&
13620 !(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_EXT_KEK_KCK &&
13621 nla_len(tb[NL80211_REKEY_DATA_KEK]) == NL80211_KCK_EXT_LEN))
e5497d76
JB
13622 return -ERANGE;
13623
78f686ca
JB
13624 rekey_data.kek = nla_data(tb[NL80211_REKEY_DATA_KEK]);
13625 rekey_data.kck = nla_data(tb[NL80211_REKEY_DATA_KCK]);
13626 rekey_data.replay_ctr = nla_data(tb[NL80211_REKEY_DATA_REPLAY_CTR]);
093a48d2
NE
13627 rekey_data.kek_len = nla_len(tb[NL80211_REKEY_DATA_KEK]);
13628 rekey_data.kck_len = nla_len(tb[NL80211_REKEY_DATA_KCK]);
13629 if (tb[NL80211_REKEY_DATA_AKM])
13630 rekey_data.akm = nla_get_u32(tb[NL80211_REKEY_DATA_AKM]);
e5497d76
JB
13631
13632 wdev_lock(wdev);
7b0a0e3c 13633 if (!wdev->connected) {
e5497d76
JB
13634 err = -ENOTCONN;
13635 goto out;
13636 }
13637
13638 if (!rdev->ops->set_rekey_data) {
13639 err = -EOPNOTSUPP;
13640 goto out;
13641 }
13642
e35e4d28 13643 err = rdev_set_rekey_data(rdev, dev, &rekey_data);
e5497d76
JB
13644 out:
13645 wdev_unlock(wdev);
13646 return err;
13647}
13648
28946da7
JB
13649static int nl80211_register_unexpected_frame(struct sk_buff *skb,
13650 struct genl_info *info)
13651{
13652 struct net_device *dev = info->user_ptr[1];
13653 struct wireless_dev *wdev = dev->ieee80211_ptr;
13654
13655 if (wdev->iftype != NL80211_IFTYPE_AP &&
13656 wdev->iftype != NL80211_IFTYPE_P2P_GO)
13657 return -EINVAL;
13658
15e47304 13659 if (wdev->ap_unexpected_nlportid)
28946da7
JB
13660 return -EBUSY;
13661
15e47304 13662 wdev->ap_unexpected_nlportid = info->snd_portid;
28946da7
JB
13663 return 0;
13664}
13665
7f6cf311
JB
13666static int nl80211_probe_client(struct sk_buff *skb,
13667 struct genl_info *info)
13668{
13669 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13670 struct net_device *dev = info->user_ptr[1];
13671 struct wireless_dev *wdev = dev->ieee80211_ptr;
13672 struct sk_buff *msg;
13673 void *hdr;
13674 const u8 *addr;
13675 u64 cookie;
13676 int err;
13677
13678 if (wdev->iftype != NL80211_IFTYPE_AP &&
13679 wdev->iftype != NL80211_IFTYPE_P2P_GO)
13680 return -EOPNOTSUPP;
13681
13682 if (!info->attrs[NL80211_ATTR_MAC])
13683 return -EINVAL;
13684
13685 if (!rdev->ops->probe_client)
13686 return -EOPNOTSUPP;
13687
13688 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
13689 if (!msg)
13690 return -ENOMEM;
13691
15e47304 13692 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
7f6cf311 13693 NL80211_CMD_PROBE_CLIENT);
cb35fba3
DC
13694 if (!hdr) {
13695 err = -ENOBUFS;
7f6cf311
JB
13696 goto free_msg;
13697 }
13698
13699 addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
13700
e35e4d28 13701 err = rdev_probe_client(rdev, dev, addr, &cookie);
7f6cf311
JB
13702 if (err)
13703 goto free_msg;
13704
2dad624e
ND
13705 if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
13706 NL80211_ATTR_PAD))
9360ffd1 13707 goto nla_put_failure;
7f6cf311
JB
13708
13709 genlmsg_end(msg, hdr);
13710
13711 return genlmsg_reply(msg, info);
13712
13713 nla_put_failure:
13714 err = -ENOBUFS;
13715 free_msg:
13716 nlmsg_free(msg);
13717 return err;
13718}
13719
5e760230
JB
13720static int nl80211_register_beacons(struct sk_buff *skb, struct genl_info *info)
13721{
13722 struct cfg80211_registered_device *rdev = info->user_ptr[0];
37c73b5f
BG
13723 struct cfg80211_beacon_registration *reg, *nreg;
13724 int rv;
5e760230
JB
13725
13726 if (!(rdev->wiphy.flags & WIPHY_FLAG_REPORTS_OBSS))
13727 return -EOPNOTSUPP;
13728
37c73b5f
BG
13729 nreg = kzalloc(sizeof(*nreg), GFP_KERNEL);
13730 if (!nreg)
13731 return -ENOMEM;
13732
13733 /* First, check if already registered. */
13734 spin_lock_bh(&rdev->beacon_registrations_lock);
13735 list_for_each_entry(reg, &rdev->beacon_registrations, list) {
13736 if (reg->nlportid == info->snd_portid) {
13737 rv = -EALREADY;
13738 goto out_err;
13739 }
13740 }
13741 /* Add it to the list */
13742 nreg->nlportid = info->snd_portid;
13743 list_add(&nreg->list, &rdev->beacon_registrations);
5e760230 13744
37c73b5f 13745 spin_unlock_bh(&rdev->beacon_registrations_lock);
5e760230
JB
13746
13747 return 0;
37c73b5f
BG
13748out_err:
13749 spin_unlock_bh(&rdev->beacon_registrations_lock);
13750 kfree(nreg);
13751 return rv;
5e760230
JB
13752}
13753
98104fde
JB
13754static int nl80211_start_p2p_device(struct sk_buff *skb, struct genl_info *info)
13755{
13756 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13757 struct wireless_dev *wdev = info->user_ptr[1];
13758 int err;
13759
13760 if (!rdev->ops->start_p2p_device)
13761 return -EOPNOTSUPP;
13762
13763 if (wdev->iftype != NL80211_IFTYPE_P2P_DEVICE)
13764 return -EOPNOTSUPP;
13765
73c7da3d 13766 if (wdev_running(wdev))
98104fde
JB
13767 return 0;
13768
358ae888 13769 if (rfkill_blocked(rdev->wiphy.rfkill))
b6a55015 13770 return -ERFKILL;
98104fde 13771
eeb126e9 13772 err = rdev_start_p2p_device(rdev, wdev);
98104fde
JB
13773 if (err)
13774 return err;
13775
73c7da3d 13776 wdev->is_running = true;
98104fde 13777 rdev->opencount++;
98104fde
JB
13778
13779 return 0;
13780}
13781
13782static int nl80211_stop_p2p_device(struct sk_buff *skb, struct genl_info *info)
13783{
13784 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13785 struct wireless_dev *wdev = info->user_ptr[1];
13786
13787 if (wdev->iftype != NL80211_IFTYPE_P2P_DEVICE)
13788 return -EOPNOTSUPP;
13789
13790 if (!rdev->ops->stop_p2p_device)
13791 return -EOPNOTSUPP;
13792
f9f47529 13793 cfg80211_stop_p2p_device(rdev, wdev);
98104fde
JB
13794
13795 return 0;
13796}
13797
cb3b7d87
AB
13798static int nl80211_start_nan(struct sk_buff *skb, struct genl_info *info)
13799{
13800 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13801 struct wireless_dev *wdev = info->user_ptr[1];
13802 struct cfg80211_nan_conf conf = {};
13803 int err;
13804
13805 if (wdev->iftype != NL80211_IFTYPE_NAN)
13806 return -EOPNOTSUPP;
13807
eeb04a96 13808 if (wdev_running(wdev))
cb3b7d87
AB
13809 return -EEXIST;
13810
358ae888 13811 if (rfkill_blocked(rdev->wiphy.rfkill))
cb3b7d87
AB
13812 return -ERFKILL;
13813
13814 if (!info->attrs[NL80211_ATTR_NAN_MASTER_PREF])
13815 return -EINVAL;
13816
cb3b7d87
AB
13817 conf.master_pref =
13818 nla_get_u8(info->attrs[NL80211_ATTR_NAN_MASTER_PREF]);
cb3b7d87 13819
8585989d
LC
13820 if (info->attrs[NL80211_ATTR_BANDS]) {
13821 u32 bands = nla_get_u32(info->attrs[NL80211_ATTR_BANDS]);
13822
13823 if (bands & ~(u32)wdev->wiphy->nan_supported_bands)
13824 return -EOPNOTSUPP;
13825
13826 if (bands && !(bands & BIT(NL80211_BAND_2GHZ)))
13827 return -EINVAL;
13828
13829 conf.bands = bands;
13830 }
cb3b7d87
AB
13831
13832 err = rdev_start_nan(rdev, wdev, &conf);
13833 if (err)
13834 return err;
13835
73c7da3d 13836 wdev->is_running = true;
cb3b7d87
AB
13837 rdev->opencount++;
13838
13839 return 0;
13840}
13841
13842static int nl80211_stop_nan(struct sk_buff *skb, struct genl_info *info)
13843{
13844 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13845 struct wireless_dev *wdev = info->user_ptr[1];
13846
13847 if (wdev->iftype != NL80211_IFTYPE_NAN)
13848 return -EOPNOTSUPP;
13849
13850 cfg80211_stop_nan(rdev, wdev);
13851
13852 return 0;
13853}
13854
a442b761
AB
13855static int validate_nan_filter(struct nlattr *filter_attr)
13856{
13857 struct nlattr *attr;
13858 int len = 0, n_entries = 0, rem;
13859
13860 nla_for_each_nested(attr, filter_attr, rem) {
13861 len += nla_len(attr);
13862 n_entries++;
13863 }
13864
13865 if (len >= U8_MAX)
13866 return -EINVAL;
13867
13868 return n_entries;
13869}
13870
13871static int handle_nan_filter(struct nlattr *attr_filter,
13872 struct cfg80211_nan_func *func,
13873 bool tx)
13874{
13875 struct nlattr *attr;
13876 int n_entries, rem, i;
13877 struct cfg80211_nan_func_filter *filter;
13878
13879 n_entries = validate_nan_filter(attr_filter);
13880 if (n_entries < 0)
13881 return n_entries;
13882
13883 BUILD_BUG_ON(sizeof(*func->rx_filters) != sizeof(*func->tx_filters));
13884
13885 filter = kcalloc(n_entries, sizeof(*func->rx_filters), GFP_KERNEL);
13886 if (!filter)
13887 return -ENOMEM;
13888
13889 i = 0;
13890 nla_for_each_nested(attr, attr_filter, rem) {
b15ca182 13891 filter[i].filter = nla_memdup(attr, GFP_KERNEL);
6ad27f52
JJ
13892 if (!filter[i].filter)
13893 goto err;
13894
a442b761
AB
13895 filter[i].len = nla_len(attr);
13896 i++;
13897 }
13898 if (tx) {
13899 func->num_tx_filters = n_entries;
13900 func->tx_filters = filter;
13901 } else {
13902 func->num_rx_filters = n_entries;
13903 func->rx_filters = filter;
13904 }
13905
13906 return 0;
6ad27f52
JJ
13907
13908err:
13909 i = 0;
13910 nla_for_each_nested(attr, attr_filter, rem) {
13911 kfree(filter[i].filter);
13912 i++;
13913 }
13914 kfree(filter);
13915 return -ENOMEM;
a442b761
AB
13916}
13917
13918static int nl80211_nan_add_func(struct sk_buff *skb,
13919 struct genl_info *info)
13920{
13921 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13922 struct wireless_dev *wdev = info->user_ptr[1];
13923 struct nlattr *tb[NUM_NL80211_NAN_FUNC_ATTR], *func_attr;
13924 struct cfg80211_nan_func *func;
13925 struct sk_buff *msg = NULL;
13926 void *hdr = NULL;
13927 int err = 0;
13928
13929 if (wdev->iftype != NL80211_IFTYPE_NAN)
13930 return -EOPNOTSUPP;
13931
73c7da3d 13932 if (!wdev_running(wdev))
a442b761
AB
13933 return -ENOTCONN;
13934
13935 if (!info->attrs[NL80211_ATTR_NAN_FUNC])
13936 return -EINVAL;
13937
8cb08174
JB
13938 err = nla_parse_nested_deprecated(tb, NL80211_NAN_FUNC_ATTR_MAX,
13939 info->attrs[NL80211_ATTR_NAN_FUNC],
13940 nl80211_nan_func_policy,
13941 info->extack);
a442b761
AB
13942 if (err)
13943 return err;
13944
13945 func = kzalloc(sizeof(*func), GFP_KERNEL);
13946 if (!func)
13947 return -ENOMEM;
13948
b60ad348 13949 func->cookie = cfg80211_assign_cookie(rdev);
a442b761 13950
cb9abd48 13951 if (!tb[NL80211_NAN_FUNC_TYPE]) {
a442b761
AB
13952 err = -EINVAL;
13953 goto out;
13954 }
13955
13956
13957 func->type = nla_get_u8(tb[NL80211_NAN_FUNC_TYPE]);
13958
13959 if (!tb[NL80211_NAN_FUNC_SERVICE_ID]) {
13960 err = -EINVAL;
13961 goto out;
13962 }
13963
13964 memcpy(func->service_id, nla_data(tb[NL80211_NAN_FUNC_SERVICE_ID]),
13965 sizeof(func->service_id));
13966
13967 func->close_range =
13968 nla_get_flag(tb[NL80211_NAN_FUNC_CLOSE_RANGE]);
13969
13970 if (tb[NL80211_NAN_FUNC_SERVICE_INFO]) {
13971 func->serv_spec_info_len =
13972 nla_len(tb[NL80211_NAN_FUNC_SERVICE_INFO]);
13973 func->serv_spec_info =
13974 kmemdup(nla_data(tb[NL80211_NAN_FUNC_SERVICE_INFO]),
13975 func->serv_spec_info_len,
13976 GFP_KERNEL);
13977 if (!func->serv_spec_info) {
13978 err = -ENOMEM;
13979 goto out;
13980 }
13981 }
13982
13983 if (tb[NL80211_NAN_FUNC_TTL])
13984 func->ttl = nla_get_u32(tb[NL80211_NAN_FUNC_TTL]);
13985
13986 switch (func->type) {
13987 case NL80211_NAN_FUNC_PUBLISH:
13988 if (!tb[NL80211_NAN_FUNC_PUBLISH_TYPE]) {
13989 err = -EINVAL;
13990 goto out;
13991 }
13992
13993 func->publish_type =
13994 nla_get_u8(tb[NL80211_NAN_FUNC_PUBLISH_TYPE]);
13995 func->publish_bcast =
13996 nla_get_flag(tb[NL80211_NAN_FUNC_PUBLISH_BCAST]);
13997
13998 if ((!(func->publish_type & NL80211_NAN_SOLICITED_PUBLISH)) &&
13999 func->publish_bcast) {
14000 err = -EINVAL;
14001 goto out;
14002 }
14003 break;
14004 case NL80211_NAN_FUNC_SUBSCRIBE:
14005 func->subscribe_active =
14006 nla_get_flag(tb[NL80211_NAN_FUNC_SUBSCRIBE_ACTIVE]);
14007 break;
14008 case NL80211_NAN_FUNC_FOLLOW_UP:
14009 if (!tb[NL80211_NAN_FUNC_FOLLOW_UP_ID] ||
3ea15452
HC
14010 !tb[NL80211_NAN_FUNC_FOLLOW_UP_REQ_ID] ||
14011 !tb[NL80211_NAN_FUNC_FOLLOW_UP_DEST]) {
a442b761
AB
14012 err = -EINVAL;
14013 goto out;
14014 }
14015
14016 func->followup_id =
14017 nla_get_u8(tb[NL80211_NAN_FUNC_FOLLOW_UP_ID]);
14018 func->followup_reqid =
14019 nla_get_u8(tb[NL80211_NAN_FUNC_FOLLOW_UP_REQ_ID]);
14020 memcpy(func->followup_dest.addr,
14021 nla_data(tb[NL80211_NAN_FUNC_FOLLOW_UP_DEST]),
14022 sizeof(func->followup_dest.addr));
14023 if (func->ttl) {
14024 err = -EINVAL;
14025 goto out;
14026 }
14027 break;
14028 default:
14029 err = -EINVAL;
14030 goto out;
14031 }
14032
14033 if (tb[NL80211_NAN_FUNC_SRF]) {
14034 struct nlattr *srf_tb[NUM_NL80211_NAN_SRF_ATTR];
14035
8cb08174
JB
14036 err = nla_parse_nested_deprecated(srf_tb,
14037 NL80211_NAN_SRF_ATTR_MAX,
14038 tb[NL80211_NAN_FUNC_SRF],
14039 nl80211_nan_srf_policy,
14040 info->extack);
a442b761
AB
14041 if (err)
14042 goto out;
14043
14044 func->srf_include =
14045 nla_get_flag(srf_tb[NL80211_NAN_SRF_INCLUDE]);
14046
14047 if (srf_tb[NL80211_NAN_SRF_BF]) {
14048 if (srf_tb[NL80211_NAN_SRF_MAC_ADDRS] ||
14049 !srf_tb[NL80211_NAN_SRF_BF_IDX]) {
14050 err = -EINVAL;
14051 goto out;
14052 }
14053
14054 func->srf_bf_len =
14055 nla_len(srf_tb[NL80211_NAN_SRF_BF]);
14056 func->srf_bf =
14057 kmemdup(nla_data(srf_tb[NL80211_NAN_SRF_BF]),
14058 func->srf_bf_len, GFP_KERNEL);
14059 if (!func->srf_bf) {
14060 err = -ENOMEM;
14061 goto out;
14062 }
14063
14064 func->srf_bf_idx =
14065 nla_get_u8(srf_tb[NL80211_NAN_SRF_BF_IDX]);
14066 } else {
14067 struct nlattr *attr, *mac_attr =
14068 srf_tb[NL80211_NAN_SRF_MAC_ADDRS];
14069 int n_entries, rem, i = 0;
14070
14071 if (!mac_attr) {
14072 err = -EINVAL;
14073 goto out;
14074 }
14075
14076 n_entries = validate_acl_mac_addrs(mac_attr);
14077 if (n_entries <= 0) {
14078 err = -EINVAL;
14079 goto out;
14080 }
14081
14082 func->srf_num_macs = n_entries;
14083 func->srf_macs =
6396bb22 14084 kcalloc(n_entries, sizeof(*func->srf_macs),
a442b761
AB
14085 GFP_KERNEL);
14086 if (!func->srf_macs) {
14087 err = -ENOMEM;
14088 goto out;
14089 }
14090
14091 nla_for_each_nested(attr, mac_attr, rem)
14092 memcpy(func->srf_macs[i++].addr, nla_data(attr),
14093 sizeof(*func->srf_macs));
14094 }
14095 }
14096
14097 if (tb[NL80211_NAN_FUNC_TX_MATCH_FILTER]) {
14098 err = handle_nan_filter(tb[NL80211_NAN_FUNC_TX_MATCH_FILTER],
14099 func, true);
14100 if (err)
14101 goto out;
14102 }
14103
14104 if (tb[NL80211_NAN_FUNC_RX_MATCH_FILTER]) {
14105 err = handle_nan_filter(tb[NL80211_NAN_FUNC_RX_MATCH_FILTER],
14106 func, false);
14107 if (err)
14108 goto out;
14109 }
14110
14111 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
14112 if (!msg) {
14113 err = -ENOMEM;
14114 goto out;
14115 }
14116
14117 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
14118 NL80211_CMD_ADD_NAN_FUNCTION);
14119 /* This can't really happen - we just allocated 4KB */
14120 if (WARN_ON(!hdr)) {
14121 err = -ENOMEM;
14122 goto out;
14123 }
14124
14125 err = rdev_add_nan_func(rdev, wdev, func);
14126out:
14127 if (err < 0) {
14128 cfg80211_free_nan_func(func);
14129 nlmsg_free(msg);
14130 return err;
14131 }
14132
14133 /* propagate the instance id and cookie to userspace */
14134 if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, func->cookie,
14135 NL80211_ATTR_PAD))
14136 goto nla_put_failure;
14137
ae0be8de 14138 func_attr = nla_nest_start_noflag(msg, NL80211_ATTR_NAN_FUNC);
a442b761
AB
14139 if (!func_attr)
14140 goto nla_put_failure;
14141
14142 if (nla_put_u8(msg, NL80211_NAN_FUNC_INSTANCE_ID,
14143 func->instance_id))
14144 goto nla_put_failure;
14145
14146 nla_nest_end(msg, func_attr);
14147
14148 genlmsg_end(msg, hdr);
14149 return genlmsg_reply(msg, info);
14150
14151nla_put_failure:
14152 nlmsg_free(msg);
14153 return -ENOBUFS;
14154}
14155
14156static int nl80211_nan_del_func(struct sk_buff *skb,
14157 struct genl_info *info)
14158{
14159 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14160 struct wireless_dev *wdev = info->user_ptr[1];
14161 u64 cookie;
14162
14163 if (wdev->iftype != NL80211_IFTYPE_NAN)
14164 return -EOPNOTSUPP;
14165
73c7da3d 14166 if (!wdev_running(wdev))
a442b761
AB
14167 return -ENOTCONN;
14168
14169 if (!info->attrs[NL80211_ATTR_COOKIE])
14170 return -EINVAL;
14171
a442b761
AB
14172 cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);
14173
14174 rdev_del_nan_func(rdev, wdev, cookie);
14175
14176 return 0;
14177}
14178
a5a9dcf2
AB
14179static int nl80211_nan_change_config(struct sk_buff *skb,
14180 struct genl_info *info)
14181{
14182 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14183 struct wireless_dev *wdev = info->user_ptr[1];
14184 struct cfg80211_nan_conf conf = {};
14185 u32 changed = 0;
14186
14187 if (wdev->iftype != NL80211_IFTYPE_NAN)
14188 return -EOPNOTSUPP;
14189
73c7da3d 14190 if (!wdev_running(wdev))
a5a9dcf2
AB
14191 return -ENOTCONN;
14192
14193 if (info->attrs[NL80211_ATTR_NAN_MASTER_PREF]) {
14194 conf.master_pref =
14195 nla_get_u8(info->attrs[NL80211_ATTR_NAN_MASTER_PREF]);
14196 if (conf.master_pref <= 1 || conf.master_pref == 255)
14197 return -EINVAL;
14198
14199 changed |= CFG80211_NAN_CONF_CHANGED_PREF;
14200 }
14201
8585989d
LC
14202 if (info->attrs[NL80211_ATTR_BANDS]) {
14203 u32 bands = nla_get_u32(info->attrs[NL80211_ATTR_BANDS]);
14204
14205 if (bands & ~(u32)wdev->wiphy->nan_supported_bands)
14206 return -EOPNOTSUPP;
14207
14208 if (bands && !(bands & BIT(NL80211_BAND_2GHZ)))
14209 return -EINVAL;
14210
14211 conf.bands = bands;
14212 changed |= CFG80211_NAN_CONF_CHANGED_BANDS;
a5a9dcf2
AB
14213 }
14214
14215 if (!changed)
14216 return -EINVAL;
14217
14218 return rdev_nan_change_conf(rdev, wdev, &conf, changed);
14219}
14220
50bcd31d
AB
14221void cfg80211_nan_match(struct wireless_dev *wdev,
14222 struct cfg80211_nan_match_params *match, gfp_t gfp)
14223{
14224 struct wiphy *wiphy = wdev->wiphy;
14225 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
14226 struct nlattr *match_attr, *local_func_attr, *peer_func_attr;
14227 struct sk_buff *msg;
14228 void *hdr;
14229
14230 if (WARN_ON(!match->inst_id || !match->peer_inst_id || !match->addr))
14231 return;
14232
14233 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
14234 if (!msg)
14235 return;
14236
14237 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NAN_MATCH);
14238 if (!hdr) {
14239 nlmsg_free(msg);
14240 return;
14241 }
14242
14243 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
14244 (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
14245 wdev->netdev->ifindex)) ||
14246 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
14247 NL80211_ATTR_PAD))
14248 goto nla_put_failure;
14249
14250 if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, match->cookie,
14251 NL80211_ATTR_PAD) ||
14252 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, match->addr))
14253 goto nla_put_failure;
14254
ae0be8de 14255 match_attr = nla_nest_start_noflag(msg, NL80211_ATTR_NAN_MATCH);
50bcd31d
AB
14256 if (!match_attr)
14257 goto nla_put_failure;
14258
ae0be8de
MK
14259 local_func_attr = nla_nest_start_noflag(msg,
14260 NL80211_NAN_MATCH_FUNC_LOCAL);
50bcd31d
AB
14261 if (!local_func_attr)
14262 goto nla_put_failure;
14263
14264 if (nla_put_u8(msg, NL80211_NAN_FUNC_INSTANCE_ID, match->inst_id))
14265 goto nla_put_failure;
14266
14267 nla_nest_end(msg, local_func_attr);
14268
ae0be8de
MK
14269 peer_func_attr = nla_nest_start_noflag(msg,
14270 NL80211_NAN_MATCH_FUNC_PEER);
50bcd31d
AB
14271 if (!peer_func_attr)
14272 goto nla_put_failure;
14273
14274 if (nla_put_u8(msg, NL80211_NAN_FUNC_TYPE, match->type) ||
14275 nla_put_u8(msg, NL80211_NAN_FUNC_INSTANCE_ID, match->peer_inst_id))
14276 goto nla_put_failure;
14277
14278 if (match->info && match->info_len &&
14279 nla_put(msg, NL80211_NAN_FUNC_SERVICE_INFO, match->info_len,
14280 match->info))
14281 goto nla_put_failure;
14282
14283 nla_nest_end(msg, peer_func_attr);
14284 nla_nest_end(msg, match_attr);
14285 genlmsg_end(msg, hdr);
14286
14287 if (!wdev->owner_nlportid)
14288 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
14289 msg, 0, NL80211_MCGRP_NAN, gfp);
14290 else
14291 genlmsg_unicast(wiphy_net(&rdev->wiphy), msg,
14292 wdev->owner_nlportid);
14293
14294 return;
14295
14296nla_put_failure:
14297 nlmsg_free(msg);
14298}
14299EXPORT_SYMBOL(cfg80211_nan_match);
14300
368e5a7b
AB
14301void cfg80211_nan_func_terminated(struct wireless_dev *wdev,
14302 u8 inst_id,
14303 enum nl80211_nan_func_term_reason reason,
14304 u64 cookie, gfp_t gfp)
14305{
14306 struct wiphy *wiphy = wdev->wiphy;
14307 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
14308 struct sk_buff *msg;
14309 struct nlattr *func_attr;
14310 void *hdr;
14311
14312 if (WARN_ON(!inst_id))
14313 return;
14314
14315 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
14316 if (!msg)
14317 return;
14318
14319 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_DEL_NAN_FUNCTION);
14320 if (!hdr) {
14321 nlmsg_free(msg);
14322 return;
14323 }
14324
14325 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
14326 (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
14327 wdev->netdev->ifindex)) ||
14328 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
14329 NL80211_ATTR_PAD))
14330 goto nla_put_failure;
14331
14332 if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
14333 NL80211_ATTR_PAD))
14334 goto nla_put_failure;
14335
ae0be8de 14336 func_attr = nla_nest_start_noflag(msg, NL80211_ATTR_NAN_FUNC);
368e5a7b
AB
14337 if (!func_attr)
14338 goto nla_put_failure;
14339
14340 if (nla_put_u8(msg, NL80211_NAN_FUNC_INSTANCE_ID, inst_id) ||
14341 nla_put_u8(msg, NL80211_NAN_FUNC_TERM_REASON, reason))
14342 goto nla_put_failure;
14343
14344 nla_nest_end(msg, func_attr);
14345 genlmsg_end(msg, hdr);
14346
14347 if (!wdev->owner_nlportid)
14348 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
14349 msg, 0, NL80211_MCGRP_NAN, gfp);
14350 else
14351 genlmsg_unicast(wiphy_net(&rdev->wiphy), msg,
14352 wdev->owner_nlportid);
14353
14354 return;
14355
14356nla_put_failure:
14357 nlmsg_free(msg);
14358}
14359EXPORT_SYMBOL(cfg80211_nan_func_terminated);
14360
3713b4e3
JB
14361static int nl80211_get_protocol_features(struct sk_buff *skb,
14362 struct genl_info *info)
14363{
14364 void *hdr;
14365 struct sk_buff *msg;
14366
14367 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
14368 if (!msg)
14369 return -ENOMEM;
14370
14371 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
14372 NL80211_CMD_GET_PROTOCOL_FEATURES);
14373 if (!hdr)
14374 goto nla_put_failure;
14375
14376 if (nla_put_u32(msg, NL80211_ATTR_PROTOCOL_FEATURES,
14377 NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP))
14378 goto nla_put_failure;
14379
14380 genlmsg_end(msg, hdr);
14381 return genlmsg_reply(msg, info);
14382
14383 nla_put_failure:
14384 kfree_skb(msg);
14385 return -ENOBUFS;
14386}
14387
355199e0
JM
14388static int nl80211_update_ft_ies(struct sk_buff *skb, struct genl_info *info)
14389{
14390 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14391 struct cfg80211_update_ft_ies_params ft_params;
14392 struct net_device *dev = info->user_ptr[1];
14393
14394 if (!rdev->ops->update_ft_ies)
14395 return -EOPNOTSUPP;
14396
14397 if (!info->attrs[NL80211_ATTR_MDID] ||
3d7af878 14398 !info->attrs[NL80211_ATTR_IE])
355199e0
JM
14399 return -EINVAL;
14400
14401 memset(&ft_params, 0, sizeof(ft_params));
14402 ft_params.md = nla_get_u16(info->attrs[NL80211_ATTR_MDID]);
14403 ft_params.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
14404 ft_params.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
14405
14406 return rdev_update_ft_ies(rdev, dev, &ft_params);
14407}
14408
5de17984
AS
14409static int nl80211_crit_protocol_start(struct sk_buff *skb,
14410 struct genl_info *info)
14411{
14412 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14413 struct wireless_dev *wdev = info->user_ptr[1];
14414 enum nl80211_crit_proto_id proto = NL80211_CRIT_PROTO_UNSPEC;
14415 u16 duration;
14416 int ret;
14417
14418 if (!rdev->ops->crit_proto_start)
14419 return -EOPNOTSUPP;
14420
14421 if (WARN_ON(!rdev->ops->crit_proto_stop))
14422 return -EINVAL;
14423
14424 if (rdev->crit_proto_nlportid)
14425 return -EBUSY;
14426
14427 /* determine protocol if provided */
14428 if (info->attrs[NL80211_ATTR_CRIT_PROT_ID])
14429 proto = nla_get_u16(info->attrs[NL80211_ATTR_CRIT_PROT_ID]);
14430
14431 if (proto >= NUM_NL80211_CRIT_PROTO)
14432 return -EINVAL;
14433
14434 /* timeout must be provided */
14435 if (!info->attrs[NL80211_ATTR_MAX_CRIT_PROT_DURATION])
14436 return -EINVAL;
14437
14438 duration =
14439 nla_get_u16(info->attrs[NL80211_ATTR_MAX_CRIT_PROT_DURATION]);
14440
5de17984
AS
14441 ret = rdev_crit_proto_start(rdev, wdev, proto, duration);
14442 if (!ret)
14443 rdev->crit_proto_nlportid = info->snd_portid;
14444
14445 return ret;
14446}
14447
14448static int nl80211_crit_protocol_stop(struct sk_buff *skb,
14449 struct genl_info *info)
14450{
14451 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14452 struct wireless_dev *wdev = info->user_ptr[1];
14453
14454 if (!rdev->ops->crit_proto_stop)
14455 return -EOPNOTSUPP;
14456
14457 if (rdev->crit_proto_nlportid) {
14458 rdev->crit_proto_nlportid = 0;
14459 rdev_crit_proto_stop(rdev, wdev);
14460 }
14461 return 0;
14462}
14463
901bb989
JB
14464static int nl80211_vendor_check_policy(const struct wiphy_vendor_command *vcmd,
14465 struct nlattr *attr,
14466 struct netlink_ext_ack *extack)
14467{
14468 if (vcmd->policy == VENDOR_CMD_RAW_DATA) {
14469 if (attr->nla_type & NLA_F_NESTED) {
14470 NL_SET_ERR_MSG_ATTR(extack, attr,
14471 "unexpected nested data");
14472 return -EINVAL;
14473 }
14474
14475 return 0;
14476 }
14477
14478 if (!(attr->nla_type & NLA_F_NESTED)) {
14479 NL_SET_ERR_MSG_ATTR(extack, attr, "expected nested data");
14480 return -EINVAL;
14481 }
14482
32d5109a 14483 return nla_validate_nested(attr, vcmd->maxattr, vcmd->policy, extack);
901bb989
JB
14484}
14485
ad7e718c
JB
14486static int nl80211_vendor_cmd(struct sk_buff *skb, struct genl_info *info)
14487{
14488 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14489 struct wireless_dev *wdev =
a05829a7
JB
14490 __cfg80211_wdev_from_attrs(rdev, genl_info_net(info),
14491 info->attrs);
ad7e718c
JB
14492 int i, err;
14493 u32 vid, subcmd;
14494
14495 if (!rdev->wiphy.vendor_commands)
14496 return -EOPNOTSUPP;
14497
14498 if (IS_ERR(wdev)) {
14499 err = PTR_ERR(wdev);
14500 if (err != -EINVAL)
14501 return err;
14502 wdev = NULL;
14503 } else if (wdev->wiphy != &rdev->wiphy) {
14504 return -EINVAL;
14505 }
14506
14507 if (!info->attrs[NL80211_ATTR_VENDOR_ID] ||
14508 !info->attrs[NL80211_ATTR_VENDOR_SUBCMD])
14509 return -EINVAL;
14510
14511 vid = nla_get_u32(info->attrs[NL80211_ATTR_VENDOR_ID]);
14512 subcmd = nla_get_u32(info->attrs[NL80211_ATTR_VENDOR_SUBCMD]);
14513 for (i = 0; i < rdev->wiphy.n_vendor_commands; i++) {
14514 const struct wiphy_vendor_command *vcmd;
14515 void *data = NULL;
14516 int len = 0;
14517
14518 vcmd = &rdev->wiphy.vendor_commands[i];
14519
14520 if (vcmd->info.vendor_id != vid || vcmd->info.subcmd != subcmd)
14521 continue;
14522
14523 if (vcmd->flags & (WIPHY_VENDOR_CMD_NEED_WDEV |
14524 WIPHY_VENDOR_CMD_NEED_NETDEV)) {
14525 if (!wdev)
14526 return -EINVAL;
14527 if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_NETDEV &&
14528 !wdev->netdev)
14529 return -EINVAL;
14530
14531 if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_RUNNING) {
73c7da3d 14532 if (!wdev_running(wdev))
ad7e718c
JB
14533 return -ENETDOWN;
14534 }
14535 } else {
14536 wdev = NULL;
14537 }
14538
4052d3d2
JS
14539 if (!vcmd->doit)
14540 return -EOPNOTSUPP;
14541
ad7e718c
JB
14542 if (info->attrs[NL80211_ATTR_VENDOR_DATA]) {
14543 data = nla_data(info->attrs[NL80211_ATTR_VENDOR_DATA]);
14544 len = nla_len(info->attrs[NL80211_ATTR_VENDOR_DATA]);
901bb989
JB
14545
14546 err = nl80211_vendor_check_policy(vcmd,
14547 info->attrs[NL80211_ATTR_VENDOR_DATA],
14548 info->extack);
14549 if (err)
14550 return err;
ad7e718c
JB
14551 }
14552
14553 rdev->cur_cmd_info = info;
901bb989 14554 err = vcmd->doit(&rdev->wiphy, wdev, data, len);
ad7e718c
JB
14555 rdev->cur_cmd_info = NULL;
14556 return err;
14557 }
14558
14559 return -EOPNOTSUPP;
14560}
14561
7bdbe400
JB
14562static int nl80211_prepare_vendor_dump(struct sk_buff *skb,
14563 struct netlink_callback *cb,
14564 struct cfg80211_registered_device **rdev,
14565 struct wireless_dev **wdev)
14566{
50508d94 14567 struct nlattr **attrbuf;
7bdbe400
JB
14568 u32 vid, subcmd;
14569 unsigned int i;
14570 int vcmd_idx = -1;
14571 int err;
14572 void *data = NULL;
14573 unsigned int data_len = 0;
14574
7bdbe400
JB
14575 if (cb->args[0]) {
14576 /* subtract the 1 again here */
14577 struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0] - 1);
14578 struct wireless_dev *tmp;
14579
ea90e0dc
JB
14580 if (!wiphy)
14581 return -ENODEV;
7bdbe400
JB
14582 *rdev = wiphy_to_rdev(wiphy);
14583 *wdev = NULL;
14584
14585 if (cb->args[1]) {
53873f13 14586 list_for_each_entry(tmp, &wiphy->wdev_list, list) {
7bdbe400
JB
14587 if (tmp->identifier == cb->args[1] - 1) {
14588 *wdev = tmp;
14589 break;
14590 }
14591 }
14592 }
14593
14594 /* keep rtnl locked in successful case */
14595 return 0;
14596 }
14597
50508d94
JB
14598 attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf), GFP_KERNEL);
14599 if (!attrbuf)
14600 return -ENOMEM;
14601
8cb08174
JB
14602 err = nlmsg_parse_deprecated(cb->nlh,
14603 GENL_HDRLEN + nl80211_fam.hdrsize,
14604 attrbuf, nl80211_fam.maxattr,
14605 nl80211_policy, NULL);
7bdbe400 14606 if (err)
50508d94 14607 goto out;
7bdbe400 14608
c90c39da 14609 if (!attrbuf[NL80211_ATTR_VENDOR_ID] ||
50508d94
JB
14610 !attrbuf[NL80211_ATTR_VENDOR_SUBCMD]) {
14611 err = -EINVAL;
14612 goto out;
14613 }
7bdbe400 14614
a05829a7 14615 *wdev = __cfg80211_wdev_from_attrs(NULL, sock_net(skb->sk), attrbuf);
7bdbe400
JB
14616 if (IS_ERR(*wdev))
14617 *wdev = NULL;
14618
c90c39da 14619 *rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk), attrbuf);
50508d94
JB
14620 if (IS_ERR(*rdev)) {
14621 err = PTR_ERR(*rdev);
14622 goto out;
14623 }
7bdbe400 14624
c90c39da
JB
14625 vid = nla_get_u32(attrbuf[NL80211_ATTR_VENDOR_ID]);
14626 subcmd = nla_get_u32(attrbuf[NL80211_ATTR_VENDOR_SUBCMD]);
7bdbe400
JB
14627
14628 for (i = 0; i < (*rdev)->wiphy.n_vendor_commands; i++) {
14629 const struct wiphy_vendor_command *vcmd;
14630
14631 vcmd = &(*rdev)->wiphy.vendor_commands[i];
14632
14633 if (vcmd->info.vendor_id != vid || vcmd->info.subcmd != subcmd)
14634 continue;
14635
50508d94
JB
14636 if (!vcmd->dumpit) {
14637 err = -EOPNOTSUPP;
14638 goto out;
14639 }
7bdbe400
JB
14640
14641 vcmd_idx = i;
14642 break;
14643 }
14644
50508d94
JB
14645 if (vcmd_idx < 0) {
14646 err = -EOPNOTSUPP;
14647 goto out;
14648 }
7bdbe400 14649
c90c39da
JB
14650 if (attrbuf[NL80211_ATTR_VENDOR_DATA]) {
14651 data = nla_data(attrbuf[NL80211_ATTR_VENDOR_DATA]);
14652 data_len = nla_len(attrbuf[NL80211_ATTR_VENDOR_DATA]);
901bb989
JB
14653
14654 err = nl80211_vendor_check_policy(
14655 &(*rdev)->wiphy.vendor_commands[vcmd_idx],
14656 attrbuf[NL80211_ATTR_VENDOR_DATA],
14657 cb->extack);
14658 if (err)
50508d94 14659 goto out;
7bdbe400
JB
14660 }
14661
14662 /* 0 is the first index - add 1 to parse only once */
14663 cb->args[0] = (*rdev)->wiphy_idx + 1;
14664 /* add 1 to know if it was NULL */
14665 cb->args[1] = *wdev ? (*wdev)->identifier + 1 : 0;
14666 cb->args[2] = vcmd_idx;
14667 cb->args[3] = (unsigned long)data;
14668 cb->args[4] = data_len;
14669
14670 /* keep rtnl locked in successful case */
50508d94
JB
14671 err = 0;
14672out:
14673 kfree(attrbuf);
14674 return err;
7bdbe400
JB
14675}
14676
14677static int nl80211_vendor_cmd_dump(struct sk_buff *skb,
14678 struct netlink_callback *cb)
14679{
14680 struct cfg80211_registered_device *rdev;
14681 struct wireless_dev *wdev;
14682 unsigned int vcmd_idx;
14683 const struct wiphy_vendor_command *vcmd;
14684 void *data;
14685 int data_len;
14686 int err;
14687 struct nlattr *vendor_data;
14688
ea90e0dc 14689 rtnl_lock();
7bdbe400
JB
14690 err = nl80211_prepare_vendor_dump(skb, cb, &rdev, &wdev);
14691 if (err)
ea90e0dc 14692 goto out;
7bdbe400
JB
14693
14694 vcmd_idx = cb->args[2];
14695 data = (void *)cb->args[3];
14696 data_len = cb->args[4];
14697 vcmd = &rdev->wiphy.vendor_commands[vcmd_idx];
14698
14699 if (vcmd->flags & (WIPHY_VENDOR_CMD_NEED_WDEV |
14700 WIPHY_VENDOR_CMD_NEED_NETDEV)) {
ea90e0dc
JB
14701 if (!wdev) {
14702 err = -EINVAL;
14703 goto out;
14704 }
7bdbe400 14705 if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_NETDEV &&
ea90e0dc
JB
14706 !wdev->netdev) {
14707 err = -EINVAL;
14708 goto out;
14709 }
7bdbe400
JB
14710
14711 if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_RUNNING) {
ea90e0dc
JB
14712 if (!wdev_running(wdev)) {
14713 err = -ENETDOWN;
14714 goto out;
14715 }
7bdbe400
JB
14716 }
14717 }
14718
14719 while (1) {
14720 void *hdr = nl80211hdr_put(skb, NETLINK_CB(cb->skb).portid,
14721 cb->nlh->nlmsg_seq, NLM_F_MULTI,
14722 NL80211_CMD_VENDOR);
14723 if (!hdr)
14724 break;
14725
14726 if (nla_put_u32(skb, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
2dad624e
ND
14727 (wdev && nla_put_u64_64bit(skb, NL80211_ATTR_WDEV,
14728 wdev_id(wdev),
14729 NL80211_ATTR_PAD))) {
7bdbe400
JB
14730 genlmsg_cancel(skb, hdr);
14731 break;
14732 }
14733
ae0be8de
MK
14734 vendor_data = nla_nest_start_noflag(skb,
14735 NL80211_ATTR_VENDOR_DATA);
7bdbe400
JB
14736 if (!vendor_data) {
14737 genlmsg_cancel(skb, hdr);
14738 break;
14739 }
14740
14741 err = vcmd->dumpit(&rdev->wiphy, wdev, skb, data, data_len,
14742 (unsigned long *)&cb->args[5]);
14743 nla_nest_end(skb, vendor_data);
14744
14745 if (err == -ENOBUFS || err == -ENOENT) {
14746 genlmsg_cancel(skb, hdr);
14747 break;
9c167b2d 14748 } else if (err <= 0) {
7bdbe400
JB
14749 genlmsg_cancel(skb, hdr);
14750 goto out;
14751 }
14752
14753 genlmsg_end(skb, hdr);
14754 }
14755
14756 err = skb->len;
14757 out:
14758 rtnl_unlock();
14759 return err;
14760}
14761
ad7e718c
JB
14762struct sk_buff *__cfg80211_alloc_reply_skb(struct wiphy *wiphy,
14763 enum nl80211_commands cmd,
14764 enum nl80211_attrs attr,
14765 int approxlen)
14766{
f26cbf40 14767 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
ad7e718c
JB
14768
14769 if (WARN_ON(!rdev->cur_cmd_info))
14770 return NULL;
14771
6c09e791 14772 return __cfg80211_alloc_vendor_skb(rdev, NULL, approxlen,
ad7e718c
JB
14773 rdev->cur_cmd_info->snd_portid,
14774 rdev->cur_cmd_info->snd_seq,
567ffc35 14775 cmd, attr, NULL, GFP_KERNEL);
ad7e718c
JB
14776}
14777EXPORT_SYMBOL(__cfg80211_alloc_reply_skb);
14778
14779int cfg80211_vendor_cmd_reply(struct sk_buff *skb)
14780{
14781 struct cfg80211_registered_device *rdev = ((void **)skb->cb)[0];
14782 void *hdr = ((void **)skb->cb)[1];
14783 struct nlattr *data = ((void **)skb->cb)[2];
14784
bd8c78e7
JB
14785 /* clear CB data for netlink core to own from now on */
14786 memset(skb->cb, 0, sizeof(skb->cb));
14787
ad7e718c
JB
14788 if (WARN_ON(!rdev->cur_cmd_info)) {
14789 kfree_skb(skb);
14790 return -EINVAL;
14791 }
14792
14793 nla_nest_end(skb, data);
14794 genlmsg_end(skb, hdr);
14795 return genlmsg_reply(skb, rdev->cur_cmd_info);
14796}
14797EXPORT_SYMBOL_GPL(cfg80211_vendor_cmd_reply);
14798
55c1fdf0
JB
14799unsigned int cfg80211_vendor_cmd_get_sender(struct wiphy *wiphy)
14800{
14801 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
14802
14803 if (WARN_ON(!rdev->cur_cmd_info))
14804 return 0;
14805
14806 return rdev->cur_cmd_info->snd_portid;
14807}
14808EXPORT_SYMBOL_GPL(cfg80211_vendor_cmd_get_sender);
14809
fa9ffc74
KP
14810static int nl80211_set_qos_map(struct sk_buff *skb,
14811 struct genl_info *info)
14812{
14813 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14814 struct cfg80211_qos_map *qos_map = NULL;
14815 struct net_device *dev = info->user_ptr[1];
14816 u8 *pos, len, num_des, des_len, des;
14817 int ret;
14818
14819 if (!rdev->ops->set_qos_map)
14820 return -EOPNOTSUPP;
14821
14822 if (info->attrs[NL80211_ATTR_QOS_MAP]) {
14823 pos = nla_data(info->attrs[NL80211_ATTR_QOS_MAP]);
14824 len = nla_len(info->attrs[NL80211_ATTR_QOS_MAP]);
14825
c8b82802 14826 if (len % 2)
fa9ffc74
KP
14827 return -EINVAL;
14828
14829 qos_map = kzalloc(sizeof(struct cfg80211_qos_map), GFP_KERNEL);
14830 if (!qos_map)
14831 return -ENOMEM;
14832
14833 num_des = (len - IEEE80211_QOS_MAP_LEN_MIN) >> 1;
14834 if (num_des) {
14835 des_len = num_des *
14836 sizeof(struct cfg80211_dscp_exception);
14837 memcpy(qos_map->dscp_exception, pos, des_len);
14838 qos_map->num_des = num_des;
14839 for (des = 0; des < num_des; des++) {
14840 if (qos_map->dscp_exception[des].up > 7) {
14841 kfree(qos_map);
14842 return -EINVAL;
14843 }
14844 }
14845 pos += des_len;
14846 }
14847 memcpy(qos_map->up, pos, IEEE80211_QOS_MAP_LEN_MIN);
14848 }
14849
14850 wdev_lock(dev->ieee80211_ptr);
14851 ret = nl80211_key_allowed(dev->ieee80211_ptr);
14852 if (!ret)
14853 ret = rdev_set_qos_map(rdev, dev, qos_map);
14854 wdev_unlock(dev->ieee80211_ptr);
14855
14856 kfree(qos_map);
14857 return ret;
14858}
14859
960d01ac
JB
14860static int nl80211_add_tx_ts(struct sk_buff *skb, struct genl_info *info)
14861{
14862 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14863 struct net_device *dev = info->user_ptr[1];
14864 struct wireless_dev *wdev = dev->ieee80211_ptr;
14865 const u8 *peer;
14866 u8 tsid, up;
14867 u16 admitted_time = 0;
14868 int err;
14869
723e73ac 14870 if (!(rdev->wiphy.features & NL80211_FEATURE_SUPPORTS_WMM_ADMISSION))
960d01ac
JB
14871 return -EOPNOTSUPP;
14872
14873 if (!info->attrs[NL80211_ATTR_TSID] || !info->attrs[NL80211_ATTR_MAC] ||
14874 !info->attrs[NL80211_ATTR_USER_PRIO])
14875 return -EINVAL;
14876
14877 tsid = nla_get_u8(info->attrs[NL80211_ATTR_TSID]);
960d01ac 14878 up = nla_get_u8(info->attrs[NL80211_ATTR_USER_PRIO]);
960d01ac
JB
14879
14880 /* WMM uses TIDs 0-7 even for TSPEC */
723e73ac 14881 if (tsid >= IEEE80211_FIRST_TSPEC_TSID) {
960d01ac 14882 /* TODO: handle 802.11 TSPEC/admission control
723e73ac
JB
14883 * need more attributes for that (e.g. BA session requirement);
14884 * change the WMM adminssion test above to allow both then
960d01ac
JB
14885 */
14886 return -EINVAL;
14887 }
14888
14889 peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
14890
14891 if (info->attrs[NL80211_ATTR_ADMITTED_TIME]) {
14892 admitted_time =
14893 nla_get_u16(info->attrs[NL80211_ATTR_ADMITTED_TIME]);
14894 if (!admitted_time)
14895 return -EINVAL;
14896 }
14897
14898 wdev_lock(wdev);
14899 switch (wdev->iftype) {
14900 case NL80211_IFTYPE_STATION:
14901 case NL80211_IFTYPE_P2P_CLIENT:
7b0a0e3c 14902 if (wdev->connected)
960d01ac
JB
14903 break;
14904 err = -ENOTCONN;
14905 goto out;
14906 default:
14907 err = -EOPNOTSUPP;
14908 goto out;
14909 }
14910
14911 err = rdev_add_tx_ts(rdev, dev, tsid, peer, up, admitted_time);
14912
14913 out:
14914 wdev_unlock(wdev);
14915 return err;
14916}
14917
14918static int nl80211_del_tx_ts(struct sk_buff *skb, struct genl_info *info)
14919{
14920 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14921 struct net_device *dev = info->user_ptr[1];
14922 struct wireless_dev *wdev = dev->ieee80211_ptr;
14923 const u8 *peer;
14924 u8 tsid;
14925 int err;
14926
14927 if (!info->attrs[NL80211_ATTR_TSID] || !info->attrs[NL80211_ATTR_MAC])
14928 return -EINVAL;
14929
14930 tsid = nla_get_u8(info->attrs[NL80211_ATTR_TSID]);
14931 peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
14932
14933 wdev_lock(wdev);
14934 err = rdev_del_tx_ts(rdev, dev, tsid, peer);
14935 wdev_unlock(wdev);
14936
14937 return err;
14938}
14939
1057d35e
AN
14940static int nl80211_tdls_channel_switch(struct sk_buff *skb,
14941 struct genl_info *info)
14942{
14943 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14944 struct net_device *dev = info->user_ptr[1];
14945 struct wireless_dev *wdev = dev->ieee80211_ptr;
14946 struct cfg80211_chan_def chandef = {};
14947 const u8 *addr;
14948 u8 oper_class;
14949 int err;
14950
14951 if (!rdev->ops->tdls_channel_switch ||
14952 !(rdev->wiphy.features & NL80211_FEATURE_TDLS_CHANNEL_SWITCH))
14953 return -EOPNOTSUPP;
14954
14955 switch (dev->ieee80211_ptr->iftype) {
14956 case NL80211_IFTYPE_STATION:
14957 case NL80211_IFTYPE_P2P_CLIENT:
14958 break;
14959 default:
14960 return -EOPNOTSUPP;
14961 }
14962
14963 if (!info->attrs[NL80211_ATTR_MAC] ||
14964 !info->attrs[NL80211_ATTR_OPER_CLASS])
14965 return -EINVAL;
14966
14967 err = nl80211_parse_chandef(rdev, info, &chandef);
14968 if (err)
14969 return err;
14970
14971 /*
14972 * Don't allow wide channels on the 2.4Ghz band, as per IEEE802.11-2012
14973 * section 10.22.6.2.1. Disallow 5/10Mhz channels as well for now, the
14974 * specification is not defined for them.
14975 */
57fbcce3 14976 if (chandef.chan->band == NL80211_BAND_2GHZ &&
1057d35e
AN
14977 chandef.width != NL80211_CHAN_WIDTH_20_NOHT &&
14978 chandef.width != NL80211_CHAN_WIDTH_20)
14979 return -EINVAL;
14980
14981 /* we will be active on the TDLS link */
923b352f
AN
14982 if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &chandef,
14983 wdev->iftype))
1057d35e
AN
14984 return -EINVAL;
14985
14986 /* don't allow switching to DFS channels */
14987 if (cfg80211_chandef_dfs_required(wdev->wiphy, &chandef, wdev->iftype))
14988 return -EINVAL;
14989
14990 addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
14991 oper_class = nla_get_u8(info->attrs[NL80211_ATTR_OPER_CLASS]);
14992
14993 wdev_lock(wdev);
14994 err = rdev_tdls_channel_switch(rdev, dev, addr, oper_class, &chandef);
14995 wdev_unlock(wdev);
14996
14997 return err;
14998}
14999
15000static int nl80211_tdls_cancel_channel_switch(struct sk_buff *skb,
15001 struct genl_info *info)
15002{
15003 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15004 struct net_device *dev = info->user_ptr[1];
15005 struct wireless_dev *wdev = dev->ieee80211_ptr;
15006 const u8 *addr;
15007
15008 if (!rdev->ops->tdls_channel_switch ||
15009 !rdev->ops->tdls_cancel_channel_switch ||
15010 !(rdev->wiphy.features & NL80211_FEATURE_TDLS_CHANNEL_SWITCH))
15011 return -EOPNOTSUPP;
15012
15013 switch (dev->ieee80211_ptr->iftype) {
15014 case NL80211_IFTYPE_STATION:
15015 case NL80211_IFTYPE_P2P_CLIENT:
15016 break;
15017 default:
15018 return -EOPNOTSUPP;
15019 }
15020
15021 if (!info->attrs[NL80211_ATTR_MAC])
15022 return -EINVAL;
15023
15024 addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
15025
15026 wdev_lock(wdev);
15027 rdev_tdls_cancel_channel_switch(rdev, dev, addr);
15028 wdev_unlock(wdev);
15029
15030 return 0;
15031}
15032
ce0ce13a
MB
15033static int nl80211_set_multicast_to_unicast(struct sk_buff *skb,
15034 struct genl_info *info)
15035{
15036 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15037 struct net_device *dev = info->user_ptr[1];
15038 struct wireless_dev *wdev = dev->ieee80211_ptr;
15039 const struct nlattr *nla;
15040 bool enabled;
15041
ce0ce13a
MB
15042 if (!rdev->ops->set_multicast_to_unicast)
15043 return -EOPNOTSUPP;
15044
15045 if (wdev->iftype != NL80211_IFTYPE_AP &&
15046 wdev->iftype != NL80211_IFTYPE_P2P_GO)
15047 return -EOPNOTSUPP;
15048
15049 nla = info->attrs[NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED];
15050 enabled = nla_get_flag(nla);
15051
15052 return rdev_set_multicast_to_unicast(rdev, dev, enabled);
15053}
15054
3a00df57
AS
15055static int nl80211_set_pmk(struct sk_buff *skb, struct genl_info *info)
15056{
15057 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15058 struct net_device *dev = info->user_ptr[1];
15059 struct wireless_dev *wdev = dev->ieee80211_ptr;
15060 struct cfg80211_pmk_conf pmk_conf = {};
15061 int ret;
15062
15063 if (wdev->iftype != NL80211_IFTYPE_STATION &&
15064 wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
15065 return -EOPNOTSUPP;
15066
15067 if (!wiphy_ext_feature_isset(&rdev->wiphy,
15068 NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X))
15069 return -EOPNOTSUPP;
15070
15071 if (!info->attrs[NL80211_ATTR_MAC] || !info->attrs[NL80211_ATTR_PMK])
15072 return -EINVAL;
15073
15074 wdev_lock(wdev);
7b0a0e3c 15075 if (!wdev->connected) {
3a00df57
AS
15076 ret = -ENOTCONN;
15077 goto out;
15078 }
15079
15080 pmk_conf.aa = nla_data(info->attrs[NL80211_ATTR_MAC]);
7b0a0e3c 15081 if (memcmp(pmk_conf.aa, wdev->u.client.connected_addr, ETH_ALEN)) {
3a00df57
AS
15082 ret = -EINVAL;
15083 goto out;
15084 }
15085
15086 pmk_conf.pmk = nla_data(info->attrs[NL80211_ATTR_PMK]);
15087 pmk_conf.pmk_len = nla_len(info->attrs[NL80211_ATTR_PMK]);
15088 if (pmk_conf.pmk_len != WLAN_PMK_LEN &&
15089 pmk_conf.pmk_len != WLAN_PMK_LEN_SUITE_B_192) {
15090 ret = -EINVAL;
15091 goto out;
15092 }
15093
cb9abd48 15094 if (info->attrs[NL80211_ATTR_PMKR0_NAME])
3a00df57
AS
15095 pmk_conf.pmk_r0_name =
15096 nla_data(info->attrs[NL80211_ATTR_PMKR0_NAME]);
3a00df57
AS
15097
15098 ret = rdev_set_pmk(rdev, dev, &pmk_conf);
15099out:
15100 wdev_unlock(wdev);
15101 return ret;
15102}
15103
15104static int nl80211_del_pmk(struct sk_buff *skb, struct genl_info *info)
15105{
15106 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15107 struct net_device *dev = info->user_ptr[1];
15108 struct wireless_dev *wdev = dev->ieee80211_ptr;
15109 const u8 *aa;
15110 int ret;
15111
15112 if (wdev->iftype != NL80211_IFTYPE_STATION &&
15113 wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
15114 return -EOPNOTSUPP;
15115
15116 if (!wiphy_ext_feature_isset(&rdev->wiphy,
15117 NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X))
15118 return -EOPNOTSUPP;
15119
15120 if (!info->attrs[NL80211_ATTR_MAC])
15121 return -EINVAL;
15122
15123 wdev_lock(wdev);
15124 aa = nla_data(info->attrs[NL80211_ATTR_MAC]);
15125 ret = rdev_del_pmk(rdev, dev, aa);
15126 wdev_unlock(wdev);
15127
15128 return ret;
15129}
15130
40cbfa90
SD
15131static int nl80211_external_auth(struct sk_buff *skb, struct genl_info *info)
15132{
15133 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15134 struct net_device *dev = info->user_ptr[1];
15135 struct cfg80211_external_auth_params params;
15136
db8d93a7 15137 if (!rdev->ops->external_auth)
40cbfa90
SD
15138 return -EOPNOTSUPP;
15139
fe494370
SD
15140 if (!info->attrs[NL80211_ATTR_SSID] &&
15141 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
15142 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
40cbfa90
SD
15143 return -EINVAL;
15144
15145 if (!info->attrs[NL80211_ATTR_BSSID])
15146 return -EINVAL;
15147
15148 if (!info->attrs[NL80211_ATTR_STATUS_CODE])
15149 return -EINVAL;
15150
15151 memset(&params, 0, sizeof(params));
15152
fe494370
SD
15153 if (info->attrs[NL80211_ATTR_SSID]) {
15154 params.ssid.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
cb9abd48 15155 if (params.ssid.ssid_len == 0)
fe494370
SD
15156 return -EINVAL;
15157 memcpy(params.ssid.ssid,
15158 nla_data(info->attrs[NL80211_ATTR_SSID]),
15159 params.ssid.ssid_len);
15160 }
40cbfa90
SD
15161
15162 memcpy(params.bssid, nla_data(info->attrs[NL80211_ATTR_BSSID]),
15163 ETH_ALEN);
15164
15165 params.status = nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]);
15166
fe494370
SD
15167 if (info->attrs[NL80211_ATTR_PMKID])
15168 params.pmkid = nla_data(info->attrs[NL80211_ATTR_PMKID]);
15169
40cbfa90
SD
15170 return rdev_external_auth(rdev, dev, &params);
15171}
15172
2576a9ac
DK
15173static int nl80211_tx_control_port(struct sk_buff *skb, struct genl_info *info)
15174{
dca9ca2d 15175 bool dont_wait_for_ack = info->attrs[NL80211_ATTR_DONT_WAIT_FOR_ACK];
2576a9ac
DK
15176 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15177 struct net_device *dev = info->user_ptr[1];
15178 struct wireless_dev *wdev = dev->ieee80211_ptr;
15179 const u8 *buf;
15180 size_t len;
15181 u8 *dest;
15182 u16 proto;
15183 bool noencrypt;
dca9ca2d 15184 u64 cookie = 0;
2576a9ac
DK
15185 int err;
15186
15187 if (!wiphy_ext_feature_isset(&rdev->wiphy,
15188 NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211))
15189 return -EOPNOTSUPP;
15190
15191 if (!rdev->ops->tx_control_port)
15192 return -EOPNOTSUPP;
15193
15194 if (!info->attrs[NL80211_ATTR_FRAME] ||
15195 !info->attrs[NL80211_ATTR_MAC] ||
15196 !info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]) {
15197 GENL_SET_ERR_MSG(info, "Frame, MAC or ethertype missing");
15198 return -EINVAL;
15199 }
15200
15201 wdev_lock(wdev);
15202
15203 switch (wdev->iftype) {
15204 case NL80211_IFTYPE_AP:
15205 case NL80211_IFTYPE_P2P_GO:
15206 case NL80211_IFTYPE_MESH_POINT:
15207 break;
15208 case NL80211_IFTYPE_ADHOC:
7b0a0e3c
JB
15209 if (wdev->u.ibss.current_bss)
15210 break;
15211 err = -ENOTCONN;
15212 goto out;
2576a9ac
DK
15213 case NL80211_IFTYPE_STATION:
15214 case NL80211_IFTYPE_P2P_CLIENT:
7b0a0e3c 15215 if (wdev->connected)
2576a9ac
DK
15216 break;
15217 err = -ENOTCONN;
15218 goto out;
15219 default:
15220 err = -EOPNOTSUPP;
15221 goto out;
15222 }
15223
15224 wdev_unlock(wdev);
15225
15226 buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
15227 len = nla_len(info->attrs[NL80211_ATTR_FRAME]);
15228 dest = nla_data(info->attrs[NL80211_ATTR_MAC]);
15229 proto = nla_get_u16(info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]);
15230 noencrypt =
15231 nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT]);
15232
dca9ca2d
MT
15233 err = rdev_tx_control_port(rdev, dev, buf, len,
15234 dest, cpu_to_be16(proto), noencrypt,
15235 dont_wait_for_ack ? NULL : &cookie);
15236 if (!err && !dont_wait_for_ack)
15237 nl_set_extack_cookie_u64(info->extack, cookie);
15238 return err;
2576a9ac
DK
15239 out:
15240 wdev_unlock(wdev);
15241 return err;
15242}
15243
81e54d08
PKC
15244static int nl80211_get_ftm_responder_stats(struct sk_buff *skb,
15245 struct genl_info *info)
15246{
15247 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15248 struct net_device *dev = info->user_ptr[1];
15249 struct wireless_dev *wdev = dev->ieee80211_ptr;
15250 struct cfg80211_ftm_responder_stats ftm_stats = {};
7b0a0e3c 15251 unsigned int link_id = nl80211_link_id(info->attrs);
81e54d08
PKC
15252 struct sk_buff *msg;
15253 void *hdr;
15254 struct nlattr *ftm_stats_attr;
15255 int err;
15256
7b0a0e3c
JB
15257 if (wdev->iftype != NL80211_IFTYPE_AP ||
15258 !wdev->links[link_id].ap.beacon_interval)
81e54d08
PKC
15259 return -EOPNOTSUPP;
15260
15261 err = rdev_get_ftm_responder_stats(rdev, dev, &ftm_stats);
15262 if (err)
15263 return err;
15264
15265 if (!ftm_stats.filled)
15266 return -ENODATA;
15267
15268 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
15269 if (!msg)
15270 return -ENOMEM;
15271
15272 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
15273 NL80211_CMD_GET_FTM_RESPONDER_STATS);
15274 if (!hdr)
1399c59f 15275 goto nla_put_failure;
81e54d08
PKC
15276
15277 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
15278 goto nla_put_failure;
15279
ae0be8de
MK
15280 ftm_stats_attr = nla_nest_start_noflag(msg,
15281 NL80211_ATTR_FTM_RESPONDER_STATS);
81e54d08
PKC
15282 if (!ftm_stats_attr)
15283 goto nla_put_failure;
15284
15285#define SET_FTM(field, name, type) \
15286 do { if ((ftm_stats.filled & BIT(NL80211_FTM_STATS_ ## name)) && \
15287 nla_put_ ## type(msg, NL80211_FTM_STATS_ ## name, \
15288 ftm_stats.field)) \
15289 goto nla_put_failure; } while (0)
15290#define SET_FTM_U64(field, name) \
15291 do { if ((ftm_stats.filled & BIT(NL80211_FTM_STATS_ ## name)) && \
15292 nla_put_u64_64bit(msg, NL80211_FTM_STATS_ ## name, \
15293 ftm_stats.field, NL80211_FTM_STATS_PAD)) \
15294 goto nla_put_failure; } while (0)
15295
15296 SET_FTM(success_num, SUCCESS_NUM, u32);
15297 SET_FTM(partial_num, PARTIAL_NUM, u32);
15298 SET_FTM(failed_num, FAILED_NUM, u32);
15299 SET_FTM(asap_num, ASAP_NUM, u32);
15300 SET_FTM(non_asap_num, NON_ASAP_NUM, u32);
15301 SET_FTM_U64(total_duration_ms, TOTAL_DURATION_MSEC);
15302 SET_FTM(unknown_triggers_num, UNKNOWN_TRIGGERS_NUM, u32);
15303 SET_FTM(reschedule_requests_num, RESCHEDULE_REQUESTS_NUM, u32);
15304 SET_FTM(out_of_window_triggers_num, OUT_OF_WINDOW_TRIGGERS_NUM, u32);
15305#undef SET_FTM
15306
15307 nla_nest_end(msg, ftm_stats_attr);
15308
15309 genlmsg_end(msg, hdr);
15310 return genlmsg_reply(msg, info);
15311
15312nla_put_failure:
15313 nlmsg_free(msg);
15314 return -ENOBUFS;
15315}
15316
cb74e977
SD
15317static int nl80211_update_owe_info(struct sk_buff *skb, struct genl_info *info)
15318{
15319 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15320 struct cfg80211_update_owe_info owe_info;
15321 struct net_device *dev = info->user_ptr[1];
15322
15323 if (!rdev->ops->update_owe_info)
15324 return -EOPNOTSUPP;
15325
15326 if (!info->attrs[NL80211_ATTR_STATUS_CODE] ||
15327 !info->attrs[NL80211_ATTR_MAC])
15328 return -EINVAL;
15329
15330 memset(&owe_info, 0, sizeof(owe_info));
15331 owe_info.status = nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]);
15332 nla_memcpy(owe_info.peer, info->attrs[NL80211_ATTR_MAC], ETH_ALEN);
15333
15334 if (info->attrs[NL80211_ATTR_IE]) {
15335 owe_info.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
15336 owe_info.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
15337 }
15338
15339 return rdev_update_owe_info(rdev, dev, &owe_info);
15340}
15341
5ab92e7f
RM
15342static int nl80211_probe_mesh_link(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 struct station_info sinfo = {};
15348 const u8 *buf;
15349 size_t len;
15350 u8 *dest;
15351 int err;
15352
15353 if (!rdev->ops->probe_mesh_link || !rdev->ops->get_station)
15354 return -EOPNOTSUPP;
15355
15356 if (!info->attrs[NL80211_ATTR_MAC] ||
15357 !info->attrs[NL80211_ATTR_FRAME]) {
15358 GENL_SET_ERR_MSG(info, "Frame or MAC missing");
15359 return -EINVAL;
15360 }
15361
15362 if (wdev->iftype != NL80211_IFTYPE_MESH_POINT)
15363 return -EOPNOTSUPP;
15364
15365 dest = nla_data(info->attrs[NL80211_ATTR_MAC]);
15366 buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
15367 len = nla_len(info->attrs[NL80211_ATTR_FRAME]);
15368
15369 if (len < sizeof(struct ethhdr))
15370 return -EINVAL;
15371
15372 if (!ether_addr_equal(buf, dest) || is_multicast_ether_addr(buf) ||
15373 !ether_addr_equal(buf + ETH_ALEN, dev->dev_addr))
15374 return -EINVAL;
15375
15376 err = rdev_get_station(rdev, dev, dest, &sinfo);
15377 if (err)
15378 return err;
15379
2a279b34
FF
15380 cfg80211_sinfo_release_content(&sinfo);
15381
5ab92e7f
RM
15382 return rdev_probe_mesh_link(rdev, dev, dest, buf, len);
15383}
15384
77f576de
T
15385static int parse_tid_conf(struct cfg80211_registered_device *rdev,
15386 struct nlattr *attrs[], struct net_device *dev,
3710a8a6 15387 struct cfg80211_tid_cfg *tid_conf,
7b0a0e3c
JB
15388 struct genl_info *info, const u8 *peer,
15389 unsigned int link_id)
77f576de
T
15390{
15391 struct netlink_ext_ack *extack = info->extack;
3710a8a6 15392 u64 mask;
77f576de
T
15393 int err;
15394
15395 if (!attrs[NL80211_TID_CONFIG_ATTR_TIDS])
15396 return -EINVAL;
15397
15398 tid_conf->config_override =
15399 nla_get_flag(attrs[NL80211_TID_CONFIG_ATTR_OVERRIDE]);
3710a8a6 15400 tid_conf->tids = nla_get_u16(attrs[NL80211_TID_CONFIG_ATTR_TIDS]);
77f576de
T
15401
15402 if (tid_conf->config_override) {
15403 if (rdev->ops->reset_tid_config) {
15404 err = rdev_reset_tid_config(rdev, dev, peer,
3710a8a6 15405 tid_conf->tids);
c0336955 15406 if (err)
77f576de
T
15407 return err;
15408 } else {
15409 return -EINVAL;
15410 }
15411 }
15412
15413 if (attrs[NL80211_TID_CONFIG_ATTR_NOACK]) {
3710a8a6 15414 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_NOACK);
77f576de
T
15415 tid_conf->noack =
15416 nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_NOACK]);
15417 }
15418
6a21d16c
T
15419 if (attrs[NL80211_TID_CONFIG_ATTR_RETRY_SHORT]) {
15420 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_RETRY_SHORT);
15421 tid_conf->retry_short =
15422 nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_RETRY_SHORT]);
15423
15424 if (tid_conf->retry_short > rdev->wiphy.max_data_retry_count)
15425 return -EINVAL;
15426 }
15427
15428 if (attrs[NL80211_TID_CONFIG_ATTR_RETRY_LONG]) {
15429 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_RETRY_LONG);
15430 tid_conf->retry_long =
15431 nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_RETRY_LONG]);
15432
15433 if (tid_conf->retry_long > rdev->wiphy.max_data_retry_count)
15434 return -EINVAL;
15435 }
15436
ade274b2
T
15437 if (attrs[NL80211_TID_CONFIG_ATTR_AMPDU_CTRL]) {
15438 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_AMPDU_CTRL);
15439 tid_conf->ampdu =
15440 nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_AMPDU_CTRL]);
15441 }
15442
04f7d142
T
15443 if (attrs[NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL]) {
15444 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL);
15445 tid_conf->rtscts =
15446 nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL]);
15447 }
15448
33462e68
SM
15449 if (attrs[NL80211_TID_CONFIG_ATTR_AMSDU_CTRL]) {
15450 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_AMSDU_CTRL);
15451 tid_conf->amsdu =
15452 nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_AMSDU_CTRL]);
15453 }
15454
9a5f6488
TC
15455 if (attrs[NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE]) {
15456 u32 idx = NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE, attr;
15457
15458 tid_conf->txrate_type = nla_get_u8(attrs[idx]);
15459
15460 if (tid_conf->txrate_type != NL80211_TX_RATE_AUTOMATIC) {
15461 attr = NL80211_TID_CONFIG_ATTR_TX_RATE;
15462 err = nl80211_parse_tx_bitrate_mask(info, attrs, attr,
857b34c4 15463 &tid_conf->txrate_mask, dev,
7b0a0e3c 15464 true, link_id);
9a5f6488
TC
15465 if (err)
15466 return err;
15467
15468 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_TX_RATE);
15469 }
15470 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE);
15471 }
15472
3710a8a6
JB
15473 if (peer)
15474 mask = rdev->wiphy.tid_config_support.peer;
15475 else
15476 mask = rdev->wiphy.tid_config_support.vif;
15477
15478 if (tid_conf->mask & ~mask) {
15479 NL_SET_ERR_MSG(extack, "unsupported TID configuration");
15480 return -ENOTSUPP;
15481 }
15482
77f576de
T
15483 return 0;
15484}
15485
15486static int nl80211_set_tid_config(struct sk_buff *skb,
15487 struct genl_info *info)
15488{
15489 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15490 struct nlattr *attrs[NL80211_TID_CONFIG_ATTR_MAX + 1];
7b0a0e3c 15491 unsigned int link_id = nl80211_link_id(info->attrs);
77f576de 15492 struct net_device *dev = info->user_ptr[1];
3710a8a6 15493 struct cfg80211_tid_config *tid_config;
77f576de
T
15494 struct nlattr *tid;
15495 int conf_idx = 0, rem_conf;
15496 int ret = -EINVAL;
15497 u32 num_conf = 0;
15498
15499 if (!info->attrs[NL80211_ATTR_TID_CONFIG])
15500 return -EINVAL;
15501
15502 if (!rdev->ops->set_tid_config)
15503 return -EOPNOTSUPP;
15504
15505 nla_for_each_nested(tid, info->attrs[NL80211_ATTR_TID_CONFIG],
15506 rem_conf)
15507 num_conf++;
15508
15509 tid_config = kzalloc(struct_size(tid_config, tid_conf, num_conf),
15510 GFP_KERNEL);
15511 if (!tid_config)
15512 return -ENOMEM;
15513
15514 tid_config->n_tid_conf = num_conf;
15515
15516 if (info->attrs[NL80211_ATTR_MAC])
15517 tid_config->peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
15518
206bbcf7
JB
15519 wdev_lock(dev->ieee80211_ptr);
15520
77f576de
T
15521 nla_for_each_nested(tid, info->attrs[NL80211_ATTR_TID_CONFIG],
15522 rem_conf) {
15523 ret = nla_parse_nested(attrs, NL80211_TID_CONFIG_ATTR_MAX,
15524 tid, NULL, NULL);
15525
15526 if (ret)
15527 goto bad_tid_conf;
15528
15529 ret = parse_tid_conf(rdev, attrs, dev,
15530 &tid_config->tid_conf[conf_idx],
7b0a0e3c 15531 info, tid_config->peer, link_id);
77f576de
T
15532 if (ret)
15533 goto bad_tid_conf;
15534
15535 conf_idx++;
15536 }
15537
15538 ret = rdev_set_tid_config(rdev, dev, tid_config);
15539
15540bad_tid_conf:
15541 kfree(tid_config);
206bbcf7 15542 wdev_unlock(dev->ieee80211_ptr);
77f576de
T
15543 return ret;
15544}
15545
0d2ab3ae
JC
15546static int nl80211_color_change(struct sk_buff *skb, struct genl_info *info)
15547{
15548 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15549 struct cfg80211_color_change_settings params = {};
15550 struct net_device *dev = info->user_ptr[1];
15551 struct wireless_dev *wdev = dev->ieee80211_ptr;
15552 struct nlattr **tb;
15553 u16 offset;
15554 int err;
15555
15556 if (!rdev->ops->color_change)
15557 return -EOPNOTSUPP;
15558
15559 if (!wiphy_ext_feature_isset(&rdev->wiphy,
15560 NL80211_EXT_FEATURE_BSS_COLOR))
15561 return -EOPNOTSUPP;
15562
15563 if (wdev->iftype != NL80211_IFTYPE_AP)
15564 return -EOPNOTSUPP;
15565
15566 if (!info->attrs[NL80211_ATTR_COLOR_CHANGE_COUNT] ||
15567 !info->attrs[NL80211_ATTR_COLOR_CHANGE_COLOR] ||
15568 !info->attrs[NL80211_ATTR_COLOR_CHANGE_ELEMS])
15569 return -EINVAL;
15570
15571 params.count = nla_get_u8(info->attrs[NL80211_ATTR_COLOR_CHANGE_COUNT]);
15572 params.color = nla_get_u8(info->attrs[NL80211_ATTR_COLOR_CHANGE_COLOR]);
15573
15574 err = nl80211_parse_beacon(rdev, info->attrs, &params.beacon_next);
15575 if (err)
15576 return err;
15577
15578 tb = kcalloc(NL80211_ATTR_MAX + 1, sizeof(*tb), GFP_KERNEL);
15579 if (!tb)
15580 return -ENOMEM;
15581
15582 err = nla_parse_nested(tb, NL80211_ATTR_MAX,
15583 info->attrs[NL80211_ATTR_COLOR_CHANGE_ELEMS],
15584 nl80211_policy, info->extack);
15585 if (err)
15586 goto out;
15587
15588 err = nl80211_parse_beacon(rdev, tb, &params.beacon_color_change);
15589 if (err)
15590 goto out;
15591
15592 if (!tb[NL80211_ATTR_CNTDWN_OFFS_BEACON]) {
15593 err = -EINVAL;
15594 goto out;
15595 }
15596
15597 if (nla_len(tb[NL80211_ATTR_CNTDWN_OFFS_BEACON]) != sizeof(u16)) {
15598 err = -EINVAL;
15599 goto out;
15600 }
15601
15602 offset = nla_get_u16(tb[NL80211_ATTR_CNTDWN_OFFS_BEACON]);
15603 if (offset >= params.beacon_color_change.tail_len) {
15604 err = -EINVAL;
15605 goto out;
15606 }
15607
15608 if (params.beacon_color_change.tail[offset] != params.count) {
15609 err = -EINVAL;
15610 goto out;
15611 }
15612
15613 params.counter_offset_beacon = offset;
15614
15615 if (tb[NL80211_ATTR_CNTDWN_OFFS_PRESP]) {
15616 if (nla_len(tb[NL80211_ATTR_CNTDWN_OFFS_PRESP]) !=
15617 sizeof(u16)) {
15618 err = -EINVAL;
15619 goto out;
15620 }
15621
15622 offset = nla_get_u16(tb[NL80211_ATTR_CNTDWN_OFFS_PRESP]);
15623 if (offset >= params.beacon_color_change.probe_resp_len) {
15624 err = -EINVAL;
15625 goto out;
15626 }
15627
15628 if (params.beacon_color_change.probe_resp[offset] !=
15629 params.count) {
15630 err = -EINVAL;
15631 goto out;
15632 }
15633
15634 params.counter_offset_presp = offset;
15635 }
15636
15637 wdev_lock(wdev);
15638 err = rdev_color_change(rdev, dev, &params);
15639 wdev_unlock(wdev);
15640
15641out:
dc1e3cb8
JC
15642 kfree(params.beacon_next.mbssid_ies);
15643 kfree(params.beacon_color_change.mbssid_ies);
0d2ab3ae
JC
15644 kfree(tb);
15645 return err;
15646}
15647
e306784a
SM
15648static int nl80211_set_fils_aad(struct sk_buff *skb,
15649 struct genl_info *info)
15650{
15651 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15652 struct net_device *dev = info->user_ptr[1];
15653 struct cfg80211_fils_aad fils_aad = {};
15654 u8 *nonces;
15655
15656 if (!info->attrs[NL80211_ATTR_MAC] ||
15657 !info->attrs[NL80211_ATTR_FILS_KEK] ||
15658 !info->attrs[NL80211_ATTR_FILS_NONCES])
15659 return -EINVAL;
15660
15661 fils_aad.macaddr = nla_data(info->attrs[NL80211_ATTR_MAC]);
15662 fils_aad.kek_len = nla_len(info->attrs[NL80211_ATTR_FILS_KEK]);
15663 fils_aad.kek = nla_data(info->attrs[NL80211_ATTR_FILS_KEK]);
15664 nonces = nla_data(info->attrs[NL80211_ATTR_FILS_NONCES]);
15665 fils_aad.snonce = nonces;
15666 fils_aad.anonce = nonces + FILS_NONCE_LEN;
15667
15668 return rdev_set_fils_aad(rdev, dev, &fils_aad);
15669}
15670
7b0a0e3c
JB
15671static int nl80211_add_link(struct sk_buff *skb, struct genl_info *info)
15672{
f2a0290b 15673 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7b0a0e3c
JB
15674 unsigned int link_id = nl80211_link_id(info->attrs);
15675 struct net_device *dev = info->user_ptr[1];
15676 struct wireless_dev *wdev = dev->ieee80211_ptr;
f2a0290b 15677 int ret;
7b0a0e3c
JB
15678
15679 if (!(wdev->wiphy->flags & WIPHY_FLAG_SUPPORTS_MLO))
15680 return -EINVAL;
15681
15682 switch (wdev->iftype) {
15683 case NL80211_IFTYPE_AP:
15684 break;
15685 default:
15686 return -EINVAL;
15687 }
15688
15689 if (!info->attrs[NL80211_ATTR_MAC] ||
15690 !is_valid_ether_addr(nla_data(info->attrs[NL80211_ATTR_MAC])))
15691 return -EINVAL;
15692
15693 wdev_lock(wdev);
15694 wdev->valid_links |= BIT(link_id);
15695 ether_addr_copy(wdev->links[link_id].addr,
15696 nla_data(info->attrs[NL80211_ATTR_MAC]));
f2a0290b
JB
15697
15698 ret = rdev_add_intf_link(rdev, wdev, link_id);
15699 if (ret) {
15700 wdev->valid_links &= ~BIT(link_id);
15701 eth_zero_addr(wdev->links[link_id].addr);
15702 }
7b0a0e3c
JB
15703 wdev_unlock(wdev);
15704
f2a0290b 15705 return ret;
7b0a0e3c
JB
15706}
15707
15708static int nl80211_remove_link(struct sk_buff *skb, struct genl_info *info)
15709{
15710 unsigned int link_id = nl80211_link_id(info->attrs);
15711 struct net_device *dev = info->user_ptr[1];
15712 struct wireless_dev *wdev = dev->ieee80211_ptr;
15713
15714 /* cannot remove if there's no link */
15715 if (!info->attrs[NL80211_ATTR_MLO_LINK_ID])
15716 return -EINVAL;
15717
15718 switch (wdev->iftype) {
15719 case NL80211_IFTYPE_AP:
15720 break;
15721 default:
15722 return -EINVAL;
15723 }
15724
7b0a0e3c 15725 wdev_lock(wdev);
cdf0a0a8 15726 cfg80211_remove_link(wdev, link_id);
7b0a0e3c
JB
15727 wdev_unlock(wdev);
15728
15729 return 0;
15730}
15731
577e5b8c
ST
15732static int
15733nl80211_add_mod_link_station(struct sk_buff *skb, struct genl_info *info,
15734 bool add)
15735{
15736 struct link_station_parameters params = {};
15737 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15738 struct net_device *dev = info->user_ptr[1];
15739 int err;
15740
15741 if ((add && !rdev->ops->add_link_station) ||
15742 (!add && !rdev->ops->mod_link_station))
15743 return -EOPNOTSUPP;
15744
15745 if (add && !info->attrs[NL80211_ATTR_MAC])
15746 return -EINVAL;
15747
15748 if (add && !info->attrs[NL80211_ATTR_MLD_ADDR])
15749 return -EINVAL;
15750
15751 if (add && !info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES])
15752 return -EINVAL;
15753
15754 if (info->attrs[NL80211_ATTR_MLD_ADDR])
15755 params.mld_mac = nla_data(info->attrs[NL80211_ATTR_MLD_ADDR]);
15756
15757 if (info->attrs[NL80211_ATTR_MAC]) {
15758 params.link_mac = nla_data(info->attrs[NL80211_ATTR_MAC]);
15759 if (!is_valid_ether_addr(params.link_mac))
15760 return -EINVAL;
15761 }
15762
15763 if (!info->attrs[NL80211_ATTR_MLO_LINK_ID])
15764 return -EINVAL;
15765
15766 params.link_id = nla_get_u8(info->attrs[NL80211_ATTR_MLO_LINK_ID]);
15767
15768 if (info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]) {
15769 params.supported_rates =
15770 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
15771 params.supported_rates_len =
15772 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
15773 }
15774
15775 if (info->attrs[NL80211_ATTR_HT_CAPABILITY])
15776 params.ht_capa =
15777 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
15778
15779 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY])
15780 params.vht_capa =
15781 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);
15782
15783 if (info->attrs[NL80211_ATTR_HE_CAPABILITY]) {
15784 params.he_capa =
15785 nla_data(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
15786 params.he_capa_len =
15787 nla_len(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
15788
15789 if (info->attrs[NL80211_ATTR_EHT_CAPABILITY]) {
15790 params.eht_capa =
15791 nla_data(info->attrs[NL80211_ATTR_EHT_CAPABILITY]);
15792 params.eht_capa_len =
15793 nla_len(info->attrs[NL80211_ATTR_EHT_CAPABILITY]);
15794
15795 if (!ieee80211_eht_capa_size_ok((const u8 *)params.he_capa,
15796 (const u8 *)params.eht_capa,
15797 params.eht_capa_len))
15798 return -EINVAL;
15799 }
15800 }
15801
15802 if (info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY])
15803 params.he_6ghz_capa =
15804 nla_data(info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY]);
15805
15806 if (info->attrs[NL80211_ATTR_OPMODE_NOTIF]) {
15807 params.opmode_notif_used = true;
15808 params.opmode_notif =
15809 nla_get_u8(info->attrs[NL80211_ATTR_OPMODE_NOTIF]);
15810 }
15811
15812 err = nl80211_parse_sta_txpower_setting(info, &params.txpwr,
15813 &params.txpwr_set);
15814 if (err)
15815 return err;
15816
858fd188 15817 wdev_lock(dev->ieee80211_ptr);
577e5b8c 15818 if (add)
858fd188
JB
15819 err = rdev_add_link_station(rdev, dev, &params);
15820 else
15821 err = rdev_mod_link_station(rdev, dev, &params);
15822 wdev_unlock(dev->ieee80211_ptr);
15823
15824 return err;
577e5b8c
ST
15825}
15826
15827static int
15828nl80211_add_link_station(struct sk_buff *skb, struct genl_info *info)
15829{
15830 return nl80211_add_mod_link_station(skb, info, true);
15831}
15832
15833static int
15834nl80211_modify_link_station(struct sk_buff *skb, struct genl_info *info)
15835{
15836 return nl80211_add_mod_link_station(skb, info, false);
15837}
15838
15839static int
15840nl80211_remove_link_station(struct sk_buff *skb, struct genl_info *info)
15841{
15842 struct link_station_del_parameters params = {};
15843 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15844 struct net_device *dev = info->user_ptr[1];
858fd188 15845 int ret;
577e5b8c
ST
15846
15847 if (!rdev->ops->del_link_station)
15848 return -EOPNOTSUPP;
15849
15850 if (!info->attrs[NL80211_ATTR_MLD_ADDR] ||
15851 !info->attrs[NL80211_ATTR_MLO_LINK_ID])
15852 return -EINVAL;
15853
15854 params.mld_mac = nla_data(info->attrs[NL80211_ATTR_MLD_ADDR]);
15855 params.link_id = nla_get_u8(info->attrs[NL80211_ATTR_MLO_LINK_ID]);
15856
858fd188
JB
15857 wdev_lock(dev->ieee80211_ptr);
15858 ret = rdev_del_link_station(rdev, dev, &params);
15859 wdev_unlock(dev->ieee80211_ptr);
15860
15861 return ret;
577e5b8c
ST
15862}
15863
4c476991
JB
15864#define NL80211_FLAG_NEED_WIPHY 0x01
15865#define NL80211_FLAG_NEED_NETDEV 0x02
15866#define NL80211_FLAG_NEED_RTNL 0x04
41265714
JB
15867#define NL80211_FLAG_CHECK_NETDEV_UP 0x08
15868#define NL80211_FLAG_NEED_NETDEV_UP (NL80211_FLAG_NEED_NETDEV |\
15869 NL80211_FLAG_CHECK_NETDEV_UP)
1bf614ef 15870#define NL80211_FLAG_NEED_WDEV 0x10
98104fde 15871/* If a netdev is associated, it must be UP, P2P must be started */
1bf614ef
JB
15872#define NL80211_FLAG_NEED_WDEV_UP (NL80211_FLAG_NEED_WDEV |\
15873 NL80211_FLAG_CHECK_NETDEV_UP)
5393b917 15874#define NL80211_FLAG_CLEAR_SKB 0x20
77cbf790 15875#define NL80211_FLAG_NO_WIPHY_MTX 0x40
7b0a0e3c
JB
15876#define NL80211_FLAG_MLO_VALID_LINK_ID 0x80
15877#define NL80211_FLAG_MLO_UNSUPPORTED 0x100
4c476991 15878
2182db91
JB
15879#define INTERNAL_FLAG_SELECTORS(__sel) \
15880 SELECTOR(__sel, NONE, 0) /* must be first */ \
15881 SELECTOR(__sel, WIPHY, \
15882 NL80211_FLAG_NEED_WIPHY) \
15883 SELECTOR(__sel, WDEV, \
15884 NL80211_FLAG_NEED_WDEV) \
15885 SELECTOR(__sel, NETDEV, \
15886 NL80211_FLAG_NEED_NETDEV) \
7b0a0e3c
JB
15887 SELECTOR(__sel, NETDEV_LINK, \
15888 NL80211_FLAG_NEED_NETDEV | \
15889 NL80211_FLAG_MLO_VALID_LINK_ID) \
15890 SELECTOR(__sel, NETDEV_NO_MLO, \
15891 NL80211_FLAG_NEED_NETDEV | \
15892 NL80211_FLAG_MLO_UNSUPPORTED) \
2182db91
JB
15893 SELECTOR(__sel, WIPHY_RTNL, \
15894 NL80211_FLAG_NEED_WIPHY | \
15895 NL80211_FLAG_NEED_RTNL) \
15896 SELECTOR(__sel, WIPHY_RTNL_NOMTX, \
15897 NL80211_FLAG_NEED_WIPHY | \
15898 NL80211_FLAG_NEED_RTNL | \
15899 NL80211_FLAG_NO_WIPHY_MTX) \
15900 SELECTOR(__sel, WDEV_RTNL, \
15901 NL80211_FLAG_NEED_WDEV | \
15902 NL80211_FLAG_NEED_RTNL) \
15903 SELECTOR(__sel, NETDEV_RTNL, \
15904 NL80211_FLAG_NEED_NETDEV | \
15905 NL80211_FLAG_NEED_RTNL) \
15906 SELECTOR(__sel, NETDEV_UP, \
15907 NL80211_FLAG_NEED_NETDEV_UP) \
7b0a0e3c
JB
15908 SELECTOR(__sel, NETDEV_UP_LINK, \
15909 NL80211_FLAG_NEED_NETDEV_UP | \
15910 NL80211_FLAG_MLO_VALID_LINK_ID) \
15911 SELECTOR(__sel, NETDEV_UP_NO_MLO, \
15912 NL80211_FLAG_NEED_NETDEV_UP | \
15913 NL80211_FLAG_MLO_UNSUPPORTED) \
15914 SELECTOR(__sel, NETDEV_UP_NO_MLO_CLEAR, \
15915 NL80211_FLAG_NEED_NETDEV_UP | \
15916 NL80211_FLAG_CLEAR_SKB | \
15917 NL80211_FLAG_MLO_UNSUPPORTED) \
2182db91
JB
15918 SELECTOR(__sel, NETDEV_UP_NOTMX, \
15919 NL80211_FLAG_NEED_NETDEV_UP | \
15920 NL80211_FLAG_NO_WIPHY_MTX) \
7b0a0e3c
JB
15921 SELECTOR(__sel, NETDEV_UP_NOTMX_NOMLO, \
15922 NL80211_FLAG_NEED_NETDEV_UP | \
15923 NL80211_FLAG_NO_WIPHY_MTX | \
15924 NL80211_FLAG_MLO_UNSUPPORTED) \
2182db91
JB
15925 SELECTOR(__sel, NETDEV_UP_CLEAR, \
15926 NL80211_FLAG_NEED_NETDEV_UP | \
15927 NL80211_FLAG_CLEAR_SKB) \
15928 SELECTOR(__sel, WDEV_UP, \
15929 NL80211_FLAG_NEED_WDEV_UP) \
7b0a0e3c
JB
15930 SELECTOR(__sel, WDEV_UP_LINK, \
15931 NL80211_FLAG_NEED_WDEV_UP | \
15932 NL80211_FLAG_MLO_VALID_LINK_ID) \
2182db91
JB
15933 SELECTOR(__sel, WDEV_UP_RTNL, \
15934 NL80211_FLAG_NEED_WDEV_UP | \
15935 NL80211_FLAG_NEED_RTNL) \
15936 SELECTOR(__sel, WIPHY_CLEAR, \
15937 NL80211_FLAG_NEED_WIPHY | \
15938 NL80211_FLAG_CLEAR_SKB)
15939
15940enum nl80211_internal_flags_selector {
15941#define SELECTOR(_, name, value) NL80211_IFL_SEL_##name,
15942 INTERNAL_FLAG_SELECTORS(_)
15943#undef SELECTOR
15944};
15945
15946static u32 nl80211_internal_flags[] = {
15947#define SELECTOR(_, name, value) [NL80211_IFL_SEL_##name] = value,
15948 INTERNAL_FLAG_SELECTORS(_)
15949#undef SELECTOR
15950};
15951
f84f771d 15952static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
4c476991
JB
15953 struct genl_info *info)
15954{
a05829a7 15955 struct cfg80211_registered_device *rdev = NULL;
7b0a0e3c
JB
15956 struct wireless_dev *wdev = NULL;
15957 struct net_device *dev = NULL;
2182db91 15958 u32 internal_flags;
7b0a0e3c 15959 int err;
2182db91
JB
15960
15961 if (WARN_ON(ops->internal_flags >= ARRAY_SIZE(nl80211_internal_flags)))
15962 return -EINVAL;
15963
15964 internal_flags = nl80211_internal_flags[ops->internal_flags];
4c476991 15965
a05829a7 15966 rtnl_lock();
2182db91 15967 if (internal_flags & NL80211_FLAG_NEED_WIPHY) {
4f7eff10 15968 rdev = cfg80211_get_dev_from_info(genl_info_net(info), info);
4c476991 15969 if (IS_ERR(rdev)) {
7b0a0e3c
JB
15970 err = PTR_ERR(rdev);
15971 goto out_unlock;
4c476991
JB
15972 }
15973 info->user_ptr[0] = rdev;
2182db91
JB
15974 } else if (internal_flags & NL80211_FLAG_NEED_NETDEV ||
15975 internal_flags & NL80211_FLAG_NEED_WDEV) {
a05829a7 15976 wdev = __cfg80211_wdev_from_attrs(NULL, genl_info_net(info),
89a54e48
JB
15977 info->attrs);
15978 if (IS_ERR(wdev)) {
7b0a0e3c
JB
15979 err = PTR_ERR(wdev);
15980 goto out_unlock;
4c476991 15981 }
89a54e48 15982
89a54e48 15983 dev = wdev->netdev;
7b0a0e3c 15984 dev_hold(dev);
f26cbf40 15985 rdev = wiphy_to_rdev(wdev->wiphy);
89a54e48 15986
2182db91 15987 if (internal_flags & NL80211_FLAG_NEED_NETDEV) {
1bf614ef 15988 if (!dev) {
7b0a0e3c
JB
15989 err = -EINVAL;
15990 goto out_unlock;
1bf614ef
JB
15991 }
15992
15993 info->user_ptr[1] = dev;
15994 } else {
15995 info->user_ptr[1] = wdev;
41265714 15996 }
1bf614ef 15997
2182db91 15998 if (internal_flags & NL80211_FLAG_CHECK_NETDEV_UP &&
73c7da3d 15999 !wdev_running(wdev)) {
7b0a0e3c
JB
16000 err = -ENETDOWN;
16001 goto out_unlock;
73c7da3d 16002 }
1bf614ef 16003
4c476991 16004 info->user_ptr[0] = rdev;
4c476991
JB
16005 }
16006
7b0a0e3c
JB
16007 if (internal_flags & NL80211_FLAG_MLO_VALID_LINK_ID) {
16008 struct nlattr *link_id = info->attrs[NL80211_ATTR_MLO_LINK_ID];
16009
16010 if (!wdev) {
16011 err = -EINVAL;
16012 goto out_unlock;
16013 }
16014
16015 /* MLO -> require valid link ID */
16016 if (wdev->valid_links &&
16017 (!link_id ||
ff3821bc 16018 !(wdev->valid_links & BIT(nla_get_u8(link_id))))) {
7b0a0e3c
JB
16019 err = -EINVAL;
16020 goto out_unlock;
16021 }
16022
16023 /* non-MLO -> no link ID attribute accepted */
16024 if (!wdev->valid_links && link_id) {
16025 err = -EINVAL;
16026 goto out_unlock;
16027 }
16028 }
16029
16030 if (internal_flags & NL80211_FLAG_MLO_UNSUPPORTED) {
16031 if (info->attrs[NL80211_ATTR_MLO_LINK_ID] ||
16032 (wdev && wdev->valid_links)) {
16033 err = -EINVAL;
16034 goto out_unlock;
16035 }
16036 }
16037
2182db91 16038 if (rdev && !(internal_flags & NL80211_FLAG_NO_WIPHY_MTX)) {
a05829a7
JB
16039 wiphy_lock(&rdev->wiphy);
16040 /* we keep the mutex locked until post_doit */
16041 __release(&rdev->wiphy.mtx);
16042 }
2182db91 16043 if (!(internal_flags & NL80211_FLAG_NEED_RTNL))
a05829a7
JB
16044 rtnl_unlock();
16045
4c476991 16046 return 0;
7b0a0e3c
JB
16047out_unlock:
16048 rtnl_unlock();
16049 dev_put(dev);
16050 return err;
4c476991
JB
16051}
16052
f84f771d 16053static void nl80211_post_doit(const struct genl_ops *ops, struct sk_buff *skb,
4c476991
JB
16054 struct genl_info *info)
16055{
2182db91
JB
16056 u32 internal_flags = nl80211_internal_flags[ops->internal_flags];
16057
1bf614ef 16058 if (info->user_ptr[1]) {
2182db91 16059 if (internal_flags & NL80211_FLAG_NEED_WDEV) {
1bf614ef
JB
16060 struct wireless_dev *wdev = info->user_ptr[1];
16061
1160dfa1 16062 dev_put(wdev->netdev);
1bf614ef
JB
16063 } else {
16064 dev_put(info->user_ptr[1]);
16065 }
16066 }
5393b917 16067
77cbf790 16068 if (info->user_ptr[0] &&
2182db91 16069 !(internal_flags & NL80211_FLAG_NO_WIPHY_MTX)) {
a05829a7
JB
16070 struct cfg80211_registered_device *rdev = info->user_ptr[0];
16071
16072 /* we kept the mutex locked since pre_doit */
16073 __acquire(&rdev->wiphy.mtx);
16074 wiphy_unlock(&rdev->wiphy);
16075 }
16076
2182db91 16077 if (internal_flags & NL80211_FLAG_NEED_RTNL)
4c476991 16078 rtnl_unlock();
5393b917
JB
16079
16080 /* If needed, clear the netlink message payload from the SKB
16081 * as it might contain key data that shouldn't stick around on
16082 * the heap after the SKB is freed. The netlink message header
16083 * is still needed for further processing, so leave it intact.
16084 */
2182db91 16085 if (internal_flags & NL80211_FLAG_CLEAR_SKB) {
5393b917
JB
16086 struct nlmsghdr *nlh = nlmsg_hdr(skb);
16087
16088 memset(nlmsg_data(nlh), 0, nlmsg_len(nlh));
16089 }
4c476991
JB
16090}
16091
6bdb68ce
CH
16092static int nl80211_set_sar_sub_specs(struct cfg80211_registered_device *rdev,
16093 struct cfg80211_sar_specs *sar_specs,
16094 struct nlattr *spec[], int index)
16095{
16096 u32 range_index, i;
16097
16098 if (!sar_specs || !spec)
16099 return -EINVAL;
16100
16101 if (!spec[NL80211_SAR_ATTR_SPECS_POWER] ||
16102 !spec[NL80211_SAR_ATTR_SPECS_RANGE_INDEX])
16103 return -EINVAL;
16104
16105 range_index = nla_get_u32(spec[NL80211_SAR_ATTR_SPECS_RANGE_INDEX]);
16106
16107 /* check if range_index exceeds num_freq_ranges */
16108 if (range_index >= rdev->wiphy.sar_capa->num_freq_ranges)
16109 return -EINVAL;
16110
16111 /* check if range_index duplicates */
16112 for (i = 0; i < index; i++) {
16113 if (sar_specs->sub_specs[i].freq_range_index == range_index)
16114 return -EINVAL;
16115 }
16116
16117 sar_specs->sub_specs[index].power =
16118 nla_get_s32(spec[NL80211_SAR_ATTR_SPECS_POWER]);
16119
16120 sar_specs->sub_specs[index].freq_range_index = range_index;
16121
16122 return 0;
16123}
16124
16125static int nl80211_set_sar_specs(struct sk_buff *skb, struct genl_info *info)
16126{
16127 struct cfg80211_registered_device *rdev = info->user_ptr[0];
16128 struct nlattr *spec[NL80211_SAR_ATTR_SPECS_MAX + 1];
16129 struct nlattr *tb[NL80211_SAR_ATTR_MAX + 1];
16130 struct cfg80211_sar_specs *sar_spec;
16131 enum nl80211_sar_type type;
16132 struct nlattr *spec_list;
16133 u32 specs;
16134 int rem, err;
16135
16136 if (!rdev->wiphy.sar_capa || !rdev->ops->set_sar_specs)
16137 return -EOPNOTSUPP;
16138
16139 if (!info->attrs[NL80211_ATTR_SAR_SPEC])
16140 return -EINVAL;
16141
16142 nla_parse_nested(tb, NL80211_SAR_ATTR_MAX,
16143 info->attrs[NL80211_ATTR_SAR_SPEC],
16144 NULL, NULL);
16145
16146 if (!tb[NL80211_SAR_ATTR_TYPE] || !tb[NL80211_SAR_ATTR_SPECS])
16147 return -EINVAL;
16148
16149 type = nla_get_u32(tb[NL80211_SAR_ATTR_TYPE]);
16150 if (type != rdev->wiphy.sar_capa->type)
16151 return -EINVAL;
16152
16153 specs = 0;
16154 nla_for_each_nested(spec_list, tb[NL80211_SAR_ATTR_SPECS], rem)
16155 specs++;
16156
16157 if (specs > rdev->wiphy.sar_capa->num_freq_ranges)
16158 return -EINVAL;
16159
40f231e7 16160 sar_spec = kzalloc(struct_size(sar_spec, sub_specs, specs), GFP_KERNEL);
6bdb68ce
CH
16161 if (!sar_spec)
16162 return -ENOMEM;
16163
16164 sar_spec->type = type;
16165 specs = 0;
16166 nla_for_each_nested(spec_list, tb[NL80211_SAR_ATTR_SPECS], rem) {
16167 nla_parse_nested(spec, NL80211_SAR_ATTR_SPECS_MAX,
16168 spec_list, NULL, NULL);
16169
16170 switch (type) {
16171 case NL80211_SAR_TYPE_POWER:
16172 if (nl80211_set_sar_sub_specs(rdev, sar_spec,
16173 spec, specs)) {
16174 err = -EINVAL;
16175 goto error;
16176 }
16177 break;
16178 default:
16179 err = -EINVAL;
16180 goto error;
16181 }
16182 specs++;
16183 }
16184
16185 sar_spec->num_sub_specs = specs;
16186
16187 rdev->cur_cmd_info = info;
16188 err = rdev_set_sar_specs(rdev, sar_spec);
16189 rdev->cur_cmd_info = NULL;
16190error:
16191 kfree(sar_spec);
16192 return err;
16193}
16194
2182db91
JB
16195#define SELECTOR(__sel, name, value) \
16196 ((__sel) == (value)) ? NL80211_IFL_SEL_##name :
16197int __missing_selector(void);
16198#define IFLAGS(__val) INTERNAL_FLAG_SELECTORS(__val) __missing_selector()
16199
4534de83 16200static const struct genl_ops nl80211_ops[] = {
55682965
JB
16201 {
16202 .cmd = NL80211_CMD_GET_WIPHY,
ef6243ac 16203 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
55682965
JB
16204 .doit = nl80211_get_wiphy,
16205 .dumpit = nl80211_dump_wiphy,
86e8cf98 16206 .done = nl80211_dump_wiphy_done,
55682965 16207 /* can be retrieved by unprivileged users */
2182db91 16208 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY),
55682965 16209 },
66a9b928
JK
16210};
16211
16212static const struct genl_small_ops nl80211_small_ops[] = {
55682965
JB
16213 {
16214 .cmd = NL80211_CMD_SET_WIPHY,
ef6243ac 16215 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
55682965 16216 .doit = nl80211_set_wiphy,
5617c6cd 16217 .flags = GENL_UNS_ADMIN_PERM,
55682965
JB
16218 },
16219 {
16220 .cmd = NL80211_CMD_GET_INTERFACE,
ef6243ac 16221 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
55682965
JB
16222 .doit = nl80211_get_interface,
16223 .dumpit = nl80211_dump_interface,
55682965 16224 /* can be retrieved by unprivileged users */
2182db91 16225 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV),
55682965
JB
16226 },
16227 {
16228 .cmd = NL80211_CMD_SET_INTERFACE,
ef6243ac 16229 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
55682965 16230 .doit = nl80211_set_interface,
5617c6cd 16231 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
16232 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV |
16233 NL80211_FLAG_NEED_RTNL),
55682965
JB
16234 },
16235 {
16236 .cmd = NL80211_CMD_NEW_INTERFACE,
ef6243ac 16237 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
55682965 16238 .doit = nl80211_new_interface,
5617c6cd 16239 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
16240 .internal_flags =
16241 IFLAGS(NL80211_FLAG_NEED_WIPHY |
16242 NL80211_FLAG_NEED_RTNL |
16243 /* we take the wiphy mutex later ourselves */
16244 NL80211_FLAG_NO_WIPHY_MTX),
55682965
JB
16245 },
16246 {
16247 .cmd = NL80211_CMD_DEL_INTERFACE,
ef6243ac 16248 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
55682965 16249 .doit = nl80211_del_interface,
5617c6cd 16250 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
16251 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV |
16252 NL80211_FLAG_NEED_RTNL),
41ade00f
JB
16253 },
16254 {
16255 .cmd = NL80211_CMD_GET_KEY,
ef6243ac 16256 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
41ade00f 16257 .doit = nl80211_get_key,
5617c6cd 16258 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16259 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
41ade00f
JB
16260 },
16261 {
16262 .cmd = NL80211_CMD_SET_KEY,
ef6243ac 16263 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
41ade00f 16264 .doit = nl80211_set_key,
5617c6cd 16265 .flags = GENL_UNS_ADMIN_PERM,
7b0a0e3c 16266 /* cannot use NL80211_FLAG_MLO_VALID_LINK_ID, depends on key */
2182db91
JB
16267 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
16268 NL80211_FLAG_CLEAR_SKB),
41ade00f
JB
16269 },
16270 {
16271 .cmd = NL80211_CMD_NEW_KEY,
ef6243ac 16272 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
41ade00f 16273 .doit = nl80211_new_key,
5617c6cd 16274 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
16275 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
16276 NL80211_FLAG_CLEAR_SKB),
41ade00f
JB
16277 },
16278 {
16279 .cmd = NL80211_CMD_DEL_KEY,
ef6243ac 16280 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
41ade00f 16281 .doit = nl80211_del_key,
5617c6cd 16282 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16283 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
55682965 16284 },
ed1b6cc7
JB
16285 {
16286 .cmd = NL80211_CMD_SET_BEACON,
ef6243ac 16287 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5617c6cd 16288 .flags = GENL_UNS_ADMIN_PERM,
8860020e 16289 .doit = nl80211_set_beacon,
7b0a0e3c
JB
16290 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
16291 NL80211_FLAG_MLO_VALID_LINK_ID),
ed1b6cc7
JB
16292 },
16293 {
8860020e 16294 .cmd = NL80211_CMD_START_AP,
ef6243ac 16295 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5617c6cd 16296 .flags = GENL_UNS_ADMIN_PERM,
8860020e 16297 .doit = nl80211_start_ap,
7b0a0e3c
JB
16298 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
16299 NL80211_FLAG_MLO_VALID_LINK_ID),
ed1b6cc7
JB
16300 },
16301 {
8860020e 16302 .cmd = NL80211_CMD_STOP_AP,
ef6243ac 16303 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5617c6cd 16304 .flags = GENL_UNS_ADMIN_PERM,
8860020e 16305 .doit = nl80211_stop_ap,
7b0a0e3c
JB
16306 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
16307 NL80211_FLAG_MLO_VALID_LINK_ID),
ed1b6cc7 16308 },
5727ef1b
JB
16309 {
16310 .cmd = NL80211_CMD_GET_STATION,
ef6243ac 16311 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5727ef1b 16312 .doit = nl80211_get_station,
2ec600d6 16313 .dumpit = nl80211_dump_station,
2182db91 16314 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
5727ef1b
JB
16315 },
16316 {
16317 .cmd = NL80211_CMD_SET_STATION,
ef6243ac 16318 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5727ef1b 16319 .doit = nl80211_set_station,
5617c6cd 16320 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16321 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
5727ef1b
JB
16322 },
16323 {
16324 .cmd = NL80211_CMD_NEW_STATION,
ef6243ac 16325 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5727ef1b 16326 .doit = nl80211_new_station,
5617c6cd 16327 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16328 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
5727ef1b
JB
16329 },
16330 {
16331 .cmd = NL80211_CMD_DEL_STATION,
ef6243ac 16332 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5727ef1b 16333 .doit = nl80211_del_station,
5617c6cd 16334 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16335 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
2ec600d6
LCC
16336 },
16337 {
16338 .cmd = NL80211_CMD_GET_MPATH,
ef6243ac 16339 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2ec600d6
LCC
16340 .doit = nl80211_get_mpath,
16341 .dumpit = nl80211_dump_mpath,
5617c6cd 16342 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16343 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
2ec600d6 16344 },
66be7d2b
HR
16345 {
16346 .cmd = NL80211_CMD_GET_MPP,
ef6243ac 16347 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
66be7d2b
HR
16348 .doit = nl80211_get_mpp,
16349 .dumpit = nl80211_dump_mpp,
5617c6cd 16350 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16351 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
66be7d2b 16352 },
2ec600d6
LCC
16353 {
16354 .cmd = NL80211_CMD_SET_MPATH,
ef6243ac 16355 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2ec600d6 16356 .doit = nl80211_set_mpath,
5617c6cd 16357 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16358 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
2ec600d6
LCC
16359 },
16360 {
16361 .cmd = NL80211_CMD_NEW_MPATH,
ef6243ac 16362 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2ec600d6 16363 .doit = nl80211_new_mpath,
5617c6cd 16364 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16365 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
2ec600d6
LCC
16366 },
16367 {
16368 .cmd = NL80211_CMD_DEL_MPATH,
ef6243ac 16369 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2ec600d6 16370 .doit = nl80211_del_mpath,
5617c6cd 16371 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16372 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
9f1ba906
JM
16373 },
16374 {
16375 .cmd = NL80211_CMD_SET_BSS,
ef6243ac 16376 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9f1ba906 16377 .doit = nl80211_set_bss,
5617c6cd 16378 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16379 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
b2e1b302 16380 },
f130347c
LR
16381 {
16382 .cmd = NL80211_CMD_GET_REG,
ef6243ac 16383 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ad30ca2c
AN
16384 .doit = nl80211_get_reg_do,
16385 .dumpit = nl80211_get_reg_dump,
f130347c
LR
16386 /* can be retrieved by unprivileged users */
16387 },
b6863036 16388#ifdef CONFIG_CFG80211_CRDA_SUPPORT
b2e1b302
LR
16389 {
16390 .cmd = NL80211_CMD_SET_REG,
ef6243ac 16391 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
b2e1b302 16392 .doit = nl80211_set_reg,
b2e1b302
LR
16393 .flags = GENL_ADMIN_PERM,
16394 },
b6863036 16395#endif
b2e1b302
LR
16396 {
16397 .cmd = NL80211_CMD_REQ_SET_REG,
ef6243ac 16398 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
b2e1b302 16399 .doit = nl80211_req_set_reg,
93da9cc1 16400 .flags = GENL_ADMIN_PERM,
16401 },
1ea4ff3e
JB
16402 {
16403 .cmd = NL80211_CMD_RELOAD_REGDB,
ef6243ac 16404 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1ea4ff3e 16405 .doit = nl80211_reload_regdb,
1ea4ff3e
JB
16406 .flags = GENL_ADMIN_PERM,
16407 },
93da9cc1 16408 {
24bdd9f4 16409 .cmd = NL80211_CMD_GET_MESH_CONFIG,
ef6243ac 16410 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
24bdd9f4 16411 .doit = nl80211_get_mesh_config,
93da9cc1 16412 /* can be retrieved by unprivileged users */
2182db91 16413 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
93da9cc1 16414 },
16415 {
24bdd9f4 16416 .cmd = NL80211_CMD_SET_MESH_CONFIG,
ef6243ac 16417 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
24bdd9f4 16418 .doit = nl80211_update_mesh_config,
5617c6cd 16419 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16420 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
9aed3cc1 16421 },
2a519311
JB
16422 {
16423 .cmd = NL80211_CMD_TRIGGER_SCAN,
ef6243ac 16424 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2a519311 16425 .doit = nl80211_trigger_scan,
5617c6cd 16426 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16427 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
2a519311 16428 },
91d3ab46
VK
16429 {
16430 .cmd = NL80211_CMD_ABORT_SCAN,
ef6243ac 16431 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
91d3ab46 16432 .doit = nl80211_abort_scan,
5617c6cd 16433 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16434 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
91d3ab46 16435 },
2a519311
JB
16436 {
16437 .cmd = NL80211_CMD_GET_SCAN,
ef6243ac 16438 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2a519311
JB
16439 .dumpit = nl80211_dump_scan,
16440 },
807f8a8c
LC
16441 {
16442 .cmd = NL80211_CMD_START_SCHED_SCAN,
ef6243ac 16443 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
807f8a8c 16444 .doit = nl80211_start_sched_scan,
5617c6cd 16445 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16446 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
807f8a8c
LC
16447 },
16448 {
16449 .cmd = NL80211_CMD_STOP_SCHED_SCAN,
ef6243ac 16450 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
807f8a8c 16451 .doit = nl80211_stop_sched_scan,
5617c6cd 16452 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16453 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
807f8a8c 16454 },
636a5d36
JM
16455 {
16456 .cmd = NL80211_CMD_AUTHENTICATE,
ef6243ac 16457 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
636a5d36 16458 .doit = nl80211_authenticate,
5617c6cd 16459 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
16460 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
16461 NL80211_FLAG_CLEAR_SKB),
636a5d36
JM
16462 },
16463 {
16464 .cmd = NL80211_CMD_ASSOCIATE,
ef6243ac 16465 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
636a5d36 16466 .doit = nl80211_associate,
5617c6cd 16467 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
16468 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
16469 NL80211_FLAG_CLEAR_SKB),
636a5d36
JM
16470 },
16471 {
16472 .cmd = NL80211_CMD_DEAUTHENTICATE,
ef6243ac 16473 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
636a5d36 16474 .doit = nl80211_deauthenticate,
5617c6cd 16475 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16476 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
636a5d36
JM
16477 },
16478 {
16479 .cmd = NL80211_CMD_DISASSOCIATE,
ef6243ac 16480 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
636a5d36 16481 .doit = nl80211_disassociate,
5617c6cd 16482 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16483 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
636a5d36 16484 },
04a773ad
JB
16485 {
16486 .cmd = NL80211_CMD_JOIN_IBSS,
ef6243ac 16487 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
04a773ad 16488 .doit = nl80211_join_ibss,
5617c6cd 16489 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16490 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
04a773ad
JB
16491 },
16492 {
16493 .cmd = NL80211_CMD_LEAVE_IBSS,
ef6243ac 16494 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
04a773ad 16495 .doit = nl80211_leave_ibss,
5617c6cd 16496 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16497 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
04a773ad 16498 },
aff89a9b
JB
16499#ifdef CONFIG_NL80211_TESTMODE
16500 {
16501 .cmd = NL80211_CMD_TESTMODE,
ef6243ac 16502 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
aff89a9b 16503 .doit = nl80211_testmode_do,
71063f0e 16504 .dumpit = nl80211_testmode_dump,
5617c6cd 16505 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16506 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY),
aff89a9b
JB
16507 },
16508#endif
b23aa676
SO
16509 {
16510 .cmd = NL80211_CMD_CONNECT,
ef6243ac 16511 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
b23aa676 16512 .doit = nl80211_connect,
5617c6cd 16513 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
16514 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
16515 NL80211_FLAG_CLEAR_SKB),
b23aa676 16516 },
088e8df8 16517 {
16518 .cmd = NL80211_CMD_UPDATE_CONNECT_PARAMS,
ef6243ac 16519 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
088e8df8 16520 .doit = nl80211_update_connect_params,
088e8df8 16521 .flags = GENL_ADMIN_PERM,
2182db91
JB
16522 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
16523 NL80211_FLAG_CLEAR_SKB),
088e8df8 16524 },
b23aa676
SO
16525 {
16526 .cmd = NL80211_CMD_DISCONNECT,
ef6243ac 16527 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
b23aa676 16528 .doit = nl80211_disconnect,
5617c6cd 16529 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16530 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
b23aa676 16531 },
463d0183
JB
16532 {
16533 .cmd = NL80211_CMD_SET_WIPHY_NETNS,
ef6243ac 16534 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
463d0183 16535 .doit = nl80211_wiphy_netns,
5617c6cd 16536 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
16537 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY |
16538 NL80211_FLAG_NEED_RTNL |
16539 NL80211_FLAG_NO_WIPHY_MTX),
463d0183 16540 },
61fa713c
HS
16541 {
16542 .cmd = NL80211_CMD_GET_SURVEY,
ef6243ac 16543 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
61fa713c
HS
16544 .dumpit = nl80211_dump_survey,
16545 },
67fbb16b
SO
16546 {
16547 .cmd = NL80211_CMD_SET_PMKSA,
ef6243ac 16548 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
67fbb16b 16549 .doit = nl80211_setdel_pmksa,
5617c6cd 16550 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
16551 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
16552 NL80211_FLAG_CLEAR_SKB),
67fbb16b
SO
16553 },
16554 {
16555 .cmd = NL80211_CMD_DEL_PMKSA,
ef6243ac 16556 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
67fbb16b 16557 .doit = nl80211_setdel_pmksa,
5617c6cd 16558 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16559 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
67fbb16b
SO
16560 },
16561 {
16562 .cmd = NL80211_CMD_FLUSH_PMKSA,
ef6243ac 16563 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
67fbb16b 16564 .doit = nl80211_flush_pmksa,
5617c6cd 16565 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16566 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
67fbb16b 16567 },
9588bbd5
JM
16568 {
16569 .cmd = NL80211_CMD_REMAIN_ON_CHANNEL,
ef6243ac 16570 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9588bbd5 16571 .doit = nl80211_remain_on_channel,
5617c6cd 16572 .flags = GENL_UNS_ADMIN_PERM,
7b0a0e3c
JB
16573 /* FIXME: requiring a link ID here is probably not good */
16574 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP |
16575 NL80211_FLAG_MLO_VALID_LINK_ID),
9588bbd5
JM
16576 },
16577 {
16578 .cmd = NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL,
ef6243ac 16579 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9588bbd5 16580 .doit = nl80211_cancel_remain_on_channel,
5617c6cd 16581 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16582 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
9588bbd5 16583 },
13ae75b1
JM
16584 {
16585 .cmd = NL80211_CMD_SET_TX_BITRATE_MASK,
ef6243ac 16586 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
13ae75b1 16587 .doit = nl80211_set_tx_bitrate_mask,
5617c6cd 16588 .flags = GENL_UNS_ADMIN_PERM,
7b0a0e3c
JB
16589 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV |
16590 NL80211_FLAG_MLO_VALID_LINK_ID),
13ae75b1 16591 },
026331c4 16592 {
2e161f78 16593 .cmd = NL80211_CMD_REGISTER_FRAME,
ef6243ac 16594 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2e161f78 16595 .doit = nl80211_register_mgmt,
5617c6cd 16596 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16597 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV),
026331c4
JM
16598 },
16599 {
2e161f78 16600 .cmd = NL80211_CMD_FRAME,
ef6243ac 16601 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2e161f78 16602 .doit = nl80211_tx_mgmt,
5617c6cd 16603 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16604 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
f7ca38df
JB
16605 },
16606 {
16607 .cmd = NL80211_CMD_FRAME_WAIT_CANCEL,
ef6243ac 16608 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
f7ca38df 16609 .doit = nl80211_tx_mgmt_cancel_wait,
5617c6cd 16610 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16611 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
026331c4 16612 },
ffb9eb3d
KV
16613 {
16614 .cmd = NL80211_CMD_SET_POWER_SAVE,
ef6243ac 16615 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ffb9eb3d 16616 .doit = nl80211_set_power_save,
5617c6cd 16617 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16618 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
ffb9eb3d
KV
16619 },
16620 {
16621 .cmd = NL80211_CMD_GET_POWER_SAVE,
ef6243ac 16622 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ffb9eb3d 16623 .doit = nl80211_get_power_save,
ffb9eb3d 16624 /* can be retrieved by unprivileged users */
2182db91 16625 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
ffb9eb3d 16626 },
d6dc1a38
JO
16627 {
16628 .cmd = NL80211_CMD_SET_CQM,
ef6243ac 16629 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
d6dc1a38 16630 .doit = nl80211_set_cqm,
5617c6cd 16631 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16632 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
d6dc1a38 16633 },
f444de05
JB
16634 {
16635 .cmd = NL80211_CMD_SET_CHANNEL,
ef6243ac 16636 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
f444de05 16637 .doit = nl80211_set_channel,
5617c6cd 16638 .flags = GENL_UNS_ADMIN_PERM,
7b0a0e3c
JB
16639 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV |
16640 NL80211_FLAG_MLO_VALID_LINK_ID),
f444de05 16641 },
29cbe68c
JB
16642 {
16643 .cmd = NL80211_CMD_JOIN_MESH,
ef6243ac 16644 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
29cbe68c 16645 .doit = nl80211_join_mesh,
5617c6cd 16646 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16647 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
29cbe68c
JB
16648 },
16649 {
16650 .cmd = NL80211_CMD_LEAVE_MESH,
ef6243ac 16651 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
29cbe68c 16652 .doit = nl80211_leave_mesh,
5617c6cd 16653 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16654 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
29cbe68c 16655 },
6e0bd6c3
RL
16656 {
16657 .cmd = NL80211_CMD_JOIN_OCB,
ef6243ac 16658 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6e0bd6c3 16659 .doit = nl80211_join_ocb,
5617c6cd 16660 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16661 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
6e0bd6c3
RL
16662 },
16663 {
16664 .cmd = NL80211_CMD_LEAVE_OCB,
ef6243ac 16665 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6e0bd6c3 16666 .doit = nl80211_leave_ocb,
5617c6cd 16667 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16668 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
6e0bd6c3 16669 },
dfb89c56 16670#ifdef CONFIG_PM
ff1b6e69
JB
16671 {
16672 .cmd = NL80211_CMD_GET_WOWLAN,
ef6243ac 16673 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ff1b6e69 16674 .doit = nl80211_get_wowlan,
ff1b6e69 16675 /* can be retrieved by unprivileged users */
2182db91 16676 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY),
ff1b6e69
JB
16677 },
16678 {
16679 .cmd = NL80211_CMD_SET_WOWLAN,
ef6243ac 16680 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ff1b6e69 16681 .doit = nl80211_set_wowlan,
5617c6cd 16682 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16683 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY),
ff1b6e69 16684 },
dfb89c56 16685#endif
e5497d76
JB
16686 {
16687 .cmd = NL80211_CMD_SET_REKEY_OFFLOAD,
ef6243ac 16688 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
e5497d76 16689 .doit = nl80211_set_rekey_data,
5617c6cd 16690 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
16691 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
16692 NL80211_FLAG_CLEAR_SKB),
e5497d76 16693 },
109086ce
AN
16694 {
16695 .cmd = NL80211_CMD_TDLS_MGMT,
ef6243ac 16696 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
109086ce 16697 .doit = nl80211_tdls_mgmt,
5617c6cd 16698 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16699 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
109086ce
AN
16700 },
16701 {
16702 .cmd = NL80211_CMD_TDLS_OPER,
ef6243ac 16703 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
109086ce 16704 .doit = nl80211_tdls_oper,
5617c6cd 16705 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16706 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
109086ce 16707 },
28946da7
JB
16708 {
16709 .cmd = NL80211_CMD_UNEXPECTED_FRAME,
ef6243ac 16710 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
28946da7 16711 .doit = nl80211_register_unexpected_frame,
5617c6cd 16712 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16713 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
28946da7 16714 },
7f6cf311
JB
16715 {
16716 .cmd = NL80211_CMD_PROBE_CLIENT,
ef6243ac 16717 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
7f6cf311 16718 .doit = nl80211_probe_client,
5617c6cd 16719 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16720 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
7f6cf311 16721 },
5e760230
JB
16722 {
16723 .cmd = NL80211_CMD_REGISTER_BEACONS,
ef6243ac 16724 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5e760230 16725 .doit = nl80211_register_beacons,
5617c6cd 16726 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16727 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY),
5e760230 16728 },
1d9d9213
SW
16729 {
16730 .cmd = NL80211_CMD_SET_NOACK_MAP,
ef6243ac 16731 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1d9d9213 16732 .doit = nl80211_set_noack_map,
5617c6cd 16733 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16734 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
1d9d9213 16735 },
98104fde
JB
16736 {
16737 .cmd = NL80211_CMD_START_P2P_DEVICE,
ef6243ac 16738 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
98104fde 16739 .doit = nl80211_start_p2p_device,
5617c6cd 16740 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
16741 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV |
16742 NL80211_FLAG_NEED_RTNL),
98104fde
JB
16743 },
16744 {
16745 .cmd = NL80211_CMD_STOP_P2P_DEVICE,
ef6243ac 16746 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
98104fde 16747 .doit = nl80211_stop_p2p_device,
5617c6cd 16748 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
16749 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP |
16750 NL80211_FLAG_NEED_RTNL),
cb3b7d87
AB
16751 },
16752 {
16753 .cmd = NL80211_CMD_START_NAN,
ef6243ac 16754 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
cb3b7d87 16755 .doit = nl80211_start_nan,
cb3b7d87 16756 .flags = GENL_ADMIN_PERM,
2182db91
JB
16757 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV |
16758 NL80211_FLAG_NEED_RTNL),
cb3b7d87
AB
16759 },
16760 {
16761 .cmd = NL80211_CMD_STOP_NAN,
ef6243ac 16762 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
cb3b7d87 16763 .doit = nl80211_stop_nan,
cb3b7d87 16764 .flags = GENL_ADMIN_PERM,
2182db91
JB
16765 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP |
16766 NL80211_FLAG_NEED_RTNL),
a442b761
AB
16767 },
16768 {
16769 .cmd = NL80211_CMD_ADD_NAN_FUNCTION,
ef6243ac 16770 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
a442b761 16771 .doit = nl80211_nan_add_func,
a442b761 16772 .flags = GENL_ADMIN_PERM,
2182db91 16773 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
a442b761
AB
16774 },
16775 {
16776 .cmd = NL80211_CMD_DEL_NAN_FUNCTION,
ef6243ac 16777 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
a442b761 16778 .doit = nl80211_nan_del_func,
a442b761 16779 .flags = GENL_ADMIN_PERM,
2182db91 16780 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
a5a9dcf2
AB
16781 },
16782 {
16783 .cmd = NL80211_CMD_CHANGE_NAN_CONFIG,
ef6243ac 16784 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
a5a9dcf2 16785 .doit = nl80211_nan_change_config,
a5a9dcf2 16786 .flags = GENL_ADMIN_PERM,
2182db91 16787 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
98104fde 16788 },
f4e583c8
AQ
16789 {
16790 .cmd = NL80211_CMD_SET_MCAST_RATE,
ef6243ac 16791 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
f4e583c8 16792 .doit = nl80211_set_mcast_rate,
5617c6cd 16793 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16794 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
77765eaf
VT
16795 },
16796 {
16797 .cmd = NL80211_CMD_SET_MAC_ACL,
ef6243ac 16798 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
77765eaf 16799 .doit = nl80211_set_mac_acl,
5617c6cd 16800 .flags = GENL_UNS_ADMIN_PERM,
7b0a0e3c
JB
16801 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV |
16802 NL80211_FLAG_MLO_UNSUPPORTED),
f4e583c8 16803 },
04f39047
SW
16804 {
16805 .cmd = NL80211_CMD_RADAR_DETECT,
ef6243ac 16806 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
04f39047 16807 .doit = nl80211_start_radar_detection,
5617c6cd 16808 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16809 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
7b0a0e3c
JB
16810 NL80211_FLAG_NO_WIPHY_MTX |
16811 NL80211_FLAG_MLO_UNSUPPORTED),
04f39047 16812 },
3713b4e3
JB
16813 {
16814 .cmd = NL80211_CMD_GET_PROTOCOL_FEATURES,
ef6243ac 16815 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
3713b4e3 16816 .doit = nl80211_get_protocol_features,
3713b4e3 16817 },
355199e0
JM
16818 {
16819 .cmd = NL80211_CMD_UPDATE_FT_IES,
ef6243ac 16820 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
355199e0 16821 .doit = nl80211_update_ft_ies,
5617c6cd 16822 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16823 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
355199e0 16824 },
5de17984
AS
16825 {
16826 .cmd = NL80211_CMD_CRIT_PROTOCOL_START,
ef6243ac 16827 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5de17984 16828 .doit = nl80211_crit_protocol_start,
5617c6cd 16829 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16830 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
5de17984
AS
16831 },
16832 {
16833 .cmd = NL80211_CMD_CRIT_PROTOCOL_STOP,
ef6243ac 16834 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5de17984 16835 .doit = nl80211_crit_protocol_stop,
5617c6cd 16836 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16837 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
be29b99a
AK
16838 },
16839 {
16840 .cmd = NL80211_CMD_GET_COALESCE,
ef6243ac 16841 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
be29b99a 16842 .doit = nl80211_get_coalesce,
2182db91 16843 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY),
be29b99a
AK
16844 },
16845 {
16846 .cmd = NL80211_CMD_SET_COALESCE,
ef6243ac 16847 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
be29b99a 16848 .doit = nl80211_set_coalesce,
5617c6cd 16849 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16850 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY),
16ef1fe2
SW
16851 },
16852 {
16853 .cmd = NL80211_CMD_CHANNEL_SWITCH,
ef6243ac 16854 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
16ef1fe2 16855 .doit = nl80211_channel_switch,
5617c6cd 16856 .flags = GENL_UNS_ADMIN_PERM,
7b0a0e3c
JB
16857 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
16858 NL80211_FLAG_MLO_VALID_LINK_ID),
16ef1fe2 16859 },
ad7e718c
JB
16860 {
16861 .cmd = NL80211_CMD_VENDOR,
ef6243ac 16862 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ad7e718c 16863 .doit = nl80211_vendor_cmd,
7bdbe400 16864 .dumpit = nl80211_vendor_cmd_dump,
5617c6cd 16865 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
16866 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY |
16867 NL80211_FLAG_CLEAR_SKB),
ad7e718c 16868 },
fa9ffc74
KP
16869 {
16870 .cmd = NL80211_CMD_SET_QOS_MAP,
ef6243ac 16871 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
fa9ffc74 16872 .doit = nl80211_set_qos_map,
5617c6cd 16873 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16874 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
fa9ffc74 16875 },
960d01ac
JB
16876 {
16877 .cmd = NL80211_CMD_ADD_TX_TS,
ef6243ac 16878 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
960d01ac 16879 .doit = nl80211_add_tx_ts,
5617c6cd 16880 .flags = GENL_UNS_ADMIN_PERM,
7b0a0e3c
JB
16881 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
16882 NL80211_FLAG_MLO_UNSUPPORTED),
960d01ac
JB
16883 },
16884 {
16885 .cmd = NL80211_CMD_DEL_TX_TS,
ef6243ac 16886 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
960d01ac 16887 .doit = nl80211_del_tx_ts,
5617c6cd 16888 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16889 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
960d01ac 16890 },
1057d35e
AN
16891 {
16892 .cmd = NL80211_CMD_TDLS_CHANNEL_SWITCH,
ef6243ac 16893 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1057d35e 16894 .doit = nl80211_tdls_channel_switch,
5617c6cd 16895 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16896 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
1057d35e
AN
16897 },
16898 {
16899 .cmd = NL80211_CMD_TDLS_CANCEL_CHANNEL_SWITCH,
ef6243ac 16900 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1057d35e 16901 .doit = nl80211_tdls_cancel_channel_switch,
5617c6cd 16902 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16903 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
1057d35e 16904 },
ce0ce13a
MB
16905 {
16906 .cmd = NL80211_CMD_SET_MULTICAST_TO_UNICAST,
ef6243ac 16907 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ce0ce13a 16908 .doit = nl80211_set_multicast_to_unicast,
ce0ce13a 16909 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16910 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
ce0ce13a 16911 },
3a00df57
AS
16912 {
16913 .cmd = NL80211_CMD_SET_PMK,
ef6243ac 16914 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
3a00df57 16915 .doit = nl80211_set_pmk,
2182db91
JB
16916 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
16917 NL80211_FLAG_CLEAR_SKB),
3a00df57
AS
16918 },
16919 {
16920 .cmd = NL80211_CMD_DEL_PMK,
ef6243ac 16921 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
3a00df57 16922 .doit = nl80211_del_pmk,
2182db91 16923 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
3a00df57 16924 },
40cbfa90
SD
16925 {
16926 .cmd = NL80211_CMD_EXTERNAL_AUTH,
ef6243ac 16927 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
40cbfa90 16928 .doit = nl80211_external_auth,
40cbfa90 16929 .flags = GENL_ADMIN_PERM,
2182db91 16930 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
40cbfa90 16931 },
2576a9ac
DK
16932 {
16933 .cmd = NL80211_CMD_CONTROL_PORT_FRAME,
ef6243ac 16934 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2576a9ac 16935 .doit = nl80211_tx_control_port,
2576a9ac 16936 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16937 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
2576a9ac 16938 },
81e54d08
PKC
16939 {
16940 .cmd = NL80211_CMD_GET_FTM_RESPONDER_STATS,
ef6243ac 16941 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
81e54d08 16942 .doit = nl80211_get_ftm_responder_stats,
7b0a0e3c
JB
16943 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV |
16944 NL80211_FLAG_MLO_VALID_LINK_ID),
81e54d08 16945 },
9bb7e0f2
JB
16946 {
16947 .cmd = NL80211_CMD_PEER_MEASUREMENT_START,
ef6243ac 16948 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9bb7e0f2 16949 .doit = nl80211_pmsr_start,
9bb7e0f2 16950 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16951 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
9bb7e0f2 16952 },
30c63115
S
16953 {
16954 .cmd = NL80211_CMD_NOTIFY_RADAR,
ef6243ac 16955 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
30c63115 16956 .doit = nl80211_notify_radar_detection,
30c63115 16957 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16958 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
30c63115 16959 },
cb74e977
SD
16960 {
16961 .cmd = NL80211_CMD_UPDATE_OWE_INFO,
16962 .doit = nl80211_update_owe_info,
16963 .flags = GENL_ADMIN_PERM,
2182db91 16964 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
5ab92e7f
RM
16965 },
16966 {
16967 .cmd = NL80211_CMD_PROBE_MESH_LINK,
16968 .doit = nl80211_probe_mesh_link,
16969 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16970 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
cb74e977 16971 },
77f576de
T
16972 {
16973 .cmd = NL80211_CMD_SET_TID_CONFIG,
16974 .doit = nl80211_set_tid_config,
16975 .flags = GENL_UNS_ADMIN_PERM,
7b0a0e3c
JB
16976 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV |
16977 NL80211_FLAG_MLO_VALID_LINK_ID),
77f576de 16978 },
6bdb68ce
CH
16979 {
16980 .cmd = NL80211_CMD_SET_SAR_SPECS,
16981 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
16982 .doit = nl80211_set_sar_specs,
16983 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
16984 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY |
16985 NL80211_FLAG_NEED_RTNL),
6bdb68ce 16986 },
0d2ab3ae
JC
16987 {
16988 .cmd = NL80211_CMD_COLOR_CHANGE_REQUEST,
16989 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
16990 .doit = nl80211_color_change,
16991 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16992 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
0d2ab3ae 16993 },
e306784a
SM
16994 {
16995 .cmd = NL80211_CMD_SET_FILS_AAD,
16996 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
16997 .doit = nl80211_set_fils_aad,
16998 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16999 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
e306784a 17000 },
7b0a0e3c
JB
17001 {
17002 .cmd = NL80211_CMD_ADD_LINK,
17003 .doit = nl80211_add_link,
17004 .flags = GENL_UNS_ADMIN_PERM,
17005 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
17006 },
17007 {
17008 .cmd = NL80211_CMD_REMOVE_LINK,
17009 .doit = nl80211_remove_link,
17010 .flags = GENL_UNS_ADMIN_PERM,
577e5b8c
ST
17011 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
17012 NL80211_FLAG_MLO_VALID_LINK_ID),
17013 },
17014 {
17015 .cmd = NL80211_CMD_ADD_LINK_STA,
17016 .doit = nl80211_add_link_station,
17017 .flags = GENL_UNS_ADMIN_PERM,
17018 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
17019 NL80211_FLAG_MLO_VALID_LINK_ID),
17020 },
17021 {
17022 .cmd = NL80211_CMD_MODIFY_LINK_STA,
17023 .doit = nl80211_modify_link_station,
17024 .flags = GENL_UNS_ADMIN_PERM,
17025 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
17026 NL80211_FLAG_MLO_VALID_LINK_ID),
17027 },
17028 {
17029 .cmd = NL80211_CMD_REMOVE_LINK_STA,
17030 .doit = nl80211_remove_link_station,
17031 .flags = GENL_UNS_ADMIN_PERM,
7b0a0e3c
JB
17032 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
17033 NL80211_FLAG_MLO_VALID_LINK_ID),
17034 },
55682965 17035};
9588bbd5 17036
56989f6d 17037static struct genl_family nl80211_fam __ro_after_init = {
489111e5
JB
17038 .name = NL80211_GENL_NAME, /* have users key off the name instead */
17039 .hdrsize = 0, /* no private header */
17040 .version = 1, /* no particular meaning now */
17041 .maxattr = NL80211_ATTR_MAX,
3b0f31f2 17042 .policy = nl80211_policy,
489111e5
JB
17043 .netnsok = true,
17044 .pre_doit = nl80211_pre_doit,
17045 .post_doit = nl80211_post_doit,
17046 .module = THIS_MODULE,
17047 .ops = nl80211_ops,
17048 .n_ops = ARRAY_SIZE(nl80211_ops),
66a9b928
JK
17049 .small_ops = nl80211_small_ops,
17050 .n_small_ops = ARRAY_SIZE(nl80211_small_ops),
489111e5
JB
17051 .mcgrps = nl80211_mcgrps,
17052 .n_mcgrps = ARRAY_SIZE(nl80211_mcgrps),
50508d94 17053 .parallel_ops = true,
489111e5
JB
17054};
17055
55682965
JB
17056/* notification functions */
17057
3bb20556
JB
17058void nl80211_notify_wiphy(struct cfg80211_registered_device *rdev,
17059 enum nl80211_commands cmd)
55682965
JB
17060{
17061 struct sk_buff *msg;
86e8cf98 17062 struct nl80211_dump_wiphy_state state = {};
55682965 17063
3bb20556
JB
17064 WARN_ON(cmd != NL80211_CMD_NEW_WIPHY &&
17065 cmd != NL80211_CMD_DEL_WIPHY);
17066
fd2120ca 17067 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
55682965
JB
17068 if (!msg)
17069 return;
17070
3bb20556 17071 if (nl80211_send_wiphy(rdev, cmd, msg, 0, 0, 0, &state) < 0) {
55682965
JB
17072 nlmsg_free(msg);
17073 return;
17074 }
17075
68eb5503 17076 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17077 NL80211_MCGRP_CONFIG, GFP_KERNEL);
55682965
JB
17078}
17079
896ff063
DK
17080void nl80211_notify_iface(struct cfg80211_registered_device *rdev,
17081 struct wireless_dev *wdev,
17082 enum nl80211_commands cmd)
17083{
17084 struct sk_buff *msg;
17085
896ff063
DK
17086 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
17087 if (!msg)
17088 return;
17089
3d1a5bbf 17090 if (nl80211_send_iface(msg, 0, 0, 0, rdev, wdev, cmd) < 0) {
896ff063
DK
17091 nlmsg_free(msg);
17092 return;
17093 }
17094
17095 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
17096 NL80211_MCGRP_CONFIG, GFP_KERNEL);
17097}
17098
362a415d
JB
17099static int nl80211_add_scan_req(struct sk_buff *msg,
17100 struct cfg80211_registered_device *rdev)
17101{
17102 struct cfg80211_scan_request *req = rdev->scan_req;
17103 struct nlattr *nest;
17104 int i;
c8cb5b85 17105 struct cfg80211_scan_info *info;
362a415d
JB
17106
17107 if (WARN_ON(!req))
17108 return 0;
17109
ae0be8de 17110 nest = nla_nest_start_noflag(msg, NL80211_ATTR_SCAN_SSIDS);
362a415d
JB
17111 if (!nest)
17112 goto nla_put_failure;
9360ffd1
DM
17113 for (i = 0; i < req->n_ssids; i++) {
17114 if (nla_put(msg, i, req->ssids[i].ssid_len, req->ssids[i].ssid))
17115 goto nla_put_failure;
17116 }
362a415d
JB
17117 nla_nest_end(msg, nest);
17118
2032f3b2
TP
17119 if (req->flags & NL80211_SCAN_FLAG_FREQ_KHZ) {
17120 nest = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQ_KHZ);
17121 if (!nest)
17122 goto nla_put_failure;
17123 for (i = 0; i < req->n_channels; i++) {
17124 if (nla_put_u32(msg, i,
17125 ieee80211_channel_to_khz(req->channels[i])))
17126 goto nla_put_failure;
17127 }
17128 nla_nest_end(msg, nest);
17129 } else {
17130 nest = nla_nest_start_noflag(msg,
17131 NL80211_ATTR_SCAN_FREQUENCIES);
17132 if (!nest)
9360ffd1 17133 goto nla_put_failure;
2032f3b2
TP
17134 for (i = 0; i < req->n_channels; i++) {
17135 if (nla_put_u32(msg, i, req->channels[i]->center_freq))
17136 goto nla_put_failure;
17137 }
17138 nla_nest_end(msg, nest);
9360ffd1 17139 }
362a415d 17140
9360ffd1
DM
17141 if (req->ie &&
17142 nla_put(msg, NL80211_ATTR_IE, req->ie_len, req->ie))
17143 goto nla_put_failure;
362a415d 17144
ae917c9f
JB
17145 if (req->flags &&
17146 nla_put_u32(msg, NL80211_ATTR_SCAN_FLAGS, req->flags))
17147 goto nla_put_failure;
ed473771 17148
c8cb5b85
TM
17149 info = rdev->int_scan_req ? &rdev->int_scan_req->info :
17150 &rdev->scan_req->info;
17151 if (info->scan_start_tsf &&
1d76250b 17152 (nla_put_u64_64bit(msg, NL80211_ATTR_SCAN_START_TIME_TSF,
c8cb5b85 17153 info->scan_start_tsf, NL80211_BSS_PAD) ||
1d76250b 17154 nla_put(msg, NL80211_ATTR_SCAN_START_TIME_TSF_BSSID, ETH_ALEN,
c8cb5b85 17155 info->tsf_bssid)))
1d76250b
AS
17156 goto nla_put_failure;
17157
362a415d
JB
17158 return 0;
17159 nla_put_failure:
17160 return -ENOBUFS;
17161}
17162
505a2e88 17163static int nl80211_prep_scan_msg(struct sk_buff *msg,
a538e2d5 17164 struct cfg80211_registered_device *rdev,
fd014284 17165 struct wireless_dev *wdev,
15e47304 17166 u32 portid, u32 seq, int flags,
a538e2d5 17167 u32 cmd)
2a519311
JB
17168{
17169 void *hdr;
17170
15e47304 17171 hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
2a519311
JB
17172 if (!hdr)
17173 return -1;
17174
9360ffd1 17175 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
fd014284
JB
17176 (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
17177 wdev->netdev->ifindex)) ||
2dad624e
ND
17178 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
17179 NL80211_ATTR_PAD))
9360ffd1 17180 goto nla_put_failure;
2a519311 17181
362a415d
JB
17182 /* ignore errors and send incomplete event anyway */
17183 nl80211_add_scan_req(msg, rdev);
2a519311 17184
053c095a
JB
17185 genlmsg_end(msg, hdr);
17186 return 0;
2a519311
JB
17187
17188 nla_put_failure:
17189 genlmsg_cancel(msg, hdr);
17190 return -EMSGSIZE;
17191}
17192
807f8a8c 17193static int
505a2e88 17194nl80211_prep_sched_scan_msg(struct sk_buff *msg,
96b08fd6 17195 struct cfg80211_sched_scan_request *req, u32 cmd)
807f8a8c
LC
17196{
17197 void *hdr;
17198
96b08fd6 17199 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
807f8a8c
LC
17200 if (!hdr)
17201 return -1;
17202
96b08fd6
AVS
17203 if (nla_put_u32(msg, NL80211_ATTR_WIPHY,
17204 wiphy_to_rdev(req->wiphy)->wiphy_idx) ||
17205 nla_put_u32(msg, NL80211_ATTR_IFINDEX, req->dev->ifindex) ||
17206 nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, req->reqid,
17207 NL80211_ATTR_PAD))
9360ffd1 17208 goto nla_put_failure;
807f8a8c 17209
053c095a
JB
17210 genlmsg_end(msg, hdr);
17211 return 0;
807f8a8c
LC
17212
17213 nla_put_failure:
17214 genlmsg_cancel(msg, hdr);
17215 return -EMSGSIZE;
17216}
17217
a538e2d5 17218void nl80211_send_scan_start(struct cfg80211_registered_device *rdev,
fd014284 17219 struct wireless_dev *wdev)
a538e2d5
JB
17220{
17221 struct sk_buff *msg;
17222
58050fce 17223 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
a538e2d5
JB
17224 if (!msg)
17225 return;
17226
505a2e88 17227 if (nl80211_prep_scan_msg(msg, rdev, wdev, 0, 0, 0,
a538e2d5
JB
17228 NL80211_CMD_TRIGGER_SCAN) < 0) {
17229 nlmsg_free(msg);
17230 return;
17231 }
17232
68eb5503 17233 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17234 NL80211_MCGRP_SCAN, GFP_KERNEL);
a538e2d5
JB
17235}
17236
f9d15d16
JB
17237struct sk_buff *nl80211_build_scan_msg(struct cfg80211_registered_device *rdev,
17238 struct wireless_dev *wdev, bool aborted)
2a519311
JB
17239{
17240 struct sk_buff *msg;
17241
fd2120ca 17242 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2a519311 17243 if (!msg)
f9d15d16 17244 return NULL;
2a519311 17245
505a2e88 17246 if (nl80211_prep_scan_msg(msg, rdev, wdev, 0, 0, 0,
f9d15d16
JB
17247 aborted ? NL80211_CMD_SCAN_ABORTED :
17248 NL80211_CMD_NEW_SCAN_RESULTS) < 0) {
2a519311 17249 nlmsg_free(msg);
f9d15d16 17250 return NULL;
2a519311
JB
17251 }
17252
f9d15d16 17253 return msg;
2a519311
JB
17254}
17255
505a2e88
AVS
17256/* send message created by nl80211_build_scan_msg() */
17257void nl80211_send_scan_msg(struct cfg80211_registered_device *rdev,
17258 struct sk_buff *msg)
807f8a8c 17259{
807f8a8c
LC
17260 if (!msg)
17261 return;
17262
68eb5503 17263 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17264 NL80211_MCGRP_SCAN, GFP_KERNEL);
807f8a8c
LC
17265}
17266
96b08fd6 17267void nl80211_send_sched_scan(struct cfg80211_sched_scan_request *req, u32 cmd)
807f8a8c
LC
17268{
17269 struct sk_buff *msg;
17270
58050fce 17271 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
807f8a8c
LC
17272 if (!msg)
17273 return;
17274
96b08fd6 17275 if (nl80211_prep_sched_scan_msg(msg, req, cmd) < 0) {
807f8a8c
LC
17276 nlmsg_free(msg);
17277 return;
17278 }
17279
96b08fd6 17280 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(req->wiphy), msg, 0,
2a94fe48 17281 NL80211_MCGRP_SCAN, GFP_KERNEL);
807f8a8c
LC
17282}
17283
b0d7aa59
JD
17284static bool nl80211_reg_change_event_fill(struct sk_buff *msg,
17285 struct regulatory_request *request)
73d54c9e 17286{
73d54c9e 17287 /* Userspace can always count this one always being set */
9360ffd1
DM
17288 if (nla_put_u8(msg, NL80211_ATTR_REG_INITIATOR, request->initiator))
17289 goto nla_put_failure;
17290
17291 if (request->alpha2[0] == '0' && request->alpha2[1] == '0') {
17292 if (nla_put_u8(msg, NL80211_ATTR_REG_TYPE,
17293 NL80211_REGDOM_TYPE_WORLD))
17294 goto nla_put_failure;
17295 } else if (request->alpha2[0] == '9' && request->alpha2[1] == '9') {
17296 if (nla_put_u8(msg, NL80211_ATTR_REG_TYPE,
17297 NL80211_REGDOM_TYPE_CUSTOM_WORLD))
17298 goto nla_put_failure;
17299 } else if ((request->alpha2[0] == '9' && request->alpha2[1] == '8') ||
17300 request->intersect) {
17301 if (nla_put_u8(msg, NL80211_ATTR_REG_TYPE,
17302 NL80211_REGDOM_TYPE_INTERSECTION))
17303 goto nla_put_failure;
17304 } else {
17305 if (nla_put_u8(msg, NL80211_ATTR_REG_TYPE,
17306 NL80211_REGDOM_TYPE_COUNTRY) ||
17307 nla_put_string(msg, NL80211_ATTR_REG_ALPHA2,
17308 request->alpha2))
17309 goto nla_put_failure;
17310 }
17311
ad30ca2c
AN
17312 if (request->wiphy_idx != WIPHY_IDX_INVALID) {
17313 struct wiphy *wiphy = wiphy_idx_to_wiphy(request->wiphy_idx);
17314
17315 if (wiphy &&
17316 nla_put_u32(msg, NL80211_ATTR_WIPHY, request->wiphy_idx))
17317 goto nla_put_failure;
1bdd716c
AN
17318
17319 if (wiphy &&
17320 wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED &&
17321 nla_put_flag(msg, NL80211_ATTR_WIPHY_SELF_MANAGED_REG))
17322 goto nla_put_failure;
ad30ca2c 17323 }
73d54c9e 17324
b0d7aa59
JD
17325 return true;
17326
17327nla_put_failure:
17328 return false;
17329}
17330
17331/*
17332 * This can happen on global regulatory changes or device specific settings
17333 * based on custom regulatory domains.
17334 */
17335void nl80211_common_reg_change_event(enum nl80211_commands cmd_id,
17336 struct regulatory_request *request)
17337{
17338 struct sk_buff *msg;
17339 void *hdr;
17340
17341 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
17342 if (!msg)
17343 return;
17344
17345 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd_id);
24f6d765 17346 if (!hdr)
17347 goto nla_put_failure;
b0d7aa59 17348
24f6d765 17349 if (!nl80211_reg_change_event_fill(msg, request))
b0d7aa59
JD
17350 goto nla_put_failure;
17351
3b7b72ee 17352 genlmsg_end(msg, hdr);
73d54c9e 17353
bc43b28c 17354 rcu_read_lock();
68eb5503 17355 genlmsg_multicast_allns(&nl80211_fam, msg, 0,
2a94fe48 17356 NL80211_MCGRP_REGULATORY, GFP_ATOMIC);
bc43b28c 17357 rcu_read_unlock();
73d54c9e
LR
17358
17359 return;
17360
17361nla_put_failure:
73d54c9e
LR
17362 nlmsg_free(msg);
17363}
17364
6039f6d2
JM
17365static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev,
17366 struct net_device *netdev,
17367 const u8 *buf, size_t len,
b0b6aa2c 17368 enum nl80211_commands cmd, gfp_t gfp,
4d9ec73d 17369 int uapsd_queues, const u8 *req_ies,
3bb02143 17370 size_t req_ies_len, bool reconnect)
6039f6d2
JM
17371{
17372 struct sk_buff *msg;
17373 void *hdr;
17374
4d9ec73d 17375 msg = nlmsg_new(100 + len + req_ies_len, gfp);
6039f6d2
JM
17376 if (!msg)
17377 return;
17378
17379 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
17380 if (!hdr) {
17381 nlmsg_free(msg);
17382 return;
17383 }
17384
9360ffd1
DM
17385 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
17386 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
4d9ec73d
JM
17387 nla_put(msg, NL80211_ATTR_FRAME, len, buf) ||
17388 (req_ies &&
17389 nla_put(msg, NL80211_ATTR_REQ_IE, req_ies_len, req_ies)))
9360ffd1 17390 goto nla_put_failure;
6039f6d2 17391
3bb02143
JB
17392 if (reconnect && nla_put_flag(msg, NL80211_ATTR_RECONNECT_REQUESTED))
17393 goto nla_put_failure;
17394
b0b6aa2c
EP
17395 if (uapsd_queues >= 0) {
17396 struct nlattr *nla_wmm =
ae0be8de 17397 nla_nest_start_noflag(msg, NL80211_ATTR_STA_WME);
b0b6aa2c
EP
17398 if (!nla_wmm)
17399 goto nla_put_failure;
17400
17401 if (nla_put_u8(msg, NL80211_STA_WME_UAPSD_QUEUES,
17402 uapsd_queues))
17403 goto nla_put_failure;
17404
17405 nla_nest_end(msg, nla_wmm);
17406 }
17407
3b7b72ee 17408 genlmsg_end(msg, hdr);
6039f6d2 17409
68eb5503 17410 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17411 NL80211_MCGRP_MLME, gfp);
6039f6d2
JM
17412 return;
17413
17414 nla_put_failure:
6039f6d2
JM
17415 nlmsg_free(msg);
17416}
17417
17418void nl80211_send_rx_auth(struct cfg80211_registered_device *rdev,
e6d6e342
JB
17419 struct net_device *netdev, const u8 *buf,
17420 size_t len, gfp_t gfp)
6039f6d2
JM
17421{
17422 nl80211_send_mlme_event(rdev, netdev, buf, len,
3bb02143
JB
17423 NL80211_CMD_AUTHENTICATE, gfp, -1, NULL, 0,
17424 false);
6039f6d2
JM
17425}
17426
17427void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev,
cd47c0f5
JB
17428 struct net_device *netdev,
17429 struct cfg80211_rx_assoc_resp *data)
6039f6d2 17430{
cd47c0f5
JB
17431 nl80211_send_mlme_event(rdev, netdev, data->buf, data->len,
17432 NL80211_CMD_ASSOCIATE, GFP_KERNEL,
17433 data->uapsd_queues,
17434 data->req_ies, data->req_ies_len, false);
6039f6d2
JM
17435}
17436
53b46b84 17437void nl80211_send_deauth(struct cfg80211_registered_device *rdev,
e6d6e342 17438 struct net_device *netdev, const u8 *buf,
3bb02143 17439 size_t len, bool reconnect, gfp_t gfp)
6039f6d2
JM
17440{
17441 nl80211_send_mlme_event(rdev, netdev, buf, len,
3bb02143
JB
17442 NL80211_CMD_DEAUTHENTICATE, gfp, -1, NULL, 0,
17443 reconnect);
6039f6d2
JM
17444}
17445
53b46b84
JM
17446void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,
17447 struct net_device *netdev, const u8 *buf,
3bb02143 17448 size_t len, bool reconnect, gfp_t gfp)
6039f6d2
JM
17449{
17450 nl80211_send_mlme_event(rdev, netdev, buf, len,
3bb02143
JB
17451 NL80211_CMD_DISASSOCIATE, gfp, -1, NULL, 0,
17452 reconnect);
6039f6d2
JM
17453}
17454
6ff57cf8
JB
17455void cfg80211_rx_unprot_mlme_mgmt(struct net_device *dev, const u8 *buf,
17456 size_t len)
cf4e594e 17457{
947add36
JB
17458 struct wireless_dev *wdev = dev->ieee80211_ptr;
17459 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 17460 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
6ff57cf8
JB
17461 const struct ieee80211_mgmt *mgmt = (void *)buf;
17462 u32 cmd;
947add36 17463
6ff57cf8
JB
17464 if (WARN_ON(len < 2))
17465 return;
cf4e594e 17466
4d797fce 17467 if (ieee80211_is_deauth(mgmt->frame_control)) {
6ff57cf8 17468 cmd = NL80211_CMD_UNPROT_DEAUTHENTICATE;
4d797fce 17469 } else if (ieee80211_is_disassoc(mgmt->frame_control)) {
6ff57cf8 17470 cmd = NL80211_CMD_UNPROT_DISASSOCIATE;
4d797fce
JM
17471 } else if (ieee80211_is_beacon(mgmt->frame_control)) {
17472 if (wdev->unprot_beacon_reported &&
17473 elapsed_jiffies_msecs(wdev->unprot_beacon_reported) < 10000)
17474 return;
17475 cmd = NL80211_CMD_UNPROT_BEACON;
17476 wdev->unprot_beacon_reported = jiffies;
17477 } else {
17478 return;
17479 }
947add36 17480
6ff57cf8 17481 trace_cfg80211_rx_unprot_mlme_mgmt(dev, buf, len);
4d9ec73d 17482 nl80211_send_mlme_event(rdev, dev, buf, len, cmd, GFP_ATOMIC, -1,
3bb02143 17483 NULL, 0, false);
cf4e594e 17484}
6ff57cf8 17485EXPORT_SYMBOL(cfg80211_rx_unprot_mlme_mgmt);
cf4e594e 17486
1b06bb40
LR
17487static void nl80211_send_mlme_timeout(struct cfg80211_registered_device *rdev,
17488 struct net_device *netdev, int cmd,
e6d6e342 17489 const u8 *addr, gfp_t gfp)
1965c853
JM
17490{
17491 struct sk_buff *msg;
17492 void *hdr;
17493
e6d6e342 17494 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
1965c853
JM
17495 if (!msg)
17496 return;
17497
17498 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
17499 if (!hdr) {
17500 nlmsg_free(msg);
17501 return;
17502 }
17503
9360ffd1
DM
17504 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
17505 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
17506 nla_put_flag(msg, NL80211_ATTR_TIMED_OUT) ||
17507 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr))
17508 goto nla_put_failure;
1965c853 17509
3b7b72ee 17510 genlmsg_end(msg, hdr);
1965c853 17511
68eb5503 17512 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17513 NL80211_MCGRP_MLME, gfp);
1965c853
JM
17514 return;
17515
17516 nla_put_failure:
1965c853
JM
17517 nlmsg_free(msg);
17518}
17519
17520void nl80211_send_auth_timeout(struct cfg80211_registered_device *rdev,
e6d6e342
JB
17521 struct net_device *netdev, const u8 *addr,
17522 gfp_t gfp)
1965c853
JM
17523{
17524 nl80211_send_mlme_timeout(rdev, netdev, NL80211_CMD_AUTHENTICATE,
e6d6e342 17525 addr, gfp);
1965c853
JM
17526}
17527
17528void nl80211_send_assoc_timeout(struct cfg80211_registered_device *rdev,
e6d6e342
JB
17529 struct net_device *netdev, const u8 *addr,
17530 gfp_t gfp)
1965c853 17531{
e6d6e342
JB
17532 nl80211_send_mlme_timeout(rdev, netdev, NL80211_CMD_ASSOCIATE,
17533 addr, gfp);
1965c853
JM
17534}
17535
b23aa676 17536void nl80211_send_connect_result(struct cfg80211_registered_device *rdev,
5349a0f7
VK
17537 struct net_device *netdev,
17538 struct cfg80211_connect_resp_params *cr,
3093ebbe 17539 gfp_t gfp)
b23aa676
SO
17540{
17541 struct sk_buff *msg;
17542 void *hdr;
efbabc11
VJ
17543 unsigned int link;
17544 size_t link_info_size = 0;
17545 const u8 *connected_addr = cr->valid_links ?
17546 cr->ap_mld_addr : cr->links[0].bssid;
17547
17548 if (cr->valid_links) {
17549 for_each_valid_link(cr, link) {
17550 /* Nested attribute header */
17551 link_info_size += NLA_HDRLEN;
17552 /* Link ID */
17553 link_info_size += nla_total_size(sizeof(u8));
17554 link_info_size += cr->links[link].addr ?
17555 nla_total_size(ETH_ALEN) : 0;
17556 link_info_size += (cr->links[link].bssid ||
17557 cr->links[link].bss) ?
17558 nla_total_size(ETH_ALEN) : 0;
17559 }
17560 }
b23aa676 17561
a3caf744 17562 msg = nlmsg_new(100 + cr->req_ie_len + cr->resp_ie_len +
76804d28 17563 cr->fils.kek_len + cr->fils.pmk_len +
efbabc11
VJ
17564 (cr->fils.pmkid ? WLAN_PMKID_LEN : 0) + link_info_size,
17565 gfp);
b23aa676
SO
17566 if (!msg)
17567 return;
17568
17569 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CONNECT);
17570 if (!hdr) {
17571 nlmsg_free(msg);
17572 return;
17573 }
17574
9360ffd1
DM
17575 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
17576 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
efbabc11
VJ
17577 (connected_addr &&
17578 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, connected_addr)) ||
bf1ecd21 17579 nla_put_u16(msg, NL80211_ATTR_STATUS_CODE,
5349a0f7
VK
17580 cr->status < 0 ? WLAN_STATUS_UNSPECIFIED_FAILURE :
17581 cr->status) ||
17582 (cr->status < 0 &&
3093ebbe 17583 (nla_put_flag(msg, NL80211_ATTR_TIMED_OUT) ||
5349a0f7
VK
17584 nla_put_u32(msg, NL80211_ATTR_TIMEOUT_REASON,
17585 cr->timeout_reason))) ||
17586 (cr->req_ie &&
17587 nla_put(msg, NL80211_ATTR_REQ_IE, cr->req_ie_len, cr->req_ie)) ||
17588 (cr->resp_ie &&
17589 nla_put(msg, NL80211_ATTR_RESP_IE, cr->resp_ie_len,
a3caf744 17590 cr->resp_ie)) ||
76804d28 17591 (cr->fils.update_erp_next_seq_num &&
a3caf744 17592 nla_put_u16(msg, NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM,
76804d28 17593 cr->fils.erp_next_seq_num)) ||
a3caf744 17594 (cr->status == WLAN_STATUS_SUCCESS &&
76804d28
AVS
17595 ((cr->fils.kek &&
17596 nla_put(msg, NL80211_ATTR_FILS_KEK, cr->fils.kek_len,
17597 cr->fils.kek)) ||
17598 (cr->fils.pmk &&
17599 nla_put(msg, NL80211_ATTR_PMK, cr->fils.pmk_len, cr->fils.pmk)) ||
17600 (cr->fils.pmkid &&
17601 nla_put(msg, NL80211_ATTR_PMKID, WLAN_PMKID_LEN, cr->fils.pmkid)))))
9360ffd1 17602 goto nla_put_failure;
b23aa676 17603
efbabc11
VJ
17604 if (cr->valid_links) {
17605 int i = 1;
17606 struct nlattr *nested;
17607
17608 nested = nla_nest_start(msg, NL80211_ATTR_MLO_LINKS);
17609 if (!nested)
17610 goto nla_put_failure;
17611
17612 for_each_valid_link(cr, link) {
17613 struct nlattr *nested_mlo_links;
17614 const u8 *bssid = cr->links[link].bss ?
17615 cr->links[link].bss->bssid :
17616 cr->links[link].bssid;
17617
17618 nested_mlo_links = nla_nest_start(msg, i);
17619 if (!nested_mlo_links)
17620 goto nla_put_failure;
17621
17622 if (nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link) ||
17623 (bssid &&
17624 nla_put(msg, NL80211_ATTR_BSSID, ETH_ALEN, bssid)) ||
17625 (cr->links[link].addr &&
17626 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN,
17627 cr->links[link].addr)))
17628 goto nla_put_failure;
17629
17630 nla_nest_end(msg, nested_mlo_links);
17631 i++;
17632 }
17633 nla_nest_end(msg, nested);
17634 }
17635
3b7b72ee 17636 genlmsg_end(msg, hdr);
b23aa676 17637
68eb5503 17638 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17639 NL80211_MCGRP_MLME, gfp);
b23aa676
SO
17640 return;
17641
17642 nla_put_failure:
b23aa676 17643 nlmsg_free(msg);
b23aa676
SO
17644}
17645
17646void nl80211_send_roamed(struct cfg80211_registered_device *rdev,
29ce6ecb
AS
17647 struct net_device *netdev,
17648 struct cfg80211_roam_info *info, gfp_t gfp)
b23aa676
SO
17649{
17650 struct sk_buff *msg;
17651 void *hdr;
efbabc11
VJ
17652 size_t link_info_size = 0;
17653 unsigned int link;
17654 const u8 *connected_addr = info->ap_mld_addr ?
17655 info->ap_mld_addr :
17656 (info->links[0].bss ?
17657 info->links[0].bss->bssid :
17658 info->links[0].bssid);
17659
17660 if (info->valid_links) {
17661 for_each_valid_link(info, link) {
17662 /* Nested attribute header */
17663 link_info_size += NLA_HDRLEN;
17664 /* Link ID */
17665 link_info_size += nla_total_size(sizeof(u8));
17666 link_info_size += info->links[link].addr ?
17667 nla_total_size(ETH_ALEN) : 0;
17668 link_info_size += (info->links[link].bssid ||
17669 info->links[link].bss) ?
17670 nla_total_size(ETH_ALEN) : 0;
17671 }
17672 }
b23aa676 17673
e841b7b1
AVS
17674 msg = nlmsg_new(100 + info->req_ie_len + info->resp_ie_len +
17675 info->fils.kek_len + info->fils.pmk_len +
efbabc11
VJ
17676 (info->fils.pmkid ? WLAN_PMKID_LEN : 0) +
17677 link_info_size, gfp);
b23aa676
SO
17678 if (!msg)
17679 return;
17680
17681 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_ROAM);
17682 if (!hdr) {
17683 nlmsg_free(msg);
17684 return;
17685 }
17686
9360ffd1
DM
17687 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
17688 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
efbabc11 17689 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, connected_addr) ||
29ce6ecb
AS
17690 (info->req_ie &&
17691 nla_put(msg, NL80211_ATTR_REQ_IE, info->req_ie_len,
17692 info->req_ie)) ||
17693 (info->resp_ie &&
17694 nla_put(msg, NL80211_ATTR_RESP_IE, info->resp_ie_len,
e841b7b1
AVS
17695 info->resp_ie)) ||
17696 (info->fils.update_erp_next_seq_num &&
17697 nla_put_u16(msg, NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM,
17698 info->fils.erp_next_seq_num)) ||
17699 (info->fils.kek &&
17700 nla_put(msg, NL80211_ATTR_FILS_KEK, info->fils.kek_len,
17701 info->fils.kek)) ||
17702 (info->fils.pmk &&
17703 nla_put(msg, NL80211_ATTR_PMK, info->fils.pmk_len, info->fils.pmk)) ||
17704 (info->fils.pmkid &&
17705 nla_put(msg, NL80211_ATTR_PMKID, WLAN_PMKID_LEN, info->fils.pmkid)))
9360ffd1 17706 goto nla_put_failure;
b23aa676 17707
efbabc11
VJ
17708 if (info->valid_links) {
17709 int i = 1;
17710 struct nlattr *nested;
17711
17712 nested = nla_nest_start(msg, NL80211_ATTR_MLO_LINKS);
17713 if (!nested)
17714 goto nla_put_failure;
17715
17716 for_each_valid_link(info, link) {
17717 struct nlattr *nested_mlo_links;
17718 const u8 *bssid = info->links[link].bss ?
17719 info->links[link].bss->bssid :
17720 info->links[link].bssid;
17721
17722 nested_mlo_links = nla_nest_start(msg, i);
17723 if (!nested_mlo_links)
17724 goto nla_put_failure;
17725
17726 if (nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link) ||
17727 (bssid &&
17728 nla_put(msg, NL80211_ATTR_BSSID, ETH_ALEN, bssid)) ||
17729 (info->links[link].addr &&
17730 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN,
17731 info->links[link].addr)))
17732 goto nla_put_failure;
17733
17734 nla_nest_end(msg, nested_mlo_links);
17735 i++;
17736 }
17737 nla_nest_end(msg, nested);
17738 }
17739
3b7b72ee 17740 genlmsg_end(msg, hdr);
b23aa676 17741
68eb5503 17742 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17743 NL80211_MCGRP_MLME, gfp);
b23aa676
SO
17744 return;
17745
503c1fb9 17746 nla_put_failure:
503c1fb9
AS
17747 nlmsg_free(msg);
17748}
17749
17750void nl80211_send_port_authorized(struct cfg80211_registered_device *rdev,
17751 struct net_device *netdev, const u8 *bssid)
17752{
17753 struct sk_buff *msg;
17754 void *hdr;
17755
17756 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
17757 if (!msg)
17758 return;
17759
17760 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_PORT_AUTHORIZED);
17761 if (!hdr) {
17762 nlmsg_free(msg);
17763 return;
17764 }
17765
f4d75993
CHH
17766 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
17767 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
17768 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid))
503c1fb9
AS
17769 goto nla_put_failure;
17770
17771 genlmsg_end(msg, hdr);
17772
17773 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
17774 NL80211_MCGRP_MLME, GFP_KERNEL);
17775 return;
17776
b23aa676 17777 nla_put_failure:
b23aa676 17778 nlmsg_free(msg);
b23aa676
SO
17779}
17780
17781void nl80211_send_disconnected(struct cfg80211_registered_device *rdev,
17782 struct net_device *netdev, u16 reason,
667503dd 17783 const u8 *ie, size_t ie_len, bool from_ap)
b23aa676
SO
17784{
17785 struct sk_buff *msg;
17786 void *hdr;
17787
4ef8c1c9 17788 msg = nlmsg_new(100 + ie_len, GFP_KERNEL);
b23aa676
SO
17789 if (!msg)
17790 return;
17791
17792 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_DISCONNECT);
17793 if (!hdr) {
17794 nlmsg_free(msg);
17795 return;
17796 }
17797
9360ffd1
DM
17798 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
17799 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
86b6c465 17800 (reason &&
9360ffd1
DM
17801 nla_put_u16(msg, NL80211_ATTR_REASON_CODE, reason)) ||
17802 (from_ap &&
17803 nla_put_flag(msg, NL80211_ATTR_DISCONNECTED_BY_AP)) ||
17804 (ie && nla_put(msg, NL80211_ATTR_IE, ie_len, ie)))
17805 goto nla_put_failure;
b23aa676 17806
3b7b72ee 17807 genlmsg_end(msg, hdr);
b23aa676 17808
68eb5503 17809 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17810 NL80211_MCGRP_MLME, GFP_KERNEL);
b23aa676
SO
17811 return;
17812
17813 nla_put_failure:
b23aa676 17814 nlmsg_free(msg);
b23aa676
SO
17815}
17816
04a773ad
JB
17817void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev,
17818 struct net_device *netdev, const u8 *bssid,
17819 gfp_t gfp)
17820{
17821 struct sk_buff *msg;
17822 void *hdr;
17823
fd2120ca 17824 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
04a773ad
JB
17825 if (!msg)
17826 return;
17827
17828 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_JOIN_IBSS);
17829 if (!hdr) {
17830 nlmsg_free(msg);
17831 return;
17832 }
17833
9360ffd1
DM
17834 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
17835 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
17836 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid))
17837 goto nla_put_failure;
04a773ad 17838
3b7b72ee 17839 genlmsg_end(msg, hdr);
04a773ad 17840
68eb5503 17841 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17842 NL80211_MCGRP_MLME, gfp);
04a773ad
JB
17843 return;
17844
17845 nla_put_failure:
04a773ad
JB
17846 nlmsg_free(msg);
17847}
17848
947add36 17849void cfg80211_notify_new_peer_candidate(struct net_device *dev, const u8 *addr,
ecbc12ad
BC
17850 const u8 *ie, u8 ie_len,
17851 int sig_dbm, gfp_t gfp)
c93b5e71 17852{
947add36 17853 struct wireless_dev *wdev = dev->ieee80211_ptr;
f26cbf40 17854 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
c93b5e71
JC
17855 struct sk_buff *msg;
17856 void *hdr;
17857
947add36
JB
17858 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_MESH_POINT))
17859 return;
17860
17861 trace_cfg80211_notify_new_peer_candidate(dev, addr);
17862
4ef8c1c9 17863 msg = nlmsg_new(100 + ie_len, gfp);
c93b5e71
JC
17864 if (!msg)
17865 return;
17866
17867 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NEW_PEER_CANDIDATE);
17868 if (!hdr) {
17869 nlmsg_free(msg);
17870 return;
17871 }
17872
9360ffd1 17873 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
947add36
JB
17874 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
17875 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
9360ffd1 17876 (ie_len && ie &&
ecbc12ad
BC
17877 nla_put(msg, NL80211_ATTR_IE, ie_len, ie)) ||
17878 (sig_dbm &&
17879 nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)))
9360ffd1 17880 goto nla_put_failure;
c93b5e71 17881
3b7b72ee 17882 genlmsg_end(msg, hdr);
c93b5e71 17883
68eb5503 17884 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17885 NL80211_MCGRP_MLME, gfp);
c93b5e71
JC
17886 return;
17887
17888 nla_put_failure:
c93b5e71
JC
17889 nlmsg_free(msg);
17890}
947add36 17891EXPORT_SYMBOL(cfg80211_notify_new_peer_candidate);
c93b5e71 17892
a3b8b056
JM
17893void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev,
17894 struct net_device *netdev, const u8 *addr,
17895 enum nl80211_key_type key_type, int key_id,
e6d6e342 17896 const u8 *tsc, gfp_t gfp)
a3b8b056
JM
17897{
17898 struct sk_buff *msg;
17899 void *hdr;
17900
e6d6e342 17901 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
a3b8b056
JM
17902 if (!msg)
17903 return;
17904
17905 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_MICHAEL_MIC_FAILURE);
17906 if (!hdr) {
17907 nlmsg_free(msg);
17908 return;
17909 }
17910
9360ffd1
DM
17911 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
17912 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
17913 (addr && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) ||
17914 nla_put_u32(msg, NL80211_ATTR_KEY_TYPE, key_type) ||
17915 (key_id != -1 &&
17916 nla_put_u8(msg, NL80211_ATTR_KEY_IDX, key_id)) ||
17917 (tsc && nla_put(msg, NL80211_ATTR_KEY_SEQ, 6, tsc)))
17918 goto nla_put_failure;
a3b8b056 17919
3b7b72ee 17920 genlmsg_end(msg, hdr);
a3b8b056 17921
68eb5503 17922 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17923 NL80211_MCGRP_MLME, gfp);
a3b8b056
JM
17924 return;
17925
17926 nla_put_failure:
a3b8b056
JM
17927 nlmsg_free(msg);
17928}
17929
6bad8766
LR
17930void nl80211_send_beacon_hint_event(struct wiphy *wiphy,
17931 struct ieee80211_channel *channel_before,
17932 struct ieee80211_channel *channel_after)
17933{
17934 struct sk_buff *msg;
17935 void *hdr;
17936 struct nlattr *nl_freq;
17937
fd2120ca 17938 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
6bad8766
LR
17939 if (!msg)
17940 return;
17941
17942 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_REG_BEACON_HINT);
17943 if (!hdr) {
17944 nlmsg_free(msg);
17945 return;
17946 }
17947
17948 /*
17949 * Since we are applying the beacon hint to a wiphy we know its
17950 * wiphy_idx is valid
17951 */
9360ffd1
DM
17952 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, get_wiphy_idx(wiphy)))
17953 goto nla_put_failure;
6bad8766
LR
17954
17955 /* Before */
ae0be8de 17956 nl_freq = nla_nest_start_noflag(msg, NL80211_ATTR_FREQ_BEFORE);
6bad8766
LR
17957 if (!nl_freq)
17958 goto nla_put_failure;
50f32718
HD
17959
17960 if (nl80211_msg_put_channel(msg, wiphy, channel_before, false))
6bad8766
LR
17961 goto nla_put_failure;
17962 nla_nest_end(msg, nl_freq);
17963
17964 /* After */
ae0be8de 17965 nl_freq = nla_nest_start_noflag(msg, NL80211_ATTR_FREQ_AFTER);
6bad8766
LR
17966 if (!nl_freq)
17967 goto nla_put_failure;
50f32718
HD
17968
17969 if (nl80211_msg_put_channel(msg, wiphy, channel_after, false))
6bad8766
LR
17970 goto nla_put_failure;
17971 nla_nest_end(msg, nl_freq);
17972
3b7b72ee 17973 genlmsg_end(msg, hdr);
6bad8766 17974
463d0183 17975 rcu_read_lock();
68eb5503 17976 genlmsg_multicast_allns(&nl80211_fam, msg, 0,
2a94fe48 17977 NL80211_MCGRP_REGULATORY, GFP_ATOMIC);
463d0183 17978 rcu_read_unlock();
6bad8766
LR
17979
17980 return;
17981
17982nla_put_failure:
6bad8766
LR
17983 nlmsg_free(msg);
17984}
17985
9588bbd5
JM
17986static void nl80211_send_remain_on_chan_event(
17987 int cmd, struct cfg80211_registered_device *rdev,
71bbc994 17988 struct wireless_dev *wdev, u64 cookie,
9588bbd5 17989 struct ieee80211_channel *chan,
9588bbd5
JM
17990 unsigned int duration, gfp_t gfp)
17991{
17992 struct sk_buff *msg;
17993 void *hdr;
17994
17995 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
17996 if (!msg)
17997 return;
17998
17999 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
18000 if (!hdr) {
18001 nlmsg_free(msg);
18002 return;
18003 }
18004
9360ffd1 18005 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
71bbc994
JB
18006 (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
18007 wdev->netdev->ifindex)) ||
2dad624e
ND
18008 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
18009 NL80211_ATTR_PAD) ||
9360ffd1 18010 nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, chan->center_freq) ||
42d97a59
JB
18011 nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
18012 NL80211_CHAN_NO_HT) ||
2dad624e
ND
18013 nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
18014 NL80211_ATTR_PAD))
9360ffd1 18015 goto nla_put_failure;
9588bbd5 18016
9360ffd1
DM
18017 if (cmd == NL80211_CMD_REMAIN_ON_CHANNEL &&
18018 nla_put_u32(msg, NL80211_ATTR_DURATION, duration))
18019 goto nla_put_failure;
9588bbd5 18020
3b7b72ee 18021 genlmsg_end(msg, hdr);
9588bbd5 18022
68eb5503 18023 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18024 NL80211_MCGRP_MLME, gfp);
9588bbd5
JM
18025 return;
18026
18027 nla_put_failure:
9588bbd5
JM
18028 nlmsg_free(msg);
18029}
18030
a083ee8a 18031void cfg80211_assoc_comeback(struct net_device *netdev,
e69dac88 18032 const u8 *ap_addr, u32 timeout)
a083ee8a
IP
18033{
18034 struct wireless_dev *wdev = netdev->ieee80211_ptr;
18035 struct wiphy *wiphy = wdev->wiphy;
18036 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
18037 struct sk_buff *msg;
18038 void *hdr;
18039
e69dac88 18040 trace_cfg80211_assoc_comeback(wdev, ap_addr, timeout);
a083ee8a
IP
18041
18042 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
18043 if (!msg)
18044 return;
18045
18046 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_ASSOC_COMEBACK);
18047 if (!hdr) {
18048 nlmsg_free(msg);
18049 return;
18050 }
18051
18052 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
18053 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
e69dac88 18054 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, ap_addr) ||
a083ee8a
IP
18055 nla_put_u32(msg, NL80211_ATTR_TIMEOUT, timeout))
18056 goto nla_put_failure;
18057
18058 genlmsg_end(msg, hdr);
18059
18060 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
18061 NL80211_MCGRP_MLME, GFP_KERNEL);
18062 return;
18063
18064 nla_put_failure:
18065 nlmsg_free(msg);
18066}
18067EXPORT_SYMBOL(cfg80211_assoc_comeback);
18068
947add36
JB
18069void cfg80211_ready_on_channel(struct wireless_dev *wdev, u64 cookie,
18070 struct ieee80211_channel *chan,
18071 unsigned int duration, gfp_t gfp)
9588bbd5 18072{
947add36 18073 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 18074 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
947add36
JB
18075
18076 trace_cfg80211_ready_on_channel(wdev, cookie, chan, duration);
9588bbd5 18077 nl80211_send_remain_on_chan_event(NL80211_CMD_REMAIN_ON_CHANNEL,
71bbc994 18078 rdev, wdev, cookie, chan,
42d97a59 18079 duration, gfp);
9588bbd5 18080}
947add36 18081EXPORT_SYMBOL(cfg80211_ready_on_channel);
9588bbd5 18082
947add36
JB
18083void cfg80211_remain_on_channel_expired(struct wireless_dev *wdev, u64 cookie,
18084 struct ieee80211_channel *chan,
18085 gfp_t gfp)
9588bbd5 18086{
947add36 18087 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 18088 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
947add36
JB
18089
18090 trace_cfg80211_ready_on_channel_expired(wdev, cookie, chan);
9588bbd5 18091 nl80211_send_remain_on_chan_event(NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL,
42d97a59 18092 rdev, wdev, cookie, chan, 0, gfp);
9588bbd5 18093}
947add36 18094EXPORT_SYMBOL(cfg80211_remain_on_channel_expired);
9588bbd5 18095
1c38c7f2
JP
18096void cfg80211_tx_mgmt_expired(struct wireless_dev *wdev, u64 cookie,
18097 struct ieee80211_channel *chan,
18098 gfp_t gfp)
18099{
18100 struct wiphy *wiphy = wdev->wiphy;
18101 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
18102
18103 trace_cfg80211_tx_mgmt_expired(wdev, cookie, chan);
18104 nl80211_send_remain_on_chan_event(NL80211_CMD_FRAME_WAIT_CANCEL,
18105 rdev, wdev, cookie, chan, 0, gfp);
18106}
18107EXPORT_SYMBOL(cfg80211_tx_mgmt_expired);
18108
947add36
JB
18109void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr,
18110 struct station_info *sinfo, gfp_t gfp)
98b62183 18111{
947add36 18112 struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
f26cbf40 18113 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
98b62183
JB
18114 struct sk_buff *msg;
18115
947add36
JB
18116 trace_cfg80211_new_sta(dev, mac_addr, sinfo);
18117
58050fce 18118 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
98b62183
JB
18119 if (!msg)
18120 return;
18121
cf5ead82 18122 if (nl80211_send_station(msg, NL80211_CMD_NEW_STATION, 0, 0, 0,
66266b3a 18123 rdev, dev, mac_addr, sinfo) < 0) {
98b62183
JB
18124 nlmsg_free(msg);
18125 return;
18126 }
18127
68eb5503 18128 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18129 NL80211_MCGRP_MLME, gfp);
98b62183 18130}
947add36 18131EXPORT_SYMBOL(cfg80211_new_sta);
98b62183 18132
cf5ead82
JB
18133void cfg80211_del_sta_sinfo(struct net_device *dev, const u8 *mac_addr,
18134 struct station_info *sinfo, gfp_t gfp)
ec15e68b 18135{
947add36 18136 struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
f26cbf40 18137 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
ec15e68b 18138 struct sk_buff *msg;
73887fd9 18139 struct station_info empty_sinfo = {};
cf5ead82 18140
73887fd9
JB
18141 if (!sinfo)
18142 sinfo = &empty_sinfo;
ec15e68b 18143
947add36
JB
18144 trace_cfg80211_del_sta(dev, mac_addr);
18145
58050fce 18146 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
7ea3e110
JB
18147 if (!msg) {
18148 cfg80211_sinfo_release_content(sinfo);
73887fd9 18149 return;
7ea3e110 18150 }
ec15e68b 18151
cf5ead82 18152 if (nl80211_send_station(msg, NL80211_CMD_DEL_STATION, 0, 0, 0,
57007121 18153 rdev, dev, mac_addr, sinfo) < 0) {
ec15e68b 18154 nlmsg_free(msg);
73887fd9 18155 return;
ec15e68b
JM
18156 }
18157
68eb5503 18158 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18159 NL80211_MCGRP_MLME, gfp);
ec15e68b 18160}
cf5ead82 18161EXPORT_SYMBOL(cfg80211_del_sta_sinfo);
ec15e68b 18162
947add36
JB
18163void cfg80211_conn_failed(struct net_device *dev, const u8 *mac_addr,
18164 enum nl80211_connect_failed_reason reason,
18165 gfp_t gfp)
ed44a951 18166{
947add36 18167 struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
f26cbf40 18168 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
ed44a951
PP
18169 struct sk_buff *msg;
18170 void *hdr;
18171
18172 msg = nlmsg_new(NLMSG_GOODSIZE, gfp);
18173 if (!msg)
18174 return;
18175
18176 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CONN_FAILED);
18177 if (!hdr) {
18178 nlmsg_free(msg);
18179 return;
18180 }
18181
18182 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
18183 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr) ||
18184 nla_put_u32(msg, NL80211_ATTR_CONN_FAILED_REASON, reason))
18185 goto nla_put_failure;
18186
18187 genlmsg_end(msg, hdr);
18188
68eb5503 18189 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18190 NL80211_MCGRP_MLME, gfp);
ed44a951
PP
18191 return;
18192
18193 nla_put_failure:
ed44a951
PP
18194 nlmsg_free(msg);
18195}
947add36 18196EXPORT_SYMBOL(cfg80211_conn_failed);
ed44a951 18197
b92ab5d8
JB
18198static bool __nl80211_unexpected_frame(struct net_device *dev, u8 cmd,
18199 const u8 *addr, gfp_t gfp)
28946da7
JB
18200{
18201 struct wireless_dev *wdev = dev->ieee80211_ptr;
f26cbf40 18202 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
28946da7
JB
18203 struct sk_buff *msg;
18204 void *hdr;
6aa7de05 18205 u32 nlportid = READ_ONCE(wdev->ap_unexpected_nlportid);
28946da7 18206
15e47304 18207 if (!nlportid)
28946da7
JB
18208 return false;
18209
18210 msg = nlmsg_new(100, gfp);
18211 if (!msg)
18212 return true;
18213
b92ab5d8 18214 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
28946da7
JB
18215 if (!hdr) {
18216 nlmsg_free(msg);
18217 return true;
18218 }
18219
9360ffd1
DM
18220 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
18221 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
18222 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr))
18223 goto nla_put_failure;
28946da7 18224
9c90a9f6 18225 genlmsg_end(msg, hdr);
15e47304 18226 genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid);
28946da7
JB
18227 return true;
18228
18229 nla_put_failure:
28946da7
JB
18230 nlmsg_free(msg);
18231 return true;
18232}
18233
947add36
JB
18234bool cfg80211_rx_spurious_frame(struct net_device *dev,
18235 const u8 *addr, gfp_t gfp)
b92ab5d8 18236{
947add36
JB
18237 struct wireless_dev *wdev = dev->ieee80211_ptr;
18238 bool ret;
18239
18240 trace_cfg80211_rx_spurious_frame(dev, addr);
18241
18242 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
18243 wdev->iftype != NL80211_IFTYPE_P2P_GO)) {
18244 trace_cfg80211_return_bool(false);
18245 return false;
18246 }
18247 ret = __nl80211_unexpected_frame(dev, NL80211_CMD_UNEXPECTED_FRAME,
18248 addr, gfp);
18249 trace_cfg80211_return_bool(ret);
18250 return ret;
b92ab5d8 18251}
947add36 18252EXPORT_SYMBOL(cfg80211_rx_spurious_frame);
b92ab5d8 18253
947add36
JB
18254bool cfg80211_rx_unexpected_4addr_frame(struct net_device *dev,
18255 const u8 *addr, gfp_t gfp)
b92ab5d8 18256{
947add36
JB
18257 struct wireless_dev *wdev = dev->ieee80211_ptr;
18258 bool ret;
18259
18260 trace_cfg80211_rx_unexpected_4addr_frame(dev, addr);
18261
18262 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
18263 wdev->iftype != NL80211_IFTYPE_P2P_GO &&
18264 wdev->iftype != NL80211_IFTYPE_AP_VLAN)) {
18265 trace_cfg80211_return_bool(false);
18266 return false;
18267 }
18268 ret = __nl80211_unexpected_frame(dev,
18269 NL80211_CMD_UNEXPECTED_4ADDR_FRAME,
18270 addr, gfp);
18271 trace_cfg80211_return_bool(ret);
18272 return ret;
b92ab5d8 18273}
947add36 18274EXPORT_SYMBOL(cfg80211_rx_unexpected_4addr_frame);
b92ab5d8 18275
2e161f78 18276int nl80211_send_mgmt(struct cfg80211_registered_device *rdev,
15e47304 18277 struct wireless_dev *wdev, u32 nlportid,
804483e9 18278 int freq, int sig_dbm,
19504cf5 18279 const u8 *buf, size_t len, u32 flags, gfp_t gfp)
026331c4 18280{
71bbc994 18281 struct net_device *netdev = wdev->netdev;
026331c4
JM
18282 struct sk_buff *msg;
18283 void *hdr;
026331c4 18284
4ef8c1c9 18285 msg = nlmsg_new(100 + len, gfp);
026331c4
JM
18286 if (!msg)
18287 return -ENOMEM;
18288
2e161f78 18289 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FRAME);
026331c4
JM
18290 if (!hdr) {
18291 nlmsg_free(msg);
18292 return -ENOMEM;
18293 }
18294
9360ffd1 18295 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
71bbc994
JB
18296 (netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
18297 netdev->ifindex)) ||
2dad624e
ND
18298 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
18299 NL80211_ATTR_PAD) ||
e76fede8 18300 nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, KHZ_TO_MHZ(freq)) ||
942ba88b 18301 nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ_OFFSET, freq % 1000) ||
9360ffd1
DM
18302 (sig_dbm &&
18303 nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)) ||
19504cf5
VK
18304 nla_put(msg, NL80211_ATTR_FRAME, len, buf) ||
18305 (flags &&
18306 nla_put_u32(msg, NL80211_ATTR_RXMGMT_FLAGS, flags)))
9360ffd1 18307 goto nla_put_failure;
026331c4 18308
3b7b72ee 18309 genlmsg_end(msg, hdr);
026331c4 18310
15e47304 18311 return genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid);
026331c4
JM
18312
18313 nla_put_failure:
026331c4
JM
18314 nlmsg_free(msg);
18315 return -ENOBUFS;
18316}
18317
dca9ca2d
MT
18318static void nl80211_frame_tx_status(struct wireless_dev *wdev, u64 cookie,
18319 const u8 *buf, size_t len, bool ack,
18320 gfp_t gfp, enum nl80211_commands command)
026331c4 18321{
947add36 18322 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 18323 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
71bbc994 18324 struct net_device *netdev = wdev->netdev;
026331c4
JM
18325 struct sk_buff *msg;
18326 void *hdr;
18327
dca9ca2d
MT
18328 if (command == NL80211_CMD_FRAME_TX_STATUS)
18329 trace_cfg80211_mgmt_tx_status(wdev, cookie, ack);
18330 else
18331 trace_cfg80211_control_port_tx_status(wdev, cookie, ack);
947add36 18332
4ef8c1c9 18333 msg = nlmsg_new(100 + len, gfp);
026331c4
JM
18334 if (!msg)
18335 return;
18336
dca9ca2d 18337 hdr = nl80211hdr_put(msg, 0, 0, 0, command);
026331c4
JM
18338 if (!hdr) {
18339 nlmsg_free(msg);
18340 return;
18341 }
18342
9360ffd1 18343 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
71bbc994
JB
18344 (netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
18345 netdev->ifindex)) ||
2dad624e
ND
18346 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
18347 NL80211_ATTR_PAD) ||
9360ffd1 18348 nla_put(msg, NL80211_ATTR_FRAME, len, buf) ||
2dad624e
ND
18349 nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
18350 NL80211_ATTR_PAD) ||
9360ffd1
DM
18351 (ack && nla_put_flag(msg, NL80211_ATTR_ACK)))
18352 goto nla_put_failure;
026331c4 18353
3b7b72ee 18354 genlmsg_end(msg, hdr);
026331c4 18355
68eb5503 18356 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18357 NL80211_MCGRP_MLME, gfp);
026331c4
JM
18358 return;
18359
dca9ca2d 18360nla_put_failure:
026331c4
JM
18361 nlmsg_free(msg);
18362}
dca9ca2d
MT
18363
18364void cfg80211_control_port_tx_status(struct wireless_dev *wdev, u64 cookie,
18365 const u8 *buf, size_t len, bool ack,
18366 gfp_t gfp)
18367{
18368 nl80211_frame_tx_status(wdev, cookie, buf, len, ack, gfp,
18369 NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS);
18370}
18371EXPORT_SYMBOL(cfg80211_control_port_tx_status);
18372
18373void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,
18374 const u8 *buf, size_t len, bool ack, gfp_t gfp)
18375{
18376 nl80211_frame_tx_status(wdev, cookie, buf, len, ack, gfp,
18377 NL80211_CMD_FRAME_TX_STATUS);
18378}
947add36 18379EXPORT_SYMBOL(cfg80211_mgmt_tx_status);
026331c4 18380
6a671a50 18381static int __nl80211_rx_control_port(struct net_device *dev,
a948f713 18382 struct sk_buff *skb,
6a671a50
DK
18383 bool unencrypted, gfp_t gfp)
18384{
18385 struct wireless_dev *wdev = dev->ieee80211_ptr;
18386 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
a948f713 18387 struct ethhdr *ehdr = eth_hdr(skb);
8d74a623 18388 const u8 *addr = ehdr->h_source;
a948f713 18389 u16 proto = be16_to_cpu(skb->protocol);
6a671a50
DK
18390 struct sk_buff *msg;
18391 void *hdr;
a948f713
DK
18392 struct nlattr *frame;
18393
6a671a50
DK
18394 u32 nlportid = READ_ONCE(wdev->conn_owner_nlportid);
18395
18396 if (!nlportid)
18397 return -ENOENT;
18398
a948f713 18399 msg = nlmsg_new(100 + skb->len, gfp);
6a671a50
DK
18400 if (!msg)
18401 return -ENOMEM;
18402
18403 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CONTROL_PORT_FRAME);
18404 if (!hdr) {
18405 nlmsg_free(msg);
18406 return -ENOBUFS;
18407 }
18408
18409 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
18410 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
18411 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
18412 NL80211_ATTR_PAD) ||
8d74a623 18413 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
6a671a50
DK
18414 nla_put_u16(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE, proto) ||
18415 (unencrypted && nla_put_flag(msg,
18416 NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT)))
18417 goto nla_put_failure;
18418
a948f713
DK
18419 frame = nla_reserve(msg, NL80211_ATTR_FRAME, skb->len);
18420 if (!frame)
18421 goto nla_put_failure;
18422
18423 skb_copy_bits(skb, 0, nla_data(frame), skb->len);
6a671a50
DK
18424 genlmsg_end(msg, hdr);
18425
18426 return genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid);
18427
18428 nla_put_failure:
18429 nlmsg_free(msg);
18430 return -ENOBUFS;
18431}
18432
18433bool cfg80211_rx_control_port(struct net_device *dev,
a948f713 18434 struct sk_buff *skb, bool unencrypted)
6a671a50
DK
18435{
18436 int ret;
18437
a948f713
DK
18438 trace_cfg80211_rx_control_port(dev, skb, unencrypted);
18439 ret = __nl80211_rx_control_port(dev, skb, unencrypted, GFP_ATOMIC);
6a671a50
DK
18440 trace_cfg80211_return_bool(ret == 0);
18441 return ret == 0;
18442}
18443EXPORT_SYMBOL(cfg80211_rx_control_port);
18444
5b97f49d
JB
18445static struct sk_buff *cfg80211_prepare_cqm(struct net_device *dev,
18446 const char *mac, gfp_t gfp)
d6dc1a38 18447{
947add36 18448 struct wireless_dev *wdev = dev->ieee80211_ptr;
5b97f49d
JB
18449 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
18450 struct sk_buff *msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
18451 void **cb;
947add36 18452
d6dc1a38 18453 if (!msg)
5b97f49d 18454 return NULL;
d6dc1a38 18455
5b97f49d
JB
18456 cb = (void **)msg->cb;
18457
18458 cb[0] = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NOTIFY_CQM);
18459 if (!cb[0]) {
d6dc1a38 18460 nlmsg_free(msg);
5b97f49d 18461 return NULL;
d6dc1a38
JO
18462 }
18463
9360ffd1 18464 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
947add36 18465 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
9360ffd1 18466 goto nla_put_failure;
d6dc1a38 18467
5b97f49d 18468 if (mac && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac))
d6dc1a38
JO
18469 goto nla_put_failure;
18470
ae0be8de 18471 cb[1] = nla_nest_start_noflag(msg, NL80211_ATTR_CQM);
5b97f49d 18472 if (!cb[1])
9360ffd1 18473 goto nla_put_failure;
d6dc1a38 18474
5b97f49d 18475 cb[2] = rdev;
d6dc1a38 18476
5b97f49d
JB
18477 return msg;
18478 nla_put_failure:
18479 nlmsg_free(msg);
18480 return NULL;
18481}
18482
18483static void cfg80211_send_cqm(struct sk_buff *msg, gfp_t gfp)
18484{
18485 void **cb = (void **)msg->cb;
18486 struct cfg80211_registered_device *rdev = cb[2];
18487
18488 nla_nest_end(msg, cb[1]);
18489 genlmsg_end(msg, cb[0]);
18490
18491 memset(msg->cb, 0, sizeof(msg->cb));
d6dc1a38 18492
68eb5503 18493 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18494 NL80211_MCGRP_MLME, gfp);
5b97f49d
JB
18495}
18496
18497void cfg80211_cqm_rssi_notify(struct net_device *dev,
18498 enum nl80211_cqm_rssi_threshold_event rssi_event,
bee427b8 18499 s32 rssi_level, gfp_t gfp)
5b97f49d
JB
18500{
18501 struct sk_buff *msg;
4a4b8169
AZ
18502 struct wireless_dev *wdev = dev->ieee80211_ptr;
18503 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
5b97f49d 18504
bee427b8 18505 trace_cfg80211_cqm_rssi_notify(dev, rssi_event, rssi_level);
5b97f49d 18506
98f03342
JB
18507 if (WARN_ON(rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW &&
18508 rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH))
18509 return;
18510
4a4b8169
AZ
18511 if (wdev->cqm_config) {
18512 wdev->cqm_config->last_rssi_event_value = rssi_level;
18513
18514 cfg80211_cqm_rssi_update(rdev, dev);
18515
18516 if (rssi_level == 0)
18517 rssi_level = wdev->cqm_config->last_rssi_event_value;
18518 }
18519
5b97f49d
JB
18520 msg = cfg80211_prepare_cqm(dev, NULL, gfp);
18521 if (!msg)
18522 return;
18523
18524 if (nla_put_u32(msg, NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT,
18525 rssi_event))
18526 goto nla_put_failure;
18527
bee427b8
AZ
18528 if (rssi_level && nla_put_s32(msg, NL80211_ATTR_CQM_RSSI_LEVEL,
18529 rssi_level))
18530 goto nla_put_failure;
18531
5b97f49d
JB
18532 cfg80211_send_cqm(msg, gfp);
18533
d6dc1a38
JO
18534 return;
18535
18536 nla_put_failure:
d6dc1a38
JO
18537 nlmsg_free(msg);
18538}
947add36 18539EXPORT_SYMBOL(cfg80211_cqm_rssi_notify);
d6dc1a38 18540
5b97f49d
JB
18541void cfg80211_cqm_txe_notify(struct net_device *dev,
18542 const u8 *peer, u32 num_packets,
18543 u32 rate, u32 intvl, gfp_t gfp)
18544{
18545 struct sk_buff *msg;
18546
18547 msg = cfg80211_prepare_cqm(dev, peer, gfp);
18548 if (!msg)
18549 return;
18550
18551 if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_PKTS, num_packets))
18552 goto nla_put_failure;
18553
18554 if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_RATE, rate))
18555 goto nla_put_failure;
18556
18557 if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_INTVL, intvl))
18558 goto nla_put_failure;
18559
18560 cfg80211_send_cqm(msg, gfp);
18561 return;
18562
18563 nla_put_failure:
18564 nlmsg_free(msg);
18565}
18566EXPORT_SYMBOL(cfg80211_cqm_txe_notify);
18567
18568void cfg80211_cqm_pktloss_notify(struct net_device *dev,
18569 const u8 *peer, u32 num_packets, gfp_t gfp)
18570{
18571 struct sk_buff *msg;
18572
18573 trace_cfg80211_cqm_pktloss_notify(dev, peer, num_packets);
18574
18575 msg = cfg80211_prepare_cqm(dev, peer, gfp);
18576 if (!msg)
18577 return;
18578
18579 if (nla_put_u32(msg, NL80211_ATTR_CQM_PKT_LOSS_EVENT, num_packets))
18580 goto nla_put_failure;
18581
18582 cfg80211_send_cqm(msg, gfp);
18583 return;
18584
18585 nla_put_failure:
18586 nlmsg_free(msg);
18587}
18588EXPORT_SYMBOL(cfg80211_cqm_pktloss_notify);
18589
98f03342
JB
18590void cfg80211_cqm_beacon_loss_notify(struct net_device *dev, gfp_t gfp)
18591{
18592 struct sk_buff *msg;
18593
18594 msg = cfg80211_prepare_cqm(dev, NULL, gfp);
18595 if (!msg)
18596 return;
18597
18598 if (nla_put_flag(msg, NL80211_ATTR_CQM_BEACON_LOSS_EVENT))
18599 goto nla_put_failure;
18600
18601 cfg80211_send_cqm(msg, gfp);
18602 return;
18603
18604 nla_put_failure:
18605 nlmsg_free(msg);
18606}
18607EXPORT_SYMBOL(cfg80211_cqm_beacon_loss_notify);
18608
947add36
JB
18609static void nl80211_gtk_rekey_notify(struct cfg80211_registered_device *rdev,
18610 struct net_device *netdev, const u8 *bssid,
18611 const u8 *replay_ctr, gfp_t gfp)
e5497d76
JB
18612{
18613 struct sk_buff *msg;
18614 struct nlattr *rekey_attr;
18615 void *hdr;
18616
58050fce 18617 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
e5497d76
JB
18618 if (!msg)
18619 return;
18620
18621 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_SET_REKEY_OFFLOAD);
18622 if (!hdr) {
18623 nlmsg_free(msg);
18624 return;
18625 }
18626
9360ffd1
DM
18627 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
18628 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
18629 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid))
18630 goto nla_put_failure;
e5497d76 18631
ae0be8de 18632 rekey_attr = nla_nest_start_noflag(msg, NL80211_ATTR_REKEY_DATA);
e5497d76
JB
18633 if (!rekey_attr)
18634 goto nla_put_failure;
18635
9360ffd1
DM
18636 if (nla_put(msg, NL80211_REKEY_DATA_REPLAY_CTR,
18637 NL80211_REPLAY_CTR_LEN, replay_ctr))
18638 goto nla_put_failure;
e5497d76
JB
18639
18640 nla_nest_end(msg, rekey_attr);
18641
3b7b72ee 18642 genlmsg_end(msg, hdr);
e5497d76 18643
68eb5503 18644 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18645 NL80211_MCGRP_MLME, gfp);
e5497d76
JB
18646 return;
18647
18648 nla_put_failure:
e5497d76
JB
18649 nlmsg_free(msg);
18650}
18651
947add36
JB
18652void cfg80211_gtk_rekey_notify(struct net_device *dev, const u8 *bssid,
18653 const u8 *replay_ctr, gfp_t gfp)
18654{
18655 struct wireless_dev *wdev = dev->ieee80211_ptr;
18656 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 18657 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
947add36
JB
18658
18659 trace_cfg80211_gtk_rekey_notify(dev, bssid);
18660 nl80211_gtk_rekey_notify(rdev, dev, bssid, replay_ctr, gfp);
18661}
18662EXPORT_SYMBOL(cfg80211_gtk_rekey_notify);
18663
18664static void
18665nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev,
18666 struct net_device *netdev, int index,
18667 const u8 *bssid, bool preauth, gfp_t gfp)
c9df56b4
JM
18668{
18669 struct sk_buff *msg;
18670 struct nlattr *attr;
18671 void *hdr;
18672
58050fce 18673 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
c9df56b4
JM
18674 if (!msg)
18675 return;
18676
18677 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_PMKSA_CANDIDATE);
18678 if (!hdr) {
18679 nlmsg_free(msg);
18680 return;
18681 }
18682
9360ffd1
DM
18683 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
18684 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex))
18685 goto nla_put_failure;
c9df56b4 18686
ae0be8de 18687 attr = nla_nest_start_noflag(msg, NL80211_ATTR_PMKSA_CANDIDATE);
c9df56b4
JM
18688 if (!attr)
18689 goto nla_put_failure;
18690
9360ffd1
DM
18691 if (nla_put_u32(msg, NL80211_PMKSA_CANDIDATE_INDEX, index) ||
18692 nla_put(msg, NL80211_PMKSA_CANDIDATE_BSSID, ETH_ALEN, bssid) ||
18693 (preauth &&
18694 nla_put_flag(msg, NL80211_PMKSA_CANDIDATE_PREAUTH)))
18695 goto nla_put_failure;
c9df56b4
JM
18696
18697 nla_nest_end(msg, attr);
18698
3b7b72ee 18699 genlmsg_end(msg, hdr);
c9df56b4 18700
68eb5503 18701 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18702 NL80211_MCGRP_MLME, gfp);
c9df56b4
JM
18703 return;
18704
18705 nla_put_failure:
c9df56b4
JM
18706 nlmsg_free(msg);
18707}
18708
947add36
JB
18709void cfg80211_pmksa_candidate_notify(struct net_device *dev, int index,
18710 const u8 *bssid, bool preauth, gfp_t gfp)
18711{
18712 struct wireless_dev *wdev = dev->ieee80211_ptr;
18713 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 18714 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
947add36
JB
18715
18716 trace_cfg80211_pmksa_candidate_notify(dev, index, bssid, preauth);
18717 nl80211_pmksa_candidate_notify(rdev, dev, index, bssid, preauth, gfp);
18718}
18719EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify);
18720
18721static void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
18722 struct net_device *netdev,
18723 struct cfg80211_chan_def *chandef,
f8d7552e
LC
18724 gfp_t gfp,
18725 enum nl80211_commands notif,
669b8413 18726 u8 count, bool quiet)
5314526b
TP
18727{
18728 struct sk_buff *msg;
18729 void *hdr;
18730
58050fce 18731 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
5314526b
TP
18732 if (!msg)
18733 return;
18734
f8d7552e 18735 hdr = nl80211hdr_put(msg, 0, 0, 0, notif);
5314526b
TP
18736 if (!hdr) {
18737 nlmsg_free(msg);
18738 return;
18739 }
18740
683b6d3b
JB
18741 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex))
18742 goto nla_put_failure;
18743
18744 if (nl80211_send_chandef(msg, chandef))
7eab0f64 18745 goto nla_put_failure;
5314526b 18746
669b8413
JB
18747 if (notif == NL80211_CMD_CH_SWITCH_STARTED_NOTIFY) {
18748 if (nla_put_u32(msg, NL80211_ATTR_CH_SWITCH_COUNT, count))
f8d7552e 18749 goto nla_put_failure;
669b8413
JB
18750 if (quiet &&
18751 nla_put_flag(msg, NL80211_ATTR_CH_SWITCH_BLOCK_TX))
f8d7552e 18752 goto nla_put_failure;
669b8413 18753 }
f8d7552e 18754
5314526b
TP
18755 genlmsg_end(msg, hdr);
18756
68eb5503 18757 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18758 NL80211_MCGRP_MLME, gfp);
5314526b
TP
18759 return;
18760
18761 nla_put_failure:
5314526b
TP
18762 nlmsg_free(msg);
18763}
18764
947add36 18765void cfg80211_ch_switch_notify(struct net_device *dev,
7b0a0e3c
JB
18766 struct cfg80211_chan_def *chandef,
18767 unsigned int link_id)
84f10708 18768{
947add36
JB
18769 struct wireless_dev *wdev = dev->ieee80211_ptr;
18770 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 18771 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
947add36 18772
e487eaeb 18773 ASSERT_WDEV_LOCK(wdev);
7b0a0e3c 18774 WARN_INVALID_LINK_ID(wdev, link_id);
947add36 18775
7b0a0e3c 18776 trace_cfg80211_ch_switch_notify(dev, chandef, link_id);
5dc8cdce 18777
7b0a0e3c
JB
18778 switch (wdev->iftype) {
18779 case NL80211_IFTYPE_STATION:
18780 case NL80211_IFTYPE_P2P_CLIENT:
18781 if (!WARN_ON(!wdev->links[link_id].client.current_bss))
18782 cfg80211_update_assoc_bss_entry(wdev, link_id,
18783 chandef->chan);
18784 break;
18785 case NL80211_IFTYPE_MESH_POINT:
18786 wdev->u.mesh.chandef = *chandef;
18787 wdev->u.mesh.preset_chandef = *chandef;
18788 break;
18789 case NL80211_IFTYPE_AP:
18790 case NL80211_IFTYPE_P2P_GO:
18791 wdev->links[link_id].ap.chandef = *chandef;
18792 break;
77e7b6ba
JB
18793 case NL80211_IFTYPE_ADHOC:
18794 wdev->u.ibss.chandef = *chandef;
18795 break;
7b0a0e3c
JB
18796 default:
18797 WARN_ON(1);
18798 break;
18799 }
5dc8cdce 18800
d34990bb
MV
18801 cfg80211_sched_dfs_chan_update(rdev);
18802
f8d7552e 18803 nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL,
669b8413 18804 NL80211_CMD_CH_SWITCH_NOTIFY, 0, false);
947add36
JB
18805}
18806EXPORT_SYMBOL(cfg80211_ch_switch_notify);
18807
f8d7552e
LC
18808void cfg80211_ch_switch_started_notify(struct net_device *dev,
18809 struct cfg80211_chan_def *chandef,
669b8413 18810 u8 count, bool quiet)
f8d7552e
LC
18811{
18812 struct wireless_dev *wdev = dev->ieee80211_ptr;
18813 struct wiphy *wiphy = wdev->wiphy;
18814 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
18815
18816 trace_cfg80211_ch_switch_started_notify(dev, chandef);
18817
18818 nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL,
669b8413
JB
18819 NL80211_CMD_CH_SWITCH_STARTED_NOTIFY,
18820 count, quiet);
f8d7552e
LC
18821}
18822EXPORT_SYMBOL(cfg80211_ch_switch_started_notify);
18823
0d2ab3ae
JC
18824int cfg80211_bss_color_notify(struct net_device *dev, gfp_t gfp,
18825 enum nl80211_commands cmd, u8 count,
18826 u64 color_bitmap)
18827{
18828 struct wireless_dev *wdev = dev->ieee80211_ptr;
18829 struct wiphy *wiphy = wdev->wiphy;
18830 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
18831 struct sk_buff *msg;
18832 void *hdr;
18833
18834 ASSERT_WDEV_LOCK(wdev);
18835
18836 trace_cfg80211_bss_color_notify(dev, cmd, count, color_bitmap);
18837
18838 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
18839 if (!msg)
18840 return -ENOMEM;
18841
18842 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
18843 if (!hdr)
18844 goto nla_put_failure;
18845
18846 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
18847 goto nla_put_failure;
18848
18849 if (cmd == NL80211_CMD_COLOR_CHANGE_STARTED &&
18850 nla_put_u32(msg, NL80211_ATTR_COLOR_CHANGE_COUNT, count))
18851 goto nla_put_failure;
18852
18853 if (cmd == NL80211_CMD_OBSS_COLOR_COLLISION &&
18854 nla_put_u64_64bit(msg, NL80211_ATTR_OBSS_COLOR_BITMAP,
18855 color_bitmap, NL80211_ATTR_PAD))
18856 goto nla_put_failure;
18857
18858 genlmsg_end(msg, hdr);
18859
18860 return genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
18861 msg, 0, NL80211_MCGRP_MLME, gfp);
18862
18863nla_put_failure:
18864 nlmsg_free(msg);
18865 return -EINVAL;
18866}
18867EXPORT_SYMBOL(cfg80211_bss_color_notify);
18868
04f39047
SW
18869void
18870nl80211_radar_notify(struct cfg80211_registered_device *rdev,
d2859df5 18871 const struct cfg80211_chan_def *chandef,
04f39047
SW
18872 enum nl80211_radar_event event,
18873 struct net_device *netdev, gfp_t gfp)
18874{
18875 struct sk_buff *msg;
18876 void *hdr;
18877
18878 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
18879 if (!msg)
18880 return;
18881
18882 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_RADAR_DETECT);
18883 if (!hdr) {
18884 nlmsg_free(msg);
18885 return;
18886 }
18887
18888 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx))
18889 goto nla_put_failure;
18890
18891 /* NOP and radar events don't need a netdev parameter */
18892 if (netdev) {
18893 struct wireless_dev *wdev = netdev->ieee80211_ptr;
18894
18895 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
2dad624e
ND
18896 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
18897 NL80211_ATTR_PAD))
04f39047
SW
18898 goto nla_put_failure;
18899 }
18900
18901 if (nla_put_u32(msg, NL80211_ATTR_RADAR_EVENT, event))
18902 goto nla_put_failure;
18903
18904 if (nl80211_send_chandef(msg, chandef))
18905 goto nla_put_failure;
18906
9c90a9f6 18907 genlmsg_end(msg, hdr);
04f39047 18908
68eb5503 18909 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18910 NL80211_MCGRP_MLME, gfp);
04f39047
SW
18911 return;
18912
18913 nla_put_failure:
04f39047
SW
18914 nlmsg_free(msg);
18915}
18916
466b9936 18917void cfg80211_sta_opmode_change_notify(struct net_device *dev, const u8 *mac,
18918 struct sta_opmode_info *sta_opmode,
18919 gfp_t gfp)
18920{
18921 struct sk_buff *msg;
18922 struct wireless_dev *wdev = dev->ieee80211_ptr;
18923 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
18924 void *hdr;
18925
18926 if (WARN_ON(!mac))
18927 return;
18928
18929 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
18930 if (!msg)
18931 return;
18932
18933 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_STA_OPMODE_CHANGED);
18934 if (!hdr) {
18935 nlmsg_free(msg);
18936 return;
18937 }
18938
18939 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx))
18940 goto nla_put_failure;
18941
18942 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
18943 goto nla_put_failure;
18944
18945 if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac))
18946 goto nla_put_failure;
18947
18948 if ((sta_opmode->changed & STA_OPMODE_SMPS_MODE_CHANGED) &&
18949 nla_put_u8(msg, NL80211_ATTR_SMPS_MODE, sta_opmode->smps_mode))
18950 goto nla_put_failure;
18951
18952 if ((sta_opmode->changed & STA_OPMODE_MAX_BW_CHANGED) &&
0016d320 18953 nla_put_u32(msg, NL80211_ATTR_CHANNEL_WIDTH, sta_opmode->bw))
466b9936 18954 goto nla_put_failure;
18955
18956 if ((sta_opmode->changed & STA_OPMODE_N_SS_CHANGED) &&
18957 nla_put_u8(msg, NL80211_ATTR_NSS, sta_opmode->rx_nss))
18958 goto nla_put_failure;
18959
18960 genlmsg_end(msg, hdr);
18961
18962 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
18963 NL80211_MCGRP_MLME, gfp);
18964
18965 return;
18966
18967nla_put_failure:
18968 nlmsg_free(msg);
18969}
18970EXPORT_SYMBOL(cfg80211_sta_opmode_change_notify);
18971
7f6cf311 18972void cfg80211_probe_status(struct net_device *dev, const u8 *addr,
c4b50cd3
VN
18973 u64 cookie, bool acked, s32 ack_signal,
18974 bool is_valid_ack_signal, gfp_t gfp)
7f6cf311
JB
18975{
18976 struct wireless_dev *wdev = dev->ieee80211_ptr;
f26cbf40 18977 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
7f6cf311
JB
18978 struct sk_buff *msg;
18979 void *hdr;
7f6cf311 18980
4ee3e063
BL
18981 trace_cfg80211_probe_status(dev, addr, cookie, acked);
18982
58050fce 18983 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
4ee3e063 18984
7f6cf311
JB
18985 if (!msg)
18986 return;
18987
18988 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_PROBE_CLIENT);
18989 if (!hdr) {
18990 nlmsg_free(msg);
18991 return;
18992 }
18993
9360ffd1
DM
18994 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
18995 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
18996 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
2dad624e
ND
18997 nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
18998 NL80211_ATTR_PAD) ||
c4b50cd3
VN
18999 (acked && nla_put_flag(msg, NL80211_ATTR_ACK)) ||
19000 (is_valid_ack_signal && nla_put_s32(msg, NL80211_ATTR_ACK_SIGNAL,
19001 ack_signal)))
9360ffd1 19002 goto nla_put_failure;
7f6cf311 19003
9c90a9f6 19004 genlmsg_end(msg, hdr);
7f6cf311 19005
68eb5503 19006 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 19007 NL80211_MCGRP_MLME, gfp);
7f6cf311
JB
19008 return;
19009
19010 nla_put_failure:
7f6cf311
JB
19011 nlmsg_free(msg);
19012}
19013EXPORT_SYMBOL(cfg80211_probe_status);
19014
e76fede8
TP
19015void cfg80211_report_obss_beacon_khz(struct wiphy *wiphy, const u8 *frame,
19016 size_t len, int freq, int sig_dbm)
5e760230 19017{
f26cbf40 19018 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
5e760230
JB
19019 struct sk_buff *msg;
19020 void *hdr;
37c73b5f 19021 struct cfg80211_beacon_registration *reg;
5e760230 19022
4ee3e063
BL
19023 trace_cfg80211_report_obss_beacon(wiphy, frame, len, freq, sig_dbm);
19024
37c73b5f
BG
19025 spin_lock_bh(&rdev->beacon_registrations_lock);
19026 list_for_each_entry(reg, &rdev->beacon_registrations, list) {
19027 msg = nlmsg_new(len + 100, GFP_ATOMIC);
19028 if (!msg) {
19029 spin_unlock_bh(&rdev->beacon_registrations_lock);
19030 return;
19031 }
5e760230 19032
37c73b5f
BG
19033 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FRAME);
19034 if (!hdr)
19035 goto nla_put_failure;
5e760230 19036
37c73b5f
BG
19037 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
19038 (freq &&
942ba88b
TP
19039 (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
19040 KHZ_TO_MHZ(freq)) ||
19041 nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ_OFFSET,
19042 freq % 1000))) ||
37c73b5f
BG
19043 (sig_dbm &&
19044 nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)) ||
19045 nla_put(msg, NL80211_ATTR_FRAME, len, frame))
19046 goto nla_put_failure;
5e760230 19047
37c73b5f 19048 genlmsg_end(msg, hdr);
5e760230 19049
37c73b5f
BG
19050 genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, reg->nlportid);
19051 }
19052 spin_unlock_bh(&rdev->beacon_registrations_lock);
5e760230
JB
19053 return;
19054
19055 nla_put_failure:
37c73b5f 19056 spin_unlock_bh(&rdev->beacon_registrations_lock);
5e760230
JB
19057 nlmsg_free(msg);
19058}
e76fede8 19059EXPORT_SYMBOL(cfg80211_report_obss_beacon_khz);
5e760230 19060
cd8f7cb4 19061#ifdef CONFIG_PM
8cd4d456
LC
19062static int cfg80211_net_detect_results(struct sk_buff *msg,
19063 struct cfg80211_wowlan_wakeup *wakeup)
19064{
19065 struct cfg80211_wowlan_nd_info *nd = wakeup->net_detect;
19066 struct nlattr *nl_results, *nl_match, *nl_freqs;
19067 int i, j;
19068
ae0be8de
MK
19069 nl_results = nla_nest_start_noflag(msg,
19070 NL80211_WOWLAN_TRIG_NET_DETECT_RESULTS);
8cd4d456
LC
19071 if (!nl_results)
19072 return -EMSGSIZE;
19073
19074 for (i = 0; i < nd->n_matches; i++) {
19075 struct cfg80211_wowlan_nd_match *match = nd->matches[i];
19076
ae0be8de 19077 nl_match = nla_nest_start_noflag(msg, i);
8cd4d456
LC
19078 if (!nl_match)
19079 break;
19080
19081 /* The SSID attribute is optional in nl80211, but for
19082 * simplicity reasons it's always present in the
19083 * cfg80211 structure. If a driver can't pass the
19084 * SSID, that needs to be changed. A zero length SSID
19085 * is still a valid SSID (wildcard), so it cannot be
19086 * used for this purpose.
19087 */
19088 if (nla_put(msg, NL80211_ATTR_SSID, match->ssid.ssid_len,
19089 match->ssid.ssid)) {
19090 nla_nest_cancel(msg, nl_match);
19091 goto out;
19092 }
19093
19094 if (match->n_channels) {
ae0be8de
MK
19095 nl_freqs = nla_nest_start_noflag(msg,
19096 NL80211_ATTR_SCAN_FREQUENCIES);
8cd4d456
LC
19097 if (!nl_freqs) {
19098 nla_nest_cancel(msg, nl_match);
19099 goto out;
19100 }
19101
19102 for (j = 0; j < match->n_channels; j++) {
5528fae8 19103 if (nla_put_u32(msg, j, match->channels[j])) {
8cd4d456
LC
19104 nla_nest_cancel(msg, nl_freqs);
19105 nla_nest_cancel(msg, nl_match);
19106 goto out;
19107 }
19108 }
19109
19110 nla_nest_end(msg, nl_freqs);
19111 }
19112
19113 nla_nest_end(msg, nl_match);
19114 }
19115
19116out:
19117 nla_nest_end(msg, nl_results);
19118 return 0;
19119}
19120
cd8f7cb4
JB
19121void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev,
19122 struct cfg80211_wowlan_wakeup *wakeup,
19123 gfp_t gfp)
19124{
f26cbf40 19125 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
cd8f7cb4
JB
19126 struct sk_buff *msg;
19127 void *hdr;
9c90a9f6 19128 int size = 200;
cd8f7cb4
JB
19129
19130 trace_cfg80211_report_wowlan_wakeup(wdev->wiphy, wdev, wakeup);
19131
19132 if (wakeup)
19133 size += wakeup->packet_present_len;
19134
19135 msg = nlmsg_new(size, gfp);
19136 if (!msg)
19137 return;
19138
19139 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_SET_WOWLAN);
19140 if (!hdr)
19141 goto free_msg;
19142
19143 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
2dad624e
ND
19144 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
19145 NL80211_ATTR_PAD))
cd8f7cb4
JB
19146 goto free_msg;
19147
19148 if (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
19149 wdev->netdev->ifindex))
19150 goto free_msg;
19151
19152 if (wakeup) {
19153 struct nlattr *reasons;
19154
ae0be8de
MK
19155 reasons = nla_nest_start_noflag(msg,
19156 NL80211_ATTR_WOWLAN_TRIGGERS);
7fa322c8
JB
19157 if (!reasons)
19158 goto free_msg;
cd8f7cb4
JB
19159
19160 if (wakeup->disconnect &&
19161 nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT))
19162 goto free_msg;
19163 if (wakeup->magic_pkt &&
19164 nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT))
19165 goto free_msg;
19166 if (wakeup->gtk_rekey_failure &&
19167 nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE))
19168 goto free_msg;
19169 if (wakeup->eap_identity_req &&
19170 nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST))
19171 goto free_msg;
19172 if (wakeup->four_way_handshake &&
19173 nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE))
19174 goto free_msg;
19175 if (wakeup->rfkill_release &&
19176 nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE))
19177 goto free_msg;
19178
19179 if (wakeup->pattern_idx >= 0 &&
19180 nla_put_u32(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN,
19181 wakeup->pattern_idx))
19182 goto free_msg;
19183
ae917c9f
JB
19184 if (wakeup->tcp_match &&
19185 nla_put_flag(msg, NL80211_WOWLAN_TRIG_WAKEUP_TCP_MATCH))
19186 goto free_msg;
2a0e047e 19187
ae917c9f
JB
19188 if (wakeup->tcp_connlost &&
19189 nla_put_flag(msg, NL80211_WOWLAN_TRIG_WAKEUP_TCP_CONNLOST))
19190 goto free_msg;
2a0e047e 19191
ae917c9f
JB
19192 if (wakeup->tcp_nomoretokens &&
19193 nla_put_flag(msg,
19194 NL80211_WOWLAN_TRIG_WAKEUP_TCP_NOMORETOKENS))
19195 goto free_msg;
2a0e047e 19196
cd8f7cb4
JB
19197 if (wakeup->packet) {
19198 u32 pkt_attr = NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211;
19199 u32 len_attr = NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN;
19200
19201 if (!wakeup->packet_80211) {
19202 pkt_attr =
19203 NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023;
19204 len_attr =
19205 NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023_LEN;
19206 }
19207
19208 if (wakeup->packet_len &&
19209 nla_put_u32(msg, len_attr, wakeup->packet_len))
19210 goto free_msg;
19211
19212 if (nla_put(msg, pkt_attr, wakeup->packet_present_len,
19213 wakeup->packet))
19214 goto free_msg;
19215 }
19216
8cd4d456
LC
19217 if (wakeup->net_detect &&
19218 cfg80211_net_detect_results(msg, wakeup))
19219 goto free_msg;
19220
cd8f7cb4
JB
19221 nla_nest_end(msg, reasons);
19222 }
19223
9c90a9f6 19224 genlmsg_end(msg, hdr);
cd8f7cb4 19225
68eb5503 19226 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 19227 NL80211_MCGRP_MLME, gfp);
cd8f7cb4
JB
19228 return;
19229
19230 free_msg:
19231 nlmsg_free(msg);
19232}
19233EXPORT_SYMBOL(cfg80211_report_wowlan_wakeup);
19234#endif
19235
3475b094
JM
19236void cfg80211_tdls_oper_request(struct net_device *dev, const u8 *peer,
19237 enum nl80211_tdls_operation oper,
19238 u16 reason_code, gfp_t gfp)
19239{
19240 struct wireless_dev *wdev = dev->ieee80211_ptr;
f26cbf40 19241 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
3475b094
JM
19242 struct sk_buff *msg;
19243 void *hdr;
3475b094
JM
19244
19245 trace_cfg80211_tdls_oper_request(wdev->wiphy, dev, peer, oper,
19246 reason_code);
19247
19248 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
19249 if (!msg)
19250 return;
19251
19252 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_TDLS_OPER);
19253 if (!hdr) {
19254 nlmsg_free(msg);
19255 return;
19256 }
19257
19258 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
19259 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
19260 nla_put_u8(msg, NL80211_ATTR_TDLS_OPERATION, oper) ||
19261 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, peer) ||
19262 (reason_code > 0 &&
19263 nla_put_u16(msg, NL80211_ATTR_REASON_CODE, reason_code)))
19264 goto nla_put_failure;
19265
9c90a9f6 19266 genlmsg_end(msg, hdr);
3475b094 19267
68eb5503 19268 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 19269 NL80211_MCGRP_MLME, gfp);
3475b094
JM
19270 return;
19271
19272 nla_put_failure:
3475b094
JM
19273 nlmsg_free(msg);
19274}
19275EXPORT_SYMBOL(cfg80211_tdls_oper_request);
19276
026331c4
JM
19277static int nl80211_netlink_notify(struct notifier_block * nb,
19278 unsigned long state,
19279 void *_notify)
19280{
19281 struct netlink_notify *notify = _notify;
19282 struct cfg80211_registered_device *rdev;
19283 struct wireless_dev *wdev;
37c73b5f 19284 struct cfg80211_beacon_registration *reg, *tmp;
026331c4 19285
8f815cdd 19286 if (state != NETLINK_URELEASE || notify->protocol != NETLINK_GENERIC)
026331c4
JM
19287 return NOTIFY_DONE;
19288
19289 rcu_read_lock();
19290
5e760230 19291 list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) {
ca986ad9 19292 struct cfg80211_sched_scan_request *sched_scan_req;
753aacfd 19293
ca986ad9
AVS
19294 list_for_each_entry_rcu(sched_scan_req,
19295 &rdev->sched_scan_req_list,
19296 list) {
19297 if (sched_scan_req->owner_nlportid == notify->portid) {
19298 sched_scan_req->nl_owner_dead = true;
753aacfd 19299 schedule_work(&rdev->sched_scan_stop_wk);
ca986ad9 19300 }
753aacfd 19301 }
78f22b6a 19302
53873f13 19303 list_for_each_entry_rcu(wdev, &rdev->wiphy.wdev_list, list) {
15e47304 19304 cfg80211_mlme_unregister_socket(wdev, notify->portid);
37c73b5f 19305
ab81007a
JB
19306 if (wdev->owner_nlportid == notify->portid) {
19307 wdev->nl_owner_dead = true;
19308 schedule_work(&rdev->destroy_work);
19309 } else if (wdev->conn_owner_nlportid == notify->portid) {
bd2522b1 19310 schedule_work(&wdev->disconnect_wk);
ab81007a 19311 }
9bb7e0f2
JB
19312
19313 cfg80211_release_pmsr(wdev, notify->portid);
78f22b6a
JB
19314 }
19315
37c73b5f
BG
19316 spin_lock_bh(&rdev->beacon_registrations_lock);
19317 list_for_each_entry_safe(reg, tmp, &rdev->beacon_registrations,
19318 list) {
19319 if (reg->nlportid == notify->portid) {
19320 list_del(&reg->list);
19321 kfree(reg);
19322 break;
19323 }
19324 }
19325 spin_unlock_bh(&rdev->beacon_registrations_lock);
5e760230 19326 }
026331c4
JM
19327
19328 rcu_read_unlock();
19329
05050753
I
19330 /*
19331 * It is possible that the user space process that is controlling the
19332 * indoor setting disappeared, so notify the regulatory core.
19333 */
19334 regulatory_netlink_notify(notify->portid);
6784c7db 19335 return NOTIFY_OK;
026331c4
JM
19336}
19337
19338static struct notifier_block nl80211_netlink_notifier = {
19339 .notifier_call = nl80211_netlink_notify,
19340};
19341
355199e0
JM
19342void cfg80211_ft_event(struct net_device *netdev,
19343 struct cfg80211_ft_event_params *ft_event)
19344{
19345 struct wiphy *wiphy = netdev->ieee80211_ptr->wiphy;
f26cbf40 19346 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
355199e0
JM
19347 struct sk_buff *msg;
19348 void *hdr;
355199e0
JM
19349
19350 trace_cfg80211_ft_event(wiphy, netdev, ft_event);
19351
19352 if (!ft_event->target_ap)
19353 return;
19354
1039d081
DL
19355 msg = nlmsg_new(100 + ft_event->ies_len + ft_event->ric_ies_len,
19356 GFP_KERNEL);
355199e0
JM
19357 if (!msg)
19358 return;
19359
19360 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FT_EVENT);
ae917c9f
JB
19361 if (!hdr)
19362 goto out;
355199e0 19363
ae917c9f
JB
19364 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
19365 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
19366 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, ft_event->target_ap))
19367 goto out;
355199e0 19368
ae917c9f
JB
19369 if (ft_event->ies &&
19370 nla_put(msg, NL80211_ATTR_IE, ft_event->ies_len, ft_event->ies))
19371 goto out;
19372 if (ft_event->ric_ies &&
19373 nla_put(msg, NL80211_ATTR_IE_RIC, ft_event->ric_ies_len,
19374 ft_event->ric_ies))
19375 goto out;
355199e0 19376
9c90a9f6 19377 genlmsg_end(msg, hdr);
355199e0 19378
68eb5503 19379 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 19380 NL80211_MCGRP_MLME, GFP_KERNEL);
ae917c9f
JB
19381 return;
19382 out:
19383 nlmsg_free(msg);
355199e0
JM
19384}
19385EXPORT_SYMBOL(cfg80211_ft_event);
19386
5de17984
AS
19387void cfg80211_crit_proto_stopped(struct wireless_dev *wdev, gfp_t gfp)
19388{
19389 struct cfg80211_registered_device *rdev;
19390 struct sk_buff *msg;
19391 void *hdr;
19392 u32 nlportid;
19393
f26cbf40 19394 rdev = wiphy_to_rdev(wdev->wiphy);
5de17984
AS
19395 if (!rdev->crit_proto_nlportid)
19396 return;
19397
19398 nlportid = rdev->crit_proto_nlportid;
19399 rdev->crit_proto_nlportid = 0;
19400
19401 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
19402 if (!msg)
19403 return;
19404
19405 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CRIT_PROTOCOL_STOP);
19406 if (!hdr)
19407 goto nla_put_failure;
19408
19409 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
2dad624e
ND
19410 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
19411 NL80211_ATTR_PAD))
5de17984
AS
19412 goto nla_put_failure;
19413
19414 genlmsg_end(msg, hdr);
19415
19416 genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid);
19417 return;
19418
19419 nla_put_failure:
5de17984 19420 nlmsg_free(msg);
5de17984
AS
19421}
19422EXPORT_SYMBOL(cfg80211_crit_proto_stopped);
19423
348baf0e
JB
19424void nl80211_send_ap_stopped(struct wireless_dev *wdev)
19425{
19426 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 19427 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
348baf0e
JB
19428 struct sk_buff *msg;
19429 void *hdr;
19430
19431 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
19432 if (!msg)
19433 return;
19434
19435 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_STOP_AP);
19436 if (!hdr)
19437 goto out;
19438
19439 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
19440 nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex) ||
2dad624e
ND
19441 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
19442 NL80211_ATTR_PAD))
348baf0e
JB
19443 goto out;
19444
19445 genlmsg_end(msg, hdr);
19446
19447 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(wiphy), msg, 0,
19448 NL80211_MCGRP_MLME, GFP_KERNEL);
19449 return;
19450 out:
19451 nlmsg_free(msg);
19452}
19453
40cbfa90
SD
19454int cfg80211_external_auth_request(struct net_device *dev,
19455 struct cfg80211_external_auth_params *params,
19456 gfp_t gfp)
19457{
19458 struct wireless_dev *wdev = dev->ieee80211_ptr;
19459 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
19460 struct sk_buff *msg;
19461 void *hdr;
19462
19463 if (!wdev->conn_owner_nlportid)
19464 return -EINVAL;
19465
19466 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
19467 if (!msg)
19468 return -ENOMEM;
19469
19470 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_EXTERNAL_AUTH);
19471 if (!hdr)
19472 goto nla_put_failure;
19473
19474 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
19475 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
19476 nla_put_u32(msg, NL80211_ATTR_AKM_SUITES, params->key_mgmt_suite) ||
19477 nla_put_u32(msg, NL80211_ATTR_EXTERNAL_AUTH_ACTION,
19478 params->action) ||
19479 nla_put(msg, NL80211_ATTR_BSSID, ETH_ALEN, params->bssid) ||
19480 nla_put(msg, NL80211_ATTR_SSID, params->ssid.ssid_len,
19481 params->ssid.ssid))
19482 goto nla_put_failure;
19483
19484 genlmsg_end(msg, hdr);
19485 genlmsg_unicast(wiphy_net(&rdev->wiphy), msg,
19486 wdev->conn_owner_nlportid);
19487 return 0;
19488
19489 nla_put_failure:
19490 nlmsg_free(msg);
19491 return -ENOBUFS;
19492}
19493EXPORT_SYMBOL(cfg80211_external_auth_request);
19494
cb74e977
SD
19495void cfg80211_update_owe_info_event(struct net_device *netdev,
19496 struct cfg80211_update_owe_info *owe_info,
19497 gfp_t gfp)
19498{
19499 struct wiphy *wiphy = netdev->ieee80211_ptr->wiphy;
19500 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
19501 struct sk_buff *msg;
19502 void *hdr;
19503
19504 trace_cfg80211_update_owe_info_event(wiphy, netdev, owe_info);
19505
19506 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
19507 if (!msg)
19508 return;
19509
19510 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_UPDATE_OWE_INFO);
19511 if (!hdr)
19512 goto nla_put_failure;
19513
19514 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
19515 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
19516 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, owe_info->peer))
19517 goto nla_put_failure;
19518
19519 if (!owe_info->ie_len ||
19520 nla_put(msg, NL80211_ATTR_IE, owe_info->ie_len, owe_info->ie))
19521 goto nla_put_failure;
19522
19523 genlmsg_end(msg, hdr);
19524
19525 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
19526 NL80211_MCGRP_MLME, gfp);
19527 return;
19528
19529nla_put_failure:
19530 genlmsg_cancel(msg, hdr);
19531 nlmsg_free(msg);
19532}
19533EXPORT_SYMBOL(cfg80211_update_owe_info_event);
19534
55682965
JB
19535/* initialisation/exit functions */
19536
56989f6d 19537int __init nl80211_init(void)
55682965 19538{
0d63cbb5 19539 int err;
55682965 19540
489111e5 19541 err = genl_register_family(&nl80211_fam);
55682965
JB
19542 if (err)
19543 return err;
19544
026331c4
JM
19545 err = netlink_register_notifier(&nl80211_netlink_notifier);
19546 if (err)
19547 goto err_out;
19548
55682965
JB
19549 return 0;
19550 err_out:
19551 genl_unregister_family(&nl80211_fam);
19552 return err;
19553}
19554
19555void nl80211_exit(void)
19556{
026331c4 19557 netlink_unregister_notifier(&nl80211_netlink_notifier);
55682965
JB
19558 genl_unregister_family(&nl80211_fam);
19559}